From 3dd3b51f7d0359a42ce1e7a76a45de05f2e12ea2 Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 21 Jul 2011 01:50:05 -0700 Subject: [PATCH 01/69] added .nojekyll --- .nojekyll | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .nojekyll diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b From 6d9bca5a6a6bca75d4c4d75e8a1ea2377c9dc0af Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 21 Jul 2011 01:55:04 -0700 Subject: [PATCH 02/69] Added index.html with redirect to wiki --- index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 index.html diff --git a/index.html b/index.html new file mode 100644 index 00000000..0faa45f3 --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ + + + Astropy redirect to wiki + + + + +The Astropy web site is not quite ready yet... redirecting you to the wiki in 5 seconds! + + + From cab14b9f832dfcf6dbd563ebdceb92b8612939e4 Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 21 Jul 2011 01:56:16 -0700 Subject: [PATCH 03/69] added README --- README | 1 + 1 file changed, 1 insertion(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 00000000..5e8a9d10 --- /dev/null +++ b/README @@ -0,0 +1 @@ +This repository contains the static web page for the Astropy project. Right now it just redirects to the astropy wiki. From 9d81a04864950080cc771fa1546c95d9201ebe7d Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 21 Jul 2011 02:00:31 -0700 Subject: [PATCH 04/69] added direct link to wiki --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 0faa45f3..96a27fca 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ -The Astropy web site is not quite ready yet... redirecting you to the wiki in 5 seconds! +The Astropy web site is not quite ready yet... redirecting you to the wiki in 5 seconds, or you can click here! From 0fc24d74a67be5cef5e7c88321127fa1e52baf2a Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 21 Jul 2011 15:19:58 -0700 Subject: [PATCH 05/69] added CNAME pointing to astropy.org --- CNAME | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 CNAME diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..89f4f2d2 --- /dev/null +++ b/CNAME @@ -0,0 +1,2 @@ +astropy.org + From 2cd42555a520db2dafeac44f3a02a82b6a9719d8 Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Mon, 25 Jul 2011 04:56:47 -0700 Subject: [PATCH 06/69] added docs built from astropy_test --- _sources/development/codeguide.txt | 203 +++++++++ _sources/development/docguide.txt | 583 +++++++++++++++++++++++++ _sources/development/index.txt | 12 + _sources/development/testguide.txt | 10 + _sources/development/vision.txt | 48 +++ _sources/index.txt | 24 ++ _static/basic.css | 528 +++++++++++++++++++++++ _static/default.css | 256 +++++++++++ _static/doctools.js | 247 +++++++++++ _static/file.png | Bin 0 -> 392 bytes _static/jquery.js | 154 +++++++ _static/minus.png | Bin 0 -> 199 bytes _static/plus.png | Bin 0 -> 199 bytes _static/pygments.css | 62 +++ _static/searchtools.js | 518 +++++++++++++++++++++++ _static/sidebar.js | 148 +++++++ _static/underscore.js | 16 + development/codeguide.html | 320 ++++++++++++++ development/docguide.html | 659 +++++++++++++++++++++++++++++ development/index.html | 118 ++++++ development/testguide.html | 110 +++++ development/vision.html | 155 +++++++ genindex.html | 90 ++++ index.html | 135 +++++- search.html | 96 +++++ searchindex.js | 1 + 26 files changed, 4484 insertions(+), 9 deletions(-) create mode 100644 _sources/development/codeguide.txt create mode 100644 _sources/development/docguide.txt create mode 100644 _sources/development/index.txt create mode 100644 _sources/development/testguide.txt create mode 100644 _sources/development/vision.txt create mode 100644 _sources/index.txt create mode 100644 _static/basic.css create mode 100644 _static/default.css create mode 100644 _static/doctools.js create mode 100644 _static/file.png create mode 100644 _static/jquery.js create mode 100644 _static/minus.png create mode 100644 _static/plus.png create mode 100644 _static/pygments.css create mode 100644 _static/searchtools.js create mode 100644 _static/sidebar.js create mode 100644 _static/underscore.js create mode 100644 development/codeguide.html create mode 100644 development/docguide.html create mode 100644 development/index.html create mode 100644 development/testguide.html create mode 100644 development/vision.html create mode 100644 genindex.html create mode 100644 search.html create mode 100644 searchindex.js diff --git a/_sources/development/codeguide.txt b/_sources/development/codeguide.txt new file mode 100644 index 00000000..21ebd2bd --- /dev/null +++ b/_sources/development/codeguide.txt @@ -0,0 +1,203 @@ +=========================== +Coding Guidelines (Draft 2) +=========================== + +.. warning:: + This document is currently in Draft form and is subject to change. + +Core Requirements and Recommendations +------------------------------------- + +This section describes requirements and guidelines that affiliated packages will have to follow before being considered for integration as a module in the core package. + +* The package should meet the interface requirements set out by the coordination committee. +* Packages must be compatible with Python 2.6, 2.7, and 3.x (for 3.x compatibility, the `2to3 tool `_ will be used). +* The package should be importable with no dependencies other than components already in the Astropy core, the `Python Standard Library (v2.6) `_, NumPy_, SciPy_, and matplotlib_ (versions for these packages will be specified in the Astropy ``setup.py`` file and on PyPI_). +* Additional dependencies are allowed for sub-modules or in function calls, but they must be noted in the package documentation and should only affect the relevant component. +* Docstrings must be present for all public classes/methods/functions, and must follow the form outlined in the :doc:`docguide` document. +* Unit tests are encouraged for all public methods and functions, and should adhere to the standards set in the :doc:`testguide` document. +* C extensions are only allowed when they provide a significant performance enhancement over pure python, or a C library already exists to provided the needed functionality. When C extensions are used, the python interface must meet interface guidelines. +* The use of Cython_ is strongly recommended for C extensions, as per the example in the template package. Cython extensions should store ``.pyx`` files in the source code repository, but they should be compiled to ``.c`` files that are updated in the repository when important changes are made to the ``.pyx`` file. +* If a C extension has a dependency on an external C library, the source code for the library should be bundled with the Astropy core. Additionally, the package must be compatible with using a system-installed library in place of the library included in Astropy. +* Packages can include data in ``path TBD`` as long as it is less than about 100 kb. These data should be accessed via the :func:`astropy.config.[funcname TBD]` mechanism. If the data exceeds this size, it should be hosted outside the source code repository and downloaded using the :func:`astropy.config.[funcname TBD]` mechanism. Exceptions to this size limit may be allowed if there are version dependencies between data and code. +* All persistent configuration should be stored using the functions in :mod:`astropy.config`, which make use of the :class:`ConfigObj` class and associated file format (http://www.voidspace.org.uk/python/configobj.html. +* General utilities necessary for but not specific to the package should be placed in the :mod:`packagename.utils` module. These utilities will be moved to the :mod:`astropy.utils` module when the package is integrated into the core package. If a utility is already present in :mod:`astropy.utils`, the package should always use that utility instead of re-implementing it in :mod:`packagename.utils`. +* Packages implementing many classes/functions not relevant to the component requested will not be accepted - the package should only include the required functionality and relevant extensions. +* The package should follow the additional style guides in the next section. + + +Coding Style/Conventions +------------------------ +These guidelines are additional style requirements for the Astropy core and recommendations for affiliated packages that are not candidates for merger into the core: + +* The code will follow the standard `PEP8 Style Guide for Python Code `_. In particular, this includes using only 4 spaces for indentation, and never tabs. +* One exception is to be made from the PEP8 style: new style relative imports of the form ``from . import modname`` are allowed and required for Astropy, as opposed to absolute (as PEP8 suggets) or the simpler ``import modname`` syntax. This is primarily due to improved relative import support since PEP8 was developed, and to simplify the process of moving modules. + +.. note:: + A pep8.py checker script is available at http://pypi.python.org/pypi/pep8. + +* In cases where C extensions are needed but Cython cannot be used, the `PEP 7 Style Guide for C Code `_ is recommended. +* The ``import numpy as np``, ``import matplotlib as mpl``, and ``import matplotlib.pyplot as plt`` naming conventions should be used wherever relevant. ``from packagename import *`` should never be used, except as a tool to flatten the namespace of a module. An example of the allowed usage is given below. +* Classes should either use direct variable access, or python’s property mechanism for setting object instance variables. ``get_value``/``set_value`` style methods should be used only when getting and setting the values requires a computationally-expensive operation. The example below illustrates this guideline. +* Classes are discouraged from using the builtin python :func:`super` function, unless absolutely needed. If used, it should be used consistentently by all subclasses, and noted in the class’s docstrings. An example illustrating why this is important (and alternative solutions) is included below. +* Affiliated packages are recommended to follow the layout and documentation form of the template package included in the core package source distribution. +* Affiliated packages are encouraged (but not required) to follow the Astropy core :doc:`docguide` and :doc:`testguide`. + +.. note:: + For more info on the pros and cons of using super, see http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ or http://keithdevens.com/weblog/archive/2011/Mar/16/Python.super) + +Affiliated Package Requirements +------------------------------- + +The following additional rules apply for affiliated packages, regardless of whether or not they are to be used in the core: + +* Affiliated packages must be registered on the `Python Package Index `_, with proper metadata for downloading and installing the source package. +* The :mod:`astropy` root package name should not be used by affiliated packages - it is reserved for use by the core package. Recommended naming conventions for an affiliated package are either simply :mod:`packagename` or :mod:`awastropy.packagename` ("affiliated with Astropy"). + +Examples +-------- + +This section shows a few examples (not all of which are correct!) to illustrate points from the guidelines. These will be moved into the template project once it has been written. + +Properties vs. get\_/set\_ +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This example shows a sample class illustrating the guideline regarding the use of properties as opposed to getter/setter methods. + +Let's assuming you've defined a :class:`Star` class and create an instance like this:: + + >>> s = Star(B=5.48, V=4.83) + +You should always use attribute syntax like this:: + + >>> s.color = 0.4 + >>> print s.color + 0.4 + +Rather than like this:: + + >>> s.set_color(0.4) #Bad form! + >>> print s.get_color() #Bad form! + 0.4 + +Using python properties, attribute syntax can still do anything possible with a get/set method. For lengthy or complex calculations, however, use a method:: + + >>> print s.compute_color(5800, age=5e9) + 0.4 + +super() vs. direct calling +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This example shows why the use of :func:`super` can be confusing for subclasses, and gives an alternative syntax:: + + #This is dangerous and bug-prone! + + class A(object): + def method(self): + print 'Doing A' + + + class B(A): + def method(self): + super(B, self).method() + print 'Doing B' + + + class C(A): + def method(self): + A.method(self) + print 'Doing C' + + + class D(C, B): + def method(self): + super(D, self).method() + print 'Doing D' + +if you then do:: + + >>> b = B() + >>> b.method() + +you will see:: + + Doing A + Doing B + +which is what you expect, and similarly for C. However, if you do:: + + >>> d = D() + >>> d.method() + +you might expect to have it call both method in the order A,C,B,D. But it doesn't - instead you see:: + + Doing A + Doing C + Doing D + +because the the ``A.method(self)`` in C effectively short-circuits the super mechanism. Thus, it's crucial that all classes in an inheritance hierarchy consistently use super and not mix super with the direct syntax. The simplest approach is to explicitly call each class' method and avoid super completely:: + + #This is safer + class A(object): + def __init__(self, a): + self.a = 1 + + + class B(A): + def __init__(self, a, b): + A.__init__(self, a) + self.b = b + + + class C(A): + def __init__(self, a, c): + A.__init__(self, a) + self.c = c + + + class D(C, B): + def __init__(self, a, b, c, d): + B.__init__(self, a, b) + C.__init__(self, a, c) + self.d = d + +Acceptable use of ``from module import *`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``from module import *`` is discouraged in a module that contains implementation code, as it impedes clarity and often imports unused variables. It can, however, be used for a package that is laid out in the following manner:: + + packagename + packagename/__init__.py + packagename/submodule1.py + packagename/submodule2.py + +In this case, ``packagename/__init__.py`` may be:: + + """ + A docstring describing the package goes here + """ + from submodule1 import * + from submodule2 import * + +This allows functions or classes in the submodules to be used directly as ``packagename.foo`` rather than ``packagename.submodule1.foo``. If this is used, it is strongly recommended that the submodules make use of the __all__ variable to specify which modules should be imported. Thus, submodule2.py might read:: + + from numpy import array,linspace + + __all__ = ('foo','AClass') + + def foo(bar): + #the function would be defined here + pass + + class AClass(object): + #the class is defined here + pass + +This ensures that ``from submodule import *`` only imports :func:`foo` and :class:`AClass`, but not :class:`numpy.array` or :func:`numpy.linspace`. + + +.. _Numpy: http://numpy.scipy.org/ +.. _Scipy: http://www.scipy.org/ +.. _matplotlib: http://matplotlib.sourceforge.net/ +.. _Cython: http://cython.org/ +.. _PyPI: http://pypi.python.org/pypi \ No newline at end of file diff --git a/_sources/development/docguide.txt b/_sources/development/docguide.txt new file mode 100644 index 00000000..cc4a726c --- /dev/null +++ b/_sources/development/docguide.txt @@ -0,0 +1,583 @@ +================================== +Documentation Guidelines (Draft 2) +================================== + +.. warning:: + This document is currently in Draft form and is subject to change. + +Astropy Documentation Rules and Recommendations +----------------------------------------------- + +This section describes the standards for documentation format affiliated packages that must follow for consideration of integration into the core module, as well as the standard Astropy docstring format. + +* Documentation shall use the Sphinx documentation tool. +* The template package will provide a recommended general structure for documentation. +* Docstrings must be provided for all public classes, methods, and functions. +* Docstrings will be incorporated into the documentation using a version of numpydoc included with astropy, and should follow the numpy/scipy docstring standards, included below. +* Examples and/or tutorials are strongly encouraged for typical use-cases of a particular module or class. +* Any external package dependencies aside from Numpy, Scipy, or matplotlib must be explicitly mentioned in the documentation. +* Configuration options using the :mod:`astropy.config` mechanisms must be explicitly mentioned in the documentation. + +Numpy/SciPy Docstring Rules +--------------------------- +The original source for these docstring standards is the numpy_ project, and the associated _numpydoc tools. The most up-to-date version of these standards can be found at `numpy's github site `_. + +.. _numpy: http://numpy.scipy.org/ +.. _numpydoc: http://pypi.python.org/pypi/numpydoc/0.3.1 + +Overview +^^^^^^^^ +In general, we follow the standard Python style conventions as described here: + * `Style Guide for C Code `_ + * `Style Guide for Python Code `_ + * `Docstring Conventions `_ + +Additional PEPs of interest regarding documentation of code: + * `Docstring Processing Framework `_ + * `Docutils Design Specification `_ + +Use a code checker: + * `pylint `_ + * `pyflakes` easy_install pyflakes + * `pep8.py `_ + +The following import conventions are used throughout the NumPy source +and documentation:: + + import numpy as np + import matplotlib as mpl + import matplotlib.pyplot as plt + +Do not abbreviate ``scipy``. There is no motivating use case to +abbreviate it in the real world, so we avoid it in the documentation +to avoid confusion. + +It is not necessary to do ``import numpy as np`` at the beginning of +an example. However, some sub-modules, such as ``fft``, are not +imported by default, and you have to include them explicitly:: + + import numpy.fft + +after which you may use it:: + + np.fft.fft2(...) + +Docstring Standard +^^^^^^^^^^^^^^^^^^ +A documentation string (docstring) is a string that describes a module, +function, class, or method definition. The docstring is a special attribute +of the object (``object.__doc__``) and, for consistency, is surrounded by +triple double quotes, i.e.:: + + """This is the form of a docstring. + + It can be spread over several lines. + + """ + +NumPy, SciPy_, and the scikits follow a common convention for +docstrings that provides for consistency, while also allowing our +toolchain to produce well-formatted reference guides. This document +describes the current community consensus for such a standard. If you +have suggestions for improvements, post them on the `numpy-discussion +list`_. + +Our docstring standard uses `re-structured text (reST) +`_ syntax and is rendered +using Sphinx_ (a pre-processor that understands the particular +documentation style we are using). While a rich set of +markup is available, we limit ourselves to a very basic subset, in +order to provide docstrings that are easy to read on text-only +terminals. + +A guiding principle is that human readers of the text are given +precedence over contorting docstrings so our tools produce nice +output. Rather than sacrificing the readability of the docstrings, we +have written pre-processors to assist Sphinx_ in its task. + +The length of docstring lines should be kept to 75 characters to +facilitate reading the docstrings in text terminals. + +Status +^^^^^^ +We are busy converting existing docstrings to the new format, +expanding them where they are lacking, as well as writing new ones for +undocumented functions. Volunteers are welcome to join the effort on +our new documentation system (see the `Documentation Editor +`_ and the `Developer Zone +`_). + +Sections +^^^^^^^^ +The sections of the docstring are: + +1. **Short summary** + + A one-line summary that does not use variable names or the function + name, e.g. + + :: + + def add(a, b): + """The sum of two numbers. + + """ + + The function signature is normally found by introspection and + displayed by the help function. For some functions (notably those + written in C) the signature is not available, so we have to specify + it as the first line of the docstring:: + + """ + add(a, b) + + The sum of two numbers. + + """ + +2. **Deprecation warning** + + A section (use if applicable) to warn users that the object is deprecated. + Section contents should include: + + * In what Numpy version the object was deprecated, and when it will be + removed. + + * Reason for deprecation if this is useful information (e.g., object + is superseded, duplicates functionality found elsewhere, etc.). + + * New recommended way of obtaining the same functionality. + + This section should use the note Sphinx directive instead of an + underlined section header. + + :: + + .. note:: Deprecated in Numpy 1.6 + `ndobj_old` will be removed in Numpy 2.0, it is replaced by + `ndobj_new` because the latter works also with array subclasses. + +3. **Extended summary** + + A few sentences giving an extended description. This section + should be used to clarify *functionality*, not to discuss + implementation detail or background theory, which should rather be + explored in the **notes** section below. You may refer to the + parameters and the function name, but parameter descriptions still + belong in the **parameters** section. + +4. **Parameters** + + Description of the function arguments, keywords and their + respective types. + + :: + + Parameters + ---------- + x : type + Description of parameter `x`. + + Enclose variables in single backticks. + + For the parameter types, be as preciese as possible. Below are a + few examples of parameters and their types. + + :: + + Parameters + ---------- + filename : str + copy : bool + dtype : data-type + iterable : iterable object + shape : int or tuple of int + files : list of str + + If it is not necessary to specify a keyword argument, use + ``optional``:: + + x : int, optional + + Optional keyword parameters have default values, which are + displayed as part of the function signature. They can also be + detailed in the description:: + + Description of parameter `x` (the default is -1, which implies summation + over all axes). + + When a parameter can only assume one of a fixed set of values, + those values can be listed in braces:: + + order : {'C', 'F', 'A'} + Description of `order`. + + When two or more input parameters have exactly the same type, shape and + description, they can be combined:: + + x1, x2 : array_like + Input arrays, description of `x1`, `x2`. + +5. **Returns** + + Explanation of the returned values and their types, of the same + format as **parameters**. + +6. **Other parameters** + + An optional section used to describe infrequently used parameters. + It should only be used if a function has a large number of keyword + prameters, to prevent cluttering the **parameters** section. + +7. **Raises** + + An optional section detailing which errors get raised and under + what conditions:: + + Raises + ------ + LinAlgException + If the matrix is not numerically invertible. + + This section should be used judiciously, i.e only for errors + that are non-obvious or have a large chance of getting raised. + +8. **See Also** + + An optional section used to refer to related code. This section + can be very useful, but should be used judiciously. The goal is to + direct users to other functions they may not be aware of, or have + easy means of discovering (by looking at the module docstring, for + example). Routines whose docstrings further explain parameters + used by this function are good candidates. + + As an example, for ``numpy.mean`` we would have:: + + See Also + -------- + average : Weighted average + + When referring to functions in the same sub-module, no prefix is + needed, and the tree is searched upwards for a match. + + Prefix functions from other sub-modules appropriately. E.g., + whilst documenting the ``random`` module, refer to a function in + ``fft`` by + + :: + + fft.fft2 : 2-D fast discrete Fourier transform + + When referring to an entirely different module:: + + scipy.random.norm : Random variates, PDFs, etc. + + Functions may be listed without descriptions, and this is + preferable if the functionality is clear from the function name:: + + See Also + -------- + func_a : Function a with its description. + func_b, func_c_, func_d + func_e + +9. **Notes** + + An optional section that provides additional information about the + code, possibly including a discussion of the algorithm. This + section may include mathematical equations, written in + `LaTeX `_ format:: + + The FFT is a fast implementation of the discrete Fourier transform: + + .. math:: X(e^{j\omega } ) = x(n)e^{ - j\omega n} + + Equations can also be typeset underneath the math directive:: + + The discrete-time Fourier time-convolution property states that + + .. math:: + + x(n) * y(n) \Leftrightarrow X(e^{j\omega } )Y(e^{j\omega } )\\ + another equation here + + Math can furthermore be used inline, i.e. + + :: + + The value of :math:`\omega` is larger than 5. + + Variable names are displayed in typewriter font, obtained by using + ``\mathtt{var}``:: + + We square the input parameter `alpha` to obtain + :math:`\mathtt{alpha}^2`. + + Note that LaTeX is not particularly easy to read, so use equations + sparingly. + + Images are allowed, but should not be central to the explanation; + users viewing the docstring as text must be able to comprehend its + meaning without resorting to an image viewer. These additional + illustrations are included using:: + + .. image:: filename + + where filename is a path relative to the reference guide source + directory. + +10. **References** + + References cited in the **notes** section may be listed here, + e.g. if you cited the article below using the text ``[1]_``, + include it as in the list as follows:: + + .. [1] O. McNoleg, "The integration of GIS, remote sensing, + expert systems and adaptive co-kriging for environmental habitat + modelling of the Highland Haggis using object-oriented, fuzzy-logic + and neural-network techniques," Computers & Geosciences, vol. 22, + pp. 585-588, 1996. + + which renders as + + .. [1] O. McNoleg, "The integration of GIS, remote sensing, + expert systems and adaptive co-kriging for environmental habitat + modelling of the Highland Haggis using object-oriented, fuzzy-logic + and neural-network techniques," Computers & Geosciences, vol. 22, + pp. 585-588, 1996. + + Referencing sources of a temporary nature, like web pages, is + discouraged. References are meant to augment the docstring, but + should not be required to understand it. References are numbered, starting + from one, in the order in which they are cited. + +11. **Examples** + + An optional section for examples, using the `doctest + `_ format. + This section is meant to illustrate usage, not to provide a + testing framework -- for that, use the ``tests/`` directory. + While optional, this section is very strongly encouraged. + + When multiple examples are provided, they should be separated by + blank lines. Comments explaining the examples should have blank + lines both above and below them:: + + >>> np.add(1, 2) + 3 + + Comment explaining the second example + + >>> np.add([1, 2], [3, 4]) + array([4, 6]) + + For tests with a result that is random or platform-dependent, mark the + output as such:: + + >>> import numpy.random + >>> np.random.rand(2) + array([ 0.35773152, 0.38568979]) #random + + You can run examples using:: + + >>> np.test(doctests=True) + + It is not necessary to use the doctest markup ```` to + indicate empty lines in the output. Note that the option to run + the examples through ``numpy.test`` is provided for checking if the + examples work, not for making the examples part of the testing framework. + + The examples may assume that ``import numpy as np`` is executed before + the example code in *numpy*. Additional examples may make use of + *matplotlib* for plotting, but should import it explicitly, e.g., + ``import matplotlib.pyplot as plt``. + + +Documenting classes +^^^^^^^^^^^^^^^^^^^ + +Class docstring +``````````````` +Use the same sections as outlined above (all except ``Returns`` are +applicable). The constructor (``__init__``) should also be documented +here, the **parameters** section of the docstring details the constructors +parameters. + +An ``Attributes`` section, located below the **parameters** section, +may be used to describe class variables:: + + Attributes + ---------- + x : float + The X coordinate. + y : float + The Y coordinate. + +Attributes that are properties and have their own docstrings can be +simply listed by name:: + + Attributes + ---------- + real + imag + x : float + The X coordinate + y : float + The Y coordinate + +In general, it is not necessary to list class methods. Those that are +not part of the public API have names that start with an underscore. +In some cases, however, a class may have a great many methods, of +which only a few are relevant (e.g., subclasses of ndarray). Then, it +becomes useful to have an additional ``Methods`` section:: + + class Photo(ndarray): + """ + Array with associated photographic information. + + ... + + Attributes + ---------- + exposure : float + Exposure in seconds. + + Methods + ------- + colorspace(c='rgb') + Represent the photo in the given colorspace. + gamma(n=1.0) + Change the photo's gamma exposure. + + """ + +If it is necessary to explain a private method (use with care!), it can +be referred to in the **extended summary** or the **notes**. Do not +list private methods in the Methods section. + +Note that `self` is *not* listed as the first parameter of methods. + +Method docstrings +````````````````` +Document these as you would any other function. Do not include +``self`` in the list of parameters. If a method has an equivalent function +(which is the case for many ndarray methods for example), the function +docstring should contain the detailed documentation, and the method docstring +should refer to it. Only put brief summary and See Also sections in the method +docstring. + + +Documenting class instances +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Instances of classes that are part of the Numpy API (for example `np.r_` +`np,c_`, `np.index_exp`, etc.) may require some care. To give these +instances a useful docstring, we do the following: + +* Single instance: If only a single instance of a class is exposed, + document the class. Examples can use the instance name. + +* Multiple instances: If multiple instances are exposed, docstrings + for each instance are written and assigned to the instances' + ``__doc__`` attributes at run time. The class is documented as usual, and + the exposed instances can be mentioned in the Notes and See Also sections. + + +Documenting constants +^^^^^^^^^^^^^^^^^^^^^ +Use the same sections as outlined for functions where applicable:: + + 1. summary + 2. extended summary (optional) + 3. see also (optional) + 4. references (optional) + 5. examples (optional) + +Docstrings for constants will not be visible in text terminals +(constants are of immutable type, so docstrings can not be assigned +to them like for for class instances), but will appear in the +documentation built with Sphinx. + + +Documenting modules +^^^^^^^^^^^^^^^^^^^ +Each module should have a docstring with at least a summary line. Other +sections are optional, and should be used in the same order as for documenting +functions when they are appropriate:: + + 1. summary + 2. extended summary + 3. routine listings + 4. see also + 5. notes + 6. references + 7. examples + +Routine listings are encouraged, especially for large modules, for which it is +hard to get a good overview of all functionality provided by looking at the +source file(s) or the __all__ dict. + +Note that license and author info, while often included in source files, do not +belong in docstrings. + + +Other points to keep in mind +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* Notes and Warnings : If there are points in the docstring that deserve + special emphasis, the reST directives for a note or warning can be used + in the vicinity of the context of the warning (inside a section). Syntax: + + :: + + .. warning:: Warning text. + + .. note:: Note text. + + Use these sparingly, as they do not look very good in text terminals + and are not often necessary. One situation in which a warning can + be useful is for marking a known bug that is not yet fixed. + +* Questions and Answers : For general questions on how to write docstrings + that are not answered in this document, refer to + ``_. + +* array_like : For functions that take arguments which can have not only + a type `ndarray`, but also types that can be converted to an ndarray + (i.e. scalar types, sequence types), those arguments can be documented + with type `array_like`. + +Common reST concepts +^^^^^^^^^^^^^^^^^^^^ +For paragraphs, indentation is significant and indicates indentation in the +output. New paragraphs are marked with a blank line. + +Use *italics*, **bold**, and ``courier`` if needed in any explanations +(but not for variable names and doctest code or multi-line code). +Variable, module and class names should be written between single +back-ticks (```numpy```). + +A more extensive example of reST markup can be found in `this example +document `_; +the `quick reference +`_ is +useful while editing. + +Line spacing and indentation are significant and should be carefully +followed. + +Conclusion +^^^^^^^^^^ + +`An example `_ of the +format shown here is available. Refer to `How to Build API/Reference +Documentation +`_ +on how to use Sphinx_ to build the manual. + +This document itself was written in ReStructuredText, and may be converted to +HTML using:: + + $ rst2html HOWTO_DOCUMENT.txt HOWTO_DOCUMENT.html + +.. _SciPy: http://www.scipy.org +.. _numpy-discussion list: http://www.scipy.org/Mailing_Lists +.. _Sphinx: http://sphinx.pocoo.org diff --git a/_sources/development/index.txt b/_sources/development/index.txt new file mode 100644 index 00000000..2241a71c --- /dev/null +++ b/_sources/development/index.txt @@ -0,0 +1,12 @@ +Documentation for Developers +============================ + +The information in the following pages are relevant for anyone interesting in contributing to AstroPy: + +.. toctree:: + :maxdepth: 1 + + vision + codeguide + docguide + testguide \ No newline at end of file diff --git a/_sources/development/testguide.txt b/_sources/development/testguide.txt new file mode 100644 index 00000000..53e9c6a4 --- /dev/null +++ b/_sources/development/testguide.txt @@ -0,0 +1,10 @@ +========================== +Testing Guidelines (Draft) +========================== + +.. warning:: + This document is currently in Draft form and is subject to change. + +This section describes the testing framework and format standards for tests in Astropy core modules (this also serves as recommendations for affiliated packages). + +* Guidelines will be filled in following a discussion on the astropy mailing list. \ No newline at end of file diff --git a/_sources/development/vision.txt b/_sources/development/vision.txt new file mode 100644 index 00000000..4ecd0541 --- /dev/null +++ b/_sources/development/vision.txt @@ -0,0 +1,48 @@ +Vision for a common Astronomy Python package +============================================ + +The following document summarizes a vision for a common Astronomy Python package, and how we can best all work together to achieve this. In the following document, this common package will be referred to as the core package. This vision is not set in stone, and we are committed to adapting it to whatever process and guidelines work in practice. + +The ultimate goal that we seek is a package that would contain much of the core functionality and some common tools required across Astronomy, but not *everything* Astronomers will ever need. The aim is primarily to avoid duplication for common core tasks, and to provide a robust framework upon which to build more complex tools. + +Such a common package should not preclude any other Astronomy package from existing, because there will always be more complex and/or specialized tools required. These tools will be able to rely on a single core library for many tasks, and thus reduce the number of dependencies, reduce duplication of functionality, and increase consistency of their interfaces. + +Procedure +--------- + +With the help of the community, the coordination committee will start by identifying a few of key areas where initial development/consolidation will be needed (such as FITS, WCS, coordinates, tables, photometry, spectra, etc.) and will encourage teams to be formed to build standalone packages implementing this functionality. These packages will be referred to as affiliated packages (meaning that they are intended for future integration in the core package). + +A set of requirements will be set out concerning the interfaces and classes/methods that affiliated packages will need to make available in order to ensure consistency between the different components. As the core package grows, new potential areas/components for the core package will be identified. Competition cannot be avoided, and will not be actively discouraged, but whenever possible, developers should strive to work as a team to provide a single and robust affiliated package, for the benefit of the community. + +The affiliated packages will be developed outside the core package in independent repositories, which will allow the teams the choice of tool and organization. Once an affiliated package has implemented the desired functionality, and satisfies quality criteria for coding style, documentation, and testing, it will be considered for inclusion in the core package, and further development will be done directly in the core package either via direct access to the repository, or via patches/pull requests (exactly how this will be done will be decided later). + +To ensure uniformity across affiliated packages, and to facilitate integration with the core package, developers who wish to submit their affiliated packages for inclusion in the core will need to follow the layout of a ‘template’ package that will be provided before development starts. + +Dependencies +------------ + +Affiliated packages should be able to be imported with only the following dependencies: + +* The Python Standard Library +* NumPy, SciPy, and Matplotlib +* Components already in the core Astronomy package + +Other packages may be used, but must be imported as needed rather than during the initial import of the package. + +If a dependency is needed, but is an affiliated package, the dependent package will need to wait until the dependency is integrated into the core package before being itself considered for inclusion. In the mean time, it can make use of the other affiliated package in its current form, or other packages, so as not to stall development. Thus, the first packages to be included in the core will be those only requiring the standard library, NumPy, SciPy, and Matplotlib. + +If the required dependency will never be part of a main package, then by default the dependency can be included but should be imported as needed (meaning that it only prevents the importing of that component, not the entire core package), unless a strong case is made and a general consensus is reached by the community that this dependency is important enough to be required at a higher level. + +This system means that packages will be integrated into the core package in an order depending on the dependency tree, and also ensures that the interfaces of packages being integrated into the core package are consistent with those already in the core package. + +Initially, no dependency on GUI toolkits will be allowed in the core package. If the community reaches agrees on a single toolkit that could be used, then this toolkit will be allowed (but will only be imported as needed). + +Keeping track of affiliated packages +------------------------------------ + +Affiliated packages will be listed in a central location (in addition to PyPI) that will allow an easy installation of all the affiliated packages, for example with a script that will seamlessly download and install all the affiliated packages. The core package will also include mechanisms to facilitate this installation process. + +Existing Packages +----------------- + +Developers who already have existing packages will be encouraged to continue supporting them for the benefit of users until the core library is considered stable, contains this functionality, and is released to the community. Thereafter, developers should encourage users to transition to using the functionality in the core package, and eventually phase out their own packages, unless they provide added value over the core package. \ No newline at end of file diff --git a/_sources/index.txt b/_sources/index.txt new file mode 100644 index 00000000..e7a5c2fd --- /dev/null +++ b/_sources/index.txt @@ -0,0 +1,24 @@ +.. AstroPy documentation master file, created by + sphinx-quickstart on Sat Jul 23 11:41:56 2011. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to AstroPy's documentation! +=================================== + +The current AstroPy documentation is limited. For more information, see the `github wiki `_ for the project. + +Contents: + +.. toctree:: + :maxdepth: 2 + + development/index + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 00000000..32630d54 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,528 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +img { + border: 0; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + clear: both; + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.refcount { + color: #060; +} + +.optional { + font-size: 1.3em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +tt.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +tt.descclassname { + background-color: transparent; +} + +tt.xref, a tt { + background-color: transparent; + font-weight: bold; +} + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} diff --git a/_static/default.css b/_static/default.css new file mode 100644 index 00000000..21f3f509 --- /dev/null +++ b/_static/default.css @@ -0,0 +1,256 @@ +/* + * default.css_t + * ~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- default theme. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: sans-serif; + font-size: 100%; + background-color: #11303d; + color: #000; + margin: 0; + padding: 0; +} + +div.document { + background-color: #1c4e63; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 230px; +} + +div.body { + background-color: #ffffff; + color: #000000; + padding: 0 20px 30px 20px; +} + +div.footer { + color: #ffffff; + width: 100%; + padding: 9px 0 9px 0; + text-align: center; + font-size: 75%; +} + +div.footer a { + color: #ffffff; + text-decoration: underline; +} + +div.related { + background-color: #133f52; + line-height: 30px; + color: #ffffff; +} + +div.related a { + color: #ffffff; +} + +div.sphinxsidebar { +} + +div.sphinxsidebar h3 { + font-family: 'Trebuchet MS', sans-serif; + color: #ffffff; + font-size: 1.4em; + font-weight: normal; + margin: 0; + padding: 0; +} + +div.sphinxsidebar h3 a { + color: #ffffff; +} + +div.sphinxsidebar h4 { + font-family: 'Trebuchet MS', sans-serif; + color: #ffffff; + font-size: 1.3em; + font-weight: normal; + margin: 5px 0 0 0; + padding: 0; +} + +div.sphinxsidebar p { + color: #ffffff; +} + +div.sphinxsidebar p.topless { + margin: 5px 10px 10px 10px; +} + +div.sphinxsidebar ul { + margin: 10px; + padding: 0; + color: #ffffff; +} + +div.sphinxsidebar a { + color: #98dbcc; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + + + +/* -- hyperlink styles ------------------------------------------------------ */ + +a { + color: #355f7c; + text-decoration: none; +} + +a:visited { + color: #355f7c; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + + + +/* -- body styles ----------------------------------------------------------- */ + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Trebuchet MS', sans-serif; + background-color: #f2f2f2; + font-weight: normal; + color: #20435c; + border-bottom: 1px solid #ccc; + margin: 20px -20px 10px -20px; + padding: 3px 0 3px 10px; +} + +div.body h1 { margin-top: 0; font-size: 200%; } +div.body h2 { font-size: 160%; } +div.body h3 { font-size: 140%; } +div.body h4 { font-size: 120%; } +div.body h5 { font-size: 110%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #c60f0f; + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + background-color: #c60f0f; + color: white; +} + +div.body p, div.body dd, div.body li { + text-align: justify; + line-height: 130%; +} + +div.admonition p.admonition-title + p { + display: inline; +} + +div.admonition p { + margin-bottom: 5px; +} + +div.admonition pre { + margin-bottom: 5px; +} + +div.admonition ul, div.admonition ol { + margin-bottom: 5px; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre { + padding: 5px; + background-color: #eeffcc; + color: #333333; + line-height: 120%; + border: 1px solid #ac9; + border-left: none; + border-right: none; +} + +tt { + background-color: #ecf0f3; + padding: 0 1px 0 1px; + font-size: 0.95em; +} + +th { + background-color: #ede; +} + +.warning tt { + background: #efc2c2; +} + +.note tt { + background: #d6d6d6; +} + +.viewcode-back { + font-family: sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} \ No newline at end of file diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 00000000..8b9bd2c0 --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,247 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilties for all documentation. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +} + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s == 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * small function to check if an array contains + * a given item. + */ +jQuery.contains = function(arr, item) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] == item) + return true; + } + return false; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node) { + if (node.nodeType == 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this); + }); + } + } + return this.each(function() { + highlight(this); + }); +}; + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated == 'undefined') + return string; + return (typeof translated == 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated == 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('.sidebar .this-page-menu')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) == 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('.sidebar .this-page-menu li.highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this == '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..d18082e397e7e54f20721af768c4c2983258f1b4 GIT binary patch literal 392 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$HyOL$D9)yc9|lc|nKf<9@eUiWd>3GuTC!a5vdfWYEazjncPj5ZQX%+1 zt8B*4=d)!cdDz4wr^#OMYfqGz$1LDFF>|#>*O?AGil(WEs?wLLy{Gj2J_@opDm%`dlax3yA*@*N$G&*ukFv>P8+2CBWO(qz zD0k1@kN>hhb1_6`&wrCswzINE(evt-5C1B^STi2@PmdKI;Vst0PQB6!2kdN literal 0 HcmV?d00001 diff --git a/_static/jquery.js b/_static/jquery.js new file mode 100644 index 00000000..7c243080 --- /dev/null +++ b/_static/jquery.js @@ -0,0 +1,154 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
"; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/_static/minus.png b/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..da1c5620d10c047525a467a425abe9ff5269cfc2 GIT binary patch literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1SHkYJtzcHoCO|{#XvD(5N2eUHAey{$X?>< z>&kweokM_|(Po{+Q=kw>iEBiObAE1aYF-J$w=>iB1I2R$WLpMkF=>bh=@O1TaS?83{1OVknK< z>&kweokM`jkU7Va11Q8%;u=xnoS&PUnpeW`?aZ|OK(QcC7sn8Z%gHvy&v=;Q4jejg zV8NnAO`-4Z@2~&zopr02WF_WB>pF literal 0 HcmV?d00001 diff --git a/_static/pygments.css b/_static/pygments.css new file mode 100644 index 00000000..1a14f2ae --- /dev/null +++ b/_static/pygments.css @@ -0,0 +1,62 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #303030 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 00000000..dae92b5e --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,518 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilties for the full-text search. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words, hlwords is the list of normal, unstemmed + * words. the first one is used to find the occurance, the + * latter for highlighting it. + */ + +jQuery.makeSearchSummary = function(text, keywords, hlwords) { + var textLower = text.toLowerCase(); + var start = 0; + $.each(keywords, function() { + var i = textLower.indexOf(this.toLowerCase()); + if (i > -1) + start = i; + }); + start = Math.max(start - 120, 0); + var excerpt = ((start > 0) ? '...' : '') + + $.trim(text.substr(start, 240)) + + ((start + 240 - text.length) ? '...' : ''); + var rv = $('
').text(excerpt); + $.each(hlwords, function() { + rv = rv.highlightText(this, 'highlighted'); + }); + return rv; +} + +/** + * Porter Stemmer + */ +var PorterStemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + + +/** + * Search Module + */ +var Search = { + + _index : null, + _queued_query : null, + _pulse_status : -1, + + init : function() { + var params = $.getQueryParameters(); + if (params.q) { + var query = params.q[0]; + $('input[name="q"]')[0].value = query; + this.performSearch(query); + } + }, + + loadIndex : function(url) { + $.ajax({type: "GET", url: url, data: null, success: null, + dataType: "script", cache: true}); + }, + + setIndex : function(index) { + var q; + this._index = index; + if ((q = this._queued_query) !== null) { + this._queued_query = null; + Search.query(q); + } + }, + + hasIndex : function() { + return this._index !== null; + }, + + deferQuery : function(query) { + this._queued_query = query; + }, + + stopPulse : function() { + this._pulse_status = 0; + }, + + startPulse : function() { + if (this._pulse_status >= 0) + return; + function pulse() { + Search._pulse_status = (Search._pulse_status + 1) % 4; + var dotString = ''; + for (var i = 0; i < Search._pulse_status; i++) + dotString += '.'; + Search.dots.text(dotString); + if (Search._pulse_status > -1) + window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something + */ + performSearch : function(query) { + // create the required interface elements + this.out = $('#search-results'); + this.title = $('

' + _('Searching') + '

').appendTo(this.out); + this.dots = $('').appendTo(this.title); + this.status = $('

').appendTo(this.out); + this.output = $('

This section should use the note Sphinx directive instead of an underlined section header.

-
.. note:: Deprecated in Numpy 1.6
-          `ndobj_old` will be removed in Numpy 2.0, it is replaced by
+
.. note:: Deprecated in AstroPy 1.2
+          `ndobj_old` will be removed in AstroPy 2.0, it is replaced by
           `ndobj_new` because the latter works also with array subclasses.
  • Extended summary

    -

    A few sentences giving an extended description. This section -should be used to clarify functionality, not to discuss -implementation detail or background theory, which should rather be -explored in the notes section below. You may refer to the -parameters and the function name, but parameter descriptions still -belong in the parameters section.

    +

    A few sentences giving an extended description. This section should be used +to clarify functionality, not to discuss implementation detail or +background theory, which should rather be explored in the notes section +below. You may refer to the parameters and the function name, but parameter +descriptions still belong in the parameters section.

  • Parameters

    -

    Description of the function arguments, keywords and their -respective types.

    +

    Description of the function arguments, keywords and their respective types.

    Parameters
     ----------
     x : type
        Description of parameter `x`.

    Enclose variables in single backticks.

    -

    For the parameter types, be as preciese as possible. Below are a -few examples of parameters and their types.

    +

    For the parameter types, be as precise as possible. Below are a few +examples of parameters and their types.

  • Other parameters

    -

    An optional section used to describe infrequently used parameters. -It should only be used if a function has a large number of keyword -prameters, to prevent cluttering the parameters section.

    +

    An optional section used to describe infrequently used parameters. It +should only be used if a function has a large number of keyword parameters, +to prevent cluttering the parameters section.

  • Raises

    -

    An optional section detailing which errors get raised and under -what conditions:

    +

    An optional section detailing which errors get raised and under what +conditions:

    Raises
     ------
    -LinAlgException
    -    If the matrix is not numerically invertible.
    +InvalidWCSException + If the WCS information is invalid.
  • -

    This section should be used judiciously, i.e only for errors -that are non-obvious or have a large chance of getting raised.

    +

    This section should be used judiciously, i.e only for errors that are +non-obvious or have a large chance of getting raised.

  • See Also

    -

    An optional section used to refer to related code. This section -can be very useful, but should be used judiciously. The goal is to -direct users to other functions they may not be aware of, or have -easy means of discovering (by looking at the module docstring, for -example). Routines whose docstrings further explain parameters -used by this function are good candidates.

    -

    As an example, for numpy.mean we would have:

    +

    An optional section used to refer to related code. This section can be very +useful, but should be used judiciously. The goal is to direct users to +other functions they may not be aware of, or have easy means of discovering +(by looking at the module docstring, for example). Routines whose +docstrings further explain parameters used by this function are good +candidates.

    +

    As an example, for a hypothetical function astropy.wcs.sky2pix +converting sky to pixel coordinates, we would have:

    See Also
     --------
    -average : Weighted average
    +pix2sky : Convert pixel to sky coordinates
    -

    When referring to functions in the same sub-module, no prefix is -needed, and the tree is searched upwards for a match.

    -

    Prefix functions from other sub-modules appropriately. E.g., -whilst documenting the random module, refer to a function in -fft by

    -
    fft.fft2 : 2-D fast discrete Fourier transform
    +

    When referring to functions in the same sub-module, no prefix is needed, +and the tree is searched upwards for a match.

    +

    Prefix functions from other sub-modules appropriately. E.g., whilst +documenting a hypothetical astropy.vo module, refer to a function in +table by

    +
    table.read : Read in a VO table

    When referring to an entirely different module:

    -
  • References

  • @@ -359,50 +358,49 @@

    Sections
  • Examples
  • -

    An optional section for examples, using the doctest format. -This section is meant to illustrate usage, not to provide a -testing framework – for that, use the tests/ directory. -While optional, this section is very strongly encouraged.

    -

    When multiple examples are provided, they should be separated by -blank lines. Comments explaining the examples should have blank -lines both above and below them:

    -
    >>> np.add(1, 2)
    -3
    +

    An optional section for examples, using the doctest format. This section +is meant to illustrate usage, not to provide a testing framework – for +that, use the tests/ directory. While optional, this section is very +strongly encouraged.

    +

    When multiple examples are provided, they should be separated by blank +lines. Comments explaining the examples should have blank lines both above +and below them:

    +
    >>> astropy.wcs.sky2pix(233.2, -12.3)
    +(134.5, 233.1)
     
     Comment explaining the second example
     
    ->>> np.add([1, 2], [3, 4])
    -array([4, 6])
    +>>> astropy.coords.fk5_to_gal("00:42:44.33 +41:16:07.5")
    +(121.1743, -21.5733)
     

    For tests with a result that is random or platform-dependent, mark the output as such:

    -
    >>> import numpy.random
    ->>> np.random.rand(2)
    -array([ 0.35773152,  0.38568979])  #random
    +
    >>> astropy.coords.randomize_position(244.9, 44.2, radius=0.1)
    +(244.855, 44.13)  #random
     

    You can run examples using:

    -
    >>> np.test(doctests=True)
    +
    >>> astropy.test(doctests=True)
     
    -

    It is not necessary to use the doctest markup <BLANKLINE> to -indicate empty lines in the output. Note that the option to run -the examples through numpy.test is provided for checking if the -examples work, not for making the examples part of the testing framework.

    -

    The examples may assume that import numpy as np is executed before -the example code in numpy. Additional examples may make use of -matplotlib for plotting, but should import it explicitly, e.g., -import matplotlib.pyplot as plt.

    +

    It is not necessary to use the doctest markup <BLANKLINE> to indicate +empty lines in the output. Note that the option to run the examples through +numpy.test is provided for checking if the examples work, not for +making the examples part of the testing framework.

    +

    The examples may assume that import numpy as np is executed before the +example code Additional examples may make use of matplotlib +for plotting, but should import it explicitly, e.g., import +matplotlib.pyplot as plt.

    @@ -410,11 +408,11 @@

    Documenting classes

    Class docstring

    Use the same sections as outlined above (all except Returns are -applicable). The constructor (__init__) should also be documented -here, the parameters section of the docstring details the constructors +applicable). The constructor (__init__) should also be documented here, +the parameters section of the docstring details the constructors parameters.

    -

    An Attributes section, located below the parameters section, -may be used to describe class variables:

    +

    An Attributes section, located below the parameters section, may be +used to describe class variables:

    Attributes
     ----------
     x : float
    @@ -422,8 +420,8 @@ 

    Class docstring
    Attributes
     ----------
     real
    @@ -433,59 +431,56 @@ 

    Class docstringMethods section:

    -
    class Photo(ndarray):
    +

    In general, it is not necessary to list class methods. Those that are not part +of the public API have names that start with an underscore. In some cases, +however, a class may have a great many methods, of which only a few are +relevant (e.g., subclasses of ndarray). Then, it becomes useful to have an +additional Methods section:

    +
    class Table(ndarray):
         """
    -    Array with associated photographic information.
    +    A class to represent tables of data
     
         ...
     
         Attributes
         ----------
    -    exposure : float
    -        Exposure in seconds.
    +    columns : list
    +        List of columns
     
         Methods
         -------
    -    colorspace(c='rgb')
    -        Represent the photo in the given colorspace.
    -    gamma(n=1.0)
    -        Change the photo's gamma exposure.
    -
    +    read(filename)
    +        Read a table from a file
    +    sort(column, order='ascending')
    +        Sort by `column`
         """
     
    -

    If it is necessary to explain a private method (use with care!), it can -be referred to in the extended summary or the notes. Do not -list private methods in the Methods section.

    -

    Note that self is not listed as the first parameter of methods.

    +

    If it is necessary to explain a private method (use with care!), it can be +referred to in the extended summary or the notes. Do not list private +methods in the Methods section.

    +

    Note that self is not listed as the first parameter of methods.

    Method docstrings

    -

    Document these as you would any other function. Do not include -self in the list of parameters. If a method has an equivalent function -(which is the case for many ndarray methods for example), the function -docstring should contain the detailed documentation, and the method docstring -should refer to it. Only put brief summary and See Also sections in the method -docstring.

    +

    Document these as you would any other function. Do not include self in the +list of parameters. If a method has an equivalent function (which is the case +for many ndarray methods for example), the function docstring should contain +the detailed documentation, and the method docstring should refer to it. Only +put brief summary and See Also sections in the method docstring.

    Documenting class instances

    -

    Instances of classes that are part of the Numpy API (for example np.r_ -np,c_, np.index_exp, etc.) may require some care. To give these -instances a useful docstring, we do the following:

    +

    Instances of classes that are part of the AstroPy API may require some care. +To give these instances a useful docstring, we do the following:

      -
    • Single instance: If only a single instance of a class is exposed, -document the class. Examples can use the instance name.
    • -
    • Multiple instances: If multiple instances are exposed, docstrings -for each instance are written and assigned to the instances’ -__doc__ attributes at run time. The class is documented as usual, and -the exposed instances can be mentioned in the Notes and See Also sections.
    • +
    • Single instance: If only a single instance of a class is exposed, document +the class. Examples can use the instance name.
    • +
    • Multiple instances: If multiple instances are exposed, docstrings for each +instance are written and assigned to the instances’ __doc__ attributes +at run time. The class is documented as usual, and the exposed instances can +be mentioned in the Notes and See Also sections.
    @@ -550,16 +545,13 @@

    Other points to keep in mind

    For paragraphs, indentation is significant and indicates indentation in the output. New paragraphs are marked with a blank line.

    -

    Use italics, bold, and courier if needed in any explanations -(but not for variable names and doctest code or multi-line code). -Variable, module and class names should be written between single -back-ticks (`numpy`).

    -

    A more extensive example of reST markup can be found in this example -document; -the quick reference is +

    Use italics, bold, and courier if needed in any explanations (but +not for variable names and doctest code or multi-line code). Variable, module +and class names should be written between single back-ticks (`astropy`).

    +

    A more extensive example of reST markup can be found in this example document; the quick +reference is useful while editing.

    -

    Line spacing and indentation are significant and should be carefully -followed.

    +

    Line spacing and indentation are significant and should be carefully followed.

    Conclusion

    @@ -567,10 +559,6 @@

    ConclusionHow to Build API/Reference Documentation on how to use Sphinx to build the manual.

    -

    This document itself was written in ReStructuredText, and may be converted to -HTML using:

    -
    $ rst2html HOWTO_DOCUMENT.txt HOWTO_DOCUMENT.html
    -

    @@ -584,11 +572,10 @@

    ConclusionTable Of Contents

    • Documentation Guidelines (Draft 2)
        -
      • Astropy Documentation Rules and Recommendations
      • -
      • Numpy/SciPy Docstring Rules
          +
        • AstroPy Documentation Rules and Recommendations
        • +
        • NumPy/SciPy Docstring Rules
          • Overview
          • Docstring Standard
          • -
          • Status
          • Sections
          • Documenting classes
            • Class docstring
            • diff --git a/searchindex.js b/searchindex.js index 2313460d..475e42ef 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{all:[3,1,5],code:[3,0,1,2,5],consider:3,whatev:5,illustr:[3,1],pep:[3,1],lack:3,signific:[3,1],concept:3,subclass:[3,1],computation:1,follow:[3,2,1,4,5],haggi:3,cython:1,privat:3,depend:[3,1,5],zone:3,elsewher:3,readabl:3,fft2:3,articl:3,environment:3,present:1,under:3,sens:3,norm:3,sourc:[3,1],string:3,ndobj_old:3,mpl:[3,1],util:1,print:1,candid:[3,1],mechan:[3,1,5],whether:1,wordpress:1,veri:3,affect:1,relev:[3,1,2],level:5,gui:5,list:[3,4,5],prefix:3,iter:3,team:5,quick:3,set_color:1,overview:3,prevent:[3,5],impli:3,work:[3,5],natur:3,consistent:1,direct:[3,1,5],second:3,blanklin:3,design:3,pass:1,download:[1,5],further:[3,5],index_exp:3,compat:1,index:[0,1],what:[3,1],sub:[3,1],section:[3,1,4],asid:3,abl:[3,5],calcul:1,uniform:5,current:[3,0,1,4,5],"public":[3,1],abbrevi:3,version:[3,1],"new":[3,1,5],ever:5,method:[3,1,5],metadata:1,submodule1:1,submodule2:1,whose:3,variat:3,gener:[3,1,5],never:[1,5],decid:5,matplotlib:[3,1,5],satisfi:5,let:1,path:[3,1],safer:1,becom:3,sinc:1,valu:[3,1,5],wait:5,convert:3,undocu:3,rst2html:3,"_numpydoc":3,doctest:3,awastropi:1,chang:[3,1,4],fourier:3,chanc:3,ourselv:3,via:[1,5],regardless:1,packagenam:1,danger:1,appli:1,modul:[3,0,1,4],prefer:3,submodul:1,backtick:3,deprec:3,api:3,visibl:3,instal:[1,5],txt:3,unit:1,plot:3,from:[3,1,5],describ:[3,1,4],would:[3,1,5],commun:[3,5],doubl:3,regist:1,two:3,next:1,few:[3,1,5],call:1,recommend:[3,1,4],simpler:1,type:3,until:5,more:[3,0,1,5],desir:5,relat:3,pylint:3,about:[3,1],enhanc:1,warn:[3,1,4],exce:1,templat:[3,1,5],particular:[3,1],known:3,set_valu:1,effort:3,must:[3,1,5],join:3,augment:3,setup:1,outlin:[3,1],paragraph:3,can:[3,1,5],imped:1,meet:1,root:1,def:[3,1],explor:3,give:[3,1],process:[3,1,5],accept:1,tab:1,unus:1,alwai:[1,5],scalar:3,multipl:3,goal:[3,5],quot:3,rather:[3,1,5],anoth:3,write:3,how:[3,5],anyon:2,"__init__":[3,1],pure:1,answer:3,instead:[3,1],config:[3,1],get_color:1,updat:1,astropi:[3,0,1,4,2],outsid:[1,5],referenc:3,keithdeven:1,after:3,"long":1,befor:[3,1,5],date:3,underscor:3,data:[3,1],grow:5,averag:3,"short":[3,1],practic:5,vicin:3,array_lik:3,spectra:5,produc:3,inform:[3,0,2],preced:3,combin:3,incorpor:3,order:[3,1,5],mcnoleg:3,origin:3,help:[3,5],rhetting:1,over:[3,1,5],move:1,becaus:[3,1,5],typewrit:3,whilst:3,through:3,hierarchi:1,still:[3,1],paramet:3,style:[3,1,5],get_valu:1,consensu:[3,5],fix:3,comprehend:3,resort:3,html:[3,1],persist:1,mail:4,main:5,might:1,them:[3,5],good:3,"return":3,thei:[3,1,5],python:[3,0,1,2,5],sentenc:3,supersed:3,initi:5,underneath:3,mention:3,facilit:[3,5],discuss:[3,4],strive:5,choic:5,document:[0,1,2,3,4,5],name:[3,1],anyth:1,edit:3,photometri:5,linspac:1,separ:3,astronom:5,achiev:5,exampl:[3,1,5],each:[3,1],found:3,complet:1,mean:[3,5],compil:1,weight:3,replac:3,hard:3,continu:5,procedur:5,mar:1,expect:1,our:3,orient:3,special:[3,5],out:[1,5],variabl:[3,1],shown:3,ndobj_new:3,matrix:3,space:[3,1],goe:1,crucial:1,content:[3,0],laid:1,adapt:[3,5],rel:[3,1],reader:3,sparingli:3,correct:1,math:3,integr:[3,1,5],clarifi:3,insid:3,situat:3,given:[3,1],standard:[3,1,4,5],standalon:5,reason:3,precies:3,theori:3,put:3,org:[3,1],care:3,indent:[3,1],could:5,keep:[3,5],length:3,place:1,circuit:1,principl:3,confus:[3,1],assign:3,first:[3,5],oper:1,rand:3,directli:[1,5],onc:[1,5],arrai:[3,1],independ:5,qualiti:5,number:[3,5],mai:[3,1,5],alreadi:[1,5],done:5,submit:5,blank:3,oppos:1,stabl:5,voidspac:1,size:1,differ:[3,5],set_:1,convent:[3,1],script:[1,5],associ:[3,1],licens:3,system:[3,1,5],least:3,checker:[3,1],underlin:3,draft:[3,0,1,4,2],similarli:1,termin:3,instanc:[3,1],cite:3,store:1,prone:1,adher:1,option:3,courier:3,especi:3,namespac:1,fuzzi:3,tool:[3,1,5],scikit:3,specifi:[3,1],getter:1,enclos:3,exactli:[3,5],than:[3,1,5],serv:4,exposur:3,photograph:3,keyword:3,whenev:5,clariti:1,remov:3,tree:[3,5],structur:3,charact:3,project:[3,0,1],stall:5,str:3,mathtt:3,thu:[1,5],pre:3,comput:3,viewer:3,thereaft:5,pro:1,mind:3,ani:[3,5],packag:[0,1,2,3,4,5],manner:1,have:[3,1,5],tabl:[0,5],need:[3,1,5],seek:5,squar:3,equival:3,self:[3,1],note:[3,1],mix:1,builtin:1,discret:3,take:3,indic:[3,0],tupl:3,techniqu:3,subject:[3,1,4],brace:3,singl:[3,5],pyx:1,simplifi:1,begin:3,copi:3,unless:[1,5],distribut:1,shall:3,track:5,who:5,reach:5,discov:3,most:3,render:3,pramet:3,phase:5,alpha:3,subset:3,judici:3,why:1,appear:3,latex:3,"__all__":[3,1],doc:3,clear:3,later:5,request:[1,5],doe:3,part:[3,5],add:3,linalgexcept:3,introspect:3,show:1,carefulli:3,text:3,random:3,syntax:[3,1],particularli:3,font:3,setter:1,absolut:1,onli:[3,1,5],explicitli:[3,1],locat:[3,5],modnam:1,merger:1,explain:3,configur:[3,1],solut:1,written:[3,1],should:[3,1,5],busi:3,dict:3,rich:3,meant:3,fft:3,contribut:2,get:[3,1],between:[3,1,5],pypi:[1,5],howto_docu:3,obviou:3,cannot:[1,5],increas:5,tbd:1,requir:[3,1,5],layout:[1,5],bar:1,organ:5,typeset:3,patch:5,provid:[3,1,5],bad:1,common:[3,0,2,5],contain:[3,1,5],where:[3,1,5],seamlessli:5,vision:[0,2,5],summari:3,wiki:0,set:[3,1,5],see:[3,0,1],result:3,reserv:1,best:5,concern:5,awar:3,statu:3,extend:3,expert:3,easi:[3,5],state:3,simplest:1,"import":[3,1,5],approach:1,across:5,attribut:[3,1],altern:1,signatur:3,kei:5,numer:3,contort:3,func_c_:3,extens:[3,1],entir:[3,5],here:[3,1],func_d:3,func_a:3,addit:[3,1,5],both:[3,1],fit:5,howev:[3,1],numpydoc:3,etc:[3,5],tutori:3,equat:3,committe:[1,5],logic:3,pdf:3,highland:3,com:1,con:1,comment:3,simpli:[3,1],consolid:5,point:[3,1],color:1,guidelin:[0,1,2,3,4,5],header:3,"5e9":1,framework:[3,4,5],respect:3,geoscienc:3,assum:[3,1],summar:5,duplic:[3,5],ultim:5,strong:5,platform:3,addition:1,invert:3,numpi:[3,1,5],due:1,been:1,github:[3,0],compon:[1,5],much:5,interest:[3,2],basic:3,func_b:3,"__doc__":3,imag:3,search:[3,0],argument:3,coordin:[3,1,5],understand:3,togeth:5,summat:3,those:[3,5],"case":[3,1,5],multi:3,look:3,properti:[3,1],aim:5,defin:1,"while":3,abov:3,error:3,exist:[3,1,5],larger:3,krige:3,vol:3,site:3,activ:5,scipi:[3,1,5],motiv:3,get_:1,sever:3,develop:[3,0,1,2,5],welcom:[3,0],author:3,perform:1,suggest:3,make:[3,1,5],belong:3,same:3,lengthi:1,complex:[1,5],eventu:5,higher:5,competit:5,archiv:1,context:3,assist:3,upon:5,effect:1,remot:3,rais:3,temporari:3,user:[3,5],mani:[3,1,5],extern:[3,1],robust:5,wherev:1,typic:3,expand:3,built:3,task:[3,5],kept:3,discourag:[3,1,5],neural:3,markup:3,well:3,inherit:1,non:3,pep8:[3,1],weblog:1,without:3,expens:1,thi:[3,1,4,5],everyth:5,latter:3,usual:3,explan:3,identifi:5,execut:3,less:1,photo:3,obtain:3,rest:3,shape:3,human:3,volunt:3,yet:3,network:3,sugget:1,web:3,expos:3,also:[3,4,5],restructuredtext:3,except:[3,1],rgb:3,spread:3,pyplot:[3,1],input:3,transit:5,match:3,build:[3,5],real:3,applic:3,which:[3,1,5],format:[3,1,4],read:[3,1],regard:[3,1],background:3,world:3,tick:3,aclass:1,like:[3,1],specif:[3,1],filenam:3,docutil:3,manual:3,benefit:5,necessari:[3,1],either:[1,5],leftrightarrow:3,output:3,page:[3,0,2],www:1,often:[3,1],habitat:3,some:[3,5],back:3,sampl:1,flatten:1,proper:1,star:1,librari:[1,5],affili:[3,1,4,5],guid:[3,1],colorspac:3,avoid:[3,1,5],normal:3,definit:3,per:1,when:[3,1],mathemat:3,larg:3,sequenc:3,toolkit:5,condit:3,foo:1,notabl:3,refer:[3,5],core:[3,1,4,5],encourag:[3,1,5],object:[3,1],run:3,bold:3,clutter:3,view:3,usag:[3,1],dtype:3,sacrif:3,funcnam:1,host:1,repositori:[1,5],immut:3,post:3,"super":1,plt:[3,1],stone:5,central:[3,5],toolchain:3,preclud:5,http:[3,1],surround:3,func_:3,includ:[3,1,5],constructor:3,commit:5,compute_color:1,upward:3,processor:3,gamma:3,routin:3,own:[3,5],emphasi:3,primarili:[1,5],convolut:3,"float":3,easy_instal:3,appropri:3,empti:3,ensur:[1,5],mark:3,inclus:5,wai:3,area:5,support:[1,5],question:3,transform:3,fast:3,pyflak:3,avail:[3,1,5],start:[3,5],reli:5,interfac:[1,5],editor:3,"var":3,"function":[3,1,5],form:[3,1,4,5],enough:5,agre:5,great:3,bundl:1,criteria:5,line:3,inlin:3,"true":3,bug:[3,1],conclus:3,info:[3,1],pull:5,tripl:3,made:[1,5],algorithm:3,consist:[3,1,5],possibl:[3,1,5],"default":[3,5],wish:5,access:[1,5],displai:3,below:[3,1],limit:[3,0,1],sum:3,configobj:1,model:3,constant:3,creat:1,"int":3,dure:5,doesn:1,repres:3,strongli:[3,1],implement:[3,1,5],file:[3,1],improv:[3,1],check:3,fill:4,allow:[3,1,5],"2to3":1,detail:3,other:[3,1,5],bool:3,futur:5,test:[0,1,2,3,4,5],you:[3,1],nice:3,intend:5,ital:3,"class":[3,1,5],astronomi:[0,2,5],docstr:[3,1],ndarrai:3,brief:3,releas:5,consid:[1,5],throughout:3,omega:3,deserv:3,reduc:5,infrequ:3,sphinx:3,furthermor:3,directori:3,descript:3,rule:[3,1],itself:[3,5],potenti:5,time:[3,5]},objtypes:{},titles:["Welcome to AstroPy’s documentation!","Coding Guidelines (Draft 2)","Documentation for Developers","Documentation Guidelines (Draft 2)","Testing Guidelines (Draft)","Vision for a common Astronomy Python package"],objnames:{},filenames:["index","development/codeguide","development/index","development/docguide","development/testguide","development/vision"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{all:[3,1,5],code:[3,0,1,2,5],consider:3,whatev:5,illustr:[3,1],pep:[3,1],signific:[3,1],concept:3,subclass:[3,1],computation:1,follow:[3,2,1,4,5],haggi:3,cython:1,privat:3,depend:[3,1,5],elsewher:3,readabl:3,fft2:3,articl:3,environment:3,present:1,under:3,sens:3,sourc:[3,1],string:3,ndobj_old:3,mpl:[3,1],util:1,print:1,candid:[3,1],mechan:[3,1,5],whether:1,wordpress:1,veri:3,affect:1,relev:[3,1,2],level:5,gui:5,list:[3,4,5],prefix:3,iter:3,team:5,quick:3,set_color:1,prevent:[3,5],impli:3,work:[3,5],natur:3,consistent:1,direct:[3,1,5],second:3,blanklin:3,design:3,pass:1,download:[1,5],further:[3,5],compat:1,index:[0,1],what:[3,1],sub:[3,1],section:[3,1,4],asid:3,abl:[3,5],calcul:1,uniform:5,current:[3,0,1,4,5],"public":[3,1],abbrevi:3,version:[3,1],"new":[3,1,5],ever:5,method:[3,1,5],metadata:1,submodule1:1,submodule2:1,whose:3,gener:[3,1,5],never:[1,5],decid:5,matplotlib:[3,1,5],satisfi:5,let:1,path:[3,1],safer:1,becom:3,sinc:1,valu:[3,1,5],wait:5,convert:3,larger:3,precis:3,doctest:3,awastropi:1,chang:[3,1,4],fourier:3,chanc:3,ourselv:3,via:[1,5],regardless:1,packagenam:1,danger:1,appli:1,modul:[3,0,1,4],prefer:3,submodul:1,backtick:3,deprec:3,api:3,visibl:3,instal:[1,5],unit:1,plot:3,from:[3,1,5],describ:[3,1,4],would:[3,1,5],commun:5,doubl:3,regist:1,two:3,next:1,few:[3,1,5],call:1,recommend:[3,1,4],simpler:1,type:3,until:5,more:[3,0,1,5],sort:3,desir:5,relat:3,pylint:3,about:[3,1],enhanc:1,warn:[3,1,4],exce:1,templat:[3,1,5],particular:[3,1],known:3,set_valu:1,must:[3,1,5],augment:3,setup:1,outlin:[3,1],paragraph:3,can:[3,1,5],imped:1,meet:1,root:1,def:[3,1],explor:3,give:[3,1],process:[3,1,5],accept:1,tab:1,unus:1,alwai:[1,5],scalar:3,multipl:3,goal:[3,5],quot:3,rather:[3,1,5],anoth:3,write:3,how:[3,5],anyon:2,"__init__":[3,1],pure:1,answer:3,instead:[3,1],config:[3,1],get_color:1,updat:1,astropi:[3,0,1,4,2],outsid:[1,5],referenc:3,keithdeven:1,after:3,"long":1,befor:[3,1,5],date:3,underscor:3,data:[3,1],grow:5,"short":[3,1],practic:5,vicin:3,array_lik:3,spectra:5,produc:3,inform:[3,0,2],preced:3,combin:3,incorpor:3,order:[3,1,5],mcnoleg:3,origin:3,help:[3,5],rhetting:1,over:[3,1,5],move:1,becaus:[3,1,5],typewrit:3,whilst:3,through:3,hierarchi:1,still:[3,1],paramet:3,style:[3,1,5],get_valu:1,fit:5,fix:3,comprehend:3,resort:3,html:1,persist:1,mail:4,main:5,might:1,pixel:3,them:[3,5],good:3,"return":3,thei:[3,1,5],python:[3,0,1,2,5],sentenc:3,supersed:3,initi:5,underneath:3,mention:3,facilit:[3,5],discuss:[3,4],strive:5,choic:5,document:[0,1,2,3,4,5],name:[3,1],anyth:1,edit:3,photometri:5,linspac:1,separ:3,astronom:5,achiev:5,exampl:[3,1,5],each:[3,1],found:3,complet:1,mean:[3,5],compil:1,pacakg:3,hard:3,continu:5,procedur:5,mar:1,expect:1,our:3,orient:3,special:[3,5],out:[1,5],variabl:[3,1],shown:3,ndobj_new:3,network:3,space:[3,1],goe:1,crucial:1,content:[3,0],laid:1,adapt:[3,5],rel:[3,1],reader:3,sparingli:3,correct:1,math:3,integr:[3,1,5],clarifi:3,insid:3,situat:3,given:[3,1],standard:[3,1,4,5],standalon:5,reason:3,theori:3,put:3,org:[3,1],care:3,indent:[3,1],could:5,keep:[3,5],length:3,place:1,circuit:1,principl:3,confus:[3,1],assign:3,first:[3,5],oper:1,directli:[1,5],onc:[1,5],arrai:[3,1],independ:5,qualiti:5,number:[3,5],mai:[3,1,5],alreadi:[1,5],done:5,submit:5,blank:3,oppos:1,stabl:5,voidspac:1,size:1,differ:[3,5],set_:1,convent:[3,1],script:[1,5],associ:[3,1],licens:3,system:[3,1,5],least:3,checker:[3,1],underlin:3,draft:[3,0,1,4,2],similarli:1,termin:3,instanc:[3,1],cite:3,store:1,prone:1,adher:1,option:3,courier:3,especi:3,namespac:1,fuzzi:3,tool:[3,1,5],copi:3,specifi:[3,1],getter:1,enclos:3,exactli:[3,5],than:[3,1,5],serv:4,keyword:3,whenev:5,clariti:1,remov:3,tree:[3,5],structur:3,charact:3,project:[3,0,1],stall:5,str:3,mathtt:3,thu:[1,5],pre:3,comput:3,viewer:3,thereaft:5,pro:1,mind:3,ani:[3,5],packag:[0,1,2,3,4,5],manner:1,have:[3,1,5],tabl:[3,0,5],need:[3,1,5],seek:5,squar:3,equival:3,self:[3,1],note:[3,1],mix:1,builtin:1,discret:3,take:3,indic:[3,0],tupl:3,techniqu:3,subject:[3,1,4],brace:3,singl:[3,5],pyx:1,simplifi:1,begin:3,regard:[3,1],unless:[1,5],distribut:1,shall:3,track:5,who:5,reach:5,discov:3,most:3,render:3,phase:5,alpha:3,subset:3,judici:3,why:1,appear:3,latex:3,"__all__":[3,1],doc:3,clear:3,later:5,request:[1,5],doe:3,part:[3,5],pyplot:[3,1],introspect:3,show:1,carefulli:3,text:3,random:3,radiu:3,syntax:[3,1],particularli:3,font:3,setter:1,absolut:1,onli:[3,1,5],explicitli:[3,1],locat:[3,5],modnam:1,merger:1,explain:3,configur:[3,1],solut:1,written:[3,1],should:[3,1,5],dict:3,rich:3,meant:3,fft:3,contribut:2,get:[3,1],between:[3,1,5],pypi:[1,5],obviou:3,cannot:[1,5],increas:5,tbd:1,requir:[3,1,5],layout:[1,5],bar:1,organ:5,coord:3,patch:5,provid:[3,1,5],bad:1,common:[3,0,2,5],contain:[3,1,5],where:[3,1,5],seamlessli:5,vision:[0,2,5],summari:3,wiki:0,set:[3,1,5],see:[3,0,1],result:3,reserv:1,best:5,concern:5,awar:3,extend:3,expert:3,state:3,simplest:1,"import":[3,1,5],approach:1,across:5,attribut:[3,1],altern:1,signatur:3,kei:5,fk5_to_gal:3,contort:3,func_c_:3,extens:[3,1],entir:[3,5],here:[3,1],func_d:3,func_a:3,addit:[3,1,5],both:[3,1],easi:[3,5],howev:[3,1],numpydoc:3,etc:[3,5],tutori:3,equat:3,committe:[1,5],logic:3,mani:[3,1,5],highland:3,com:1,con:1,comment:3,simpli:[3,1],consolid:5,point:[3,1],color:1,guidelin:[0,1,2,3,4,5],header:3,"5e9":1,sky2pix:3,framework:[3,4,5],respect:3,geoscienc:3,assum:[3,1],summar:5,duplic:[3,5],ultim:5,strong:5,platform:3,addition:1,numpi:[3,1,5],due:1,been:[3,1],github:[3,0],compon:[1,5],much:5,interest:[3,2],basic:3,func_b:3,"__doc__":3,imag:3,search:[3,0],argument:3,coordin:[3,1,5],understand:3,togeth:5,summat:3,those:[3,5],"case":[3,1,5],multi:3,look:3,properti:[3,1],aim:5,defin:[3,1],"while":3,abov:3,error:3,pix2ski:3,krige:3,vol:3,site:3,activ:5,scipi:[3,1,5],motiv:3,get_:1,sever:3,develop:[0,1,2,5],welcom:0,author:3,perform:1,make:[3,1,5],belong:3,same:3,handl:3,lengthi:1,complex:[1,5],eventu:5,higher:5,competit:5,archiv:1,context:3,assist:3,upon:5,effect:1,remot:3,rais:3,temporari:3,user:[3,5],improv:1,extern:[3,1],robust:5,wherev:1,typic:3,built:3,task:[3,5],kept:3,discourag:[3,1,5],neural:3,markup:3,well:3,hypothet:3,inherit:1,non:3,pep8:[3,1],weblog:1,without:3,expens:1,thi:[3,1,4,5],everyth:5,latter:3,usual:3,explan:3,identifi:5,execut:3,less:1,when:[3,1],obtain:3,rest:3,shape:3,human:3,yet:3,sugget:1,web:3,expos:3,also:[3,4,5],sky:3,except:[3,1],add:3,spread:3,overview:3,input:3,transit:5,match:3,build:[3,5],real:3,applic:3,which:[3,1,5],format:[3,1,4],read:[3,1],consensu:5,invalidwcsexcept:3,background:3,world:3,tick:3,aclass:1,like:[3,1],specif:[3,1],filenam:3,docutil:3,manual:3,benefit:5,necessari:[3,1],either:[1,5],leftrightarrow:3,output:3,page:[3,0,2],www:1,often:[3,1],habitat:3,ascend:3,back:3,sampl:1,flatten:1,proper:1,star:1,librari:[1,5],affili:[3,1,4,5],guid:[3,1],avoid:[3,1,5],normal:3,definit:3,per:1,mathemat:3,larg:3,sequenc:3,toolkit:5,condit:3,foo:1,notabl:3,refer:[3,5],core:[3,1,4,5],encourag:[3,1,5],object:[3,1],run:3,bold:3,clutter:3,view:3,usag:[3,1],dtype:3,sacrif:3,funcnam:1,host:1,great:3,repositori:[1,5],immut:3,"super":1,plt:[3,1],stone:5,central:[3,5],column:3,toolchain:3,preclud:5,http:[3,1],surround:3,func_:3,constructor:3,commit:5,compute_color:1,upward:3,processor:3,routin:3,own:[3,5],emphasi:3,primarili:[1,5],convolut:3,"float":3,appropri:3,randomize_posit:3,empti:3,ensur:[1,5],mark:3,inclus:5,wai:3,area:5,support:[1,5],question:3,transform:3,fast:3,pyflak:3,avail:[3,1,5],start:[3,5],reli:5,interfac:[1,5],includ:[3,1,5],replac:3,"var":3,"function":[3,1,5],form:[3,1,4,5],enough:5,agre:5,some:[3,5],bundl:1,criteria:5,line:3,inlin:3,"true":3,bug:[3,1],conclus:3,info:[3,1],pull:5,tripl:3,made:[1,5],algorithm:3,consist:[3,1,5],possibl:[3,1,5],"default":[3,5],wish:5,access:[1,5],displai:3,below:[3,1],limit:[3,0,1],sum:3,configobj:1,model:3,constant:3,creat:1,"int":3,dure:5,doesn:1,repres:3,strongli:[3,1],implement:[3,1,5],file:[3,1],exist:[1,5],typeset:3,check:3,fill:4,allow:[3,1,5],"2to3":1,detail:3,invalid:3,other:[3,1,5],bool:3,futur:5,test:[0,1,2,3,4,5],you:[3,1],nice:3,intend:5,ital:3,"class":[3,1,5],astronomi:[0,2,5],docstr:[3,1],ndarrai:3,brief:3,releas:5,consid:[1,5],throughout:3,omega:3,deserv:3,reduc:5,infrequ:3,sphinx:3,furthermor:3,directori:3,descript:3,rule:[3,1],itself:5,potenti:5,time:[3,5]},objtypes:{},titles:["Welcome to AstroPy’s documentation!","Coding Guidelines (Draft 2)","Documentation for Developers","Documentation Guidelines (Draft 2)","Testing Guidelines (Draft)","Vision for a common Astronomy Python package"],objnames:{},filenames:["index","development/codeguide","development/index","development/docguide","development/testguide","development/vision"]}) \ No newline at end of file From f36dac050e463a2d36c8859b1280f5d4ada78c49 Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Wed, 17 Aug 2011 10:38:11 -0700 Subject: [PATCH 08/69] updated to latest version from astropy docs --- _images/branch_dropdown.png | Bin 0 -> 16311 bytes _images/forking_button.png | Bin 0 -> 13092 bytes _images/pull_button.png | Bin 0 -> 12893 bytes _sources/development/codeguide.txt | 278 +++++--- _sources/development/codeguide_emacs.txt | 203 ++++++ _sources/development/index.txt | 3 +- _sources/development/vision.txt | 2 + .../workflow/development_workflow.txt | 30 + .../development_workflow_advanced.txt | 534 ++++++++++++++++ .../workflow/development_workflow_basic.txt | 133 ++++ .../development/workflow/git_configure.txt | 168 +++++ _sources/development/workflow/git_install.txt | 41 ++ .../development/workflow/git_resources.txt | 59 ++ _sources/development/workflow/index.txt | 78 +++ .../workflow/maintainer_workflow.txt | 105 ++++ _sources/index.txt | 10 +- _static/astropyicon.ico | Bin 0 -> 1150 bytes _static/astropylogo.png | Bin 0 -> 79223 bytes development/codeguide.html | 241 +++++-- development/codeguide_emacs.html | 306 +++++++++ development/docguide.html | 24 +- development/index.html | 25 +- development/testguide.html | 14 +- development/vision.html | 26 +- .../workflow/development_workflow.html | 138 ++++ .../development_workflow_advanced.html | 594 ++++++++++++++++++ .../workflow/development_workflow_basic.html | 247 ++++++++ development/workflow/git_configure.html | 274 ++++++++ development/workflow/git_install.html | 156 +++++ development/workflow/git_resources.html | 181 ++++++ development/workflow/index.html | 192 ++++++ development/workflow/maintainer_workflow.html | 210 +++++++ genindex.html | 14 +- index.html | 24 +- objects.inv | Bin 0 -> 726 bytes search.html | 14 +- searchindex.js | 2 +- 37 files changed, 4123 insertions(+), 203 deletions(-) create mode 100644 _images/branch_dropdown.png create mode 100644 _images/forking_button.png create mode 100644 _images/pull_button.png create mode 100644 _sources/development/codeguide_emacs.txt create mode 100644 _sources/development/workflow/development_workflow.txt create mode 100644 _sources/development/workflow/development_workflow_advanced.txt create mode 100644 _sources/development/workflow/development_workflow_basic.txt create mode 100644 _sources/development/workflow/git_configure.txt create mode 100644 _sources/development/workflow/git_install.txt create mode 100644 _sources/development/workflow/git_resources.txt create mode 100644 _sources/development/workflow/index.txt create mode 100644 _sources/development/workflow/maintainer_workflow.txt create mode 100644 _static/astropyicon.ico create mode 100644 _static/astropylogo.png create mode 100644 development/codeguide_emacs.html create mode 100644 development/workflow/development_workflow.html create mode 100644 development/workflow/development_workflow_advanced.html create mode 100644 development/workflow/development_workflow_basic.html create mode 100644 development/workflow/git_configure.html create mode 100644 development/workflow/git_install.html create mode 100644 development/workflow/git_resources.html create mode 100644 development/workflow/index.html create mode 100644 development/workflow/maintainer_workflow.html create mode 100644 objects.inv diff --git a/_images/branch_dropdown.png b/_images/branch_dropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..1bb7a577732c91ee6aa31de8f81045b5622126b2 GIT binary patch literal 16311 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 literal 0 HcmV?d00001 diff --git a/_images/pull_button.png b/_images/pull_button.png new file mode 100644 index 0000000000000000000000000000000000000000..e5031681b97bcc3b323a01653153c8d6bcfb5507 GIT binary patch literal 12893 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 I#f$>~7cL{PD*ylh literal 0 HcmV?d00001 diff --git a/_sources/development/codeguide.txt b/_sources/development/codeguide.txt index 21ebd2bd..1451740c 100644 --- a/_sources/development/codeguide.txt +++ b/_sources/development/codeguide.txt @@ -1,170 +1,273 @@ =========================== -Coding Guidelines (Draft 2) +Coding Guidelines (Draft 3) =========================== -.. warning:: +.. warning:: This document is currently in Draft form and is subject to change. -Core Requirements and Recommendations -------------------------------------- +This section describes requirements and guidelines that affiliated packages +will have to follow before being considered for integration as a module in the +core package. -This section describes requirements and guidelines that affiliated packages will have to follow before being considered for integration as a module in the core package. +Interface and Dependencies +-------------------------- -* The package should meet the interface requirements set out by the coordination committee. -* Packages must be compatible with Python 2.6, 2.7, and 3.x (for 3.x compatibility, the `2to3 tool `_ will be used). -* The package should be importable with no dependencies other than components already in the Astropy core, the `Python Standard Library (v2.6) `_, NumPy_, SciPy_, and matplotlib_ (versions for these packages will be specified in the Astropy ``setup.py`` file and on PyPI_). -* Additional dependencies are allowed for sub-modules or in function calls, but they must be noted in the package documentation and should only affect the relevant component. -* Docstrings must be present for all public classes/methods/functions, and must follow the form outlined in the :doc:`docguide` document. -* Unit tests are encouraged for all public methods and functions, and should adhere to the standards set in the :doc:`testguide` document. -* C extensions are only allowed when they provide a significant performance enhancement over pure python, or a C library already exists to provided the needed functionality. When C extensions are used, the python interface must meet interface guidelines. -* The use of Cython_ is strongly recommended for C extensions, as per the example in the template package. Cython extensions should store ``.pyx`` files in the source code repository, but they should be compiled to ``.c`` files that are updated in the repository when important changes are made to the ``.pyx`` file. -* If a C extension has a dependency on an external C library, the source code for the library should be bundled with the Astropy core. Additionally, the package must be compatible with using a system-installed library in place of the library included in Astropy. -* Packages can include data in ``path TBD`` as long as it is less than about 100 kb. These data should be accessed via the :func:`astropy.config.[funcname TBD]` mechanism. If the data exceeds this size, it should be hosted outside the source code repository and downloaded using the :func:`astropy.config.[funcname TBD]` mechanism. Exceptions to this size limit may be allowed if there are version dependencies between data and code. -* All persistent configuration should be stored using the functions in :mod:`astropy.config`, which make use of the :class:`ConfigObj` class and associated file format (http://www.voidspace.org.uk/python/configobj.html. -* General utilities necessary for but not specific to the package should be placed in the :mod:`packagename.utils` module. These utilities will be moved to the :mod:`astropy.utils` module when the package is integrated into the core package. If a utility is already present in :mod:`astropy.utils`, the package should always use that utility instead of re-implementing it in :mod:`packagename.utils`. -* Packages implementing many classes/functions not relevant to the component requested will not be accepted - the package should only include the required functionality and relevant extensions. -* The package should follow the additional style guides in the next section. +* The package should meet the interface requirements set out by the + coordination committee. +* Packages implementing many classes/functions not relevant to the component + requested will not be accepted - the package should only include the + required functionality and relevant extensions. -Coding Style/Conventions ------------------------- -These guidelines are additional style requirements for the Astropy core and recommendations for affiliated packages that are not candidates for merger into the core: +* Packages must be compatible with Python 2.6, 2.7, and 3.x (for 3.x + compatibility, the `2to3 tool `_ + will be used). + +* The package should be importable with no dependencies other than components + already in the Astropy core, the `Python Standard Library (v2.6) + `_, NumPy_, SciPy_, + and Matplotlib_ (versions for these packages will be specified in the + Astropy ``setup.py`` file and on PyPI_). -* The code will follow the standard `PEP8 Style Guide for Python Code `_. In particular, this includes using only 4 spaces for indentation, and never tabs. -* One exception is to be made from the PEP8 style: new style relative imports of the form ``from . import modname`` are allowed and required for Astropy, as opposed to absolute (as PEP8 suggets) or the simpler ``import modname`` syntax. This is primarily due to improved relative import support since PEP8 was developed, and to simplify the process of moving modules. +* Additional dependencies are allowed for sub-modules or in function calls, + but they must be noted in the package documentation and should only affect + the relevant component. -.. note:: - A pep8.py checker script is available at http://pypi.python.org/pypi/pep8. +* General utilities necessary for but not specific to the package should be + placed in the :mod:`packagename.utils` module. These utilities will be moved + to the :mod:`astropy.utils` module when the package is integrated into the + core package. If a utility is already present in :mod:`astropy.utils`, the + package should always use that utility instead of re-implementing it in + :mod:`packagename.utils`. -* In cases where C extensions are needed but Cython cannot be used, the `PEP 7 Style Guide for C Code `_ is recommended. -* The ``import numpy as np``, ``import matplotlib as mpl``, and ``import matplotlib.pyplot as plt`` naming conventions should be used wherever relevant. ``from packagename import *`` should never be used, except as a tool to flatten the namespace of a module. An example of the allowed usage is given below. -* Classes should either use direct variable access, or python’s property mechanism for setting object instance variables. ``get_value``/``set_value`` style methods should be used only when getting and setting the values requires a computationally-expensive operation. The example below illustrates this guideline. -* Classes are discouraged from using the builtin python :func:`super` function, unless absolutely needed. If used, it should be used consistentently by all subclasses, and noted in the class’s docstrings. An example illustrating why this is important (and alternative solutions) is included below. -* Affiliated packages are recommended to follow the layout and documentation form of the template package included in the core package source distribution. -* Affiliated packages are encouraged (but not required) to follow the Astropy core :doc:`docguide` and :doc:`testguide`. +Documentation and Testing +------------------------- -.. note:: - For more info on the pros and cons of using super, see http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ or http://keithdevens.com/weblog/archive/2011/Mar/16/Python.super) +* Docstrings must be present for all public classes/methods/functions, and + must follow the form outlined in the :doc:`docguide` document. -Affiliated Package Requirements -------------------------------- +* Unit tests are encouraged for all public methods and functions, and should + adhere to the standards set in the :doc:`testguide` document. -The following additional rules apply for affiliated packages, regardless of whether or not they are to be used in the core: +Data and Configuration +---------------------- -* Affiliated packages must be registered on the `Python Package Index `_, with proper metadata for downloading and installing the source package. -* The :mod:`astropy` root package name should not be used by affiliated packages - it is reserved for use by the core package. Recommended naming conventions for an affiliated package are either simply :mod:`packagename` or :mod:`awastropy.packagename` ("affiliated with Astropy"). +* Packages can include data in ``path TBD`` as long as it is less than about + 100 kb. These data should be accessed via the + :func:`astropy.config.[funcname TBD]` mechanism. If the data exceeds this + size, it should be hosted outside the source code repository and downloaded + using the :func:`astropy.config.[funcname TBD]` mechanism. Exceptions to + this size limit may be allowed if there are version dependencies between + data and code. + +* All persistent configuration should be stored using the functions in + :mod:`astropy.config`, which make use of the :class:`ConfigObj` class and + associated file format (http://www.voidspace.org.uk/python/configobj.html. + +Coding Style/Conventions +------------------------ + +* The code will follow the standard `PEP8 Style Guide for Python Code + `_. In particular, this includes + using only 4 spaces for indentation, and never tabs. + +* One exception is to be made from the PEP8 style: new style relative imports + of the form ``from . import modname`` are allowed and required for Astropy, + as opposed to absolute (as PEP8 suggets) or the simpler ``import modname`` + syntax. This is primarily due to improved relative import support since PEP8 + was developed, and to simplify the process of moving modules. + +.. note:: A pep8.py checker script is available at + http://pypi.python.org/pypi/pep8. + + See :doc:`codeguide_emacs` for some configuration options for + Emacs that helps in ensuring conformance to PEP8. + +* The ``import numpy as np``, ``import matplotlib as mpl``, and ``import + matplotlib.pyplot as plt`` naming conventions should be used wherever + relevant. ``from packagename import *`` should never be used, except as a + tool to flatten the namespace of a module. An example of the allowed usage + is given below. + +* Classes should either use direct variable access, or python’s property + mechanism for setting object instance variables. ``get_value``/``set_value`` + style methods should be used only when getting and setting the values + requires a computationally-expensive operation. The example below + illustrates this guideline. + +* Classes are discouraged from using the builtin python :func:`super` + function, unless absolutely needed. If used, it should be used + consistentently by all subclasses, and noted in the class’s docstrings. An + example illustrating why this is important (and alternative solutions) is + included below. + +* Affiliated packages are required to follow the layout and documentation form + of the template package included in the core package source distribution. + +.. note:: For more info on the pros and cons of using super, see + http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ + or http://keithdevens.com/weblog/archive/2011/Mar/16/Python.super) + +Including C code +---------------- + +* C extensions are only allowed when they provide a significant performance + enhancement over pure python, or a robust C library already exists to + provided the needed functionality. When C extensions are used, the Python + interface must meet interface guidelines. + +* The use of Cython_ is strongly recommended for C extensions, as per the + example in the template package. Cython extensions should store ``.pyx`` + files in the source code repository, but they should be compiled to ``.c`` + files that are updated in the repository when important changes are made to + the ``.pyx`` file. + +* If a C extension has a dependency on an external C library, the source code + for the library should be bundled with the Astropy core, provided the + license for the C library is compatible with the Astropy license. + Additionally, the package must be compatible with using a system-installed + library in place of the library included in Astropy. + +* In cases where C extensions are needed but Cython cannot be used, the `PEP 7 + Style Guide for C Code `_ is + recommended. + +Requirements specific to Affiliated Packages +-------------------------------------------- + +* Affiliated packages must be registered on the `Python Package Index + `_, with proper metadata for downloading and + installing the source package. + +* The :mod:`astropy` root package name should not be used by affiliated + packages - it is reserved for use by the core package. Recommended naming + conventions for an affiliated package are either simply :mod:`packagename` + or :mod:`awastropy.packagename` ("affiliated with Astropy"). Examples -------- -This section shows a few examples (not all of which are correct!) to illustrate points from the guidelines. These will be moved into the template project once it has been written. +This section shows a few examples (not all of which are correct!) to +illustrate points from the guidelines. These will be moved into the template +project once it has been written. Properties vs. get\_/set\_ ^^^^^^^^^^^^^^^^^^^^^^^^^^ -This example shows a sample class illustrating the guideline regarding the use of properties as opposed to getter/setter methods. +This example shows a sample class illustrating the guideline regarding the use +of properties as opposed to getter/setter methods. + +Let's assuming you've defined a :class:`Star` class and create an instance +like this:: -Let's assuming you've defined a :class:`Star` class and create an instance like this:: - >>> s = Star(B=5.48, V=4.83) - + You should always use attribute syntax like this:: - + >>> s.color = 0.4 >>> print s.color 0.4 - + Rather than like this:: >>> s.set_color(0.4) #Bad form! >>> print s.get_color() #Bad form! 0.4 - -Using python properties, attribute syntax can still do anything possible with a get/set method. For lengthy or complex calculations, however, use a method:: - + +Using python properties, attribute syntax can still do anything possible with +a get/set method. For lengthy or complex calculations, however, use a method:: + >>> print s.compute_color(5800, age=5e9) 0.4 - + super() vs. direct calling ^^^^^^^^^^^^^^^^^^^^^^^^^^ -This example shows why the use of :func:`super` can be confusing for subclasses, and gives an alternative syntax:: +This example shows why the use of :func:`super` can be confusing for +subclasses, and gives an alternative syntax:: #This is dangerous and bug-prone! - + class A(object): def method(self): print 'Doing A' - - + + class B(A): def method(self): super(B, self).method() print 'Doing B' - - + + class C(A): def method(self): A.method(self) print 'Doing C' - - + + class D(C, B): def method(self): super(D, self).method() print 'Doing D' - + if you then do:: >>> b = B() >>> b.method() - + you will see:: Doing A Doing B - + which is what you expect, and similarly for C. However, if you do:: >>> d = D() >>> d.method() - -you might expect to have it call both method in the order A,C,B,D. But it doesn't - instead you see:: + +you might expect to have it call both method in the order A,C,B,D. But it +doesn't - instead you see:: Doing A Doing C Doing D -because the the ``A.method(self)`` in C effectively short-circuits the super mechanism. Thus, it's crucial that all classes in an inheritance hierarchy consistently use super and not mix super with the direct syntax. The simplest approach is to explicitly call each class' method and avoid super completely:: +because the the ``A.method(self)`` in C effectively short-circuits the super +mechanism. Thus, it's crucial that all classes in an inheritance hierarchy +consistently use super and not mix super with the direct syntax. The simplest +approach is to explicitly call each class' method and avoid super completely:: #This is safer class A(object): def __init__(self, a): self.a = 1 - - + + class B(A): def __init__(self, a, b): A.__init__(self, a) self.b = b - - + + class C(A): def __init__(self, a, c): A.__init__(self, a) self.c = c - - + + class D(C, B): def __init__(self, a, b, c, d): B.__init__(self, a, b) C.__init__(self, a, c) self.d = d - + Acceptable use of ``from module import *`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``from module import *`` is discouraged in a module that contains implementation code, as it impedes clarity and often imports unused variables. It can, however, be used for a package that is laid out in the following manner:: +``from module import *`` is discouraged in a module that contains +implementation code, as it impedes clarity and often imports unused variables. +It can, however, be used for a package that is laid out in the following +manner:: packagename packagename/__init__.py @@ -179,25 +282,42 @@ In this case, ``packagename/__init__.py`` may be:: from submodule1 import * from submodule2 import * -This allows functions or classes in the submodules to be used directly as ``packagename.foo`` rather than ``packagename.submodule1.foo``. If this is used, it is strongly recommended that the submodules make use of the __all__ variable to specify which modules should be imported. Thus, submodule2.py might read:: +This allows functions or classes in the submodules to be used directly as +``packagename.foo`` rather than ``packagename.submodule1.foo``. If this is +used, it is strongly recommended that the submodules make use of the __all__ +variable to specify which modules should be imported. Thus, submodule2.py +might read:: from numpy import array,linspace - + __all__ = ('foo','AClass') - + def foo(bar): #the function would be defined here pass - + class AClass(object): #the class is defined here pass - -This ensures that ``from submodule import *`` only imports :func:`foo` and :class:`AClass`, but not :class:`numpy.array` or :func:`numpy.linspace`. + +This ensures that ``from submodule import *`` only imports :func:`foo` and +:class:`AClass`, but not :class:`numpy.array` or :func:`numpy.linspace`. + + +Additional Resources +-------------------- + +Further tips and hints relating to the coding guidelines are included below. + +.. toctree:: + :maxdepth: 1 + + codeguide_emacs + .. _Numpy: http://numpy.scipy.org/ .. _Scipy: http://www.scipy.org/ .. _matplotlib: http://matplotlib.sourceforge.net/ .. _Cython: http://cython.org/ -.. _PyPI: http://pypi.python.org/pypi \ No newline at end of file +.. _PyPI: http://pypi.python.org/pypi diff --git a/_sources/development/codeguide_emacs.txt b/_sources/development/codeguide_emacs.txt new file mode 100644 index 00000000..b71de549 --- /dev/null +++ b/_sources/development/codeguide_emacs.txt @@ -0,0 +1,203 @@ +============================================= + Emacs setup for following coding guidelines +============================================= + +.. _flymake: http://www.emacswiki.org/emacs/FlyMake +.. _pyflakes: http://pypi.python.org/pypi/pyflakes +.. _pep8: http://pypi.python.org/pypi/pep8 + +The AstroPy coding guidelines are listed in :doc:`codeguide`. This +document will describe some configuration options for Emacs, that will +help in ensuring that Python code satisfies the guidelines. Emacs can +be configured in several different ways. So instead of providing a drop +in configuration file, only the individual configurations are presented +below. + +For this setup we will need flymake_, pyflakes_ and the pep8_ Python +script, in addition to `python-mode`. + +Flymake comes with Emacs 23. The rest can be obtained from their +websites, or can be installed using `easy_install` or `pip`. + +Global settings +=============== + +No tabs +------- + +This setting will cause all tabs to be replaced with spaces. The number +of spaces to use is set in the :ref:`basic settings` section below. + +.. code-block:: scheme + + ;; Don't use TABS for indentations. + (setq-default indent-tabs-mode nil) + +Maximum number of characters in a line +-------------------------------------- + +Emacs will automatically insert a new line after "fill-column" number +of columns. PEP8 specifies a maximum of 79, but this can be set to a +smaller value also, for example 72. + +.. code-block:: scheme + + ;; Set the number to the number of columns to use. + (setq-default fill-column 79) + + ;; Add Autofill mode to mode hooks. + (add-hook 'text-mode-hook 'turn-on-auto-fill) + + ;; Show line number in the mode line. + (line-number-mode 1) + + ;; Show column number in the mode line. + (column-number-mode 1) + +Syntax highlighting +------------------- + +Enable syntax highlighting. This will also highlight lines that form a +region. + +.. code-block:: scheme + + (global-font-lock-mode 1) + +Python specific settings +======================== + +.. _`basic settings`: + +Basic settings +-------------- + +Indentation is automatically added. When a tab is pressed it is +replaced with 4 spaces. When backspace is pressed on an empty line, the +cursor will jump to the previous indentation level. + +.. code-block:: scheme + + (load-library "python") + + (autoload 'python-mode "python-mode" "Python Mode." t) + (add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)) + (add-to-list 'interpreter-mode-alist '("python" . python-mode)) + + (setq interpreter-mode-alist + (cons '("python" . python-mode) + interpreter-mode-alist) + python-mode-hook + '(lambda () (progn + (set-variable 'py-indent-offset 4) + (set-variable 'indent-tabs-mode nil)))) + +Highlight the column where a line must stop +------------------------------------------- + +The "fill-column" column is highlighted in red. For this to work, +download `column-marker.el +`_ and place it in the +Emacs configuration directory. + +.. code-block:: scheme + + ;; Highlight character at "fill-column" position. + (require 'column-marker) + (set-face-background 'column-marker-1 "red") + (add-hook 'python-mode-hook + (lambda () (interactive) + (column-marker-1 fill-column))) + +Flymake +------- + +Flymake will mark lines that do not satisfy syntax requirements in +red. When cursor is on such a line a message is displayed in the +mini-buffer. When mouse pointer is on such a line a "tool tip" message +is also shown. + +For flymake to work with `pep8` and `pyflakes`, create an +executable file named `pychecker` with the following contents. This +file must be in the system path. + +.. code-block:: sh + + #!/bin/bash + + pyflakes "$1" + pep8 --ignore=E221,E701,E202 --repeat "$1" + true + +Add the following code to Emacs configurations. + +.. code-block:: scheme + + ;; Setup for Flymake code checking. + (require 'flymake) + (load-library "flymake-cursor") + + ;; Script that flymake uses to check code. This script must be + ;; present in the system path. + (setq pycodechecker "pychecker") + + (when (load "flymake" t) + (defun flymake-pycodecheck-init () + (let* ((temp-file (flymake-init-create-temp-buffer-copy + 'flymake-create-temp-inplace)) + (local-file (file-relative-name + temp-file + (file-name-directory buffer-file-name)))) + (list pycodechecker (list local-file)))) + (add-to-list 'flymake-allowed-file-name-masks + '("\\.py\\'" flymake-pycodecheck-init))) + + (add-hook 'python-mode-hook 'flymake-mode) + +.. note:: + + Flymake will save files with suffix *_flymake* in the current + directory. If it crashes for some reason, then these files will not + get deleted. + + Sometimes there is a delay in refreshing the results. + +Delete trailing white spaces and blank lines +-------------------------------------------- + +To manually delete trailing whitespaces, press `C-t C-w`, which will +run the command "delete-whitespaces`. This command is also run when a +file is saved, and hence all trailing whitespaces will be deleted on +saving a Python file. + +To make sure that all "words" are separated by only one space, type +`M-SPC` (use the ALT key since `M-SPC` sometimes brings up a context +menu.). + +To collapse a set of blank lines to one blank line, place the cursor on +one of these and press `C-x C-o`. This is useful for deleting multiple +black lines at the end of a file. + +.. code-block:: scheme + + ;; Remove trailing whitespace manually by typing C-t C-w. + (add-hook 'python-mode-hook + (lambda () + (local-set-key (kbd "C-t C-w") + 'delete-trailing-whitespace))) + + ;; Automatically remove trailing whitespace when file is saved. + (add-hook 'python-mode-hook + (lambda() + (add-hook 'local-write-file-hooks + '(lambda() + (save-excursion + (delete-trailing-whitespace)))))) + + ;; Use M-SPC (use ALT key) to make sure that words are separated by + ;; just one space. Use C-x C-o to collapse a set of empty lines + ;; around the cursor to one empty line. Useful for deleting all but + ;; one blank line at end of file. To do this go to end of file (M->) + ;; and type C-x C-o. + +.. LocalWords: whitespaces diff --git a/_sources/development/index.txt b/_sources/development/index.txt index 2241a71c..fc40daa2 100644 --- a/_sources/development/index.txt +++ b/_sources/development/index.txt @@ -7,6 +7,7 @@ The information in the following pages are relevant for anyone interesting in co :maxdepth: 1 vision + workflow/index codeguide docguide - testguide \ No newline at end of file + testguide diff --git a/_sources/development/vision.txt b/_sources/development/vision.txt index 4ecd0541..0ef1f6a8 100644 --- a/_sources/development/vision.txt +++ b/_sources/development/vision.txt @@ -1,3 +1,5 @@ +.. _vision: + Vision for a common Astronomy Python package ============================================ diff --git a/_sources/development/workflow/development_workflow.txt b/_sources/development/workflow/development_workflow.txt new file mode 100644 index 00000000..f5516c9d --- /dev/null +++ b/_sources/development/workflow/development_workflow.txt @@ -0,0 +1,30 @@ +.. _development-workflow: + +#################### +Development workflow +#################### + +This document describes how to contribute to a git repository hosted on +GitHub. The example shown here is that of the core ``astropy`` repository, but +the workflow can work equally well for the internal development of an +affiliated package. + +Before following the instructions on this page, make sure you have correctly +installed and configured git: + +.. toctree:: + :maxdepth: 1 + + git_install + git_configure + +The following documents describe a beginner and advanced workflow for +contributing respectively: + +.. toctree:: + :maxdepth: 1 + + development_workflow_basic.rst + development_workflow_advanced.rst + +.. include:: links.inc diff --git a/_sources/development/workflow/development_workflow_advanced.txt b/_sources/development/workflow/development_workflow_advanced.txt new file mode 100644 index 00000000..0ae99a66 --- /dev/null +++ b/_sources/development/workflow/development_workflow_advanced.txt @@ -0,0 +1,534 @@ +.. _advanced-workflow: + +=============================== +Development Workflow (Advanced) +=============================== + +In the present document, we refer to the AstroPy ``master`` branch, as the +*trunk*. + +.. _forking: + +Creating a fork +=============== + +You need to do this only once for each package you want to contribute to. The +instructions here are very similar to the instructions at +http://help.github.com/fork-a-repo/ |emdash| please see that page for more +details. We're repeating some of it here just to give the specifics for the +Astropy_ project, and to suggest some default names. + +Set up and configure a GitHub account +------------------------------------- + +If you don't have a GitHub account, go to the GitHub page, and make one. + +You then need to configure your account to allow write access |emdash| see +the ``Generating SSH keys`` help on `github help`_. + +Create your own fork of a repository +------------------------------------ + +The following example shows how to fork the core ``astropy`` repository, but the same applies to other packages: + +#. Log into your GitHub account. + +#. Go to the Astropy_ GitHub home at `Astropy github`_. + +#. Click on the *fork* button: + + .. image:: forking_button.png + + Now, after a short pause and some 'Hardcore forking action', you + should find yourself at the home page for your own forked copy of Astropy_. + + + +Setting up the fork to work on +------------------------------ + +.. _linking-to-upstream: + +Overview +^^^^^^^^ + +This is done using:: + + git clone git@github.com:your-user-name/astropy.git + cd astropy + git remote add upstream git://github.com/astropy/astropy.git + +In detail +^^^^^^^^^ + +#. Clone your fork to the local computer:: + + git clone git@github.com:your-user-name/astropy.git + +#. Change directory to your new repo:: + + cd astropy + + Then type:: + + git branch -a + + to show you all branches. You'll get something like:: + + * master + remotes/origin/master + + This tells you that you are currently on the ``master`` branch, and + that you also have a ``remote`` connection to ``origin/master``. + What remote repository is ``remote/origin``? Try ``git remote -v`` to + see the URLs for the remote. They will point to your github fork. + + Now you want to connect to the `Astropy github`_ repository, so you can + merge in changes from the trunk:: + + cd astropy + git remote add upstream git://github.com/astropy/astropy.git + + ``upstream`` here is just the arbitrary name we're using to refer to the + main Astropy_ repository at `Astropy github`_. + + Note that we've used ``git://`` for the URL rather than ``git@``. The + ``git://`` URL is read only. This means we that we can't accidentally (or + deliberately) write to the upstream repo, and we are only going to use it + to merge into our own code. + + Just for your own satisfaction, show yourself that you now have a new + 'remote', with ``git remote -v show``, giving you something like:: + + upstream git://github.com/astropy/astropy.git (fetch) + upstream git://github.com/astropy/astropy.git (push) + origin git@github.com:your-user-name/astropy.git (fetch) + origin git@github.com:your-user-name/astropy.git (push) + + Your fork is now set up correctly, and you are ready to hack away. + +Workflow summary +================ + +This section gives a summary of the workflow once you have successfully forked +the repository, and details are given for each of these steps in the following +sections. + +* Don't use your ``master`` branch for anything. Consider deleting it. + +* When you are starting a new set of changes, fetch any changes from the + trunk, and start a new *feature branch* from that. + +* Make a new branch for each separable set of changes |emdash| "one task, one + branch" (`ipython git workflow`_). + +* Name your branch for the purpose of the changes - e.g. + ``bugfix-for-issue-14`` or ``refactor-database-code``. + +* If you can possibly avoid it, avoid merging trunk or any other branches into + your feature branch while you are working. + +* If you do find yourself merging from the trunk, consider :ref:`rebase-on-trunk` + +* Ask on the `Astropy mailing list`_ if you get stuck. + +* Ask for code review! + +This way of working helps to keep work well organized, with readable history. +This in turn makes it easier for project maintainers (that might be you) to +see what you've done, and why you did it. + +See `linux git workflow`_ and `ipython git workflow`_ for some explanation. + +Deleting your master branch +=========================== + +It may sound strange, but deleting your own ``master`` branch can help reduce +confusion about which branch you are on. See `deleting master on github`_ for +details. + +.. _update-mirror-trunk: + +Updating the mirror of trunk +============================ + +From time to time you should fetch the upstream (trunk) changes from github:: + + git fetch upstream + +This will pull down any commits you don't have, and set the remote branches to +point to the right commit. For example, 'trunk' is the branch referred to by +(remote/branchname) ``upstream/master`` - and if there have been commits since +you last checked, ``upstream/master`` will change after you do the fetch. + +.. _make-feature-branch: + +Making a new feature branch +=========================== + +When you are ready to make some changes to the code, you should start a new +branch. Branches that are for a collection of related edits are often called +'feature branches'. + +Making an new branch for each set of related changes will make it easier for +someone reviewing your branch to see what you are doing. + +Choose an informative name for the branch to remind yourself and the rest of +us what the changes in the branch are for. For example ``add-ability-to-fly``, +or ``buxfix-for-issue-42``. + +:: + + # Update the mirror of trunk + git fetch upstream + + # Make new feature branch starting at current trunk + git branch my-new-feature upstream/master + git checkout my-new-feature + +Generally, you will want to keep your feature branches on your public github_ +fork of Astropy_. To do this, you `git push`_ this new branch up to your +github repo. Generally (if you followed the instructions in these pages, and +by default), git will have a link to your GitHub repo, called ``origin``. You +push up to your own repo on GitHub with:: + + git push origin my-new-feature + +In git >= 1.7 you can ensure that the link is correctly set by using the +``--set-upstream`` option:: + + git push --set-upstream origin my-new-feature + +From now on git will know that ``my-new-feature`` is related to the +``my-new-feature`` branch in the GitHub repo. + +.. _edit-flow: + +The editing workflow +==================== + +Overview +-------- + +:: + + git add my_new_file + git commit -am 'NF - some message' + git push + +In more detail +-------------- + +#. Make some changes + +#. See which files have changed with ``git status`` (see `git status`_). + You'll see a listing like this one:: + + # On branch ny-new-feature + # Changed but not updated: + # (use "git add ..." to update what will be committed) + # (use "git checkout -- ..." to discard changes in working directory) + # + # modified: README + # + # Untracked files: + # (use "git add ..." to include in what will be committed) + # + # INSTALL + no changes added to commit (use "git add" and/or "git commit -a") + +#. Check what the actual changes are with ``git diff`` (`git diff`_). + +#. Add any new files to version control ``git add new_file_name`` (see + `git add`_). + +#. To commit all modified files into the local copy of your repo,, do + ``git commit -am 'A commit message'``. Note the ``-am`` options to + ``commit``. The ``m`` flag just signals that you're going to type a message + on the command line. The ``a`` flag |emdash| you can just take on faith + |emdash| or see `why the -a flag?`_ |emdash| and the helpful use-case + description in the `tangled working copy problem`_. The `git commit`_ + manual + page might also be useful. + +#. To push the changes up to your forked repo on github, do a ``git + push`` (see `git push`_). + +Asking for your changes to be reviewed or merged +================================================ + +When you are ready to ask for someone to review your code and consider a merge: + +#. Go to the URL of your forked repo, say + ``http://github.com/your-user-name/astropy``. + +#. Use the 'Switch Branches' dropdown menu near the top left of the page to + select the branch with your changes: + + .. image:: branch_dropdown.png + +#. Click on the 'Pull request' button: + + .. image:: pull_button.png + + Enter a title for the set of changes, and some explanation of what you've + done. Say if there is anything you'd like particular attention for - like a + complicated change or some code you are not happy with. + + If you don't think your request is ready to be merged, just say so in your + pull request message. This is still a good way of getting some preliminary + code review. + +Some other things you might want to do +====================================== + +Delete a branch on github +------------------------- + +:: + + # change to the master branch (if you still have one, otherwise change to + # another branch) + git checkout master + + # delete branch locally + git branch -D my-unwanted-branch + + # delete branch on github + git push origin :my-unwanted-branch + +(Note the colon ``:`` before ``test-branch``. See also: +http://github.com/guides/remove-a-remote-branch + +Several people sharing a single repository +------------------------------------------ + +If you want to work on some stuff with other people, where you are all +committing into the same repository, or even the same branch, then just +share it via github. + +First fork Astropy into your account, as from :ref:`forking`. + +Then, go to your forked repository GitHub page, say +``http://github.com/your-user-name/astropy`` + +Click on the 'Admin' button, and add anyone else to the repo as a +collaborator: + + .. image:: pull_button.png + +Now all those people can do:: + + git clone git@githhub.com:your-user-name/astropy.git + +Remember that links starting with ``git@`` use the ssh protocol and are +read-write; links starting with ``git://`` are read-only. + +Your collaborators can then commit directly into that repo with the +usual:: + + git commit -am 'ENH - much better code' + git push origin master # pushes directly into your repo + +Explore your repository +----------------------- + +To see a graphical representation of the repository branches and +commits:: + + gitk --all + +To see a linear list of commits for this branch:: + + git log + +You can also look at the `network graph visualizer`_ for your github +repo. + +Finally the :ref:`fancy-log` ``lg`` alias will give you a reasonable +text-based graph of the repository. + +.. _rebase-on-trunk: + +Rebasing on trunk +----------------- + +Let's say you thought of some work you'd like to do. You +:ref:`update-mirror-trunk` and :ref:`make-feature-branch` called +``cool-feature``. At this stage trunk is at some commit, let's call it E. Now +you make some new commits on your ``cool-feature`` branch, let's call them A, +B, C. Maybe your changes take a while, or you come back to them after a while. +In the meantime, trunk has progressed from commit E to commit (say) G:: + + A---B---C cool-feature + / + D---E---F---G trunk + +At this stage you consider merging trunk into your feature branch, and you +remember that this here page sternly advises you not to do that, because the +history will get messy. Most of the time you can just ask for a review, and +not worry that trunk has got a little ahead. But sometimes, the changes in +trunk might affect your changes, and you need to harmonize them. In this +situation you may prefer to do a rebase. + +Rebase takes your changes (A, B, C) and replays them as if they had been made +to the current state of ``trunk``. In other words, in this case, it takes the +changes represented by A, B, C and replays them on top of G. After the rebase, +your history will look like this:: + + A'--B'--C' cool-feature + / + D---E---F---G trunk + +See `rebase without tears`_ for more detail. + +To do a rebase on trunk:: + + # Update the mirror of trunk + git fetch upstream + + # Go to the feature branch + git checkout cool-feature + + # Make a backup in case you mess up + git branch tmp cool-feature + + # Rebase cool-feature onto trunk + git rebase --onto upstream/master upstream/master cool-feature + +In this situation, where you are already on branch ``cool-feature``, the last +command can be written more succinctly as:: + + git rebase upstream/master + +When all looks good you can delete your backup branch:: + + git branch -D tmp + +If it doesn't look good you may need to have a look at +:ref:`recovering-from-mess-up`. + +If you have made changes to files that have also changed in trunk, this may +generate merge conflicts that you need to resolve - see the `git rebase`_ man +page for some instructions at the end of the "Description" section. There is +some related help on merging in the git user manual - see `resolving a +merge`_. + +.. _recovering-from-mess-up: + +Recovering from mess-ups +------------------------ + +Sometimes, you mess up merges or rebases. Luckily, in git it is relatively +straightforward to recover from such mistakes. + +If you mess up during a rebase:: + + git rebase --abort + +If you notice you messed up after the rebase:: + + # Reset branch back to the saved point + git reset --hard tmp + +If you forgot to make a backup branch:: + + # Look at the reflog of the branch + git reflog show cool-feature + + 8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately + 278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d + 26aa21a cool-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj + ... + + # Reset the branch to where it was before the botched rebase + git reset --hard cool-feature@{2} + +.. _rewriting-commit-history: + +Rewriting commit history +------------------------ + +.. note:: + + Do this only for your own feature branches. + +There's an embarrassing typo in a commit you made? Or perhaps the you +made several false starts you would like the posterity not to see. + +This can be done via *interactive rebasing*. + +Suppose that the commit history looks like this:: + + git log --oneline + eadc391 Fix some remaining bugs + a815645 Modify it so that it works + 2dec1ac Fix a few bugs + disable + 13d7934 First implementation + 6ad92e5 * masked is now an instance of a new object, MaskedConstant + 29001ed Add pre-nep for a copule of structured_array_extensions. + ... + +and ``6ad92e5`` is the last commit in the ``cool-feature`` branch. Suppose we +want to make the following changes: + +* Rewrite the commit message for ``13d7934`` to something more sensible. +* Combine the commits ``2dec1ac``, ``a815645``, ``eadc391`` into a single one. + +We do as follows:: + + # make a backup of the current state + git branch tmp HEAD + # interactive rebase + git rebase -i 6ad92e5 + +This will open an editor with the following text in it:: + + pick 13d7934 First implementation + pick 2dec1ac Fix a few bugs + disable + pick a815645 Modify it so that it works + pick eadc391 Fix some remaining bugs + + # Rebase 6ad92e5..eadc391 onto 6ad92e5 + # + # Commands: + # p, pick = use commit + # r, reword = use commit, but edit the commit message + # e, edit = use commit, but stop for amending + # s, squash = use commit, but meld into previous commit + # f, fixup = like "squash", but discard this commit's log message + # + # If you remove a line here THAT COMMIT WILL BE LOST. + # However, if you remove everything, the rebase will be aborted. + # + +To achieve what we want, we will make the following changes to it:: + + r 13d7934 First implementation + pick 2dec1ac Fix a few bugs + disable + f a815645 Modify it so that it works + f eadc391 Fix some remaining bugs + +This means that (i) we want to edit the commit message for ``13d7934``, and +(ii) collapse the last three commits into one. Now we save and quit the +editor. + +Git will then immediately bring up an editor for editing the commit message. +After revising it, we get the output:: + + [detached HEAD 721fc64] FOO: First implementation + 2 files changed, 199 insertions(+), 66 deletions(-) + [detached HEAD 0f22701] Fix a few bugs + disable + 1 files changed, 79 insertions(+), 61 deletions(-) + Successfully rebased and updated refs/heads/my-feature-branch. + +and the history looks now like this:: + + 0f22701 Fix a few bugs + disable + 721fc64 ENH: Sophisticated feature + 6ad92e5 * masked is now an instance of a new object, MaskedConstant + +If it went wrong, recovery is again possible as explained :ref:`above +`. + +.. include:: links.inc diff --git a/_sources/development/workflow/development_workflow_basic.txt b/_sources/development/workflow/development_workflow_basic.txt new file mode 100644 index 00000000..65bfca64 --- /dev/null +++ b/_sources/development/workflow/development_workflow_basic.txt @@ -0,0 +1,133 @@ +.. _basic-workflow: + +=============================== +Development Workflow (Beginner) +=============================== + +You've discovered a bug or something else you want to change +in Astropy_ |emdash| excellent! + +You've worked out a way to fix it |emdash| even better! + +You want to tell us about it |emdash| best of all! + +The easiest way is to make a *patch* or set of patches. Here we explain how. +Making a patch is the simplest and quickest, but if you're going to be doing +anything more than simple quick things, please consider following +:ref:`advanced-workflow` instead. + +Making patches +============== + +Overview +-------- + +If you haven't already configured git (:ref:`git-configure-impatient`):: + + git config --global user.name "Your Name" + git config --global user.email you@yourdomain.example.com + +Then, the workflow is the following: +:: + + # Get the repository if you don't have it + git clone git://github.com/astropy/astropy.git + + # Make a branch for your patching + cd astropy + git branch the-fix-im-thinking-of + git checkout the-fix-im-thinking-of + + # hack, hack, hack + + # Tell git about any new files you've made + git add somewhere/tests/test_my_bug.py + + # Commit work in progress as you go + git commit -am 'BF - added tests for Funny bug' + + # hack hack, hack + + # Commit work + git commit -am 'BF - added fix for Funny bug' + + # Make the patch files + git format-patch -M -C master + +Then, send the generated patch files to the `Astropy mailing list`_ |emdash| +where we will thank you warmly. + +In detail +--------- + +#. Tell git who you are so it can label the commits you've + made:: + + git config --global user.name "Your Name" + git config --global user.email you@yourdomain.example.com + + This is only necessary if you haven't already done this, and you haven't + followed :ref:`configure-git`. + +#. If you don't already have one, clone a copy of the + Astropy_ repository:: + + git clone git://github.com/astropy/astropy.git + cd astropy + +#. Make a 'feature branch'. This will be where you work on your bug fix. It's + nice and safe and leaves you with access to an unmodified copy of the code + in the main branch:: + + git branch the-fix-im-thinking-of + git checkout the-fix-im-thinking-of + +#. Do some edits, and commit them as you go:: + + # hack, hack, hack + + # Tell git about any new files you've made + git add somewhere/tests/test_my_bug.py + + # Commit work in progress as you go + git commit -am 'BF - added tests for Funny bug' + + # hack hack, hack + + # Commit work + git commit -am 'BF - added fix for Funny bug' + + Note the ``-am`` options to ``commit``. The ``m`` flag just + signals that you're going to type a message on the command + line. The ``a`` flag |emdash| you can just take on faith |emdash| + or see `why the -a flag?`_. + +#. When you have finished, check you have committed all your changes:: + + git status + +#. Finally, make your commits into patches. You want all the commits since you + branched from the ``master`` branch:: + + git format-patch -M -C master + + You will now have several files named for the commits:: + + 0001-BF-added-tests-for-Funny-bug.patch + 0002-BF-added-fix-for-Funny-bug.patch + + Send these files to the `Astropy mailing list`_. + +When you are done, to switch back to the main copy of the +code, just return to the ``master`` branch:: + + git checkout master + +Moving from patching to development +=================================== + +If you find you have done some patches, and you have one or more feature +branches, you will probably want to switch to a more advanced development +mode. You can do this with the repository you have. See :ref:`advanced-workflow` for more details. + +.. include:: links.inc diff --git a/_sources/development/workflow/git_configure.txt b/_sources/development/workflow/git_configure.txt new file mode 100644 index 00000000..e258eef5 --- /dev/null +++ b/_sources/development/workflow/git_configure.txt @@ -0,0 +1,168 @@ +.. _configure-git: + +================ + Configuring git +================ + +.. _git-config-basic: + +Bare Minimum +============ + +The only absolutely necessary configuration step is identifying yourself and your contact info:: + + git config --global user.name "Your Name" + git config --global user.email you@yourdomain.example.com + +Once you've done this, you can actually ignore the rest of the document unless you want to customize the behavior of git. + +Overview +======== + +Your personal git configurations are saved in the ``.gitconfig`` file in +your home directory. + +Here is an example ``.gitconfig`` file:: + + [user] + name = Your Name + email = you@yourdomain.example.com + + [alias] + ci = commit -a + co = checkout + st = status + stat = status + br = branch + wdiff = diff --color-words + + [core] + editor = vim + + [merge] + log = true + +You can edit this file directly or you can use the ``git config --global`` +command:: + + git config --global user.name "Your Name" + git config --global user.email you@yourdomain.example.com + git config --global alias.ci "commit -a" + git config --global alias.co checkout + git config --global alias.st "status -a" + git config --global alias.stat "status -a" + git config --global alias.br branch + git config --global alias.wdiff "diff --color-words" + git config --global core.editor vim + git config --global merge.summary true + +To set up on another computer, you can copy your ``~/.gitconfig`` file, +or run the commands above. + +In detail +========= + +user.name and user.email +------------------------ + +It is good practice to tell git_ who you are, for labeling any changes +you make to the code. The simplest way to do this is from the command +line:: + + git config --global user.name "Your Name" + git config --global user.email you@yourdomain.example.com + +This will write the settings into your git configuration file, which +should now contain a user section with your name and email:: + + [user] + name = Your Name + email = you@yourdomain.example.com + +Of course you'll need to replace ``Your Name`` and ``you@yourdomain.example.com`` +with your actual name and email address. + +Aliases +------- + +You might well benefit from some aliases to common commands. + +For example, you might well want to be able to shorten ``git checkout`` +to ``git co``. Or you may want to alias ``git diff --color-words`` +(which gives a nicely formatted output of the diff) to ``git wdiff`` + +The following ``git config --global`` commands:: + + git config --global alias.ci "commit -a" + git config --global alias.co checkout + git config --global alias.st "status -a" + git config --global alias.stat "status -a" + git config --global alias.br branch + git config --global alias.wdiff "diff --color-words" + +will create an ``alias`` section in your ``.gitconfig`` file with contents +like this:: + + [alias] + ci = commit -a + co = checkout + st = status -a + stat = status -a + br = branch + wdiff = diff --color-words + +Editor +------ + +You may also want to make sure that your editor of choice is used :: + + git config --global core.editor vim + +Merging +------- + +To enforce summaries when doing merges (``~/.gitconfig`` file again):: + + [merge] + log = true + +Or from the command line:: + + git config --global merge.log true + +.. _fancy-log: + +Fancy log output +---------------- + +This is a very nice alias to get a fancy log output; it should go in the +``alias`` section of your ``.gitconfig`` file:: + + lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative + +You use the alias with:: + + git lg + +and it gives graph / text output something like this (but with color!):: + + * 6d8e1ee - (HEAD, origin/my-fancy-feature, my-fancy-feature) NF - a fancy file (45 minutes ago) [Matthew Brett] + * d304a73 - (origin/placeholder, placeholder) Merge pull request #48 from hhuuggoo/master (2 weeks ago) [Jonathan Terhorst] + |\ + | * 4aff2a8 - fixed bug 35, and added a test in test_bugfixes (2 weeks ago) [Hugo] + |/ + * a7ff2e5 - Added notes on discussion/proposal made during Data Array Summit. (2 weeks ago) [Corran Webster] + * 68f6752 - Initial implimentation of AxisIndexer - uses 'index_by' which needs to be changed to a call on an Axes object - this is all very sketchy right now. (2 weeks ago) [Corr + * 376adbd - Merge pull request #46 from terhorst/master (2 weeks ago) [Jonathan Terhorst] + |\ + | * b605216 - updated joshu example to current api (3 weeks ago) [Jonathan Terhorst] + | * 2e991e8 - add testing for outer ufunc (3 weeks ago) [Jonathan Terhorst] + | * 7beda5a - prevent axis from throwing an exception if testing equality with non-axis object (3 weeks ago) [Jonathan Terhorst] + | * 65af65e - convert unit testing code to assertions (3 weeks ago) [Jonathan Terhorst] + | * 956fbab - Merge remote-tracking branch 'upstream/master' (3 weeks ago) [Jonathan Terhorst] + | |\ + | |/ + +Thanks to Yury V. Zaytsev for posting it. + +.. include:: links.inc diff --git a/_sources/development/workflow/git_install.txt b/_sources/development/workflow/git_install.txt new file mode 100644 index 00000000..284d7a9d --- /dev/null +++ b/_sources/development/workflow/git_install.txt @@ -0,0 +1,41 @@ +.. _install-git: + +=============== + Installing git +=============== + +The instructions here are adapted from http://book.git-scm.com/2_installing_git.html + +Debian/Ubuntu +------------- + +:: + + sudo apt-get install git-core + +Fedora +------ + +:: + + sudo yum install git-core + +MacOS X +------- + +There are several ways to install git on Mac. The easiest is to simply download the OS X installer (git-osx-installer_). If you have MacPorts installed, you can also do:: + + sudo port install git-core + +If you have Fink installed, you can do:: + + sudo apt-get install git + +In addition, you may want to use a GUI to manage your git repositories. A good example of a free Mac GUI is `GitX `_. Other (non-free) examples include `Tower `_ and `SourceTree `_. GitHub have also recently released `GitHub for Mac `_. + +Windows +------- + +Download and install msysGit_ + +.. include:: links.inc diff --git a/_sources/development/workflow/git_resources.txt b/_sources/development/workflow/git_resources.txt new file mode 100644 index 00000000..8e5cff7a --- /dev/null +++ b/_sources/development/workflow/git_resources.txt @@ -0,0 +1,59 @@ +.. _git-resources: + +============= +Git resources +============= + +Tutorials and summaries +======================= + +* `github help`_ has an excellent series of how-to guides. +* `learn.github`_ has an excellent series of tutorials +* The `pro git book`_ is a good in-depth book on git. +* A `git cheat sheet`_ is a page giving summaries of common commands. +* The `git user manual`_ +* The `git tutorial`_ +* The `git community book`_ +* `git ready`_ |emdash| a nice series of tutorials +* `git casts`_ |emdash| video snippets giving git how-tos. +* `git magic`_ |emdash| extended introduction with intermediate detail +* The `git parable`_ is an easy read explaining the concepts behind git. +* `git foundation`_ expands on the `git parable`_. +* Fernando Perez' git page |emdash| `Fernando's git page`_ |emdash| many + links and tips +* A good but technical page on `git concepts`_ +* `git svn crash course`_: git for those of us used to subversion_ + +Advanced git workflow +===================== + +There are many ways of working with git; here are some posts on the +rules of thumb that other projects have come up with: + +* Linus Torvalds on `git management`_ +* Linus Torvalds on `linux git workflow`_ . Summary; use the git tools + to make the history of your edits as clean as possible; merge from + upstream edits as little as possible in branches where you are doing + active development. + +Manual pages online +=================== + +You can get these on your own machine with (e.g) ``git help push`` or +(same thing) ``git push --help``, but, for convenience, here are the +online manual pages for some common commands: + +* `git add`_ +* `git branch`_ +* `git checkout`_ +* `git clone`_ +* `git commit`_ +* `git config`_ +* `git diff`_ +* `git log`_ +* `git pull`_ +* `git push`_ +* `git remote`_ +* `git status`_ + +.. include:: links.inc diff --git a/_sources/development/workflow/index.txt b/_sources/development/workflow/index.txt new file mode 100644 index 00000000..076d6604 --- /dev/null +++ b/_sources/development/workflow/index.txt @@ -0,0 +1,78 @@ +.. _using-git: + +Contributing To/Developing Astropy or Affiliated Packages +========================================================= + +Summary +------- + +As described in :ref:`vision`, development of components intended for +inclusion in the core ``astropy`` package will initially be done by different +teams via *affiliated packages*. These affiliated packages will then be +submitted for inclusion in the ``astropy`` core package by creating a git fork +of the core repository, merging the new component into the fork, and +submitting the package as a pull request. The step of creating a fork and +merging the affiliated package into the fork can be done either by the team +contributing the affiliated package, or by the coordination committee if +requested. + +Once an affiliated package has been accepted and integrated as a component +into the core ``astropy`` package, subsequent improvements and bug fixes can +be made in the same way by forking the core repository and submitting a pull +request. + +The bottom line is that teams working on various components are free to choose +the version control system and workflow that they want, but ultimately the +changes need to be merged into a fork of the core repository and submitted via +a pull request to the core repository, either by the team or by the +coordination committee. + +.. _git-configure-impatient: + +For the Impatient +----------------- + +The only absolutely necessary configuration step is identifying yourself and your contact info:: + + git config --global user.name "Your Name" + git config --global user.email you@yourdomain.example.com + +More detailed information and instructions are below. + +After that, if you then just want to get the latest ``astropy`` source code, cd to a directory on your computer you want to put the source code, and do:: + + git clone git@github.com:astropy/astropy.git + +You will then have a new copy of the source code in the ``astropy`` directory. + +Later, if you want to update to the most recent version of the ``astropy`` code, just go do:: + + cd astropy + git pull + +If you find a bug and want to fix it, see :ref:`basic-workflow` or :ref:`advanced-workflow` depending on how comfortable you are with git. + +Git Documentation +----------------- + +The following sections cover the installation of the git software, the basic configuration, and links to resources to learn more about using git. However, you can also directly go to the `GitHub help pages `_ which offer a great introduction to git and GitHub. + +.. toctree:: + :maxdepth: 1 + + git_install + git_configure + git_resources + +Workflow +-------- + +The following two sections describe the workflow for the ``astropy`` core +package, but teams working on affiliated packages that have chosen to use git +are encouraged to also follow these guidelines internally. + +.. toctree:: + :maxdepth: 1 + + development_workflow + maintainer_workflow diff --git a/_sources/development/workflow/maintainer_workflow.txt b/_sources/development/workflow/maintainer_workflow.txt new file mode 100644 index 00000000..8ae79723 --- /dev/null +++ b/_sources/development/workflow/maintainer_workflow.txt @@ -0,0 +1,105 @@ +.. _maintainer-workflow: + +################### +Maintainer workflow +################### + +This page is for maintainers |emdash| those of us who merge our own or other +peoples' changes into the upstream repository. + +Being as how you're a maintainer, you are completely on top of the basic stuff +in :ref:`development-workflow`. + +******************************************************* +Integrating changes via the web interface (recommended) +******************************************************* + +Whenever possible, merge pull requests automatically via the pull request manager on GitHub. Merging should only be done manually if there is a really good reason to do this! + +Make sure that pull requests do not contain a messy history with merges, etc. If this is the case, then follow the manual instructions, and make sure the fork is rebased to tidy the history before committing. + +**************************** +Integrating changes manually +**************************** + +First, check out the ``astropy`` repository. The instructions in :ref:`linking-to-upstream` add a remote that has read-only +access to the upstream repo. Being a maintainer, you've got read-write access. + +It's good to have your upstream remote have a scary name, to remind you that +it's a read-write remote:: + + git remote add upstream-rw git@github.com:astropy/astropy.git + git fetch upstream-rw + +Let's say you have some changes that need to go into trunk +(``upstream-rw/master``). + +The changes are in some branch that you are currently on. For example, you are +looking at someone's changes like this:: + + git remote add someone git://github.com/someone/astropy.git + git fetch someone + git branch cool-feature --track someone/cool-feature + git checkout cool-feature + +So now you are on the branch with the changes to be incorporated upstream. The +rest of this section assumes you are on this branch. + +A few commits +============= + +If there are only a few commits, consider rebasing to upstream:: + + # Fetch upstream changes + git fetch upstream-rw + + # Rebase + git rebase upstream-rw/master + +Remember that, if you do a rebase, and push that, you'll have to close any +github pull requests manually, because github will not be able to detect the +changes have already been merged. + +A long series of commits +======================== + +If there are a longer series of related commits, consider a merge instead:: + + git fetch upstream-rw + git merge --no-ff upstream-rw/master + +The merge will be detected by github, and should close any related pull +requests automatically. + +Note the ``--no-ff`` above. This forces git to make a merge commit, rather +than doing a fast-forward, so that these set of commits branch off trunk then +rejoin the main history with a merge, rather than appearing to have been made +directly on top of trunk. + +Check the history +================= + +Now, in either case, you should check that the history is sensible and you +have the right commits:: + + git log --oneline --graph + git log -p upstream-rw/master.. + +The first line above just shows the history in a compact way, with a text +representation of the history graph. The second line shows the log of commits +excluding those that can be reached from trunk (``upstream-rw/master``), and +including those that can be reached from current HEAD (implied with the ``..`` +at the end). So, it shows the commits unique to this branch compared to trunk. +The ``-p`` option shows the diff for these commits in patch form. + +Push to trunk +============= + +:: + + git push upstream-rw my-new-feature:master + +This pushes the ``my-new-feature`` branch in this repository to the ``master`` +branch in the ``upstream-rw`` repository. + +.. include:: links.inc diff --git a/_sources/index.txt b/_sources/index.txt index e7a5c2fd..c72f8fa2 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -1,12 +1,13 @@ -.. AstroPy documentation master file, created by - sphinx-quickstart on Sat Jul 23 11:41:56 2011. +.. Astropy documentation master file, created by + sphinx-quickstart on Tue Jul 26 02:59:34 2011. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to AstroPy's documentation! +Welcome to Astropy's documentation! =================================== -The current AstroPy documentation is limited. For more information, see the `github wiki `_ for the project. +The current AstroPy documentation is limited, as no code has yet been developed. +For more information, see the `github wiki `_ page of the project. Contents: @@ -15,6 +16,7 @@ Contents: development/index + Indices and tables ================== diff --git a/_static/astropyicon.ico b/_static/astropyicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2aee54ce096ffb5a7299b91655ae1cc8d33eb971 GIT binary patch literal 1150 zcmb7ES#Q%o5H?b5ua8~dcAPW^X=&01wKPo+C8Y(ijhgX%Xc!7NX+SV>u37*1BNW29j!7A1%s*^j^r{7U6 zZxI&*G|Nwj$`MSOqkM9MFl%6vggMzeYw&#Ohq$uOFw%%(V=>bvN6hz_HO0hVY$a=r z@^;-Xxm6UGxlLAC{uQy7d6C*Qc@b_RK39`DeB!3Hwtc5suw&1ZD2niExe3Mit3`{W zS&hAE52y1Mk46IC;tcqWcAx8keKn!kjn;O0>;_^x+Ru$9?}tdGmN Y5RN2v*$yoC5<|H6S^xe2ga3X12YH=4vj6}9 literal 0 HcmV?d00001 diff --git a/_static/astropylogo.png b/_static/astropylogo.png new file mode 100644 index 0000000000000000000000000000000000000000..708de1938767f9b6082035adb6cd8143860168c7 GIT binary patch literal 79223 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 literal 0 HcmV?d00001 diff --git a/development/codeguide.html b/development/codeguide.html index 06ae7f23..d34d2eea 100644 --- a/development/codeguide.html +++ b/development/codeguide.html @@ -7,7 +7,7 @@ - Coding Guidelines (Draft 2) — AstroPy v0.0.0 documentation + Coding Guidelines (Draft 3) — Astropy v0.0.0 documentation - + + - - + +

            @@ -50,71 +51,153 @@

            Navigation

            -
            -

            Coding Guidelines (Draft 2)

            +
            +

            Coding Guidelines (Draft 3)

            Warning

            This document is currently in Draft form and is subject to change.

            -
            -

            Core Requirements and Recommendations

            -

            This section describes requirements and guidelines that affiliated packages will have to follow before being considered for integration as a module in the core package.

            +

            This section describes requirements and guidelines that affiliated packages +will have to follow before being considered for integration as a module in the +core package.

            +
            +

            Interface and Dependencies

              -
            • The package should meet the interface requirements set out by the coordination committee.
            • -
            • Packages must be compatible with Python 2.6, 2.7, and 3.x (for 3.x compatibility, the 2to3 tool will be used).
            • -
            • The package should be importable with no dependencies other than components already in the Astropy core, the Python Standard Library (v2.6), NumPy, SciPy, and matplotlib (versions for these packages will be specified in the Astropy setup.py file and on PyPI).
            • -
            • Additional dependencies are allowed for sub-modules or in function calls, but they must be noted in the package documentation and should only affect the relevant component.
            • -
            • Docstrings must be present for all public classes/methods/functions, and must follow the form outlined in the Documentation Guidelines (Draft 2) document.
            • -
            • Unit tests are encouraged for all public methods and functions, and should adhere to the standards set in the Testing Guidelines (Draft) document.
            • -
            • C extensions are only allowed when they provide a significant performance enhancement over pure python, or a C library already exists to provided the needed functionality. When C extensions are used, the python interface must meet interface guidelines.
            • -
            • The use of Cython is strongly recommended for C extensions, as per the example in the template package. Cython extensions should store .pyx files in the source code repository, but they should be compiled to .c files that are updated in the repository when important changes are made to the .pyx file.
            • -
            • If a C extension has a dependency on an external C library, the source code for the library should be bundled with the Astropy core. Additionally, the package must be compatible with using a system-installed library in place of the library included in Astropy.
            • -
            • Packages can include data in path TBD as long as it is less than about 100 kb. These data should be accessed via the astropy.config.[funcname TBD]() mechanism. If the data exceeds this size, it should be hosted outside the source code repository and downloaded using the astropy.config.[funcname TBD]() mechanism. Exceptions to this size limit may be allowed if there are version dependencies between data and code.
            • -
            • All persistent configuration should be stored using the functions in astropy.config, which make use of the ConfigObj class and associated file format (http://www.voidspace.org.uk/python/configobj.html.
            • -
            • General utilities necessary for but not specific to the package should be placed in the packagename.utils module. These utilities will be moved to the astropy.utils module when the package is integrated into the core package. If a utility is already present in astropy.utils, the package should always use that utility instead of re-implementing it in packagename.utils.
            • -
            • Packages implementing many classes/functions not relevant to the component requested will not be accepted - the package should only include the required functionality and relevant extensions.
            • -
            • The package should follow the additional style guides in the next section.
            • +
            • The package should meet the interface requirements set out by the +coordination committee.
            • +
            • Packages implementing many classes/functions not relevant to the component +requested will not be accepted - the package should only include the +required functionality and relevant extensions.
            • +
            • Packages must be compatible with Python 2.6, 2.7, and 3.x (for 3.x +compatibility, the 2to3 tool +will be used).
            • +
            • The package should be importable with no dependencies other than components +already in the Astropy core, the Python Standard Library (v2.6), NumPy, SciPy, +and Matplotlib (versions for these packages will be specified in the +Astropy setup.py file and on PyPI).
            • +
            • Additional dependencies are allowed for sub-modules or in function calls, +but they must be noted in the package documentation and should only affect +the relevant component.
            • +
            • General utilities necessary for but not specific to the package should be +placed in the packagename.utils module. These utilities will be moved +to the astropy.utils module when the package is integrated into the +core package. If a utility is already present in astropy.utils, the +package should always use that utility instead of re-implementing it in +packagename.utils.
            • +
            +
            +
            +

            Documentation and Testing

            +
              +
            • Docstrings must be present for all public classes/methods/functions, and +must follow the form outlined in the Documentation Guidelines (Draft 2) document.
            • +
            • Unit tests are encouraged for all public methods and functions, and should +adhere to the standards set in the Testing Guidelines (Draft) document.
            • +
            +
            +
            +

            Data and Configuration

            +
              +
            • Packages can include data in path TBD as long as it is less than about +100 kb. These data should be accessed via the +astropy.config.[funcname TBD]() mechanism. If the data exceeds this +size, it should be hosted outside the source code repository and downloaded +using the astropy.config.[funcname TBD]() mechanism. Exceptions to +this size limit may be allowed if there are version dependencies between +data and code.
            • +
            • All persistent configuration should be stored using the functions in +astropy.config, which make use of the ConfigObj class and +associated file format (http://www.voidspace.org.uk/python/configobj.html.

            Coding Style/Conventions

            -

            These guidelines are additional style requirements for the Astropy core and recommendations for affiliated packages that are not candidates for merger into the core:

              -
            • The code will follow the standard PEP8 Style Guide for Python Code. In particular, this includes using only 4 spaces for indentation, and never tabs.
            • -
            • One exception is to be made from the PEP8 style: new style relative imports of the form from . import modname are allowed and required for Astropy, as opposed to absolute (as PEP8 suggets) or the simpler import modname syntax. This is primarily due to improved relative import support since PEP8 was developed, and to simplify the process of moving modules.
            • +
            • The code will follow the standard PEP8 Style Guide for Python Code. In particular, this includes +using only 4 spaces for indentation, and never tabs.
            • +
            • One exception is to be made from the PEP8 style: new style relative imports +of the form from . import modname are allowed and required for Astropy, +as opposed to absolute (as PEP8 suggets) or the simpler import modname +syntax. This is primarily due to improved relative import support since PEP8 +was developed, and to simplify the process of moving modules.

            Note

            -

            A pep8.py checker script is available at http://pypi.python.org/pypi/pep8.

            +

            A pep8.py checker script is available at +http://pypi.python.org/pypi/pep8.

            +

            See Emacs setup for following coding guidelines for some configuration options for +Emacs that helps in ensuring conformance to PEP8.

              -
            • In cases where C extensions are needed but Cython cannot be used, the PEP 7 Style Guide for C Code is recommended.
            • -
            • The import numpy as np, import matplotlib as mpl, and import matplotlib.pyplot as plt naming conventions should be used wherever relevant. from packagename import * should never be used, except as a tool to flatten the namespace of a module. An example of the allowed usage is given below.
            • -
            • Classes should either use direct variable access, or python’s property mechanism for setting object instance variables. get_value/set_value style methods should be used only when getting and setting the values requires a computationally-expensive operation. The example below illustrates this guideline.
            • -
            • Classes are discouraged from using the builtin python super() function, unless absolutely needed. If used, it should be used consistentently by all subclasses, and noted in the class’s docstrings. An example illustrating why this is important (and alternative solutions) is included below.
            • -
            • Affiliated packages are recommended to follow the layout and documentation form of the template package included in the core package source distribution.
            • -
            • Affiliated packages are encouraged (but not required) to follow the Astropy core Documentation Guidelines (Draft 2) and Testing Guidelines (Draft).
            • +
            • The import numpy as np, import matplotlib as mpl, and import +matplotlib.pyplot as plt naming conventions should be used wherever +relevant. from packagename import * should never be used, except as a +tool to flatten the namespace of a module. An example of the allowed usage +is given below.
            • +
            • Classes should either use direct variable access, or python’s property +mechanism for setting object instance variables. get_value/set_value +style methods should be used only when getting and setting the values +requires a computationally-expensive operation. The example below +illustrates this guideline.
            • +
            • Classes are discouraged from using the builtin python super() +function, unless absolutely needed. If used, it should be used +consistentently by all subclasses, and noted in the class’s docstrings. An +example illustrating why this is important (and alternative solutions) is +included below.
            • +
            • Affiliated packages are required to follow the layout and documentation form +of the template package included in the core package source distribution.
            +
            +

            Including C code

            +
              +
            • C extensions are only allowed when they provide a significant performance +enhancement over pure python, or a robust C library already exists to +provided the needed functionality. When C extensions are used, the Python +interface must meet interface guidelines.
            • +
            • The use of Cython is strongly recommended for C extensions, as per the +example in the template package. Cython extensions should store .pyx +files in the source code repository, but they should be compiled to .c +files that are updated in the repository when important changes are made to +the .pyx file.
            • +
            • If a C extension has a dependency on an external C library, the source code +for the library should be bundled with the Astropy core, provided the +license for the C library is compatible with the Astropy license. +Additionally, the package must be compatible with using a system-installed +library in place of the library included in Astropy.
            • +
            • In cases where C extensions are needed but Cython cannot be used, the PEP 7 +Style Guide for C Code is +recommended.
            • +
            -
            -

            Affiliated Package Requirements

            -

            The following additional rules apply for affiliated packages, regardless of whether or not they are to be used in the core:

            +
            +

            Requirements specific to Affiliated Packages

              -
            • Affiliated packages must be registered on the Python Package Index, with proper metadata for downloading and installing the source package.
            • -
            • The astropy root package name should not be used by affiliated packages - it is reserved for use by the core package. Recommended naming conventions for an affiliated package are either simply packagename or awastropy.packagename (“affiliated with Astropy”).
            • +
            • Affiliated packages must be registered on the Python Package Index, with proper metadata for downloading and +installing the source package.
            • +
            • The astropy root package name should not be used by affiliated +packages - it is reserved for use by the core package. Recommended naming +conventions for an affiliated package are either simply packagename +or awastropy.packagename (“affiliated with Astropy”).

            Examples

            -

            This section shows a few examples (not all of which are correct!) to illustrate points from the guidelines. These will be moved into the template project once it has been written.

            +

            This section shows a few examples (not all of which are correct!) to +illustrate points from the guidelines. These will be moved into the template +project once it has been written.

            Properties vs. get_/set_

            -

            This example shows a sample class illustrating the guideline regarding the use of properties as opposed to getter/setter methods.

            -

            Let’s assuming you’ve defined a Star class and create an instance like this:

            +

            This example shows a sample class illustrating the guideline regarding the use +of properties as opposed to getter/setter methods.

            +

            Let’s assuming you’ve defined a Star class and create an instance +like this:

            >>> s = Star(B=5.48, V=4.83)
             
            @@ -130,7 +213,8 @@

            Properties vs. get_/set_0.4

            -

            Using python properties, attribute syntax can still do anything possible with a get/set method. For lengthy or complex calculations, however, use a method:

            +

            Using python properties, attribute syntax can still do anything possible with +a get/set method. For lengthy or complex calculations, however, use a method:

            >>> print s.compute_color(5800, age=5e9)
             0.4
             
            @@ -138,7 +222,8 @@

            Properties vs. get_/set_

            super() vs. direct calling

            -

            This example shows why the use of super() can be confusing for subclasses, and gives an alternative syntax:

            +

            This example shows why the use of super() can be confusing for +subclasses, and gives an alternative syntax:

            #This is dangerous and bug-prone!
             
             class A(object):
            @@ -178,12 +263,16 @@ 

            super() vs. direct calling>>> d.method()

            -

            you might expect to have it call both method in the order A,C,B,D. But it doesn’t - instead you see:

            +

            you might expect to have it call both method in the order A,C,B,D. But it +doesn’t - instead you see:

            Doing A
             Doing C
             Doing D
            -

            because the the A.method(self) in C effectively short-circuits the super mechanism. Thus, it’s crucial that all classes in an inheritance hierarchy consistently use super and not mix super with the direct syntax. The simplest approach is to explicitly call each class’ method and avoid super completely:

            +

            because the the A.method(self) in C effectively short-circuits the super +mechanism. Thus, it’s crucial that all classes in an inheritance hierarchy +consistently use super and not mix super with the direct syntax. The simplest +approach is to explicitly call each class’ method and avoid super completely:

            #This is safer
             class A(object):
                 def __init__(self, a):
            @@ -212,7 +301,10 @@ 

            super() vs. direct calling

            Acceptable use of from module import *

            -

            from module import * is discouraged in a module that contains implementation code, as it impedes clarity and often imports unused variables. It can, however, be used for a package that is laid out in the following manner:

            +

            from module import * is discouraged in a module that contains +implementation code, as it impedes clarity and often imports unused variables. +It can, however, be used for a package that is laid out in the following +manner:

            packagename
             packagename/__init__.py
             packagename/submodule1.py
            @@ -227,7 +319,11 @@ 

            Acceptable use of from from submodule2 import *

            -

            This allows functions or classes in the submodules to be used directly as packagename.foo rather than packagename.submodule1.foo. If this is used, it is strongly recommended that the submodules make use of the __all__ variable to specify which modules should be imported. Thus, submodule2.py might read:

            +

            This allows functions or classes in the submodules to be used directly as +packagename.foo rather than packagename.submodule1.foo. If this is +used, it is strongly recommended that the submodules make use of the __all__ +variable to specify which modules should be imported. Thus, submodule2.py +might read:

            from numpy import array,linspace
             
             __all__ = ('foo','AClass')
            @@ -241,7 +337,17 @@ 

            Acceptable use of from pass

            -

            This ensures that from submodule import * only imports foo() and AClass, but not numpy.array or numpy.linspace().

            +

            This ensures that from submodule import * only imports foo() and +AClass, but not numpy.array or numpy.linspace().

            +

            +
            +
            +

            Additional Resources

            +

            Further tips and hints relating to the coding guidelines are included below.

            +
            @@ -252,28 +358,37 @@

            Acceptable use of from

            diff --git a/development/codeguide_emacs.html b/development/codeguide_emacs.html new file mode 100644 index 00000000..614c09ec --- /dev/null +++ b/development/codeguide_emacs.html @@ -0,0 +1,306 @@ + + + + + + + + + Emacs setup for following coding guidelines — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
            +
            +
            +
            + +
            +

            Emacs setup for following coding guidelines

            +

            The AstroPy coding guidelines are listed in Coding Guidelines (Draft 3). This +document will describe some configuration options for Emacs, that will +help in ensuring that Python code satisfies the guidelines. Emacs can +be configured in several different ways. So instead of providing a drop +in configuration file, only the individual configurations are presented +below.

            +

            For this setup we will need flymake, pyflakes and the pep8 Python +script, in addition to python-mode.

            +

            Flymake comes with Emacs 23. The rest can be obtained from their +websites, or can be installed using easy_install or pip.

            +
            +

            Global settings

            +
            +

            No tabs

            +

            This setting will cause all tabs to be replaced with spaces. The number +of spaces to use is set in the Basic settings section below.

            +
            ;; Don't use TABS for indentations.
            +(setq-default indent-tabs-mode nil)
            +
            +
            +
            +
            +

            Maximum number of characters in a line

            +

            Emacs will automatically insert a new line after “fill-column” number +of columns. PEP8 specifies a maximum of 79, but this can be set to a +smaller value also, for example 72.

            +
            ;; Set the number to the number of columns to use.
            +(setq-default fill-column 79)
            +
            +;; Add Autofill mode to mode hooks.
            +(add-hook 'text-mode-hook 'turn-on-auto-fill)
            +
            +;; Show line number in the mode line.
            +(line-number-mode 1)
            +
            +;; Show column number in the mode line.
            +(column-number-mode 1)
            +
            +
            +
            +
            +

            Syntax highlighting

            +

            Enable syntax highlighting. This will also highlight lines that form a +region.

            +
            (global-font-lock-mode 1)
            +
            +
            +
            +
            +
            +

            Python specific settings

            +
            +

            Basic settings

            +

            Indentation is automatically added. When a tab is pressed it is +replaced with 4 spaces. When backspace is pressed on an empty line, the +cursor will jump to the previous indentation level.

            +
            (load-library "python")
            +
            +(autoload 'python-mode "python-mode" "Python Mode." t)
            +(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))
            +(add-to-list 'interpreter-mode-alist '("python" . python-mode))
            +
            +(setq interpreter-mode-alist
            +      (cons '("python" . python-mode)
            +            interpreter-mode-alist)
            +      python-mode-hook
            +      '(lambda () (progn
            +                    (set-variable 'py-indent-offset 4)
            +                    (set-variable 'indent-tabs-mode nil))))
            +
            +
            +
            +
            +

            Highlight the column where a line must stop

            +

            The “fill-column” column is highlighted in red. For this to work, +download column-marker.el and place it in the +Emacs configuration directory.

            +
            ;; Highlight character at "fill-column" position.
            +(require 'column-marker)
            +(set-face-background 'column-marker-1 "red")
            +(add-hook 'python-mode-hook
            +          (lambda () (interactive)
            +            (column-marker-1 fill-column)))
            +
            +
            +
            +
            +

            Flymake

            +

            Flymake will mark lines that do not satisfy syntax requirements in +red. When cursor is on such a line a message is displayed in the +mini-buffer. When mouse pointer is on such a line a “tool tip” message +is also shown.

            +

            For flymake to work with pep8 and pyflakes, create an +executable file named pychecker with the following contents. This +file must be in the system path.

            +
            #!/bin/bash
            +
            +pyflakes "$1"
            +pep8 --ignore=E221,E701,E202 --repeat "$1"
            +true
            +
            +
            +

            Add the following code to Emacs configurations.

            +
            ;; Setup for Flymake code checking.
            +(require 'flymake)
            +(load-library "flymake-cursor")
            +
            +;; Script that flymake uses to check code. This script must be
            +;; present in the system path.
            +(setq pycodechecker "pychecker")
            +
            +(when (load "flymake" t)
            +  (defun flymake-pycodecheck-init ()
            +    (let* ((temp-file (flymake-init-create-temp-buffer-copy
            +                       'flymake-create-temp-inplace))
            +           (local-file (file-relative-name
            +                        temp-file
            +                        (file-name-directory buffer-file-name))))
            +      (list pycodechecker (list local-file))))
            +  (add-to-list 'flymake-allowed-file-name-masks
            +               '("\\.py\\'" flymake-pycodecheck-init)))
            +
            +(add-hook 'python-mode-hook 'flymake-mode)
            +
            +
            +
            +

            Note

            +

            Flymake will save files with suffix _flymake in the current +directory. If it crashes for some reason, then these files will not +get deleted.

            +

            Sometimes there is a delay in refreshing the results.

            +
            +
            +
            +

            Delete trailing white spaces and blank lines

            +

            To manually delete trailing whitespaces, press C-t C-w, which will +run the command “delete-whitespaces`. This command is also run when a +file is saved, and hence all trailing whitespaces will be deleted on +saving a Python file.

            +

            To make sure that all “words” are separated by only one space, type +M-SPC (use the ALT key since M-SPC sometimes brings up a context +menu.).

            +

            To collapse a set of blank lines to one blank line, place the cursor on +one of these and press C-x C-o. This is useful for deleting multiple +black lines at the end of a file.

            +
            ;; Remove trailing whitespace manually by typing C-t C-w.
            +(add-hook 'python-mode-hook
            +          (lambda ()
            +            (local-set-key (kbd "C-t C-w")
            +                           'delete-trailing-whitespace)))
            +
            +;; Automatically remove trailing whitespace when file is saved.
            +(add-hook 'python-mode-hook
            +      (lambda()
            +        (add-hook 'local-write-file-hooks
            +              '(lambda()
            +                 (save-excursion
            +                   (delete-trailing-whitespace))))))
            +
            +;; Use M-SPC (use ALT key) to make sure that words are separated by
            +;; just one space. Use C-x C-o to collapse a set of empty lines
            +;; around the cursor to one empty line. Useful for deleting all but
            +;; one blank line at end of file. To do this go to end of file (M->)
            +;; and type C-x C-o.
            +
            +
            +
            +
            +
            + + +
            +
            +
            + +
            +
            + + + + \ No newline at end of file diff --git a/development/docguide.html b/development/docguide.html index 28d69d5a..193168be 100644 --- a/development/docguide.html +++ b/development/docguide.html @@ -7,7 +7,7 @@ - Documentation Guidelines (Draft 2) — AstroPy v0.0.0 documentation + Documentation Guidelines (Draft 2) — Astropy v0.0.0 documentation - + + - +
          • - previous |
          • -
          • AstroPy v0.0.0 documentation »
          • +
          • Astropy v0.0.0 documentation »
          • Documentation for Developers »
          @@ -569,6 +570,9 @@

          Conclusion diff --git a/development/index.html b/development/index.html index 6f9f1352..8ffc3bf0 100644 --- a/development/index.html +++ b/development/index.html @@ -7,7 +7,7 @@ - Documentation for Developers — AstroPy v0.0.0 documentation + Documentation for Developers — Astropy v0.0.0 documentation - + + - +

        • - previous |
        • -
        • AstroPy v0.0.0 documentation »
        • +
        • Astropy v0.0.0 documentation »
        @@ -54,7 +55,8 @@

        Documentation for Developers @@ -67,9 +69,12 @@

        Documentation for Developers
        +

        Previous topic

        Welcome to AstroPy’s documentation!

        + title="previous chapter">Welcome to Astropy’s documentation!

        Next topic

        Vision for a common Astronomy Python package

        @@ -105,13 +110,13 @@

        Navigation

        next |

      • - previous |
      • -
      • AstroPy v0.0.0 documentation »
      • +
      • Astropy v0.0.0 documentation »
      diff --git a/development/testguide.html b/development/testguide.html index 15161c83..14177c71 100644 --- a/development/testguide.html +++ b/development/testguide.html @@ -7,7 +7,7 @@ - Testing Guidelines (Draft) — AstroPy v0.0.0 documentation + Testing Guidelines (Draft) — Astropy v0.0.0 documentation - + + @@ -36,7 +37,7 @@

      Navigation

    • previous |
    • -
    • AstroPy v0.0.0 documentation »
    • +
    • Astropy v0.0.0 documentation »
    • Documentation for Developers »
    @@ -64,6 +65,9 @@

    Testing Guidelines (Draft) diff --git a/development/vision.html b/development/vision.html index ea85976c..8f88163b 100644 --- a/development/vision.html +++ b/development/vision.html @@ -7,7 +7,7 @@ - Vision for a common Astronomy Python package — AstroPy v0.0.0 documentation + Vision for a common Astronomy Python package — Astropy v0.0.0 documentation - + + - + @@ -35,12 +36,12 @@

    Navigation

    index
  • - next |
  • previous |
  • -
  • AstroPy v0.0.0 documentation »
  • +
  • Astropy v0.0.0 documentation »
  • Documentation for Developers »
  • @@ -51,7 +52,7 @@

    Navigation

    -

    Vision for a common Astronomy Python package

    +

    Vision for a common Astronomy Python package

    The following document summarizes a vision for a common Astronomy Python package, and how we can best all work together to achieve this. In the following document, this common package will be referred to as the core package. This vision is not set in stone, and we are committed to adapting it to whatever process and guidelines work in practice.

    The ultimate goal that we seek is a package that would contain much of the core functionality and some common tools required across Astronomy, but not everything Astronomers will ever need. The aim is primarily to avoid duplication for common core tasks, and to provide a robust framework upon which to build more complex tools.

    Such a common package should not preclude any other Astronomy package from existing, because there will always be more complex and/or specialized tools required. These tools will be able to rely on a single core library for many tasks, and thus reduce the number of dependencies, reduce duplication of functionality, and increase consistency of their interfaces.

    @@ -92,6 +93,9 @@

    Existing Packages

    index
  • - next |
  • previous |
  • -
  • AstroPy v0.0.0 documentation »
  • +
  • Astropy v0.0.0 documentation »
  • Documentation for Developers »
  • diff --git a/development/workflow/development_workflow.html b/development/workflow/development_workflow.html new file mode 100644 index 00000000..b7b06456 --- /dev/null +++ b/development/workflow/development_workflow.html @@ -0,0 +1,138 @@ + + + + + + + + + Development workflow — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Development workflow

    +

    This document describes how to contribute to a git repository hosted on +GitHub. The example shown here is that of the core astropy repository, but +the workflow can work equally well for the internal development of an +affiliated package.

    +

    Before following the instructions on this page, make sure you have correctly +installed and configured git:

    + +

    The following documents describe a beginner and advanced workflow for +contributing respectively:

    + +
    + + +
    +
    +
    +
    +
    + +

    Previous topic

    +

    Git resources

    +

    Next topic

    +

    Installing git

    +

    This Page

    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/development/workflow/development_workflow_advanced.html b/development/workflow/development_workflow_advanced.html new file mode 100644 index 00000000..f8f28d2b --- /dev/null +++ b/development/workflow/development_workflow_advanced.html @@ -0,0 +1,594 @@ + + + + + + + + + Development Workflow (Advanced) — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Development Workflow (Advanced)

    +

    In the present document, we refer to the AstroPy master branch, as the +trunk.

    +
    +

    Creating a fork

    +

    You need to do this only once for each package you want to contribute to. The +instructions here are very similar to the instructions at +http://help.github.com/fork-a-repo/ — please see that page for more +details. We’re repeating some of it here just to give the specifics for the +Astropy project, and to suggest some default names.

    +
    +

    Set up and configure a GitHub account

    +

    If you don’t have a GitHub account, go to the GitHub page, and make one.

    +

    You then need to configure your account to allow write access — see +the Generating SSH keys help on github help.

    +
    +
    +

    Create your own fork of a repository

    +

    The following example shows how to fork the core astropy repository, but the same applies to other packages:

    +
      +
    1. Log into your GitHub account.

      +
    2. +
    3. Go to the Astropy GitHub home at Astropy github.

      +
    4. +
    5. Click on the fork button:

      +../../_images/forking_button.png +

      Now, after a short pause and some ‘Hardcore forking action’, you +should find yourself at the home page for your own forked copy of Astropy.

      +
    6. +
    +
    +
    +

    Setting up the fork to work on

    +
    +

    Overview

    +

    This is done using:

    +
    git clone git@github.com:your-user-name/astropy.git
    +cd astropy
    +git remote add upstream git://github.com/astropy/astropy.git
    +
    +
    +
    +

    In detail

    +
      +
    1. Clone your fork to the local computer:

      +
      git clone git@github.com:your-user-name/astropy.git
      +
      +
    2. +
    3. Change directory to your new repo:

      +
      cd astropy
      +
      +

      Then type:

      +
      git branch -a
      +
      +

      to show you all branches. You’ll get something like:

      +
      * master
      +remotes/origin/master
      +
      +

      This tells you that you are currently on the master branch, and +that you also have a remote connection to origin/master. +What remote repository is remote/origin? Try git remote -v to +see the URLs for the remote. They will point to your github fork.

      +

      Now you want to connect to the Astropy github repository, so you can +merge in changes from the trunk:

      +
      cd astropy
      +git remote add upstream git://github.com/astropy/astropy.git
      +
      +

      upstream here is just the arbitrary name we’re using to refer to the +main Astropy repository at Astropy github.

      +

      Note that we’ve used git:// for the URL rather than git@. The +git:// URL is read only. This means we that we can’t accidentally (or +deliberately) write to the upstream repo, and we are only going to use it +to merge into our own code.

      +

      Just for your own satisfaction, show yourself that you now have a new +‘remote’, with git remote -v show, giving you something like:

      +
      upstream   git://github.com/astropy/astropy.git (fetch)
      +upstream   git://github.com/astropy/astropy.git (push)
      +origin     git@github.com:your-user-name/astropy.git (fetch)
      +origin     git@github.com:your-user-name/astropy.git (push)
      +
      +

      Your fork is now set up correctly, and you are ready to hack away.

      +
    4. +
    +
    +
    +
    +
    +

    Workflow summary

    +

    This section gives a summary of the workflow once you have successfully forked +the repository, and details are given for each of these steps in the following +sections.

    +
      +
    • Don’t use your master branch for anything. Consider deleting it.
    • +
    • When you are starting a new set of changes, fetch any changes from the +trunk, and start a new feature branch from that.
    • +
    • Make a new branch for each separable set of changes — “one task, one +branch” (ipython git workflow).
    • +
    • Name your branch for the purpose of the changes - e.g. +bugfix-for-issue-14 or refactor-database-code.
    • +
    • If you can possibly avoid it, avoid merging trunk or any other branches into +your feature branch while you are working.
    • +
    • If you do find yourself merging from the trunk, consider Rebasing on trunk
    • +
    • Ask on the Astropy mailing list if you get stuck.
    • +
    • Ask for code review!
    • +
    +

    This way of working helps to keep work well organized, with readable history. +This in turn makes it easier for project maintainers (that might be you) to +see what you’ve done, and why you did it.

    +

    See linux git workflow and ipython git workflow for some explanation.

    +
    +
    +

    Deleting your master branch

    +

    It may sound strange, but deleting your own master branch can help reduce +confusion about which branch you are on. See deleting master on github for +details.

    +
    +
    +

    Updating the mirror of trunk

    +

    From time to time you should fetch the upstream (trunk) changes from github:

    +
    git fetch upstream
    +
    +

    This will pull down any commits you don’t have, and set the remote branches to +point to the right commit. For example, ‘trunk’ is the branch referred to by +(remote/branchname) upstream/master - and if there have been commits since +you last checked, upstream/master will change after you do the fetch.

    +
    +
    +

    Making a new feature branch

    +

    When you are ready to make some changes to the code, you should start a new +branch. Branches that are for a collection of related edits are often called +‘feature branches’.

    +

    Making an new branch for each set of related changes will make it easier for +someone reviewing your branch to see what you are doing.

    +

    Choose an informative name for the branch to remind yourself and the rest of +us what the changes in the branch are for. For example add-ability-to-fly, +or buxfix-for-issue-42.

    +
    # Update the mirror of trunk
    +git fetch upstream
    +
    +# Make new feature branch starting at current trunk
    +git branch my-new-feature upstream/master
    +git checkout my-new-feature
    +
    +

    Generally, you will want to keep your feature branches on your public github +fork of Astropy. To do this, you git push this new branch up to your +github repo. Generally (if you followed the instructions in these pages, and +by default), git will have a link to your GitHub repo, called origin. You +push up to your own repo on GitHub with:

    +
    git push origin my-new-feature
    +
    +

    In git >= 1.7 you can ensure that the link is correctly set by using the +--set-upstream option:

    +
    git push --set-upstream origin my-new-feature
    +
    +

    From now on git will know that my-new-feature is related to the +my-new-feature branch in the GitHub repo.

    +
    +
    +

    The editing workflow

    +
    +

    Overview

    +
    git add my_new_file
    +git commit -am 'NF - some message'
    +git push
    +
    +
    +
    +

    In more detail

    +
      +
    1. Make some changes

      +
    2. +
    3. See which files have changed with git status (see git status). +You’ll see a listing like this one:

      +
      # On branch ny-new-feature
      +# Changed but not updated:
      +#   (use "git add <file>..." to update what will be committed)
      +#   (use "git checkout -- <file>..." to discard changes in working directory)
      +#
      +#  modified:   README
      +#
      +# Untracked files:
      +#   (use "git add <file>..." to include in what will be committed)
      +#
      +#  INSTALL
      +no changes added to commit (use "git add" and/or "git commit -a")
      +
      +
    4. +
    5. Check what the actual changes are with git diff (git diff).

      +
    6. +
    7. Add any new files to version control git add new_file_name (see +git add).

      +
    8. +
    9. To commit all modified files into the local copy of your repo,, do +git commit -am 'A commit message'. Note the -am options to +commit. The m flag just signals that you’re going to type a message +on the command line. The a flag — you can just take on faith +— or see why the -a flag? — and the helpful use-case +description in the tangled working copy problem. The git commit +manual +page might also be useful.

      +
    10. +
    11. To push the changes up to your forked repo on github, do a git +push (see git push).

      +
    12. +
    +
    +
    +
    +

    Asking for your changes to be reviewed or merged

    +

    When you are ready to ask for someone to review your code and consider a merge:

    +
      +
    1. Go to the URL of your forked repo, say +http://github.com/your-user-name/astropy.

      +
    2. +
    3. Use the ‘Switch Branches’ dropdown menu near the top left of the page to +select the branch with your changes:

      +../../_images/branch_dropdown.png +
    4. +
    5. Click on the ‘Pull request’ button:

      +../../_images/pull_button.png +

      Enter a title for the set of changes, and some explanation of what you’ve +done. Say if there is anything you’d like particular attention for - like a +complicated change or some code you are not happy with.

      +

      If you don’t think your request is ready to be merged, just say so in your +pull request message. This is still a good way of getting some preliminary +code review.

      +
    6. +
    +
    +
    +

    Some other things you might want to do

    +
    +

    Delete a branch on github

    +
    # change to the master branch (if you still have one, otherwise change to
    +# another branch)
    +git checkout master
    +
    +# delete branch locally
    +git branch -D my-unwanted-branch
    +
    +# delete branch on github
    +git push origin :my-unwanted-branch
    +
    +

    (Note the colon : before test-branch. See also: +http://github.com/guides/remove-a-remote-branch

    +
    +
    +

    Several people sharing a single repository

    +

    If you want to work on some stuff with other people, where you are all +committing into the same repository, or even the same branch, then just +share it via github.

    +

    First fork Astropy into your account, as from Creating a fork.

    +

    Then, go to your forked repository GitHub page, say +http://github.com/your-user-name/astropy

    +

    Click on the ‘Admin’ button, and add anyone else to the repo as a +collaborator:

    +
    +
    ../../_images/pull_button.png +
    +

    Now all those people can do:

    +
    git clone git@githhub.com:your-user-name/astropy.git
    +
    +

    Remember that links starting with git@ use the ssh protocol and are +read-write; links starting with git:// are read-only.

    +

    Your collaborators can then commit directly into that repo with the +usual:

    +
    git commit -am 'ENH - much better code'
    +git push origin master # pushes directly into your repo
    +
    +
    +
    +

    Explore your repository

    +

    To see a graphical representation of the repository branches and +commits:

    +
    gitk --all
    +
    +
    +

    To see a linear list of commits for this branch:

    +
    git log
    +
    +

    You can also look at the network graph visualizer for your github +repo.

    +

    Finally the Fancy log output lg alias will give you a reasonable +text-based graph of the repository.

    +
    +
    +

    Rebasing on trunk

    +

    Let’s say you thought of some work you’d like to do. You +Updating the mirror of trunk and Making a new feature branch called +cool-feature. At this stage trunk is at some commit, let’s call it E. Now +you make some new commits on your cool-feature branch, let’s call them A, +B, C. Maybe your changes take a while, or you come back to them after a while. +In the meantime, trunk has progressed from commit E to commit (say) G:

    +
          A---B---C cool-feature
    +     /
    +D---E---F---G trunk
    +
    +

    At this stage you consider merging trunk into your feature branch, and you +remember that this here page sternly advises you not to do that, because the +history will get messy. Most of the time you can just ask for a review, and +not worry that trunk has got a little ahead. But sometimes, the changes in +trunk might affect your changes, and you need to harmonize them. In this +situation you may prefer to do a rebase.

    +

    Rebase takes your changes (A, B, C) and replays them as if they had been made +to the current state of trunk. In other words, in this case, it takes the +changes represented by A, B, C and replays them on top of G. After the rebase, +your history will look like this:

    +
                  A'--B'--C' cool-feature
    +             /
    +D---E---F---G trunk
    +
    +

    See rebase without tears for more detail.

    +

    To do a rebase on trunk:

    +
    # Update the mirror of trunk
    +git fetch upstream
    +
    +# Go to the feature branch
    +git checkout cool-feature
    +
    +# Make a backup in case you mess up
    +git branch tmp cool-feature
    +
    +# Rebase cool-feature onto trunk
    +git rebase --onto upstream/master upstream/master cool-feature
    +
    +

    In this situation, where you are already on branch cool-feature, the last +command can be written more succinctly as:

    +
    git rebase upstream/master
    +
    +

    When all looks good you can delete your backup branch:

    +
    git branch -D tmp
    +
    +

    If it doesn’t look good you may need to have a look at +Recovering from mess-ups.

    +

    If you have made changes to files that have also changed in trunk, this may +generate merge conflicts that you need to resolve - see the git rebase man +page for some instructions at the end of the “Description” section. There is +some related help on merging in the git user manual - see resolving a +merge.

    +
    +
    +

    Recovering from mess-ups

    +

    Sometimes, you mess up merges or rebases. Luckily, in git it is relatively +straightforward to recover from such mistakes.

    +

    If you mess up during a rebase:

    +
    git rebase --abort
    +
    +

    If you notice you messed up after the rebase:

    +
    # Reset branch back to the saved point
    +git reset --hard tmp
    +
    +

    If you forgot to make a backup branch:

    +
    # Look at the reflog of the branch
    +git reflog show cool-feature
    +
    +8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately
    +278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d
    +26aa21a cool-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj
    +...
    +
    +# Reset the branch to where it was before the botched rebase
    +git reset --hard cool-feature@{2}
    +
    +
    +
    +

    Rewriting commit history

    +
    +

    Note

    +

    Do this only for your own feature branches.

    +
    +

    There’s an embarrassing typo in a commit you made? Or perhaps the you +made several false starts you would like the posterity not to see.

    +

    This can be done via interactive rebasing.

    +

    Suppose that the commit history looks like this:

    +
    git log --oneline
    +eadc391 Fix some remaining bugs
    +a815645 Modify it so that it works
    +2dec1ac Fix a few bugs + disable
    +13d7934 First implementation
    +6ad92e5 * masked is now an instance of a new object, MaskedConstant
    +29001ed Add pre-nep for a copule of structured_array_extensions.
    +...
    +
    +

    and 6ad92e5 is the last commit in the cool-feature branch. Suppose we +want to make the following changes:

    +
      +
    • Rewrite the commit message for 13d7934 to something more sensible.
    • +
    • Combine the commits 2dec1ac, a815645, eadc391 into a single one.
    • +
    +

    We do as follows:

    +
    # make a backup of the current state
    +git branch tmp HEAD
    +# interactive rebase
    +git rebase -i 6ad92e5
    +
    +

    This will open an editor with the following text in it:

    +
    pick 13d7934 First implementation
    +pick 2dec1ac Fix a few bugs + disable
    +pick a815645 Modify it so that it works
    +pick eadc391 Fix some remaining bugs
    +
    +# Rebase 6ad92e5..eadc391 onto 6ad92e5
    +#
    +# Commands:
    +#  p, pick = use commit
    +#  r, reword = use commit, but edit the commit message
    +#  e, edit = use commit, but stop for amending
    +#  s, squash = use commit, but meld into previous commit
    +#  f, fixup = like "squash", but discard this commit's log message
    +#
    +# If you remove a line here THAT COMMIT WILL BE LOST.
    +# However, if you remove everything, the rebase will be aborted.
    +#
    +
    +

    To achieve what we want, we will make the following changes to it:

    +
    r 13d7934 First implementation
    +pick 2dec1ac Fix a few bugs + disable
    +f a815645 Modify it so that it works
    +f eadc391 Fix some remaining bugs
    +
    +

    This means that (i) we want to edit the commit message for 13d7934, and +(ii) collapse the last three commits into one. Now we save and quit the +editor.

    +

    Git will then immediately bring up an editor for editing the commit message. +After revising it, we get the output:

    +
    [detached HEAD 721fc64] FOO: First implementation
    + 2 files changed, 199 insertions(+), 66 deletions(-)
    +[detached HEAD 0f22701] Fix a few bugs + disable
    + 1 files changed, 79 insertions(+), 61 deletions(-)
    +Successfully rebased and updated refs/heads/my-feature-branch.
    +
    +

    and the history looks now like this:

    +
    0f22701 Fix a few bugs + disable
    +721fc64 ENH: Sophisticated feature
    +6ad92e5 * masked is now an instance of a new object, MaskedConstant
    +
    +

    If it went wrong, recovery is again possible as explained above.

    +
    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/development/workflow/development_workflow_basic.html b/development/workflow/development_workflow_basic.html new file mode 100644 index 00000000..628cf208 --- /dev/null +++ b/development/workflow/development_workflow_basic.html @@ -0,0 +1,247 @@ + + + + + + + + + Development Workflow (Beginner) — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Development Workflow (Beginner)

    +

    You’ve discovered a bug or something else you want to change +in Astropy — excellent!

    +

    You’ve worked out a way to fix it — even better!

    +

    You want to tell us about it — best of all!

    +

    The easiest way is to make a patch or set of patches. Here we explain how. +Making a patch is the simplest and quickest, but if you’re going to be doing +anything more than simple quick things, please consider following +Development Workflow (Advanced) instead.

    +
    +

    Making patches

    +
    +

    Overview

    +

    If you haven’t already configured git (For the Impatient):

    +
    git config --global user.name "Your Name"
    +git config --global user.email you@yourdomain.example.com
    +
    +

    Then, the workflow is the following:

    +
    # Get the repository if you don't have it
    +git clone git://github.com/astropy/astropy.git
    +
    +# Make a branch for your patching
    +cd astropy
    +git branch the-fix-im-thinking-of
    +git checkout the-fix-im-thinking-of
    +
    +# hack, hack, hack
    +
    +# Tell git about any new files you've made
    +git add somewhere/tests/test_my_bug.py
    +
    +# Commit work in progress as you go
    +git commit -am 'BF - added tests for Funny bug'
    +
    +# hack hack, hack
    +
    +# Commit work
    +git commit -am 'BF - added fix for Funny bug'
    +
    +# Make the patch files
    +git format-patch -M -C master
    +
    +

    Then, send the generated patch files to the Astropy mailing list — +where we will thank you warmly.

    +
    +
    +

    In detail

    +
      +
    1. Tell git who you are so it can label the commits you’ve +made:

      +
      git config --global user.name "Your Name"
      +git config --global user.email you@yourdomain.example.com
      +
      +

      This is only necessary if you haven’t already done this, and you haven’t +followed Configuring git.

      +
    2. +
    3. If you don’t already have one, clone a copy of the +Astropy repository:

      +
      git clone git://github.com/astropy/astropy.git
      +cd astropy
      +
      +
    4. +
    5. Make a ‘feature branch’. This will be where you work on your bug fix. It’s +nice and safe and leaves you with access to an unmodified copy of the code +in the main branch:

      +
      git branch the-fix-im-thinking-of
      +git checkout the-fix-im-thinking-of
      +
      +
    6. +
    7. Do some edits, and commit them as you go:

      +
      # hack, hack, hack
      +
      +# Tell git about any new files you've made
      +git add somewhere/tests/test_my_bug.py
      +
      +# Commit work in progress as you go
      +git commit -am 'BF - added tests for Funny bug'
      +
      +# hack hack, hack
      +
      +# Commit work
      +git commit -am 'BF - added fix for Funny bug'
      +
      +

      Note the -am options to commit. The m flag just +signals that you’re going to type a message on the command +line. The a flag — you can just take on faith — +or see why the -a flag?.

      +
    8. +
    9. When you have finished, check you have committed all your changes:

      +
      git status
      +
      +
    10. +
    11. Finally, make your commits into patches. You want all the commits since you +branched from the master branch:

      +
      git format-patch -M -C master
      +
      +

      You will now have several files named for the commits:

      +
      0001-BF-added-tests-for-Funny-bug.patch
      +0002-BF-added-fix-for-Funny-bug.patch
      +
      +

      Send these files to the Astropy mailing list.

      +
    12. +
    +

    When you are done, to switch back to the main copy of the +code, just return to the master branch:

    +
    git checkout master
    +
    +
    +
    +
    +

    Moving from patching to development

    +

    If you find you have done some patches, and you have one or more feature +branches, you will probably want to switch to a more advanced development +mode. You can do this with the repository you have. See Development Workflow (Advanced) for more details.

    +
    +
    + + +
    +
    +
    +
    +
    + +

    Table Of Contents

    + + +

    Previous topic

    +

    Configuring git

    +

    Next topic

    +

    Development Workflow (Advanced)

    +

    This Page

    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/development/workflow/git_configure.html b/development/workflow/git_configure.html new file mode 100644 index 00000000..abd5e096 --- /dev/null +++ b/development/workflow/git_configure.html @@ -0,0 +1,274 @@ + + + + + + + + + Configuring git — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Configuring git

    +
    +

    Bare Minimum

    +

    The only absolutely necessary configuration step is identifying yourself and your contact info:

    +
    git config --global user.name "Your Name"
    +git config --global user.email you@yourdomain.example.com
    +
    +

    Once you’ve done this, you can actually ignore the rest of the document unless you want to customize the behavior of git.

    +
    +
    +

    Overview

    +

    Your personal git configurations are saved in the .gitconfig file in +your home directory.

    +

    Here is an example .gitconfig file:

    +
    [user]
    +        name = Your Name
    +        email = you@yourdomain.example.com
    +
    +[alias]
    +        ci = commit -a
    +        co = checkout
    +        st = status
    +        stat = status
    +        br = branch
    +        wdiff = diff --color-words
    +
    +[core]
    +        editor = vim
    +
    +[merge]
    +        log = true
    +
    +

    You can edit this file directly or you can use the git config --global +command:

    +
    git config --global user.name "Your Name"
    +git config --global user.email you@yourdomain.example.com
    +git config --global alias.ci "commit -a"
    +git config --global alias.co checkout
    +git config --global alias.st "status -a"
    +git config --global alias.stat "status -a"
    +git config --global alias.br branch
    +git config --global alias.wdiff "diff --color-words"
    +git config --global core.editor vim
    +git config --global merge.summary true
    +
    +

    To set up on another computer, you can copy your ~/.gitconfig file, +or run the commands above.

    +
    +
    +

    In detail

    +
    +

    user.name and user.email

    +

    It is good practice to tell git who you are, for labeling any changes +you make to the code. The simplest way to do this is from the command +line:

    +
    git config --global user.name "Your Name"
    +git config --global user.email you@yourdomain.example.com
    +
    +

    This will write the settings into your git configuration file, which +should now contain a user section with your name and email:

    +
    [user]
    +      name = Your Name
    +      email = you@yourdomain.example.com
    +
    +

    Of course you’ll need to replace Your Name and you@yourdomain.example.com +with your actual name and email address.

    +
    +
    +

    Aliases

    +

    You might well benefit from some aliases to common commands.

    +

    For example, you might well want to be able to shorten git checkout +to git co. Or you may want to alias git diff --color-words +(which gives a nicely formatted output of the diff) to git wdiff

    +

    The following git config --global commands:

    +
    git config --global alias.ci "commit -a"
    +git config --global alias.co checkout
    +git config --global alias.st "status -a"
    +git config --global alias.stat "status -a"
    +git config --global alias.br branch
    +git config --global alias.wdiff "diff --color-words"
    +
    +

    will create an alias section in your .gitconfig file with contents +like this:

    +
    [alias]
    +        ci = commit -a
    +        co = checkout
    +        st = status -a
    +        stat = status -a
    +        br = branch
    +        wdiff = diff --color-words
    +
    +
    +
    +

    Editor

    +

    You may also want to make sure that your editor of choice is used

    +
    git config --global core.editor vim
    +
    +
    +
    +

    Merging

    +

    To enforce summaries when doing merges (~/.gitconfig file again):

    +
    [merge]
    +   log = true
    +
    +

    Or from the command line:

    +
    git config --global merge.log true
    +
    +
    +
    +

    Fancy log output

    +

    This is a very nice alias to get a fancy log output; it should go in the +alias section of your .gitconfig file:

    +
    lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative
    +
    +

    You use the alias with:

    +
    git lg
    +
    +

    and it gives graph / text output something like this (but with color!):

    +
    * 6d8e1ee - (HEAD, origin/my-fancy-feature, my-fancy-feature) NF - a fancy file (45 minutes ago) [Matthew Brett]
    +*   d304a73 - (origin/placeholder, placeholder) Merge pull request #48 from hhuuggoo/master (2 weeks ago) [Jonathan Terhorst]
    +|\
    +| * 4aff2a8 - fixed bug 35, and added a test in test_bugfixes (2 weeks ago) [Hugo]
    +|/
    +* a7ff2e5 - Added notes on discussion/proposal made during Data Array Summit. (2 weeks ago) [Corran Webster]
    +* 68f6752 - Initial implimentation of AxisIndexer - uses 'index_by' which needs to be changed to a call on an Axes object - this is all very sketchy right now. (2 weeks ago) [Corr
    +*   376adbd - Merge pull request #46 from terhorst/master (2 weeks ago) [Jonathan Terhorst]
    +|\
    +| * b605216 - updated joshu example to current api (3 weeks ago) [Jonathan Terhorst]
    +| * 2e991e8 - add testing for outer ufunc (3 weeks ago) [Jonathan Terhorst]
    +| * 7beda5a - prevent axis from throwing an exception if testing equality with non-axis object (3 weeks ago) [Jonathan Terhorst]
    +| * 65af65e - convert unit testing code to assertions (3 weeks ago) [Jonathan Terhorst]
    +| *   956fbab - Merge remote-tracking branch 'upstream/master' (3 weeks ago) [Jonathan Terhorst]
    +| |\
    +| |/
    +
    +

    Thanks to Yury V. Zaytsev for posting it.

    +
    +
    +
    + + +
    +
    +
    +
    +
    + +

    Table Of Contents

    + + +

    Previous topic

    +

    Installing git

    +

    Next topic

    +

    Development Workflow (Beginner)

    +

    This Page

    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/development/workflow/git_install.html b/development/workflow/git_install.html new file mode 100644 index 00000000..2d1df5b6 --- /dev/null +++ b/development/workflow/git_install.html @@ -0,0 +1,156 @@ + + + + + + + + + Installing git — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Installing git

    +

    The instructions here are adapted from http://book.git-scm.com/2_installing_git.html

    +
    +

    Debian/Ubuntu

    +
    sudo apt-get install git-core
    +
    +
    +
    +

    Fedora

    +
    sudo yum install git-core
    +
    +
    +
    +

    MacOS X

    +

    There are several ways to install git on Mac. The easiest is to simply download the OS X installer (git-osx-installer). If you have MacPorts installed, you can also do:

    +
    sudo port install git-core
    +
    +

    If you have Fink installed, you can do:

    +
    sudo apt-get install git
    +
    +

    In addition, you may want to use a GUI to manage your git repositories. A good example of a free Mac GUI is GitX. Other (non-free) examples include Tower and SourceTree. GitHub have also recently released GitHub for Mac.

    +
    +
    +

    Windows

    +

    Download and install msysGit

    +
    +
    + + +
    +
    +
    +
    +
    + +

    Table Of Contents

    + + +

    Previous topic

    +

    Development workflow

    +

    Next topic

    +

    Configuring git

    +

    This Page

    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/development/workflow/git_resources.html b/development/workflow/git_resources.html new file mode 100644 index 00000000..42ec2219 --- /dev/null +++ b/development/workflow/git_resources.html @@ -0,0 +1,181 @@ + + + + + + + + + Git resources — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Git resources

    +
    +

    Tutorials and summaries

    + +
    +
    +

    Advanced git workflow

    +

    There are many ways of working with git; here are some posts on the +rules of thumb that other projects have come up with:

    +
      +
    • Linus Torvalds on git management
    • +
    • Linus Torvalds on linux git workflow . Summary; use the git tools +to make the history of your edits as clean as possible; merge from +upstream edits as little as possible in branches where you are doing +active development.
    • +
    +
    +
    +

    Manual pages online

    +

    You can get these on your own machine with (e.g) git help push or +(same thing) git push --help, but, for convenience, here are the +online manual pages for some common commands:

    + +
    +
    + + +
    +
    +
    +
    +
    + +

    Table Of Contents

    + + +

    Previous topic

    +

    Configuring git

    +

    Next topic

    +

    Development workflow

    +

    This Page

    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/development/workflow/index.html b/development/workflow/index.html new file mode 100644 index 00000000..0eeaf5ab --- /dev/null +++ b/development/workflow/index.html @@ -0,0 +1,192 @@ + + + + + + + + + Contributing To/Developing Astropy or Affiliated Packages — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Contributing To/Developing Astropy or Affiliated Packages

    +
    +

    Summary

    +

    As described in Vision for a common Astronomy Python package, development of components intended for +inclusion in the core astropy package will initially be done by different +teams via affiliated packages. These affiliated packages will then be +submitted for inclusion in the astropy core package by creating a git fork +of the core repository, merging the new component into the fork, and +submitting the package as a pull request. The step of creating a fork and +merging the affiliated package into the fork can be done either by the team +contributing the affiliated package, or by the coordination committee if +requested.

    +

    Once an affiliated package has been accepted and integrated as a component +into the core astropy package, subsequent improvements and bug fixes can +be made in the same way by forking the core repository and submitting a pull +request.

    +

    The bottom line is that teams working on various components are free to choose +the version control system and workflow that they want, but ultimately the +changes need to be merged into a fork of the core repository and submitted via +a pull request to the core repository, either by the team or by the +coordination committee.

    +
    +
    +

    For the Impatient

    +

    The only absolutely necessary configuration step is identifying yourself and your contact info:

    +
    git config --global user.name "Your Name"
    +git config --global user.email you@yourdomain.example.com
    +
    +

    More detailed information and instructions are below.

    +

    After that, if you then just want to get the latest astropy source code, cd to a directory on your computer you want to put the source code, and do:

    +
    git clone git@github.com:astropy/astropy.git
    +
    +

    You will then have a new copy of the source code in the astropy directory.

    +

    Later, if you want to update to the most recent version of the astropy code, just go do:

    +
    cd astropy
    +git pull
    +
    +

    If you find a bug and want to fix it, see Development Workflow (Beginner) or Development Workflow (Advanced) depending on how comfortable you are with git.

    +
    +
    +

    Git Documentation

    +

    The following sections cover the installation of the git software, the basic configuration, and links to resources to learn more about using git. However, you can also directly go to the GitHub help pages which offer a great introduction to git and GitHub.

    + +
    +
    +

    Workflow

    +

    The following two sections describe the workflow for the astropy core +package, but teams working on affiliated packages that have chosen to use git +are encouraged to also follow these guidelines internally.

    + +
    +
    + + +
    +
    +
    +
    +
    + +

    Table Of Contents

    + + +

    Previous topic

    +

    Vision for a common Astronomy Python package

    +

    Next topic

    +

    Installing git

    +

    This Page

    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/development/workflow/maintainer_workflow.html b/development/workflow/maintainer_workflow.html new file mode 100644 index 00000000..83ff72d4 --- /dev/null +++ b/development/workflow/maintainer_workflow.html @@ -0,0 +1,210 @@ + + + + + + + + + Maintainer workflow — Astropy v0.0.0 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Maintainer workflow

    +

    This page is for maintainers — those of us who merge our own or other +peoples’ changes into the upstream repository.

    +

    Being as how you’re a maintainer, you are completely on top of the basic stuff +in Development workflow.

    + +
    +

    Integrating changes manually

    +

    First, check out the astropy repository. The instructions in Overview add a remote that has read-only +access to the upstream repo. Being a maintainer, you’ve got read-write access.

    +

    It’s good to have your upstream remote have a scary name, to remind you that +it’s a read-write remote:

    +
    git remote add upstream-rw git@github.com:astropy/astropy.git
    +git fetch upstream-rw
    +
    +

    Let’s say you have some changes that need to go into trunk +(upstream-rw/master).

    +

    The changes are in some branch that you are currently on. For example, you are +looking at someone’s changes like this:

    +
    git remote add someone git://github.com/someone/astropy.git
    +git fetch someone
    +git branch cool-feature --track someone/cool-feature
    +git checkout cool-feature
    +
    +

    So now you are on the branch with the changes to be incorporated upstream. The +rest of this section assumes you are on this branch.

    +
    +

    A few commits

    +

    If there are only a few commits, consider rebasing to upstream:

    +
    # Fetch upstream changes
    +git fetch upstream-rw
    +
    +# Rebase
    +git rebase upstream-rw/master
    +
    +

    Remember that, if you do a rebase, and push that, you’ll have to close any +github pull requests manually, because github will not be able to detect the +changes have already been merged.

    +
    +
    +

    A long series of commits

    +

    If there are a longer series of related commits, consider a merge instead:

    +
    git fetch upstream-rw
    +git merge --no-ff upstream-rw/master
    +
    +

    The merge will be detected by github, and should close any related pull +requests automatically.

    +

    Note the --no-ff above. This forces git to make a merge commit, rather +than doing a fast-forward, so that these set of commits branch off trunk then +rejoin the main history with a merge, rather than appearing to have been made +directly on top of trunk.

    +
    +
    +

    Check the history

    +

    Now, in either case, you should check that the history is sensible and you +have the right commits:

    +
    git log --oneline --graph
    +git log -p upstream-rw/master..
    +
    +

    The first line above just shows the history in a compact way, with a text +representation of the history graph. The second line shows the log of commits +excluding those that can be reached from trunk (upstream-rw/master), and +including those that can be reached from current HEAD (implied with the .. +at the end). So, it shows the commits unique to this branch compared to trunk. +The -p option shows the diff for these commits in patch form.

    +
    +
    +

    Push to trunk

    +
    git push upstream-rw my-new-feature:master
    +
    +

    This pushes the my-new-feature branch in this repository to the master +branch in the upstream-rw repository.

    +
    +
    +
    + + +
    +
    +
    +
    +
    + +

    Table Of Contents

    + + +

    Previous topic

    +

    Development Workflow (Advanced)

    +

    Next topic

    +

    Coding Guidelines (Draft 3)

    +

    This Page

    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/genindex.html b/genindex.html index e23062b9..944dfc51 100644 --- a/genindex.html +++ b/genindex.html @@ -7,7 +7,7 @@ - Index — AstroPy v0.0.0 documentation + Index — Astropy v0.0.0 documentation - + + @@ -53,6 +54,9 @@

    Index

    + @@ -79,11 +83,11 @@

    Navigation

  • index
  • -
  • AstroPy v0.0.0 documentation »
  • +
  • Astropy v0.0.0 documentation »
  • diff --git a/index.html b/index.html index 962eb4fe..bd641076 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ - Welcome to AstroPy’s documentation! — AstroPy v0.0.0 documentation + Welcome to Astropy’s documentation! — Astropy v0.0.0 documentation - + + @@ -35,7 +36,7 @@

    Navigation

  • next |
  • -
  • AstroPy v0.0.0 documentation »
  • +
  • Astropy v0.0.0 documentation »
  • @@ -45,14 +46,16 @@

    Navigation

    -

    Welcome to AstroPy’s documentation!

    -

    The current AstroPy documentation is limited. For more information, see the github wiki for the project.

    +

    Welcome to Astropy’s documentation!

    +

    The current AstroPy documentation is limited, as no code has yet been developed. +For more information, see the github wiki page of the project.

    Contents:

    @@ -75,6 +76,9 @@

    Search

    @@ -85,11 +89,11 @@

    Navigation

  • index
  • -
  • AstroPy v0.0.0 documentation »
  • +
  • Astropy v0.0.0 documentation »
  • diff --git a/searchindex.js b/searchindex.js index 475e42ef..0ef27e7e 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{all:[3,1,5],code:[3,0,1,2,5],consider:3,whatev:5,illustr:[3,1],pep:[3,1],signific:[3,1],concept:3,subclass:[3,1],computation:1,follow:[3,2,1,4,5],haggi:3,cython:1,privat:3,depend:[3,1,5],elsewher:3,readabl:3,fft2:3,articl:3,environment:3,present:1,under:3,sens:3,sourc:[3,1],string:3,ndobj_old:3,mpl:[3,1],util:1,print:1,candid:[3,1],mechan:[3,1,5],whether:1,wordpress:1,veri:3,affect:1,relev:[3,1,2],level:5,gui:5,list:[3,4,5],prefix:3,iter:3,team:5,quick:3,set_color:1,prevent:[3,5],impli:3,work:[3,5],natur:3,consistent:1,direct:[3,1,5],second:3,blanklin:3,design:3,pass:1,download:[1,5],further:[3,5],compat:1,index:[0,1],what:[3,1],sub:[3,1],section:[3,1,4],asid:3,abl:[3,5],calcul:1,uniform:5,current:[3,0,1,4,5],"public":[3,1],abbrevi:3,version:[3,1],"new":[3,1,5],ever:5,method:[3,1,5],metadata:1,submodule1:1,submodule2:1,whose:3,gener:[3,1,5],never:[1,5],decid:5,matplotlib:[3,1,5],satisfi:5,let:1,path:[3,1],safer:1,becom:3,sinc:1,valu:[3,1,5],wait:5,convert:3,larger:3,precis:3,doctest:3,awastropi:1,chang:[3,1,4],fourier:3,chanc:3,ourselv:3,via:[1,5],regardless:1,packagenam:1,danger:1,appli:1,modul:[3,0,1,4],prefer:3,submodul:1,backtick:3,deprec:3,api:3,visibl:3,instal:[1,5],unit:1,plot:3,from:[3,1,5],describ:[3,1,4],would:[3,1,5],commun:5,doubl:3,regist:1,two:3,next:1,few:[3,1,5],call:1,recommend:[3,1,4],simpler:1,type:3,until:5,more:[3,0,1,5],sort:3,desir:5,relat:3,pylint:3,about:[3,1],enhanc:1,warn:[3,1,4],exce:1,templat:[3,1,5],particular:[3,1],known:3,set_valu:1,must:[3,1,5],augment:3,setup:1,outlin:[3,1],paragraph:3,can:[3,1,5],imped:1,meet:1,root:1,def:[3,1],explor:3,give:[3,1],process:[3,1,5],accept:1,tab:1,unus:1,alwai:[1,5],scalar:3,multipl:3,goal:[3,5],quot:3,rather:[3,1,5],anoth:3,write:3,how:[3,5],anyon:2,"__init__":[3,1],pure:1,answer:3,instead:[3,1],config:[3,1],get_color:1,updat:1,astropi:[3,0,1,4,2],outsid:[1,5],referenc:3,keithdeven:1,after:3,"long":1,befor:[3,1,5],date:3,underscor:3,data:[3,1],grow:5,"short":[3,1],practic:5,vicin:3,array_lik:3,spectra:5,produc:3,inform:[3,0,2],preced:3,combin:3,incorpor:3,order:[3,1,5],mcnoleg:3,origin:3,help:[3,5],rhetting:1,over:[3,1,5],move:1,becaus:[3,1,5],typewrit:3,whilst:3,through:3,hierarchi:1,still:[3,1],paramet:3,style:[3,1,5],get_valu:1,fit:5,fix:3,comprehend:3,resort:3,html:1,persist:1,mail:4,main:5,might:1,pixel:3,them:[3,5],good:3,"return":3,thei:[3,1,5],python:[3,0,1,2,5],sentenc:3,supersed:3,initi:5,underneath:3,mention:3,facilit:[3,5],discuss:[3,4],strive:5,choic:5,document:[0,1,2,3,4,5],name:[3,1],anyth:1,edit:3,photometri:5,linspac:1,separ:3,astronom:5,achiev:5,exampl:[3,1,5],each:[3,1],found:3,complet:1,mean:[3,5],compil:1,pacakg:3,hard:3,continu:5,procedur:5,mar:1,expect:1,our:3,orient:3,special:[3,5],out:[1,5],variabl:[3,1],shown:3,ndobj_new:3,network:3,space:[3,1],goe:1,crucial:1,content:[3,0],laid:1,adapt:[3,5],rel:[3,1],reader:3,sparingli:3,correct:1,math:3,integr:[3,1,5],clarifi:3,insid:3,situat:3,given:[3,1],standard:[3,1,4,5],standalon:5,reason:3,theori:3,put:3,org:[3,1],care:3,indent:[3,1],could:5,keep:[3,5],length:3,place:1,circuit:1,principl:3,confus:[3,1],assign:3,first:[3,5],oper:1,directli:[1,5],onc:[1,5],arrai:[3,1],independ:5,qualiti:5,number:[3,5],mai:[3,1,5],alreadi:[1,5],done:5,submit:5,blank:3,oppos:1,stabl:5,voidspac:1,size:1,differ:[3,5],set_:1,convent:[3,1],script:[1,5],associ:[3,1],licens:3,system:[3,1,5],least:3,checker:[3,1],underlin:3,draft:[3,0,1,4,2],similarli:1,termin:3,instanc:[3,1],cite:3,store:1,prone:1,adher:1,option:3,courier:3,especi:3,namespac:1,fuzzi:3,tool:[3,1,5],copi:3,specifi:[3,1],getter:1,enclos:3,exactli:[3,5],than:[3,1,5],serv:4,keyword:3,whenev:5,clariti:1,remov:3,tree:[3,5],structur:3,charact:3,project:[3,0,1],stall:5,str:3,mathtt:3,thu:[1,5],pre:3,comput:3,viewer:3,thereaft:5,pro:1,mind:3,ani:[3,5],packag:[0,1,2,3,4,5],manner:1,have:[3,1,5],tabl:[3,0,5],need:[3,1,5],seek:5,squar:3,equival:3,self:[3,1],note:[3,1],mix:1,builtin:1,discret:3,take:3,indic:[3,0],tupl:3,techniqu:3,subject:[3,1,4],brace:3,singl:[3,5],pyx:1,simplifi:1,begin:3,regard:[3,1],unless:[1,5],distribut:1,shall:3,track:5,who:5,reach:5,discov:3,most:3,render:3,phase:5,alpha:3,subset:3,judici:3,why:1,appear:3,latex:3,"__all__":[3,1],doc:3,clear:3,later:5,request:[1,5],doe:3,part:[3,5],pyplot:[3,1],introspect:3,show:1,carefulli:3,text:3,random:3,radiu:3,syntax:[3,1],particularli:3,font:3,setter:1,absolut:1,onli:[3,1,5],explicitli:[3,1],locat:[3,5],modnam:1,merger:1,explain:3,configur:[3,1],solut:1,written:[3,1],should:[3,1,5],dict:3,rich:3,meant:3,fft:3,contribut:2,get:[3,1],between:[3,1,5],pypi:[1,5],obviou:3,cannot:[1,5],increas:5,tbd:1,requir:[3,1,5],layout:[1,5],bar:1,organ:5,coord:3,patch:5,provid:[3,1,5],bad:1,common:[3,0,2,5],contain:[3,1,5],where:[3,1,5],seamlessli:5,vision:[0,2,5],summari:3,wiki:0,set:[3,1,5],see:[3,0,1],result:3,reserv:1,best:5,concern:5,awar:3,extend:3,expert:3,state:3,simplest:1,"import":[3,1,5],approach:1,across:5,attribut:[3,1],altern:1,signatur:3,kei:5,fk5_to_gal:3,contort:3,func_c_:3,extens:[3,1],entir:[3,5],here:[3,1],func_d:3,func_a:3,addit:[3,1,5],both:[3,1],easi:[3,5],howev:[3,1],numpydoc:3,etc:[3,5],tutori:3,equat:3,committe:[1,5],logic:3,mani:[3,1,5],highland:3,com:1,con:1,comment:3,simpli:[3,1],consolid:5,point:[3,1],color:1,guidelin:[0,1,2,3,4,5],header:3,"5e9":1,sky2pix:3,framework:[3,4,5],respect:3,geoscienc:3,assum:[3,1],summar:5,duplic:[3,5],ultim:5,strong:5,platform:3,addition:1,numpi:[3,1,5],due:1,been:[3,1],github:[3,0],compon:[1,5],much:5,interest:[3,2],basic:3,func_b:3,"__doc__":3,imag:3,search:[3,0],argument:3,coordin:[3,1,5],understand:3,togeth:5,summat:3,those:[3,5],"case":[3,1,5],multi:3,look:3,properti:[3,1],aim:5,defin:[3,1],"while":3,abov:3,error:3,pix2ski:3,krige:3,vol:3,site:3,activ:5,scipi:[3,1,5],motiv:3,get_:1,sever:3,develop:[0,1,2,5],welcom:0,author:3,perform:1,make:[3,1,5],belong:3,same:3,handl:3,lengthi:1,complex:[1,5],eventu:5,higher:5,competit:5,archiv:1,context:3,assist:3,upon:5,effect:1,remot:3,rais:3,temporari:3,user:[3,5],improv:1,extern:[3,1],robust:5,wherev:1,typic:3,built:3,task:[3,5],kept:3,discourag:[3,1,5],neural:3,markup:3,well:3,hypothet:3,inherit:1,non:3,pep8:[3,1],weblog:1,without:3,expens:1,thi:[3,1,4,5],everyth:5,latter:3,usual:3,explan:3,identifi:5,execut:3,less:1,when:[3,1],obtain:3,rest:3,shape:3,human:3,yet:3,sugget:1,web:3,expos:3,also:[3,4,5],sky:3,except:[3,1],add:3,spread:3,overview:3,input:3,transit:5,match:3,build:[3,5],real:3,applic:3,which:[3,1,5],format:[3,1,4],read:[3,1],consensu:5,invalidwcsexcept:3,background:3,world:3,tick:3,aclass:1,like:[3,1],specif:[3,1],filenam:3,docutil:3,manual:3,benefit:5,necessari:[3,1],either:[1,5],leftrightarrow:3,output:3,page:[3,0,2],www:1,often:[3,1],habitat:3,ascend:3,back:3,sampl:1,flatten:1,proper:1,star:1,librari:[1,5],affili:[3,1,4,5],guid:[3,1],avoid:[3,1,5],normal:3,definit:3,per:1,mathemat:3,larg:3,sequenc:3,toolkit:5,condit:3,foo:1,notabl:3,refer:[3,5],core:[3,1,4,5],encourag:[3,1,5],object:[3,1],run:3,bold:3,clutter:3,view:3,usag:[3,1],dtype:3,sacrif:3,funcnam:1,host:1,great:3,repositori:[1,5],immut:3,"super":1,plt:[3,1],stone:5,central:[3,5],column:3,toolchain:3,preclud:5,http:[3,1],surround:3,func_:3,constructor:3,commit:5,compute_color:1,upward:3,processor:3,routin:3,own:[3,5],emphasi:3,primarili:[1,5],convolut:3,"float":3,appropri:3,randomize_posit:3,empti:3,ensur:[1,5],mark:3,inclus:5,wai:3,area:5,support:[1,5],question:3,transform:3,fast:3,pyflak:3,avail:[3,1,5],start:[3,5],reli:5,interfac:[1,5],includ:[3,1,5],replac:3,"var":3,"function":[3,1,5],form:[3,1,4,5],enough:5,agre:5,some:[3,5],bundl:1,criteria:5,line:3,inlin:3,"true":3,bug:[3,1],conclus:3,info:[3,1],pull:5,tripl:3,made:[1,5],algorithm:3,consist:[3,1,5],possibl:[3,1,5],"default":[3,5],wish:5,access:[1,5],displai:3,below:[3,1],limit:[3,0,1],sum:3,configobj:1,model:3,constant:3,creat:1,"int":3,dure:5,doesn:1,repres:3,strongli:[3,1],implement:[3,1,5],file:[3,1],exist:[1,5],typeset:3,check:3,fill:4,allow:[3,1,5],"2to3":1,detail:3,invalid:3,other:[3,1,5],bool:3,futur:5,test:[0,1,2,3,4,5],you:[3,1],nice:3,intend:5,ital:3,"class":[3,1,5],astronomi:[0,2,5],docstr:[3,1],ndarrai:3,brief:3,releas:5,consid:[1,5],throughout:3,omega:3,deserv:3,reduc:5,infrequ:3,sphinx:3,furthermor:3,directori:3,descript:3,rule:[3,1],itself:5,potenti:5,time:[3,5]},objtypes:{},titles:["Welcome to AstroPy’s documentation!","Coding Guidelines (Draft 2)","Documentation for Developers","Documentation Guidelines (Draft 2)","Testing Guidelines (Draft)","Vision for a common Astronomy Python package"],objnames:{},filenames:["index","development/codeguide","development/index","development/docguide","development/testguide","development/vision"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{scm:14,represent:[12,4],all:[2,5,6,9,12,13,11],code:[1,2,5,3,6,9,10,12,13,11],consider:5,osx:14,illustr:[5,2],pep:[5,2],global:[10,6,9,13],yellow:13,signific:[5,2],concept:[0,5],per:2,computation:2,follow:[2,7,4,5,6,3,8,9,10,12,13,11],alt:6,haggi:5,compact:4,cython:2,privat:5,complet:[2,4],depend:[5,2,11,10],system:[5,11,2,6,10],graph:[12,4,13],elsewher:5,readabl:[5,12],pycodecheck:6,fft2:5,articl:5,environment:5,messi:[12,4],init:6,present:[12,2,6],under:5,sens:5,save:[12,6,13],messag:[12,6,9],adapt:[5,11,14],"case":[5,11,2,12,4],file:[2,5,6,9,12,13],sourc:[5,2,10],string:5,ndobj_old:5,fals:12,mpl:[5,2],util:2,print:2,candid:5,mechan:[5,2,11],upstream:[0,12,4,13],veri:[5,12,13],affect:[2,12],relev:[5,2,3],method:[5,2,11],cool:[12,4],magic:0,when:[2,5,6,9,12,13],level:[11,6],did:12,notabl:5,flymak:6,list:[5,7,6,9,12,11],prefix:5,iter:5,"try":12,red:6,team:[10,11],quick:[5,9],set_color:2,refer:[5,11,12],overview:[5,12,9,4,13],pleas:[12,9],prevent:[5,11,13],impli:[5,4],smaller:6,abil:12,natur:5,consistent:2,direct:[5,2,11],meld:12,maintain:[10,12,4],jump:6,second:[5,4],blanklin:5,design:5,pass:2,download:[6,2,11,14],further:[5,2,11],click:12,compat:2,index:[1,2],what:[5,2,12],msysgit:14,sub:[5,2],compar:4,defin:[5,2],infrequ:5,section:[2,4,5,7,6,10,12,13],asid:5,abl:[5,11,4,13],brief:5,uniform:11,access:[11,2,12,9,4],delet:[12,6],abbrevi:5,version:[5,2,12,10],"new":[2,4,5,6,10,9,12,11],setter:2,ever:11,"public":[5,2,12],nep:12,metadata:2,submodule1:2,submodule2:2,dropdown:12,gener:[5,11,2,12,9],never:[2,11],decid:11,matplotlib:[5,2,11],instanc:[5,2,12],satisfi:[11,6],explicitli:[5,2],let:[12,2,6,4],cursor:6,agre:11,trunk:[12,4],path:[5,2,6],safer:2,becom:5,modifi:12,sinc:[12,2,6,9],valu:[5,11,2,6],wait:11,convert:[5,13],produc:5,ahead:12,larger:5,host:[2,8],scari:4,precis:5,doctest:5,pick:12,action:12,awastropi:2,implement:[5,11,2,12],fourier:5,chanc:5,ourselv:5,via:[11,2,12,10,4],repositori:[10,4,11,8,2,9,12,14],packagenam:2,danger:2,dtype:5,modul:[5,1,2,7],prefer:[5,12],submodul:2,backtick:5,vim:13,deprec:5,api:[5,13],send:9,visibl:5,marker:6,instal:[10,6,8,2,11,12,14],should:[2,4,5,12,13,11],unit:[2,13],sky:5,plot:5,from:[0,2,4,5,11,6,9,12,13,14],describ:[2,5,8,7,6,10],would:[5,11,2,12],commun:[0,11],fill:[7,6],doubl:5,regist:2,two:[5,10],subvers:0,websit:6,few:[5,11,2,12,4],call:[2,12,13],typo:12,recommend:[5,2,7,4],black:6,jonathan:13,type:[5,12,6,9],until:11,more:[1,2,5,9,10,12,11],sort:5,desir:11,henc:6,relat:[5,2,12,4],pylint:5,about:[5,2,12,9,10],notic:12,enhanc:2,warn:[5,2,7],trail:6,flag:[12,9],exce:2,templat:[5,2,11],particular:[5,2,12],known:5,set_valu:2,easiest:[14,9],must:[5,11,2,6],fly:12,"_flymak":6,account:12,graphic:12,word:[12,6,13],augment:5,alia:[12,13],setup:[2,6],outlin:[5,2],uniqu:4,histori:[0,12,4],remain:12,paragraph:5,can:[0,2,4,5,6,8,9,10,11,12,13,14],learn:[0,10],imped:2,webster:13,purpos:12,root:2,fetch:[12,4],def:[5,2],appropri:5,control:[10,12],backspac:6,explor:[5,12],"65af65":13,give:[0,5,2,12,13],process:[5,2,11],lock:6,sudo:14,share:12,calcul:2,indic:[5,1],abort:12,tab:[2,6],onlin:0,standard:[5,2,7,11],spc:6,unus:2,delai:6,alwai:[2,11],scalar:5,cours:[0,13],multipl:[5,6],goal:[5,11],quot:5,pycheck:6,anoth:[5,12,13],comfort:10,length:5,invalidwcsexcept:5,aclass:2,snippet:0,how:[0,10,4,5,8,9,12,11],anyon:[3,12],recoveri:12,pure:2,"__all__":[5,2],answer:5,instead:[5,2,6,9,4],config:[0,2,5,9,10,13],get_color:2,updat:[2,12,10,13],mar:2,resourc:[0,2,10],circuit:2,referenc:5,mess:12,keithdeven:2,clone:[0,10,12,9],after:[5,12,10,6],minimum:13,"956fbab":13,befor:[2,4,5,8,12,11],wrong:12,attent:12,commit:[0,4,9,12,13,11],mai:[2,5,14,12,13,11],end:[12,6,4],underscor:5,associ:[5,2],grow:11,harmon:12,mous:6,"short":[5,2,12],practic:[11,13],vicin:5,array_lik:5,read:[0,5,2,12,4],confus:[5,2,12],spectra:11,buxfix:12,corran:13,assign:5,caus:6,enh:12,geoscienc:5,preced:5,combin:[5,12],allow:[5,12,2,11,6],enter:12,lambda:6,order:[5,2,11],mcnoleg:5,excurs:6,hugo:13,help:[0,2,5,6,10,12,11],rhetting:2,over:[5,2,11],move:[2,9],becaus:[5,11,2,12,4],kbd:6,typewrit:5,whilst:5,through:5,same:[0,5,10,12],left:12,hierarchi:2,still:[5,2,12],pointer:6,e701:6,paramet:5,"2_installing_git":14,write:[5,12,6,4,13],style:[5,2,11],outer:13,get_valu:2,fit:11,matthew:13,chosen:10,invalid:5,fix:[5,10,12,9,13],sourcetre:14,better:[12,9],resort:5,window:14,html:[2,14],wordpress:2,persist:2,bin:6,mail:[7,12,9],main:[11,12,9,4],might:[2,12,13],pixel:5,them:[5,11,12,9],scipi:[5,2,11],crash:[0,6],thei:[5,11,2,12,10],python:[1,2,5,3,6,10,11],auto:6,supersed:5,alist:6,initi:[10,11,13],underneath:5,mention:5,facilit:[5,11],now:[12,9,4,13],discuss:[5,7,13],oper:2,introduct:[0,10],choic:[11,13],document:[1,2,3,5,6,7,8,10,12,13,11],somewher:9,name:[2,4,5,6,10,9,12,13],anyth:[2,12,9],edit:[0,5,12,9,13],simpl:9,wdiff:13,refresh:6,linspac:2,separ:[5,12,6],astronom:11,achiev:[11,12],alreadi:[11,2,12,9,4],mode:[6,9],each:[5,2,12],"29001ed":12,found:5,went:12,collaps:[12,6],button:12,mean:[5,11,12],compil:2,inplac:6,"6ad92e5":12,replac:[5,6,13],individu:6,hard:[5,12],continu:11,procedur:11,realli:4,tip:[0,2,6],astropi:[1,2,3,4,5,6,7,8,9,10,12],expect:2,forgot:12,our:[5,12,4],thing:[0,12,9],orient:5,special:[5,11],out:[2,11,9,4],variabl:[5,2,6],shown:[5,6,8],voidspac:2,network:[5,12],space:[5,2,6],goe:2,b605216:13,crucial:2,"4aff2a8":13,identifi:[10,11,13],your:[0,10,4,9,12,13,14],content:[5,1,6,13],rewrit:12,laid:2,reflog:12,rel:[5,12,2,6,13],reader:5,sparingli:5,got:[12,4],current:[1,2,4,5,7,6,12,13,11],ref:12,correct:2,math:5,integr:[5,2,11,10,4],clarifi:5,linear:12,insid:5,workflow:[0,10,4,8,9,12],brett:13,situat:[5,12],given:[5,2,12],free:[10,14],test_bugfix:13,standalon:11,reason:[5,12,6,4],base:12,modnam:2,theori:5,usual:[5,12],put:[5,10],embarrass:12,new_file_nam:12,bash:6,care:5,indent:[5,2,6],unwant:12,could:11,ask:12,mac:14,advanc:[0,12,10,8,9],keep:[5,11,12],recov:12,turn:[12,6],perhap:12,enforc:13,place:[2,6],outsid:[2,11],enough:11,principl:5,onto:12,interact:[12,6],first:[5,11,12,4],origin:[5,12,13],softwar:10,suffix:6,directli:[2,4,10,12,13,11],onc:[11,2,12,10,13],arrai:[5,2,13],independ:11,qualiti:11,number:[5,11,6],yourself:[10,12,13],hook:6,instruct:[12,14,10,8,4],"68f6752":13,done:[10,4,9,12,13,11],fast:[5,4],blank:[5,6],oppos:2,stabl:11,ndobj_new:5,open:12,"long":[2,4],fanci:[12,13],size:2,"7beda5a":13,differ:[5,11,10,6],set_:2,reword:12,convent:[5,2],script:[11,2,6],data:[5,2,13],top:[12,4],sometim:[12,6],least:5,checker:[5,2],underlin:5,draft:[1,2,3,5,7,6],accept:[2,10],similarli:2,termin:5,white:6,man:12,cite:5,store:2,prone:2,adher:2,luckili:12,option:[2,4,5,6,9,12],courier:5,especi:5,namespac:2,fuzzi:5,tool:[0,5,2,11,6],copi:[10,5,6,9,12,13],specifi:[5,2,6],"var":5,yuri:13,getter:2,enclos:5,checkout:[0,12,9,4,13],kept:5,exactli:[5,11],haven:9,progn:6,serv:7,succinctli:12,conveni:0,tangl:12,keyword:5,whenev:[11,4],clariti:2,remov:[5,12,6],branchnam:12,tree:[5,11],see:[1,2,5,9,10,12],structur:5,charact:[5,6],project:[0,1,2,12,5],apt:14,stall:11,str:5,posit:6,video:0,minut:13,other:[0,2,4,5,11,12,14],mathtt:5,beginn:[10,8,9],seri:[0,4],pre:[5,12],mini:6,sai:[12,4],comput:[5,10,12,13],abov:[5,12,4,13],summar:11,"26aa21a":12,viewer:5,thereaft:11,pro:[0,2],mind:5,ani:[4,5,9,12,13,11],packag:[1,2,3,5,7,8,10,12,11],clutter:5,manner:2,have:[0,2,4,5,11,8,9,10,12,14],propos:13,need:[2,4,5,6,10,12,13,11],exclud:4,seek:11,normal:5,issu:12,date:[5,13],squar:5,equival:5,inform:[5,1,10,3,12],self:[5,2],"switch":[12,9],port:14,note:[2,4,5,6,9,12,13],mix:2,builtin:2,discret:5,take:[5,12,9],advis:12,tupl:5,techniqu:5,subject:[5,2,7],brace:5,bundl:2,singl:[5,11,12],expens:2,pyx:2,simplifi:2,begin:5,sure:[6,8,4,13],unless:[2,11,13],distribut:2,preliminari:12,buffer:6,githhub:12,previou:[12,6],reach:[11,4],discov:[5,9],most:[5,10,12],render:5,larg:5,phase:11,alpha:5,subset:5,judici:5,everyth:[11,12],appear:[5,4],latex:5,wish:11,don:[12,6,9],expert:5,consist:[5,2,11],url:12,doc:5,clear:5,later:[10,11],cover:10,doe:5,abbrev:13,part:[5,11],yum:14,clean:0,warmli:9,hardcor:12,latest:10,pyplot:[5,2],tear:12,introspect:5,show:[12,2,6,4],joshu:13,text:[5,12,6,4,13],random:5,radiu:5,syntax:[5,2,6],connect:12,bring:[12,6],fink:14,you:[0,2,4,5,8,9,10,12,13,14],particularli:5,hack:[12,9],inherit:2,font:[5,6],find:[10,12,9],"0f22701":12,absolut:[2,10,13],onli:[2,4,5,6,10,9,12,13,11],maskedconst:12,locat:[5,11],execut:[5,6],pretti:13,plt:[5,2],menu:[12,6],explain:[0,5,12,9],configur:[2,5,8,6,9,10,12,13],solut:2,written:[5,2,12],than:[2,4,5,9,12,11],dict:5,rich:5,local:[12,6],creset:13,meant:5,info:[5,2,10,13],"6d8e1e":13,contribut:[12,1,10,3,8],variou:10,satisfact:12,between:[5,2,11],pypi:[2,11],func_b:5,autoload:6,repo:[12,4],obviou:5,cannot:[2,11],ssh:12,cheat:0,"import":[5,2,11],increas:11,tbd:2,requir:[5,11,2,6],layout:[2,11],think:[12,9],bar:2,enabl:6,organ:[11,12],typeset:5,parabl:0,specif:[5,12,2,6],coord:5,patch:[11,9,4],provid:[5,11,2,6],bad:2,stuff:[12,4],common:[0,1,10,5,3,13,11],contain:[5,2,11,4,13],"376adbd":13,where:[0,2,5,6,9,12,11],seamlessli:11,vision:[1,10,3,11],summari:[0,5,10,12,13],wiki:1,conform:2,reduc:[11,12],set:[2,4,5,6,9,12,13,11],detail:[0,10,5,9,12,13],respect:[5,8],placehold:13,maximum:6,index_bi:13,emac:[2,6],bare:13,result:[5,6],reserv:2,close:[12,4],zaytsev:13,best:[11,9],concern:11,awar:5,statu:[0,12,9,13],detect:4,kei:[12,11,6],correctli:[12,8],databas:12,someth:[12,9,13],thumb:0,"278dd2a":12,hhuuggoo:13,state:[5,12],quickest:9,simplest:[2,9,13],progress:[12,9],awai:12,approach:2,across:11,attribut:[5,2],altern:2,signatur:5,unmodifi:9,terhorst:13,extend:[0,5],exampl:[2,4,5,6,8,9,10,11,12,13,14],fk5_to_gal:5,contort:5,sophist:12,copul:12,extens:[5,2],entir:[5,11],here:[0,2,5,8,9,12,13,14],recent:[10,14],highlight:6,ipython:12,func_d:5,come:[0,12,6],thank:[9,13],func_c_:5,sketchi:13,accident:12,last:12,easi:[0,5,11],impliment:13,admin:12,similar:12,howev:[5,2,12,10],hint:2,equal:[8,13],etc:[5,11,4],tutori:[0,5],equat:5,committe:[2,11,10],logic:5,mani:[0,5,2,11],highland:5,com:[10,4,2,9,12,13,14],con:[2,6],load:6,simpli:[5,2,14],consolid:11,technic:0,point:[5,2,12],color:[2,13],guidelin:[1,2,3,5,7,6,10,11],format:[5,2,7,9,13],ubuntu:14,gitk:12,header:5,"5e9":2,sky2pix:5,framework:[5,7,11],linux:[0,12],diff:[0,12,4,13],comprehend:5,gitx:14,e221:6,simpler:2,duplic:[5,11],sever:[5,6,14,9,12],quit:12,ultim:[10,11],strong:11,why:[2,12,9],platform:5,addition:2,func_a:5,numpi:[5,2,11],three:12,been:[1,2,4,5,10,12],mark:[5,6],compon:[2,11,10],much:[11,12],autofil:6,interpret:6,interest:[5,3],basic:[5,10,6,4],addit:[5,6,2,11,14],"__doc__":5,rather:[5,11,2,12,4],both:[5,2],imag:5,star:2,search:[5,1],argument:5,deliber:12,coordin:[5,2,11,10],understand:5,togeth:11,input:5,summat:5,impati:[10,9],those:[0,5,11,12,4],blue:13,sound:12,multi:5,onelin:[12,4],look:[5,12,4],amend:12,cred:13,also:[10,5,11,7,6,12,13,14],properti:[5,2],easier:12,aim:11,cast:0,"while":[5,12],my_new_fil:12,behavior:13,error:5,pix2ski:5,region:6,rebas:[12,4],stop:[12,6],krige:5,vol:5,made:[10,4,2,9,12,13,11],tabl:[5,1,11],readm:12,site:5,worri:12,numpydoc:5,"2dec1ac":12,pip:6,good:[0,4,5,12,13,14],motiv:5,get_:2,"return":[5,9],revis:12,"__init__":[5,2],around:6,disabl:12,develop:[0,1,2,4,10,3,8,9,12,11],welcom:1,author:5,perform:2,suggest:12,make:[0,2,4,5,6,8,9,12,13,11],belong:5,shorten:13,defun:6,who:[11,9,4,13],funni:9,lengthi:2,complex:[2,11],gui:[11,14],sentenc:5,fedora:14,eventu:11,start:[5,11,12],conflict:12,higher:11,week:13,competit:11,finish:[12,9],archiv:2,context:[5,6],nil:6,pyflak:[5,6],assist:5,upon:11,someon:[12,4],remot:[0,5,12,4,13],rais:5,temporari:5,user:[0,10,5,9,12,13,11],improv:[2,10],extern:[5,2],robust:[2,11],wherev:2,typic:5,expand:0,built:5,safe:9,task:[5,11,12],off:4,lib:12,discourag:[5,2,11],neural:5,incorpor:[5,4],markup:5,happi:12,well:[5,12,8,13],hypothet:5,object:[5,2,12,13],without:[5,12],thought:12,person:13,weblog:2,contact:[10,13],command:[0,12,6,9,13],setq:6,thi:[2,4,5,8,7,6,9,12,13,11],choos:[10,12],gzip:12,strive:11,latter:5,meet:2,explan:[5,12],comment:5,itself:11,protocol:12,paus:12,just:[12,10,6,9,4],less:2,excel:[0,9],obtain:[5,6],rest:[5,12,6,4,13],activ:[0,11],collabor:12,shape:5,pep8:[5,2,6],spread:5,human:5,behind:0,yet:[5,1],sugget:2,web:[5,4],detach:12,expos:5,botch:12,preclud:11,had:12,except:[5,2,13],littl:[0,12],add:[0,4,5,6,9,12,13],macport:14,"2e991e8":13,appli:12,effect:2,els:[12,9],ufunc:13,subsequ:10,transit:11,match:5,build:[5,11],real:5,applic:5,torvald:0,"11ee694744f2552d":12,which:[2,5,6,10,12,13,11],whatev:11,mayb:12,handl:[5,12],foundat:0,regard:[5,2],consensu:11,suppos:12,alias:13,know:12,background:[5,6],press:6,world:5,tick:5,non:[5,14,13],licens:[5,2],review:12,sternli:12,insert:[12,6],fixup:12,like:[5,2,12,4,13],lost:12,whitespac:6,"721fc64":12,d304a73:13,signal:[12,9],arbitrari:12,manual:[0,5,6,4,12],fernando:0,collect:12,benefit:[11,13],necessari:[5,2,9,10,13],eadc391:12,docutil:5,leftrightarrow:5,output:[5,12,13],tower:14,manag:[0,14,4],www:2,drop:6,often:[5,2,12],habitat:5,ascend:5,back:[5,12,9],resolv:12,intern:[10,8],a7ff2e5:13,sampl:2,flatten:2,mask:[12,6],mistak:12,proper:2,home:[12,13],successfulli:12,librari:[11,2,6],tmp:12,thu:[2,11],guid:[0,5,2,12],remind:[12,4],assum:[5,2,4],avoid:[5,11,2,12],shall:5,definit:5,subclass:[5,2],get:[0,2,5,6,9,10,12,13,14],track:[11,4,13],mathemat:5,leav:9,select:12,sequenc:5,toolkit:11,condit:5,foo:[2,12],complic:12,either:[2,11,10,4],machin:0,core:[2,5,11,7,8,10,12,13,14],encourag:[5,2,11,10],sensibl:[12,4],run:[5,6,13],bold:[5,13],whose:5,view:5,usag:[5,2],sacrif:5,funcnam:2,step:[10,12,13],great:[5,10],ndarrai:5,corr:13,offset:6,meantim:12,immut:5,post:[0,13],"super":2,"throw":13,stage:12,fft:5,faith:[12,9],stone:11,photometri:11,central:[5,11],column:[5,6],toolchain:5,structured_array_extens:12,http:[5,12,2,14],label:[9,13],surround:5,page:[0,1,10,4,5,3,8,12],includ:[2,4,5,14,12,11],constructor:5,discard:12,compute_color:2,upward:5,backup:12,processor:5,routin:5,own:[0,5,11,12,4],emphasi:5,"final":[12,9],primarili:[2,11],convolut:5,"float":5,easy_instal:6,automat:[6,4],due:2,down:12,maco:14,randomize_posit:5,replai:12,master:[12,9,4,13],empti:[5,6],ensur:[12,2,11,6],chang:[2,4,5,7,10,9,12,13],test_my_bug:9,sheet:0,merg:[0,10,12,4,13],straightforward:12,inclus:[10,11],git:[0,10,4,8,9,12,13,14],axisindex:13,log:[0,12,4,13],wai:[0,10,4,5,6,9,12,13,14],area:11,support:[2,11],question:5,transform:5,submit:[10,11],custom:13,avail:[5,2,11],stuck:12,reli:11,gitconfig:13,interfac:[2,11,4],editor:[12,13],address:13,pacakg:5,forward:4,yourdomain:[10,9,13],rejoin:4,"function":[5,2,11],svn:0,head:[12,4,13],seek_gzip_factori:12,form:[2,4,5,7,6,11],offer:10,forc:4,poster:12,linu:0,criteria:11,github:[0,1,10,4,5,8,9,12,14],tidi:4,link:[0,10,12],branch:[0,12,9,4,13],line:[10,4,5,6,9,12,13],inlin:5,"true":[5,6,13],bug:[2,5,9,10,12,13],conclus:5,reset:12,pull:[0,10,4,12,13,11],tripl:5,immedi:12,algorithm:5,temp:6,possibl:[0,2,4,5,12,11],"default":[5,12,11,6],bugfix:12,displai:[5,6],strang:12,tell:[12,9,13],work:[0,10,5,6,8,9,12,11],below:[5,2,6,10],limit:[5,1,2],time:[5,11,12],sum:5,otherwis:12,problem:12,even:[12,9],email:[10,9,13],a815645:12,configobj:2,model:5,featur:[12,9,4,13],constant:5,creat:[12,2,6,10,13],"int":5,request:[2,4,10,12,13,11],dure:[11,12,13],mirror:12,filenam:5,doesn:[2,12],repres:[5,12],strongli:[5,2],e202:6,right:[12,4,13],carefulli:5,some:[0,2,4,5,6,9,12,13,11],perez:0,exist:[2,11],face:6,check:[5,12,6,9,4],probabl:9,again:[12,13],readi:[0,12],want:[12,10,14,9,13],titl:12,"2to3":2,depth:0,refactor:12,book:[0,14],bool:5,futur:11,rememb:[12,4],peopl:[12,4],test:[1,2,3,5,7,9,12,13,11],func_:5,intermedi:0,nice:[0,5,9,13],fork:[10,12,4],stat:13,repeat:[12,6],intend:[10,11],colon:12,affili:[1,2,3,5,7,8,10,11],actual:[12,13],ital:5,org:[5,2],astronomi:[1,10,3,11],docstr:[5,2],cgreen:13,squash:12,"class":[5,2,11],releas:[11,14],consid:[11,2,12,9,4],throughout:5,omega:5,debian:14,deserv:5,ago:13,assert:13,axi:13,sphinx:5,longer:4,furthermor:5,untrack:12,directori:[5,12,10,6,13],bottom:10,descript:[5,12],visual:12,rule:[0,5],"13d7934":12,summit:13,ignor:[6,13],obj:12,potenti:11,leak:12,push:[0,12,4]},objtypes:{},titles:["Git resources","Welcome to Astropy’s documentation!","Coding Guidelines (Draft 3)","Documentation for Developers","Maintainer workflow","Documentation Guidelines (Draft 2)","Emacs setup for following coding guidelines","Testing Guidelines (Draft)","Development workflow","Development Workflow (Beginner)","Contributing To/Developing Astropy or Affiliated Packages","Vision for a common Astronomy Python package","Development Workflow (Advanced)","Configuring git","Installing git"],objnames:{},filenames:["development/workflow/git_resources","index","development/codeguide","development/index","development/workflow/maintainer_workflow","development/docguide","development/codeguide_emacs","development/testguide","development/workflow/development_workflow","development/workflow/development_workflow_basic","development/workflow/index","development/vision","development/workflow/development_workflow_advanced","development/workflow/git_configure","development/workflow/git_install"]}) \ No newline at end of file From cff79aabbfda7364cce5c1a39a378e35ba5e4171 Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 19 Jan 2012 14:05:54 -0800 Subject: [PATCH 09/69] updated to recent docs --- README | 2 +- ...291effbf8fa69d4aad95cc3ac035b2f6726a28.png | Bin 0 -> 49775 bytes ...ffbf8fa69d4aad95cc3ac035b2f6726a28.png.map | 2 + ...4563669cfd1729a6777088d6be9e21c8889310.png | Bin 0 -> 50434 bytes ...669cfd1729a6777088d6be9e21c8889310.png.map | 2 + ...33a0922f5fc94c2076bb1330e6d8bb39cf71c1.png | Bin 0 -> 25253 bytes ...922f5fc94c2076bb1330e6d8bb39cf71c1.png.map | 17 + ...035f78b7760b2f76f4df0f21b8be07cd18e555.png | Bin 0 -> 25502 bytes ...78b7760b2f76f4df0f21b8be07cd18e555.png.map | 17 + _modules/astropy/config/configs.html | 540 +++ _modules/astropy/config/data.html | 760 ++++ _modules/astropy/config/paths.html | 278 ++ _modules/astropy/io/vo/converters.html | 1285 +++++++ _modules/astropy/io/vo/exceptions.html | 1489 ++++++++ _modules/astropy/io/vo/table.html | 340 ++ _modules/astropy/io/vo/tree.html | 3178 +++++++++++++++++ _modules/astropy/io/vo/ucd.html | 296 ++ _modules/astropy/io/vo/unit.html | 164 + _modules/astropy/io/vo/util.html | 326 ++ _modules/astropy/io/vo/validator/main.html | 267 ++ _modules/astropy/io/vo/xmlutil.html | 229 ++ _modules/astropy/tools/misc.html | 211 ++ _modules/astropy/utils/collections.html | 156 + _modules/astropy/utils/console.html | 706 ++++ _modules/astropy/utils/misc.html | 313 ++ _modules/astropy/utils/xml/check.html | 178 + _modules/astropy/utils/xml/iterparser.html | 344 ++ _modules/astropy/utils/xml/validate.html | 153 + _modules/astropy/utils/xml/writer.html | 383 ++ _modules/astropy/wcs.html | 159 + _modules/index.html | 123 + _sources/configs.txt | 100 + _sources/development/building_packaging.txt | 135 + _sources/development/codeguide.txt | 236 +- _sources/development/codeguide_emacs.txt | 2 +- _sources/development/docguide.txt | 35 +- _sources/development/index.txt | 8 +- _sources/development/scripts.txt | 63 + _sources/development/testguide.txt | 442 ++- _sources/development/vision.txt | 104 +- .../development_workflow_advanced.txt | 2 +- _sources/index.txt | 21 +- _sources/install.txt | 111 + _sources/overview.txt | 56 + _sources/tools.txt | 27 + _sources/utils/api_collections.txt | 8 + _sources/utils/api_console.txt | 8 + _sources/utils/api_misc.txt | 8 + _sources/utils/api_xml.txt | 38 + _sources/utils/index.txt | 14 + _sources/vo/api.txt | 30 + _sources/vo/api_converters.txt | 13 + _sources/vo/api_exceptions.txt | 39 + _sources/vo/api_table.txt | 9 + _sources/vo/api_tree.txt | 13 + _sources/vo/api_ucd.txt | 10 + _sources/vo/api_unit.txt | 10 + _sources/vo/api_util.txt | 10 + _sources/vo/api_validator.txt | 11 + _sources/vo/api_xmlutil.txt | 9 + _sources/vo/index.txt | 10 + _sources/vo/intro_table.txt | 282 ++ _sources/wcs/api.txt | 23 + _sources/wcs/api_distortion.txt | 10 + _sources/wcs/api_sip.txt | 10 + _sources/wcs/api_units.txt | 299 ++ _sources/wcs/api_wcs.txt | 14 + _sources/wcs/api_wcsprm.txt | 26 + _sources/wcs/examples.txt | 22 + _sources/wcs/history.txt | 90 + _sources/wcs/index.txt | 31 + _sources/wcs/relax.txt | 365 ++ _static/ajax-loader.gif | Bin 0 -> 673 bytes _static/basic.css | 16 +- _static/comment-bright.png | Bin 0 -> 3500 bytes _static/comment-close.png | Bin 0 -> 3578 bytes _static/comment.png | Bin 0 -> 3445 bytes _static/doctools.js | 10 +- _static/down-pressed.png | Bin 0 -> 368 bytes _static/down.png | Bin 0 -> 363 bytes _static/searchtools.js | 140 +- _static/sidebar.js | 3 + _static/underscore.js | 7 + _static/up-pressed.png | Bin 0 -> 372 bytes _static/up.png | Bin 0 -> 363 bytes _static/websupport.js | 808 +++++ configs.html | 938 +++++ development/building_packaging.html | 280 ++ development/codeguide.html | 285 +- development/codeguide_emacs.html | 69 +- development/docguide.html | 73 +- development/index.html | 63 +- development/scripts.html | 184 + development/testguide.html | 486 ++- development/vision.html | 130 +- .../workflow/development_workflow.html | 31 +- .../development_workflow_advanced.html | 49 +- .../workflow/development_workflow_basic.html | 31 +- development/workflow/git_configure.html | 31 +- development/workflow/git_install.html | 31 +- development/workflow/git_resources.html | 59 +- development/workflow/index.html | 41 +- development/workflow/maintainer_workflow.html | 39 +- genindex.html | 1889 +++++++++- index.html | 99 +- install.html | 245 ++ np-modindex.html | 231 ++ objects.inv | Bin 726 -> 8529 bytes overview.html | 209 ++ py-modindex.html | 231 ++ search.html | 29 +- searchindex.js | 2 +- tools.html | 250 ++ utils/api_collections.html | 203 ++ utils/api_console.html | 545 +++ utils/api_misc.html | 292 ++ utils/api_xml.html | 532 +++ utils/index.html | 155 + vo/api.html | 174 + vo/api_converters.html | 165 + vo/api_exceptions.html | 1034 ++++++ vo/api_table.html | 265 ++ vo/api_tree.html | 1064 ++++++ vo/api_ucd.html | 205 ++ vo/api_unit.html | 149 + vo/api_util.html | 226 ++ vo/api_validator.html | 180 + vo/api_xmlutil.html | 204 ++ vo/index.html | 144 + vo/intro_table.html | 439 +++ wcs/api.html | 196 + wcs/api_distortion.html | 217 ++ wcs/api_sip.html | 335 ++ wcs/api_units.html | 991 +++++ wcs/api_wcs.html | 1065 ++++++ wcs/api_wcsprm.html | 1943 ++++++++++ wcs/examples.html | 240 ++ wcs/history.html | 227 ++ wcs/index.html | 193 + wcs/relax.html | 493 +++ 140 files changed, 33013 insertions(+), 524 deletions(-) create mode 100644 _images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png create mode 100644 _images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png.map create mode 100644 _images/inheritance-c64563669cfd1729a6777088d6be9e21c8889310.png create mode 100644 _images/inheritance-c64563669cfd1729a6777088d6be9e21c8889310.png.map create mode 100644 _images/inheritance-e033a0922f5fc94c2076bb1330e6d8bb39cf71c1.png create mode 100644 _images/inheritance-e033a0922f5fc94c2076bb1330e6d8bb39cf71c1.png.map create mode 100644 _images/inheritance-f7035f78b7760b2f76f4df0f21b8be07cd18e555.png create mode 100644 _images/inheritance-f7035f78b7760b2f76f4df0f21b8be07cd18e555.png.map create mode 100644 _modules/astropy/config/configs.html create mode 100644 _modules/astropy/config/data.html create mode 100644 _modules/astropy/config/paths.html create mode 100644 _modules/astropy/io/vo/converters.html create mode 100644 _modules/astropy/io/vo/exceptions.html create mode 100644 _modules/astropy/io/vo/table.html create mode 100644 _modules/astropy/io/vo/tree.html create mode 100644 _modules/astropy/io/vo/ucd.html create mode 100644 _modules/astropy/io/vo/unit.html create mode 100644 _modules/astropy/io/vo/util.html create mode 100644 _modules/astropy/io/vo/validator/main.html create mode 100644 _modules/astropy/io/vo/xmlutil.html create mode 100644 _modules/astropy/tools/misc.html create mode 100644 _modules/astropy/utils/collections.html create mode 100644 _modules/astropy/utils/console.html create mode 100644 _modules/astropy/utils/misc.html create mode 100644 _modules/astropy/utils/xml/check.html create mode 100644 _modules/astropy/utils/xml/iterparser.html create mode 100644 _modules/astropy/utils/xml/validate.html create mode 100644 _modules/astropy/utils/xml/writer.html create mode 100644 _modules/astropy/wcs.html create mode 100644 _modules/index.html create mode 100644 _sources/configs.txt create mode 100644 _sources/development/building_packaging.txt create mode 100644 _sources/development/scripts.txt create mode 100644 _sources/install.txt create mode 100644 _sources/overview.txt create mode 100644 _sources/tools.txt create mode 100644 _sources/utils/api_collections.txt create mode 100644 _sources/utils/api_console.txt create mode 100644 _sources/utils/api_misc.txt create mode 100644 _sources/utils/api_xml.txt create mode 100644 _sources/utils/index.txt create mode 100644 _sources/vo/api.txt create mode 100644 _sources/vo/api_converters.txt create mode 100644 _sources/vo/api_exceptions.txt create mode 100644 _sources/vo/api_table.txt create mode 100644 _sources/vo/api_tree.txt create mode 100644 _sources/vo/api_ucd.txt create mode 100644 _sources/vo/api_unit.txt create mode 100644 _sources/vo/api_util.txt create mode 100644 _sources/vo/api_validator.txt create mode 100644 _sources/vo/api_xmlutil.txt create mode 100644 _sources/vo/index.txt create mode 100644 _sources/vo/intro_table.txt create mode 100644 _sources/wcs/api.txt create mode 100644 _sources/wcs/api_distortion.txt create mode 100644 _sources/wcs/api_sip.txt create mode 100644 _sources/wcs/api_units.txt create mode 100644 _sources/wcs/api_wcs.txt create mode 100644 _sources/wcs/api_wcsprm.txt create mode 100644 _sources/wcs/examples.txt create mode 100644 _sources/wcs/history.txt create mode 100644 _sources/wcs/index.txt create mode 100644 _sources/wcs/relax.txt create mode 100644 _static/ajax-loader.gif create mode 100644 _static/comment-bright.png create mode 100644 _static/comment-close.png create mode 100644 _static/comment.png create mode 100644 _static/down-pressed.png create mode 100644 _static/down.png create mode 100644 _static/up-pressed.png create mode 100644 _static/up.png create mode 100644 _static/websupport.js create mode 100644 configs.html create mode 100644 development/building_packaging.html create mode 100644 development/scripts.html create mode 100644 install.html create mode 100644 np-modindex.html create mode 100644 overview.html create mode 100644 py-modindex.html create mode 100644 tools.html create mode 100644 utils/api_collections.html create mode 100644 utils/api_console.html create mode 100644 utils/api_misc.html create mode 100644 utils/api_xml.html create mode 100644 utils/index.html create mode 100644 vo/api.html create mode 100644 vo/api_converters.html create mode 100644 vo/api_exceptions.html create mode 100644 vo/api_table.html create mode 100644 vo/api_tree.html create mode 100644 vo/api_ucd.html create mode 100644 vo/api_unit.html create mode 100644 vo/api_util.html create mode 100644 vo/api_validator.html create mode 100644 vo/api_xmlutil.html create mode 100644 vo/index.html create mode 100644 vo/intro_table.html create mode 100644 wcs/api.html create mode 100644 wcs/api_distortion.html create mode 100644 wcs/api_sip.html create mode 100644 wcs/api_units.html create mode 100644 wcs/api_wcs.html create mode 100644 wcs/api_wcsprm.html create mode 100644 wcs/examples.html create mode 100644 wcs/history.html create mode 100644 wcs/index.html create mode 100644 wcs/relax.html diff --git a/README b/README index 5e8a9d10..96449d94 100644 --- a/README +++ b/README @@ -1 +1 @@ -This repository contains the static web page for the Astropy project. Right now it just redirects to the astropy wiki. +This repository contains the static web page for the Astropy project. Right now it is a fixed build of the docs. diff --git a/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png b/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png new file mode 100644 index 0000000000000000000000000000000000000000..fcf8eea5f910dd8327832888a374d647e2f182a0 GIT binary patch literal 49775 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 TLu%G?J|q?77R$~p6%9WC2R(%6 literal 0 HcmV?d00001 diff --git a/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png.map b/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png.map new file mode 100644 index 00000000..5f7c3c74 --- /dev/null +++ b/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png.map @@ -0,0 +1,2 @@ + + diff --git a/_images/inheritance-c64563669cfd1729a6777088d6be9e21c8889310.png b/_images/inheritance-c64563669cfd1729a6777088d6be9e21c8889310.png new file mode 100644 index 0000000000000000000000000000000000000000..0dd34b6a7d314f238ae12db6eef5131326221a82 GIT binary patch literal 50434 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 + diff --git a/_images/inheritance-e033a0922f5fc94c2076bb1330e6d8bb39cf71c1.png b/_images/inheritance-e033a0922f5fc94c2076bb1330e6d8bb39cf71c1.png new file mode 100644 index 0000000000000000000000000000000000000000..26a43f427b7faf662e1da6923c3edccd5da4260f GIT binary patch literal 25253 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 bk=NI+z%8wz_=5dKJ|Ti + + + + + + + + + + + + + + + + diff --git a/_images/inheritance-f7035f78b7760b2f76f4df0f21b8be07cd18e555.png b/_images/inheritance-f7035f78b7760b2f76f4df0f21b8be07cd18e555.png new file mode 100644 index 0000000000000000000000000000000000000000..1b16b2d9e955b566438cab240701eeea757aa2de GIT binary patch literal 25502 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 UPFQ$? + + + + + + + + + + + + + + + + diff --git a/_modules/astropy/config/configs.html b/_modules/astropy/config/configs.html new file mode 100644 index 00000000..aa853151 --- /dev/null +++ b/_modules/astropy/config/configs.html @@ -0,0 +1,540 @@ + + + + + + + + + + astropy.config.configs — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.config.configs

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""This module contains classes and functions to standardize access to
    +configuration files for Astropy and affiliated packages.
    +
    +.. note::
    +    The configuration system makes use of the 'configobj' package, which stores
    +    configuration in a text format like that used in the standard library
    +    `ConfigParser`. More information and documentation for configobj can be
    +    found at http://www.voidspace.org.uk/python/configobj.html.
    +"""
    +
    +from __future__ import division
    +from ..extern.configobj import configobj, validate
    +
    +__all__ = ['ConfigurationItem', 'InvalidConfigurationItemWarning',
    +            'get_config', 'save_config', 'reload_config']
    +
    +
    +
    [docs]class InvalidConfigurationItemWarning(Warning): + """ A Warning that is issued when the configuration value specified in the + astropy configuration file does not match the type expected for that + configuration value. + """ + +
    +
    [docs]class ConfigurationItem(object): + """ A setting and associated value stored in the astropy configuration + files. + + These objects are typically defined at the top of astropy subpackages + or affiliated packages, and store values or option settings that can be + modified by the user to + + Parameters + ---------- + name : str + The (case-sensitive) name of this parameter, as shown in the + configuration file. + defaultvalue + The default value for this item. If this is a list of strings, this item + will be interpreted as an 'options' value - this item must be one of + those values, and the first in the list will be taken as the default + value. + description : str or None + A description of this item (will be shown as a comment in the + configuration file) + cfgtype : str or None + A type specifier like those used as the *values* of a particular key in + a `configspec` file of `configobj`. If None, the type will be inferred + from the default value. + module : str or None + The full module name that this item is associated with. The first + element (e.g. 'astropy' if this is 'astropy.config.configs') will be + used to determine the name of the configuration file, while the + remaining items determine the section. If None, the package will be + inferred from the package within whiich this object's initializer is + called. + + Raises + ------ + RuntimeError + If `module` is None, but the module this item is created from cannot + be determined. + + Examples + -------- + The following example will create an item 'cfgoption = 42' in the + '[configs]' section of astropy.cfg (located in the directory that + `astropy.config.paths.get_config_dir` returns), or if the option is already + set, it will take the value from the configuration file:: + + from astropy.config import ConfigurationItem + + CFG_OPTION = ConfigurationItem('cfgoption',42,module='astropy.configs') + + If called as ``CFG_OPTION()``, this will return the value ``42``, or some + other integer if the ``astropy.cfg`` file specifies a different value. + + If this were in the ``astropy/configs/__init__.py`` file, the `module` + option would not be necessary, as it would automatically detect the correct + module. + + """ + + #this is used to make validation faster so a Validator object doesn't + #have to be created every time + _validator = validate.Validator() + + def __init__(self, name, defaultvalue='', description=None, cfgtype=None, + module=None): + from warnings import warn + from ..utils import find_current_module + + if module is None: + module = find_current_module(2) + if module is None: + msg1 = 'Cannot automatically determine get_config module, ' + msg2 = 'because it is not called from inside a valid module' + raise RuntimeError(msg1 + msg2) + else: + module = module.__name__ + + self.name = name + self.module = module + self.description = description + + #now determine cfgtype if it is not given + if cfgtype is None: + if isinstance(defaultvalue, list): + #it is an options list + dvstr = [str(v) for v in defaultvalue] + cfgtype = 'option(' + ', '.join(dvstr) + ')' + defaultvalue = dvstr[0] + elif isinstance(defaultvalue, bool): + cfgtype = 'boolean' + elif isinstance(defaultvalue, int): + cfgtype = 'integer' + elif isinstance(defaultvalue, float): + cfgtype = 'float' + else: + cfgtype = 'string' + defaultvalue = str(defaultvalue) + + self.cfgtype = cfgtype + + self._validate_val(defaultvalue) + self.defaultvalue = defaultvalue + + #note that the actual value is stored in the ConfigObj file for this + #package + + #this checks the current value to make sure it's valid for the type + #as well as updating the ConfigObj with the default value, if it's not + #actually in the ConfigObj + try: + self() + except TypeError as e: + # make sure it's a TypeError from __call__ + if 'Configuration value not valid:' in e.args[0]: + warn(InvalidConfigurationItemWarning(*e.args)) + else: + raise + +
    [docs] def set(self, value): + """ Sets the current value of this `ConfigurationItem`. + + This also updates the comments that give the description and type + information. + + .. note:: + This does *not* save the value of this `ConfigurationItem` to the + configuration file. To do that, use `ConfigurationItem.save` or + `save_config`. + + Parameters + ---------- + value + The value this item should be set to. + + Raises + ------ + TypeError + If the provided `value` is not valid for this `ConfigurationItem`. + """ + try: + value = self._validate_val(value) + except validate.ValidateError as e: + msg = 'Provided value for configuration item {0} not valid: {1}' + raise TypeError(msg.format(self.name, e.args[0])) + + sec = get_config(self.module) + + sec[self.name] = value + sec.comments[self.name] = self._generate_comments() +
    +
    [docs] def save(self, value=None): + """ Writes a value for this `ConfigurationItem` to the relevant + configuration file. + + This also writes updated versions of the comments that give the + description and type information. + + .. note:: + This only saves the value of this *particular* `ConfigurationItem`. + To save all configuration settings for this package at once, see + `save_config`. + + Parameters + ---------- + value + Save this value to the configuration file. If None, the current + value of this `ConfigurationItem` will be saved. + + Raises + ------ + TypeError + If the provided `value` is not valid for this `ConfigurationItem`. + """ + try: + value = self() if value is None else self._validate_val(value) + except validate.ValidateError as e: + msg = 'Provided value for configuration item {0} not valid: {1}' + raise TypeError(msg.format(self.name, e.args[0])) + + #Now find the ConfigObj that this is based on + baseobj = get_config(self.module) + secname = baseobj.name + cobj = baseobj + #a ConfigObj's parent is itself, so we look for the parent with that + while cobj.parent is not cobj: + cobj = cobj.parent + + #use the current on disk version, which will be modified with the + #given value and type/description + newobj = configobj.ConfigObj(cobj.filename) + if secname is not None: + if secname not in newobj: + newobj[secname] = {} + newsec = newobj[secname] + + newsec[self.name] = value + newsec.comments[self.name] = self._generate_comments() + newobj.write() +
    +
    [docs] def reload(self): + """ Reloads the value of this `ConfigurationItem` from the relevant + configuration file. + + Returns + ------- + val + The new value loaded from the configuration file. + """ + baseobj = get_config(self.module) + secname = baseobj.name + + cobj = baseobj + #a ConfigObj's parent is itself, so we look for the parent with that + while cobj.parent is not cobj: + cobj = cobj.parent + + newobj = configobj.ConfigObj(cobj.filename) + if secname is not None: + newobj = newobj[secname] + + baseobj[self.name] = newobj[self.name] +
    + def __call__(self): + """ Returns the value of this `ConfigurationItem` + + Returns + ------- + val + This item's value, with a type determined by the `cfgtype` + attribute. + + Raises + ------ + TypeError + If the configuration value as stored is not this item's type. + """ + + #get the value from the relevant `configobj.ConfigObj` object + sec = get_config(self.module) + if self.name not in sec: + self.set(self.defaultvalue) + val = sec[self.name] + + try: + return self._validate_val(val) + except validate.ValidateError as e: + raise TypeError('Configuration value not valid:' + e.args[0]) + + def _validate_val(self, val): + """ Validates the provided value based on cfgtype and returns the + type-cast value + + throws the underlying configobj exception if it fails + """ + #note that this will normally use the *class* attribute `_validator`, + #but if some arcane reason is needed for making a special one for an + #instance or sub-class, it will be used + return self._validator.check(self.cfgtype, val) + + def _generate_comments(self): + comments = [] + if self.description is not None: + comments.append(self.description) + if self.cfgtype is not None: + comments.append(self.cfgtype) + comments.append('') # adds a blank line after every entry + return comments + + +# this dictionary stores the master copy of the ConfigObj's for each +# root package
    +_cfgobjs = {} + + +
    [docs]def get_config(packageormod=None, reload=False): + """ Gets the configuration object or section associated with a particular + package or module. + + Parameters + ----------- + packageormod : str or None + The package for which to retrieve the configuration object. If a string, + it must be a valid package name, or if None, the package from which this + function is called will be used. + + Returns + ------- + cfgobj : `configobj.ConfigObj` or `configobj.Section` + If the requested package is a base package, this will be the + `configobj.ConfigObj` for that package, or if it is a subpackage or + module, it will return the relevant `configobj.Section` object. + + Raises + ------ + RuntimeError + If `package` is None, but the package this item is created from cannot + be determined. + + """ + from os.path import join + from .paths import get_config_dir + from ..utils import find_current_module + + if packageormod is None: + packageormod = find_current_module(2) + if packageormod is None: + msg1 = 'Cannot automatically determine get_config module, ' + msg2 = 'because it is not called from inside a valid module' + raise RuntimeError(msg1 + msg2) + else: + packageormod = packageormod.__name__ + + packageormodspl = packageormod.split('.') + rootname = packageormodspl[0] + secname = '.'.join(packageormodspl[1:]) + + cobj = _cfgobjs.get(rootname, None) + if cobj is None: + cfgfn = join(get_config_dir(), rootname + '.cfg') + _cfgobjs[rootname] = cobj = configobj.ConfigObj(cfgfn) + + if secname: # not the root package + if secname not in cobj: + cobj[secname] = {} + return cobj[secname] + else: + return cobj + +
    +
    [docs]def save_config(packageormod=None): + """ Saves all configuration settings to the configuration file for the + root package of the requested package/module. + + This overwrites any configuration items that have been changed in + `ConfigurationItem` objects that are based on the configuration file + determined by the *root* package of `packageormod` (e.g. 'astropy.cfg' for + the 'astropy.config.configs' module). + + .. note:: + To save only a single item, use the `ConfigurationItem.save` method - + this will save all options in the current session that may have been + changed. + + Parameters + ---------- + packageormod : str or None + The package or module name - see `get_config` for details. + """ + sec = get_config(packageormod) + #look for the section that is its own parent - that's the base object + while sec.parent is not sec: + sec = sec.parent + sec.write() + +
    +
    [docs]def reload_config(packageormod=None): + """ Reloads configuration settings from a configuration file for the root + package of the requested package/module. + + This overwrites any changes that may have been made in `ConfigurationItem` + objects. This applies for any items that are based on this file, which is + determined by the *root* package of `packageormod` (e.g. 'astropy.cfg' for + the 'astropy.config.configs' module). + + Parameters + ---------- + packageormod : str or None + The package or module name - see `get_config` for details. + """ + sec = get_config(packageormod) + #look for the section that is its own parent - that's the base object + while sec.parent is not sec: + sec = sec.parent + sec.reload() + +
    +def _generate_all_config_items(pkgornm=None, reset_to_default=False): + """ Given a root package name or package, this function simply walks through + all the subpackages and modules, which should populate any ConfigurationItem + objects defined at the module level. If `reset_to_default` is True, it also + sets all of the items to their default values, regardless of what the file's + value currently is. It then saves the `ConfigObj`. + + If `pkgname` is None, it determines the package based on the root package of + the function where this function is called. Be a bit cautious about this, + though - this might not always be what you want. + """ + from pkgutil import find_module, walk_packages + from types import ModuleType + + from ..utils import find_current_module + + if pkgornm is None: + pkgornm = find_current_module(1).__name__.split('.')[0] + + if isinstance(pkgornm, basestring): + package = find_module(pkgornm).load_module(pkgornm) + elif isinstance(pkgornm, ModuleType) and '__init__' in pkgornm.__file__: + package = pkgornm + else: + msg = '_generate_all_config_items was not given a package/package name' + raise TypeError(msg) + + for imper, nm, ispkg in walk_packages(package.__path__, + package.__name__ + '.'): + mod = imper.load_module(nm) + if reset_to_default: + for v in mod.__dict__.itervalues(): + if isinstance(v, ConfigurationItem): + v.set(v.defaultvalue) + save_config(package.__name__) +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/config/data.html b/_modules/astropy/config/data.html new file mode 100644 index 00000000..da41c2ae --- /dev/null +++ b/_modules/astropy/config/data.html @@ -0,0 +1,760 @@ + + + + + + + + + + astropy.config.data — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.config.data

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +""" This module contains helper functions for accessing, downloading, and
    +caching data files.
    +"""
    +
    +from __future__ import division
    +from .configs import ConfigurationItem
    +from sys import version_info
    +
    +__all__ = ['get_data_fileobj', 'get_data_filename', 'get_data_contents',
    +           'get_data_fileobjs', 'get_data_filenames', 'compute_hash',
    +           'clear_data_cache']
    +
    +DATAURL = ConfigurationItem(
    +    'dataurl', 'http://data.astropy.org/', 'URL for astropy remote data site.')
    +REMOTE_TIMEOUT = ConfigurationItem(
    +    'remote_timeout', 3., 'Time to wait for remote data query (in seconds).')
    +COMPUTE_HASH_BLOCK_SIZE = ConfigurationItem(
    +    'hash_block_size', 2 ** 16,  # 64K
    +    'Block size for computing MD5 file hashes.')
    +DATA_CACHE_DL_BLOCK_SIZE = ConfigurationItem(
    +    'data_dl_block_size', 2 ** 16,  # 64K
    +    'Number of bytes of remote data to download per step.')
    +DATA_CACHE_LOCK_ATTEMPTS = ConfigurationItem(
    +    'data_cache_lock_attempts', 3, 'Number of times to try to get the lock ' +
    +    'while accessing the data cache before giving up.')
    +
    +if version_info[0] < 3:
    +    #used for supporting with statements in get_data_fileobj
    +    def _fake_enter(self):
    +        return self
    +
    +    def _fake_exit(self, type, value, traceback):
    +        self.close()
    +
    +
    +
    [docs]def get_data_fileobj(dataname, cache=True): + """ + Retrieves a data file from the standard locations and provides the file as + a file-like object. + + Parameters + ---------- + dataname : str + Name/location of the desired data file. One of the following: + + * The name of a data file included in the source + distribution. The path is relative to the module + calling this function. For example, if calling from + `astropy.pkname`, use ``'data/file.dat'`` to get the + file in ``astropy/pkgname/data/file.dat``. Double-dots + can be used to go up a level. In the same example, use + ``'../data/file.dat'`` to get ``astropy/data/file.dat``. + * If a matching local file does not exist, the Astropy + data server will be queried for the file. + * A hash like that produced by `compute_hash` can be + requested, prefixed by 'hash/' + e.g. 'hash/395dd6493cc584df1e78b474fb150840'. The hash + will first be searched for locally, and if not found, + the Astropy data server will be queried. + * A URL to some other file. + + cache : bool + If True, the file will be downloaded and saved locally or the + already-cached local copy will be accessed. If False, the file-like + object will directly access the resource (e.g. if a remote URL is + accessed, an object like that from `urllib2.urlopen` is returned). + + Returns + ------- + fileobj : file-like + An object with the contents of the data file available via :func:`read`. + Can be used as part of a ``with`` statement, automatically closing + itself after the ``with`` block. + + Raises + ------ + urllib2.URLError + If a remote file cannot be found. + IOError + If problems occur writing or reading a local file. + + Examples + -------- + + This will retrieve a data file and its contents for the `astropy.wcs` + tests:: + + from astropy.config import get_data_fileobj + + with get_data_fileobj('data/3d_cd.hdr') as fobj: + fcontents = fobj.read() + + + This downloads a data file and its contents from a specified URL, and does + *not* cache it remotely:: + + from astropy.config import get_data_fileobj + + vegaurl = 'ftp://ftp.stsci.edu/cdbs/grid/k93models/standards/vega.fits' + with get_data_fileobj(vegaurl,False) as fobj: + fcontents = fobj.read() + + See Also + -------- + get_data_contents : returns the contents of a file or url as a bytes object + get_data_filename : returns a local name for a file containing the data + """ + from os.path import isdir, isfile + from urlparse import urlparse + from urllib2 import urlopen + from types import MethodType + + if cache: + return open(get_data_filename(dataname), 'rb') + else: + url = urlparse(dataname) + if url[0] != '': # url[0]==url.scheme, but url[0] is py 2.6-compat + #it's actually a url for a net location + urlres = urlopen(dataname, timeout=REMOTE_TIMEOUT()) + else: + datafn = _find_pkg_data_path(dataname) + if isdir(datafn): + raise IOError( + "Tried to access a data file that's actually " + "a package data directory") + elif isfile(datafn): + return open(datafn, 'rb') + else: + #not local file - need to get remote data + urlres = urlopen(DATAURL() + datafn, timeout=REMOTE_TIMEOUT()) + + if version_info[0] < 3: + #need to add in context managers to support with urlopen for <3.x + urlres.__enter__ = MethodType(_fake_enter, urlres) + urlres.__exit__ = MethodType(_fake_exit, urlres) + + return urlres + +
    +
    [docs]def get_data_filename(dataname): + """ + Retrieves a data file from the standard locations and provides the local + name of the file. + + This function is similar to `get_data_fileobj` but returns the file *name* + instead of a readable file-like object. This means that this function must + always cache remote files locally, unlike `get_data_fileobj`. + + Parameters + ---------- + dataname : str + Name/location of the desired data file. One of the following: + + * The name of a data file included in the source + distribution. The path is relative to the module + calling this function. For example, if calling from + `astropy.pkname`, use ``'data/file.dat'`` to get the + file in ``astropy/pkgname/data/file.dat``. Double-dots + can be used to go up a level. In the same example, use + ``'../data/file.dat'`` to get ``astropy/data/file.dat``. + * If a matching local file does not exist, the Astropy + data server will be queried for the file. + * A hash like that produced by `compute_hash` can be + requested, prefixed by 'hash/' + e.g. 'hash/395dd6493cc584df1e78b474fb150840'. The hash + will first be searched for locally, and if not found, + the Astropy data server will be queried. + * A URL to some other file. + + Raises + ------ + urllib2.URLError + If a remote file cannot be found. + IOError + If problems occur writing or reading a local file. + + Returns + ------- + filename : str + A file path on the local file system corresponding to the data + requested in `dataname`. + + Examples + -------- + + This will retrieve the contents of the data file for the `astropy.wcs` + tests:: + + from astropy.config import get_data_filename + + fn = get_data_filename('data/3d_cd.hdr') + with open(fn) as f: + fcontents = f.read() + + + This retrieves a data file by hash either locally or from the astropy data + server:: + + from astropy.config import get_data_filename + + fn = get_data_filename('hash/da34a7b07ef153eede67387bf950bb32') + with open(fn) as f: + fcontents = f.read() + + See Also + -------- + get_data_contents : returns the contents of a file or url as a bytes object + get_data_fileobj : returns a file-like object with the data + """ + from os.path import isdir, isfile + from urlparse import urlparse + + url = urlparse(dataname) + if url[0] != '': # url[0]==url.scheme, but url[0] is py 2.6-compat + #it's actually a url for a net location + return _cache_remote(dataname) + elif dataname.startswith('hash/'): + #first try looking for a local version if a hash is specified + hashfn = _find_hash_fn(dataname[5:]) + if hashfn is None: + return _cache_remote(DATAURL() + dataname) + else: + return hashfn + else: + datafn = _find_pkg_data_path(dataname) + if isdir(datafn): + raise IOError( + "Tried to access a data file that's actually " + "a package data directory") + elif isfile(datafn): + return datafn + else: + #look for the file on the data server + return _cache_remote(DATAURL() + dataname) + +
    +
    [docs]def get_data_contents(dataname, cache=True): + """ + Retrieves a data file from the standard locations and returns its + contents as a bytes object. + + Parameters + ---------- + dataname : str + Name/location of the desired data file. One of the following: + + * The name of a data file included in the source + distribution. The path is relative to the module + calling this function. For example, if calling from + `astropy.pkname`, use ``'data/file.dat'`` to get the + file in ``astropy/pkgname/data/file.dat``. Double-dots + can be used to go up a level. In the same example, use + ``'../data/file.dat'`` to get ``astropy/data/file.dat``. + * If a matching local file does not exist, the Astropy + data server will be queried for the file. + * A hash like that produced by `compute_hash` can be + requested, prefixed by 'hash/' + e.g. 'hash/395dd6493cc584df1e78b474fb150840'. The hash + will first be searched for locally, and if not found, + the Astropy data server will be queried. + * A URL to some other file. + + cache : bool + If True, the file will be downloaded and saved locally or the + already-cached local copy will be accessed. If False, the file-like + object will directly access the resource (e.g. if a remote URL is + accessed, an object like that from `urllib2.urlopen` is returned). + + Returns + ------- + contents : bytes + The complete contents of the file as a bytes object. + + Raises + ------ + urllib2.URLError + If a remote file cannot be found. + IOError + If problems occur writing or reading a local file. + + See Also + -------- + get_data_fileobj : returns a file-like object with the data + get_data_filename : returns a local name for a file containing the data + """ + with get_data_fileobj(dataname, cache=cache) as fd: + contents = fd.read() + return contents + +
    +
    [docs]def get_data_filenames(datadir, pattern='*'): + """ + Returns the path of all of the data files in a given directory + that match a given glob pattern. + + Parameters + ---------- + datadir : str + Name/location of the desired data files. One of the following: + + * The name of a directory included in the source + distribution. The path is relative to the module + calling this function. For example, if calling from + `astropy.pkname`, use ``'data'`` to get the + files in ``astropy/pkgname/data``. + * Remote URLs are not currently supported. + + pattern : str, optional + A UNIX-style filename glob pattern to match files. See the + `glob` module in the standard library for more information. + By default, matches all files. + + Returns + ------- + filenames : iterator of str + Paths on the local filesystem in *datadir* matching *pattern*. + + Examples + -------- + This will retrieve the contents of the data file for the `astropy.wcs` + tests:: + + from astropy.config import get_data_filenames + + for fn in get_data_filename('maps', '*.hdr'): + with open(fn) as f: + fcontents = f.read() + """ + import fnmatch + from os.path import isdir, isfile, join + from os import listdir + + path = _find_pkg_data_path(datadir) + if isfile(path): + raise IOError( + "Tried to access a data directory that's actually " + "a package data file") + elif isdir(path): + for filename in listdir(path): + if fnmatch.fnmatch(filename, pattern): + yield join(path, filename) + else: + raise IOError("Path not found") + +
    +
    [docs]def get_data_fileobjs(datadir, pattern='*'): + """ + Returns readable file objects for all of the data files in a given + directory that match a given glob pattern. + + Parameters + ---------- + datadir : str + Name/location of the desired data files. One of the following: + + * The name of a directory included in the source + distribution. The path is relative to the module + calling this function. For example, if calling from + `astropy.pkname`, use ``'data'`` to get the + files in ``astropy/pkgname/data`` + * Remote URLs are not currently supported + + pattern : str, optional + A UNIX-style filename glob pattern to match files. See the + `glob` module in the standard library for more information. + By default, matches all files. + + Returns + ------- + fileobjs : iterator of file objects + File objects for each of the files on the local filesystem in + *datadir* matching *pattern*. + + Examples + -------- + This will retrieve the contents of the data file for the `astropy.wcs` + tests:: + + from astropy.config import get_data_filenames + + for fd in get_data_filename('maps', '*.hdr'): + fcontents = fd.read() + """ + for fn in get_data_filenames(datadir, pattern): + with open(fn, 'rb') as fd: + yield fd + +
    +
    [docs]def compute_hash(localfn): + """ Computes the MD5 hash for a file. + + The hash for a data file is used for looking up data files in a unique + fashion. This is of particular use for tests; a test may require a + particular version of a particular file, in which case it can be accessed + via hash to get the appropriate version. + + Typically, if you wish to write a test that requires a particular data + file, you will want to submit that file to the astropy data servers, and + use e.g. ``get_data_filename('hash/a725fa6ba642587436612c2df0451956')``, + but with the hash for your file in place of the hash in the example. + + Parameters + ---------- + localfn : str + The path to the file for which the hash should be generated. + + Returns + ------- + md5hash : str + The hex digest of the MD5 hash for the contents of the `localfn` file. + + """ + import hashlib + + with open(localfn, 'rb') as f: + h = hashlib.md5() + block = f.read(COMPUTE_HASH_BLOCK_SIZE()) + while block: + h.update(block) + block = f.read(COMPUTE_HASH_BLOCK_SIZE()) + + return h.hexdigest() + +
    +def _find_pkg_data_path(dataname): + """ + Look for data in the source-included data directories and return the + path. + """ + from os.path import abspath, dirname, join + from ..utils.misc import find_current_module + + module = find_current_module(1, True) + rootpkgname = module.__package__.split('.')[0] + rootpkg = __import__(rootpkgname) + + module_path = dirname(module.__file__) + path = join(module_path, dataname) + + root_dir = dirname(rootpkg.__file__) + assert abspath(path).startswith(abspath(root_dir)), \ + ("attempted to get a local data file outside " + "of the " + rootpkgname + " tree") + + return path + + +def _find_hash_fn(hash): + """ + Looks for a local file by hash - returns file name if found and a valid + file, otherwise returns None. + """ + from os.path import isfile, join + + dldir, urlmapfn = _get_data_cache_locs() + hashfn = join(dldir, hash) + if isfile(hashfn): + return hashfn + else: + return None + + +def _cache_remote(remoteurl): + """ + Accepts a URL, downloads and caches the result returning the filename, with + a name determined by the file's MD5 hash. If present in the cache, just + returns the filename. + """ + import hashlib + from contextlib import closing + from os.path import join + from shutil import move + from urllib2 import urlopen + from ..utils.console import ProgressBarOrSpinner + + dldir, urlmapfn = _get_data_cache_locs() + _acquire_data_cache_lock() + try: + with _open_shelve(urlmapfn, True) as url2hash: + if str(remoteurl) in url2hash: + localpath = url2hash[str(remoteurl)] + else: + with closing(urlopen(remoteurl, + timeout=REMOTE_TIMEOUT())) as remote: + #save the file to a temporary file + tmpfn = join(dldir, 'cachedl.tmp') + hash = hashlib.md5() + + info = remote.info() + if 'Content-Length' in info: + try: + size = int(info['Content-Length']) + except ValueError: + size = None + else: + size = None + + dlmsg = "Downloading {0}".format(remoteurl) + with ProgressBarOrSpinner(size, dlmsg) as p: + with open(tmpfn, 'wb') as f: + bytes_read = 0 + block = remote.read(DATA_CACHE_DL_BLOCK_SIZE()) + while block: + f.write(block) + hash.update(block) + bytes_read += len(block) + p.update(bytes_read) + block = remote.read(DATA_CACHE_DL_BLOCK_SIZE()) + + localpath = join(dldir, hash.hexdigest()) + move(tmpfn, localpath) + url2hash[str(remoteurl)] = localpath + finally: + _release_data_cache_lock() + + return localpath + + +
    [docs]def clear_data_cache(hashorurl=None): + """ Clears the data file cache by deleting the local file(s). + + Parameters + ---------- + hashorurl : str or None + If None, the whole cache is cleared. Otherwise, either specifies a hash + for the cached file that is supposed to be deleted, or a URL that has + previously been downloaded to the cache. + + Raises + ------ + OSEerror + If the requested filename is not present in the data directory. + + """ + from os import unlink + from os.path import join, exists, abspath + from shutil import rmtree + + dldir, urlmapfn = _get_data_cache_locs() + _acquire_data_cache_lock() + try: + + if hashorurl is None: + if exists(dldir): + rmtree(dldir) + if exists(urlmapfn): + unlink(urlmapfn) + else: + with _open_shelve(urlmapfn, True) as url2hash: + filepath = join(dldir, hashorurl) + assert abspath(filepath).startswith(abspath(dldir)), \ + ("attempted to use clear_data_cache on a location" + + " that's not inside the data cache directory") + + if exists(filepath): + for k, v in url2hash.items(): + if v == filepath: + del url2hash[k] + unlink(filepath) + + elif hashorurl in url2hash: + filepath = url2hash[hashorurl] + del url2hash[hashorurl] + unlink(filepath) + + else: + msg = 'Could not find file or url {0}' + raise OSError(msg.format(hashorurl)) + finally: + _release_data_cache_lock() + +
    +def _get_data_cache_locs(): + """ Finds the path to the data cache directory. + + Returns + ------- + datadir : str + The path to the data cache directory. + shelveloc : str + The path to the shelve object that stores the cache info. + """ + from .paths import get_cache_dir + from os.path import exists, isdir, join + from os import mkdir + + datadir = join(get_cache_dir(), 'data') + shelveloc = join(get_cache_dir(), 'data_urlmap') + if not exists(datadir): + mkdir(datadir) + elif not isdir(datadir): + msg = 'Data cache directory {0} is not a directory' + raise IOError(msg.format(datadir)) + + if isdir(shelveloc): + msg = 'Data cache shelve object location {0} is a directory' + raise IOError(msg.format(shelveloc)) + + return datadir, shelveloc + + +def _open_shelve(shelffn, withclosing=False): + """ + opens a shelf in a way that is py3.x and py2.x compatible. If + `withclosing` is True, it will be opened with closing, allowing use like: + + with _open_shelve('somefile',True) as s: + ... + """ + import shelve + from contextlib import closing + from sys import version_info + + if version_info[0] > 2: + shelf = shelve.open(shelffn, protocol=2) + else: + shelf = shelve.open(shelffn + '.db', protocol=2) + + if withclosing: + return closing(shelf) + else: + return shelf + + +#the cache directory must be locked before any writes are performed. Same for +#the hash shelve, so this should be used for both. Note +def _acquire_data_cache_lock(): + from os.path import join + from os import mkdir + from time import sleep + + lockdir = join(_get_data_cache_locs()[0], 'lock') + for i in range(DATA_CACHE_LOCK_ATTEMPTS()): + try: + mkdir(lockdir) + except OSError: + sleep(1) + else: + return + msg = 'Unable to acquire lock for cache directory ({0} exists)' + raise RuntimeError(msg.format(lockdir)) + + +def _release_data_cache_lock(): + from os.path import join, exists, isdir + from os import rmdir + + lockdir = join(_get_data_cache_locs()[0], 'lock') + + if exists(lockdir) and isdir(lockdir): + rmdir(lockdir) + else: + msg = 'Error releasing lock. "{0}" either does not exist or is not ' +\ + 'a directory.' + raise RuntimeError(msg.format(lockdir)) +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/config/paths.html b/_modules/astropy/config/paths.html new file mode 100644 index 00000000..387a0a81 --- /dev/null +++ b/_modules/astropy/config/paths.html @@ -0,0 +1,278 @@ + + + + + + + + + + astropy.config.paths — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.config.paths

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +""" This module contains functions to determine where configuration and
    +data/cache files used by Astropy should be placed.
    +"""
    +
    +from __future__ import division
    +
    +__all__ = ['get_config_dir', 'get_cache_dir']
    +
    +
    +def _find_home():
    +    """ Locates and return the home directory (or best approximation) on this
    +    system.
    +
    +    Raises
    +    ------
    +    OSError
    +        If the home directory cannot be located - usually means you are running
    +        Astropy on some obscure platform that doesn't have standard home
    +        directories.
    +    """
    +    import os
    +    import sys
    +    from os import environ as env
    +
    +    # this is used below to make fix up encoding issues that sometimes crop up
    +    # in py2.x but not in py3.x
    +    if sys.version_info[0] < 3:
    +        decodepath = lambda pth: pth.decode(sys.getfilesystemencoding())
    +    else:
    +        decodepath = lambda pth: pth
    +
    +    #First find the home directory - this is inspired by the scheme ipython
    +    #uses to identify "home"
    +    if os.name == 'posix':
    +        # Linux, Unix, AIX, OS X
    +        if 'HOME' in env:
    +            homedir = decodepath(env['HOME'])
    +        else:
    +            raise OSError('Could not find unix home directory to search for' +\
    +                          ' astropy config dir')
    +    elif os.name == 'nt':  # This is for all modern Windows (NT or after)
    +        #Try for a network home first
    +        if 'HOMESHARE' in env:
    +            homedir = decodepath(env['HOMESHARE'])
    +        #See if there's a local home
    +        elif 'HOMEDRIVE' in env and 'HOMEPATH' in env:
    +            homedir = os.path.join(env['HOMEDRIVE'], env['HOMEPATH'])
    +            homedir = decodepath(homedir)
    +        #Maybe a user profile?
    +        elif 'USERPROFILE' in env:
    +            homedir = decodepath(os.path.join(env['USERPROFILE']))
    +        else:
    +            try:
    +                import _winreg as wreg
    +                key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
    +            'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
    +
    +                homedir = wreg.QueryValueEx(key, 'Personal')[0]
    +                homedir = decodepath(homedir)
    +                key.Close()
    +            except:
    +                #As a final possible resort, see if HOME is present
    +                if 'HOME' in env:
    +                    homedir = decodepath(env['HOME'])
    +                else:
    +                    raise OSError('Could not find windows home directory to' +\
    +                                  ' search for astropy config dir')
    +    else:
    +        #for other platforms, try HOME, although it probably isn't there
    +        if 'HOME' in env:
    +            homedir = decodepath(env['HOME'])
    +        else:
    +            raise OSError('Could not find a home directory to search for ' +\
    +                 'astropy config dir - are you on an unspported platform?')
    +    return homedir
    +
    +
    +
    [docs]def get_config_dir(create=True): + """ + Determines the Astropy configuration directory name and creates the + directory if it doesn't exist. + + This directory is typically ``$HOME/.astropy/config``, but if the + XDG_CONFIG_HOME environment variable is set and the + ``$XDG_CONFIG_HOME/astropy`` directory exists, it will be that directory. + If neither exists, the former will be created and symlinked to the latter. + + Returns + ------- + configdir : str + The absolute path to the configuration directory. + + """ + from os import path, environ + + #symlink will be set to this if the directory is created + linkto = None + #first look for XDG_CONFIG_HOME + xch = environ.get('XDG_CONFIG_HOME') + + if xch is not None: + xchpth = path.join(xch, 'astropy') + if not path.islink(xchpth): + if path.exists(xchpth): + return path.abspath(xchpth) + else: + linkto = xchpth + + return path.abspath(_find_or_create_astropy_dir('config', linkto)) + +
    +
    [docs]def get_cache_dir(): + """ + Determines the Astropy cache directory name and creates the directory if it + doesn't exist. + + This directory is typically ``$HOME/.astropy/cache``, but if the + XDG_CACHE_HOME environment variable is set and the + ``$XDG_CACHE_HOME/astropy`` directory exists, it will be that directory. + If neither exists, the former will be created and symlinked to the latter. + + Returns + ------- + cachedir : str + The absolute path to the cache directory. + + """ + from os import path, environ + + #symlink will be set to this if the directory is created + linkto = None + #first look for XDG_CACHE_HOME + xch = environ.get('XDG_CACHE_HOME') + + if xch is not None: + xchpth = path.join(xch, 'astropy') + if not path.islink(xchpth): + if path.exists(xchpth): + return path.abspath(xchpth) + else: + linkto = xchpth + + return path.abspath(_find_or_create_astropy_dir('cache', linkto)) + +
    +def _find_or_create_astropy_dir(dirnm, linkto): + from os import path, mkdir + import sys + + innerdir = path.join(_find_home(), '.astropy') + maindir = path.join(_find_home(), '.astropy', dirnm) + + if not path.exists(maindir): + #first create .astropy dir if needed + if not path.exists(innerdir): + mkdir(innerdir) + elif not path.isdir(innerdir): + msg = 'Intended Astropy directory {0} is actually a file.' + raise IOError(msg.format(innerdir)) + + mkdir(maindir) + + if (not sys.platform.startswith('win') and + linkto is not None and + not path.exists(linkto)): + from os import symlink + symlink(maindir, linkto) + + elif not path.isdir(maindir): + msg = 'Intended Astropy {0} directory {1} is actually a file.' + raise IOError(msg.format(dirnm, maindir)) + + return path.abspath(maindir) +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/converters.html b/_modules/astropy/io/vo/converters.html new file mode 100644 index 00000000..8363d432 --- /dev/null +++ b/_modules/astropy/io/vo/converters.html @@ -0,0 +1,1285 @@ + + + + + + + + + + astropy.io.vo.converters — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.converters

    +"""
    +This module handles the conversion of various VOTABLE datatypes
    +to/from TABLEDATA_ and BINARY_ formats.
    +"""
    +
    +from __future__ import division, absolute_import
    +
    +# STDLIB
    +import re
    +from struct import unpack as struct_unpack
    +from struct import pack as struct_pack
    +import sys
    +
    +# THIRD-PARTY
    +import numpy as np
    +
    +# ASTROPY
    +from ...utils.xml.writer import xml_escape_cdata
    +
    +# LOCAL
    +from .exceptions import (vo_raise, vo_warn, warn_or_raise, W01, W26,
    +    W30, W31, W32, W39, W46, W47, W49, E01, E02, E03, E04, E05, E06)
    +from .util import IS_PY3K
    +
    +if not IS_PY3K:
    +    def bytes(s, encoding):
    +        return str(s)
    +
    +
    +__all__ = ['get_converter']
    +
    +
    +pedantic_array_splitter = re.compile(r" +")
    +array_splitter = re.compile(r"\s+|(?:\s*,\s*)")
    +"""
    +A regex to handle splitting values on either whitespace or commas.
    +
    +SPEC: Usage of commas is not actually allowed by the spec, but many
    +files in the wild use them.
    +"""
    +
    +_zero_int = bytes('\0\0\0\0', 'ascii')
    +_empty_bytes = bytes('', 'ascii')
    +_zero_byte = bytes('\0', 'ascii')
    +
    +
    +class Converter(object):
    +    """
    +    The base class for all converters.  Each subclass handles
    +    converting a specific VOTABLE data type to/from the TABLEDATA_ and
    +    BINARY_ on-disk representations.
    +    """
    +    def __init__(self, field, config={}, pos=None):
    +        """
    +        Parameters
    +        ----------
    +        field : `~astropy.io.vo.table.Field`
    +            object describing the datatype
    +
    +        config : dict
    +            The parser configuration dictionary
    +
    +        pos : tuple
    +            The position in the XML file where the FIELD object was
    +            found.  Used for error messages.
    +        """
    +        pass
    +
    +    @staticmethod
    +    def _parse_length(read):
    +        return struct_unpack(">I", read(4))[0]
    +
    +    @staticmethod
    +    def _write_length(length):
    +        return struct_pack(">I", int(length))
    +
    +    def parse(self, value, config={}, pos=None):
    +        """
    +        Convert the string *value* from the TABLEDATA_ format into an
    +        object with the correct native in-memory datatype and mask flag.
    +
    +        Parameters
    +        ----------
    +        value : str
    +            value in TABLEDATA format
    +
    +        Returns
    +        -------
    +        native : tuple (value, mask)
    +            The value as a Numpy array or scalar, and *mask* is True
    +            if the value is missing.
    +        """
    +        raise NotImplementedError(
    +            "This datatype must implement a 'parse' method.")
    +
    +    def parse_scalar(self, value, config={}, pos=None):
    +        """
    +        Parse a single scalar of the underlying type of the converter.
    +        For non-array converters, this is equivalent to parse.  For
    +        array converters, this is used to parse a single
    +        element of the array.
    +
    +        Parameters
    +        ----------
    +        value : str
    +            value in TABLEDATA format
    +
    +        Returns
    +        -------
    +        native : tuple (value, mask)
    +            The value as a Numpy array or scalar, and *mask* is True
    +            if the value is missing.
    +        """
    +        return self.parse(value, config, pos)
    +
    +    def output(self, value, mask):
    +        """
    +        Convert the object *value* (in the native in-memory datatype)
    +        to a string suitable for serializing in the TABLEDATA_ format.
    +
    +        Parameters
    +        ----------
    +        value : native type corresponding to this converter
    +            The value
    +
    +        mask : bool
    +            If `True`, will return the string representation of a
    +            masked value.
    +
    +        Returns
    +        -------
    +        tabledata_repr : str
    +        """
    +        raise NotImplementedError(
    +            "This datatype must implement a 'output' method.")
    +
    +    def binparse(self, read):
    +        """
    +        Reads some number of bytes from the BINARY_ format
    +        representation by calling the function *read*, and returns the
    +        native in-memory object representation for the datatype
    +        handled by *self*.
    +
    +        Parameters
    +        ----------
    +        read : function
    +            A function that given a number of bytes, returns a byte
    +            string.
    +
    +        Returns
    +        -------
    +        native : tuple (value, mask)
    +            The value as a Numpy array or scalar, and *mask* is True
    +            if the value is missing.
    +        """
    +        raise NotImplementedError(
    +            "This datatype must implement a 'binparse' method.")
    +
    +    def binoutput(self, value, mask):
    +        """
    +        Convert the object *value* in the native in-memory datatype to
    +        a string of bytes suitable for serialization in the BINARY_
    +        format.
    +
    +        Parameters
    +        ----------
    +        value : native type corresponding to this converter
    +            The value
    +
    +        mask : bool
    +            If `True`, will return the string representation of a
    +            masked value.
    +
    +        Returns
    +        -------
    +        bytes : byte string
    +            The binary representation of the value, suitable for
    +            serialization in the BINARY_ format.
    +        """
    +        raise NotImplementedError(
    +            "This datatype must implement a 'binoutput' method.")
    +
    +
    +class Char(Converter):
    +    """
    +    Handles the char datatype. (7-bit unsigned characters)
    +
    +    Missing values are not handled for string or unicode types.
    +    """
    +    default = _empty_bytes
    +
    +    def __init__(self, field, config={}, pos=None):
    +        Converter.__init__(self, field, config, pos)
    +
    +        if field.arraysize is None:
    +            vo_warn(W47, (), config, pos)
    +            field.arraysize = '1'
    +
    +        if field.arraysize == '*':
    +            self.format = 'O'
    +            self.binparse = self._binparse_var
    +            self.binoutput = self._binoutput_var
    +            self.arraysize = '*'
    +        else:
    +            if field.arraysize.endswith('*'):
    +                field.arraysize = field.arraysize[:-1]
    +            try:
    +                self.arraysize = int(field.arraysize)
    +            except ValueError:
    +                vo_raise(E01, (field.arraysize, 'char', field.ID), config)
    +            self.format = 'S%d' % self.arraysize
    +            self.binparse = self._binparse_fixed
    +            self.binoutput = self._binoutput_fixed
    +            self._struct_format = ">%ds" % self.arraysize
    +
    +        if config.get('pedantic'):
    +            self.parse = self._ascii_parse
    +        else:
    +            self.parse = self._str_parse
    +
    +    def _ascii_parse(self, value, config={}, pos=None):
    +        if self.arraysize != '*' and len(value) > self.arraysize:
    +            vo_warn(W46, ('char', self.arraysize), config, pos)
    +        return value.encode('ascii'), False
    +
    +    if IS_PY3K:
    +        def _str_parse(self, value, config={}, pos=None):
    +            if self.arraysize != '*' and len(value) > self.arraysize:
    +                vo_warn(W46, ('char', self.arraysize), config, pos)
    +            return bytes(value, 'ascii'), False
    +    else:
    +        def _str_parse(self, value, config={}, pos=None):
    +            if self.arraysize != '*' and len(value) > self.arraysize:
    +                vo_warn(W46, ('char', self.arraysize), config, pos)
    +            return str(value), False
    +
    +    if IS_PY3K:
    +        def output(self, value, mask):
    +            if mask:
    +                return ''
    +            if not isinstance(value, str):
    +                value = value.decode('ascii')
    +            return xml_escape_cdata(value)
    +    else:
    +        def output(self, value, mask):
    +            if mask:
    +                return ''
    +            return xml_escape_cdata(value).encode('ascii')
    +
    +    def _binparse_var(self, read):
    +        length = self._parse_length(read)
    +        return read(length), False
    +
    +    def _binparse_fixed(self, read):
    +        s = struct_unpack(self._struct_format, read(self.arraysize))[0]
    +        end = s.find(_zero_byte)
    +        if end != -1:
    +            return s[:end], False
    +        return s, False
    +
    +    def _binoutput_var(self, value, mask):
    +        if mask or value is None or value == '':
    +            return _zero_int
    +        return self._write_length(len(value)) + value
    +
    +    def _binoutput_fixed(self, value, mask):
    +        if mask:
    +            value = _empty_bytes
    +        return struct_pack(self._struct_format, value)
    +
    +
    +class UnicodeChar(Converter):
    +    """
    +    Handles the unicodeChar data type. UTF-16-BE.
    +
    +    Missing values are not handled for string or unicode types.
    +    """
    +    default = u''
    +
    +    def __init__(self, field, config={}, pos=None):
    +        Converter.__init__(self, field, config, pos)
    +
    +        if field.arraysize is None:
    +            vo_warn(W47, (), config, pos)
    +            field.arraysize = '1'
    +
    +        if field.arraysize == '*':
    +            self.format = 'O'
    +            self.binparse = self._binparse_var
    +            self.binoutput = self._binoutput_var
    +            self.arraysize = '*'
    +        else:
    +            try:
    +                self.arraysize = int(field.arraysize)
    +            except ValueError:
    +                vo_raise(E01, (field.arraysize, 'unicode', field.ID), config)
    +            self.format = 'U%d' % self.arraysize
    +            self.binparse = self._binparse_fixed
    +            self.binoutput = self._binoutput_fixed
    +            self._struct_format = ">%ds" % (self.arraysize * 2)
    +
    +    if IS_PY3K:
    +        def parse(self, value, config={}, pos=None):
    +            if self.arraysize != '*' and len(value) > self.arraysize:
    +                vo_warn(W46, ('unicodeChar', self.arraysize), config, pos)
    +            return value, False
    +    else:
    +        def parse(self, value, config={}, pos=None):
    +            value = unicode(value, 'utf-8')
    +            if self.arraysize != '*' and len(value) > self.arraysize:
    +                vo_warn(W46, ('unicodeChar', self.arraysize), config, pos)
    +            return value, False
    +
    +    if IS_PY3K:
    +        def output(self, value, mask):
    +            if mask:
    +                return ''
    +            return xml_escape_cdata(value)
    +    else:
    +        def output(self, value, mask):
    +            if mask:
    +                return ''
    +            return xml_escape_cdata(value).encode('utf-8')
    +
    +    def _binparse_var(self, read):
    +        length = self._parse_length(read)
    +        return read(length * 2).decode('utf_16_be'), False
    +
    +    def _binparse_fixed(self, read):
    +        s = struct_unpack(self._struct_format, read(self.arraysize * 2))[0]
    +        s = s.decode('utf_16_be')
    +        end = s.find('\0')
    +        if end != -1:
    +            return s[:end], False
    +        return s, False
    +
    +    def _binoutput_var(self, value, mask):
    +        if mask or value is None or value == '':
    +            return _zero_int
    +        encoded = value.encode('utf_16_be')
    +        return self._write_length(len(encoded) / 2) + encoded
    +
    +    def _binoutput_fixed(self, value, mask):
    +        if mask:
    +            value = u''
    +        return struct_pack(self._struct_format, value.encode('utf_16_be'))
    +
    +
    +class Array(Converter):
    +    """
    +    Handles both fixed and variable-lengths arrays.
    +    """
    +    def __init__(self, field, config={}, pos=None):
    +        Converter.__init__(self, field, config, pos)
    +
    +        if config.get('pedantic'):
    +            self._splitter = self._splitter_pedantic
    +        else:
    +            self._splitter = self._splitter_lax
    +
    +    def parse_scalar(self, value, config={}, pos=0):
    +        return self._base.parse_scalar(value, config, pos)
    +
    +    @staticmethod
    +    def _splitter_pedantic(value, config={}, pos=None):
    +        return pedantic_array_splitter.split(value)
    +
    +    @staticmethod
    +    def _splitter_lax(value, config={}, pos=None):
    +        if ',' in value:
    +            vo_warn(W01, (), config, pos)
    +        return array_splitter.split(value)
    +
    +
    +class VarArray(Array):
    +    """
    +    Handles variable lengths arrays (i.e. where *arraysize* is '*').
    +    """
    +    format = 'O'
    +
    +    def __init__(self, field, base, arraysize, config={}, pos=None):
    +        Array.__init__(self, field, config)
    +
    +        self._base = base
    +        self.default = np.array([], dtype=self._base.format)
    +
    +    def output(self, value, mask):
    +        output = self._base.output
    +        result = [output(x, m) for x, m in np.broadcast(value, mask)]
    +        return ' '.join(result)
    +
    +    def binparse(self, read):
    +        length = self._parse_length(read)
    +
    +        result = []
    +        result_mask = []
    +        binparse = self._base.binparse
    +        for i in xrange(length):
    +            val, mask = binparse(read)
    +            result.append(val)
    +            result_mask.append(mask)
    +        return (np.array(result),
    +                np.array(result_mask, dtype='bool'))
    +
    +    def binoutput(self, value, mask):
    +        if value is None or len(value) == 0:
    +            return _zero_int
    +
    +        length = len(value)
    +        result = [self._write_length(length)]
    +        binoutput = self._base.binoutput
    +        for x, m in zip(value, mask):
    +            result.append(binoutput(x, m))
    +        return _empty_bytes.join(result)
    +
    +
    +class ArrayVarArray(VarArray):
    +    """
    +    Handles an array of variable-length arrays, i.e. where *arraysize*
    +    ends in '*'.
    +    """
    +    def parse(self, value, config={}, pos=None):
    +        if value.strip() == '':
    +            return np.array([]), True
    +
    +        parts = self._splitter(value, config, pos)
    +        items = self._base._items
    +        parse_parts = self._base.parse_parts
    +        if len(parts) % items != 0:
    +            vo_raise(E02, (items, len(parts)), config, pos)
    +        result = []
    +        result_mask = []
    +        for i in xrange(0, len(parts), items):
    +            value, mask = parse_parts(parts[i:i+items], config, pos)
    +            result.append(value)
    +            result_mask.append(mask)
    +        return np.array(result), np.array(result_mask, dtype='bool')
    +
    +
    +class ScalarVarArray(VarArray):
    +    """
    +    Handles a variable-length array of numeric scalars.
    +    """
    +    def parse(self, value, config={}, pos=None):
    +        if value.strip() == '':
    +            return np.array([]), True
    +
    +        parts = self._splitter(value, config, pos)
    +
    +        parse = self._base.parse
    +        result = []
    +        result_mask = []
    +        for x in parts:
    +            value, mask = parse(x, config, pos)
    +            result.append(value)
    +            result_mask.append(mask)
    +        return (np.array(result, dtype=self._base.format),
    +                np.array(result_mask, dtype='bool'))
    +
    +
    +class NumericArray(Array):
    +    """
    +    Handles a fixed-length array of numeric scalars.
    +    """
    +    vararray_type = ArrayVarArray
    +
    +    def __init__(self, field, base, arraysize, config={}, pos=None):
    +        Array.__init__(self, field, config, pos)
    +
    +        self._base = base
    +        self._arraysize = arraysize
    +        self.format = "%s%s" % (tuple(arraysize), base.format)
    +
    +        self._items = 1
    +        for dim in arraysize:
    +            self._items *= dim
    +
    +        self._memsize = np.dtype(self.format).itemsize
    +        self._bigendian_format = '>' + self.format
    +
    +        self.default = (
    +            np.ones(arraysize, dtype=self._base.format) *
    +            self._base.default)
    +
    +    def parse(self, value, config={}, pos=None):
    +        parts = self._splitter(value, config, pos)
    +        if len(parts) != self._items:
    +            warn_or_raise(E02, E02, (self._items, len(parts)), config, pos)
    +        if config.get('pedantic'):
    +            return self.parse_parts(parts, config, pos)
    +        else:
    +            if len(parts) == self._items:
    +                pass
    +            elif len(parts) > self._items:
    +                parts = parts[:self._items]
    +            else:
    +                parts = (parts +
    +                         ([self._base.default] * (self._items - len(parts))))
    +            return self.parse_parts(parts, config, pos)
    +
    +    def parse_parts(self, parts, config={}, pos=None):
    +        base_parse = self._base.parse
    +        result = []
    +        result_mask = []
    +        for x in parts:
    +            value, mask = base_parse(x, config, pos)
    +            result.append(value)
    +            result_mask.append(mask)
    +        result = np.array(result, dtype=self._base.format).reshape(
    +            self._arraysize)
    +        result_mask = np.array(result_mask, dtype='bool').reshape(
    +            self._arraysize)
    +        return result, result_mask
    +
    +    def output(self, value, mask):
    +        base_output = self._base.output
    +        value = np.asarray(value)
    +        mask = np.asarray(mask)
    +        return ' '.join(base_output(x, m) for x, m in
    +                        zip(value.flat, mask.flat))
    +
    +    def binparse(self, read):
    +        result = np.fromstring(read(self._memsize),
    +                               dtype=self._bigendian_format)[0]
    +        result_mask = self._base.is_null(result)
    +        return result, result_mask
    +
    +    def binoutput(self, value, mask):
    +        filtered = self._base.filter_array(value, mask)
    +        if filtered.dtype.byteorder != '>':
    +            filtered = filtered.byteswap()
    +        return filtered.tostring()
    +
    +
    +class Numeric(Converter):
    +    """
    +    The base class for all numeric data types.
    +    """
    +    array_type = NumericArray
    +    vararray_type = ScalarVarArray
    +    null = None
    +
    +    def __init__(self, field, config={}, pos=None):
    +        Converter.__init__(self, field, config, pos)
    +
    +        self._memsize = np.dtype(self.format).itemsize
    +        self._bigendian_format = '>' + self.format
    +        if field.values.null is not None:
    +            self.null = np.asarray(field.values.null, dtype=self.format)
    +            self.default = self.null
    +            self.is_null = self._is_null
    +        else:
    +            self.is_null = np.isnan
    +
    +    def binparse(self, read):
    +        result = np.fromstring(read(self._memsize),
    +                               dtype=self._bigendian_format)
    +        return result[0], self.is_null(result[0])
    +
    +    def _is_null(self, value):
    +        return value == self.null
    +
    +
    +class FloatingPoint(Numeric):
    +    """
    +    The base class for floating-point datatypes.
    +    """
    +    default = np.nan
    +
    +    def __init__(self, field, config={}, pos=None):
    +        Numeric.__init__(self, field, config, pos)
    +
    +        precision = field.precision
    +        if precision is None:
    +            self._output_format = '%g'
    +        elif precision.startswith("E"):
    +            self._output_format = "%%.%dE" % (int(precision[1:]))
    +        elif precision.startswith("F"):
    +            self._output_format = "%%.%dg" % (int(precision[1:]))
    +        else:
    +            self._output_format = "%%.%dg" % (int(precision))
    +
    +        self.nan = np.array(np.nan, self.format)
    +
    +        if self.null is None:
    +            self._null_output = 'NaN'
    +            self._null_binoutput = self.binoutput(self.nan, False)
    +            self.filter_array = self._filter_nan
    +        else:
    +            self._null_output = self.output(np.asarray(self.null), False)
    +            self._null_binoutput = self.binoutput(np.asarray(self.null), False)
    +            self.filter_array = self._filter_null
    +
    +        if config.get('pedantic'):
    +            self.parse = self._parse_pedantic
    +        else:
    +            self.parse = self._parse_permissive
    +
    +    def _parse_pedantic(self, value, config={}, pos=None):
    +        if value.strip() == '':
    +            return self.null, True
    +        f = float(value)
    +        return f, self.is_null(f)
    +
    +    def _parse_permissive(self, value, config={}, pos=None):
    +        try:
    +            f = float(value)
    +            return f, self.is_null(f)
    +        except ValueError:
    +            # IRSA VOTables use the word 'null' to specify empty values,
    +            # but this is not defined in the VOTable spec.
    +            if value.strip() != '':
    +                vo_warn(W30, value, config, pos)
    +            return self.null, True
    +
    +    def output(self, value, mask):
    +        if mask:
    +            return self._null_output
    +        if np.isfinite(value):
    +            return self._output_format % value
    +        elif np.isnan(value):
    +            return 'NaN'
    +        elif np.isposinf(value):
    +            return '+InF'
    +        elif np.isneginf(value):
    +            return '-InF'
    +        # Should never raise
    +        vo_raise("Invalid floating point value '%s'" % value)
    +
    +    def binoutput(self, value, mask):
    +        if mask:
    +            return self._null_binoutput
    +
    +        if value.dtype.byteorder != '>':
    +            value = value.byteswap()
    +        return value.tostring()
    +
    +    def _filter_nan(self, value, mask):
    +        return np.where(mask, np.nan, value)
    +
    +    def _filter_null(self, value, mask):
    +        return np.where(mask, self.null, value)
    +
    +
    +class Double(FloatingPoint):
    +    """
    +    Handles the double datatype.  Double-precision IEEE
    +    floating-point.
    +    """
    +    format = 'f8'
    +
    +
    +class Float(FloatingPoint):
    +    """
    +    Handles the float datatype.  Single-precision IEEE floating-point.
    +    """
    +    format = 'f4'
    +
    +
    +class Integer(Numeric):
    +    """
    +    The base class for all the integral datatypes.
    +    """
    +    default = 0
    +
    +    def __init__(self, field, config={}, pos=None):
    +        Numeric.__init__(self, field, config, pos)
    +
    +    def parse(self, value, config={}, pos=None):
    +        mask = False
    +        if isinstance(value, basestring):
    +            value = value.lower()
    +            if value == '':
    +                warn_or_raise(W49, W49, (), config, pos)
    +                if self.null is not None:
    +                    value = self.null
    +                else:
    +                    value = self.default
    +            elif value == 'nan':
    +                mask = True
    +                if self.null is None:
    +                    warn_or_raise(W31, W31, (), config, pos)
    +                    value = self.default
    +                else:
    +                    value = self.null
    +            elif value.startswith('0x'):
    +                value = int(value[2:], 16)
    +            else:
    +                value = int(value, 10)
    +        else:
    +            value = int(value)
    +        if self.null is not None and value == self.null:
    +            mask = True
    +        return value, mask
    +
    +    def output(self, value, mask):
    +        if mask:
    +            if self.null is None:
    +                warn_or_raise(W31, W31, (), config, pos)
    +                return 'NaN'
    +            return str(self.null)
    +        return str(value)
    +
    +    def binoutput(self, value, mask):
    +        if mask:
    +            if self.null is None:
    +                vo_raise(W31, (), config, pos)
    +            else:
    +                value = self.null
    +        if value.dtype.byteorder != '>':
    +            value = value.byteswap()
    +        return value.tostring()
    +
    +    def filter_array(self, value, mask):
    +        if np.any(mask):
    +            if self.null is not None:
    +                return np.where(mask, self.null, value)
    +            else:
    +                vo_raise(W31, (), config, pos)
    +        return value
    +
    +
    +class UnsignedByte(Integer):
    +    """
    +    Handles the unsignedByte datatype.  Unsigned 8-bit integer.
    +    """
    +    format = 'u1'
    +
    +
    +class Short(Integer):
    +    """
    +    Handles the short datatype.  Signed 16-bit integer.
    +    """
    +    format = 'i2'
    +
    +
    +class Int(Integer):
    +    """
    +    Handles the int datatype.  Signed 32-bit integer.
    +    """
    +    format = 'i4'
    +
    +
    +class Long(Integer):
    +    """
    +    Handles the long datatype.  Signed 64-bit integer.
    +    """
    +    format = 'i8'
    +
    +
    +class ComplexArrayVarArray(VarArray):
    +    """
    +    Handles an array of variable-length arrays of complex numbers.
    +    """
    +    def __init__(self, field, base, arraysize, config={}, pos=None):
    +        VarArray.__init__(self, field, base, arraysize, config, pos)
    +
    +    def parse(self, value, config={}, pos=None):
    +        if value.strip() == '':
    +            return np.array([]), True
    +
    +        parts = self._splitter(value, config, pos)
    +        items = self._base._items
    +        parse_parts = self._base.parse_parts
    +        if len(parts) % items != 0:
    +            vo_raise(E02, (items, len(parts)), config, pos)
    +        result = []
    +        result_mask = []
    +        for i in xrange(0, len(parts), items):
    +            value, mask = parse_parts(parts[i:i + items], config, pos)
    +            result.append(value)
    +            result_mask.append(mask)
    +        return np.array(result), np.array(result_mask, dtype='bool')
    +
    +
    +class ComplexVarArray(VarArray):
    +    """
    +    Handles a variable-length array of complex numbers.
    +    """
    +    def __init__(self, field, base, arraysize, config={}, pos=None):
    +        VarArray.__init__(self, field, base, arraysize, config, pos)
    +
    +    def parse(self, value, config={}, pos=None):
    +        if value.strip() == '':
    +            return np.array([]), True
    +
    +        parts = self._splitter(value, config, pos)
    +        parse_parts = self._base.parse_parts
    +        result = []
    +        result_mask = []
    +        for i in xrange(0, len(parts), 2):
    +            value = [float(x) for x in parts[i:i + 2]]
    +            value, mask = parse_parts(value, config, pos)
    +            result.append(value)
    +            result_mask.append(mask)
    +        return (np.array(result, dtype=self._base.format),
    +                np.array(result_mask, dtype='bool'))
    +
    +
    +class ComplexArray(NumericArray):
    +    """
    +    Handles a fixed-size array of complex numbers.
    +    """
    +    vararray_type = ComplexArrayVarArray
    +
    +    def __init__(self, field, base, arraysize, config={}, pos=None):
    +        NumericArray.__init__(self, field, base, arraysize, config, pos)
    +        self._items *= 2
    +
    +    def parse(self, value, config={}, pos=None):
    +        parts = self._splitter(value, config, pos)
    +        if parts == ['']:
    +            parts = []
    +        return self.parse_parts(parts, config, pos)
    +
    +    def parse_parts(self, parts, config={}, pos=None):
    +        if len(parts) != self._items:
    +            vo_raise(E02, (self._items, len(parts)), config, pos)
    +        base_parse = self._base.parse_parts
    +        result = []
    +        result_mask = []
    +        for i in xrange(0, self._items, 2):
    +            value = [float(x) for x in parts[i:i + 2]]
    +            value, mask = base_parse(value, config, pos)
    +            result.append(value)
    +            result_mask.append(mask)
    +        result = np.array(
    +            result, dtype=self._base.format).reshape(self._arraysize)
    +        result_mask = np.array(
    +            result_mask, dtype='bool').reshape(self._arraysize)
    +        return result, result_mask
    +
    +
    +class Complex(FloatingPoint, Array):
    +    """
    +    The base class for complex numbers.
    +    """
    +    array_type = ComplexArray
    +    vararray_type = ComplexVarArray
    +    default = np.nan
    +
    +    def __init__(self, field, config={}, pos=None):
    +        FloatingPoint.__init__(self, field, config, pos)
    +        Array.__init__(self, field, config, pos)
    +
    +        self._output_format = self._output_format + " " + self._output_format
    +
    +    def parse(self, value, config={}, pos=None):
    +        if value.strip() == '':
    +            return np.nan, True
    +        splitter = self._splitter
    +        parts = [float(x) for x in splitter(value, config, pos)]
    +        if len(parts) != 2:
    +            vo_raise(E03, (value,), config, pos)
    +        return self.parse_parts(parts, config, pos)
    +    _parse_permissive = parse
    +    _parse_pedantic = parse
    +
    +    def parse_parts(self, parts, config={}, pos=None):
    +        value = complex(*parts)
    +        return value, self.is_null(value)
    +
    +    def output(self, value, mask):
    +        if mask:
    +            if self.null is None:
    +                return 'NaN'
    +            else:
    +                value = self.null
    +        return self._output_format % (value.real, value.imag)
    +
    +
    +class FloatComplex(Complex):
    +    """
    +    Handle floatComplex datatype.  Pair of single-precision IEEE
    +    floating-point numbers.
    +    """
    +    format = 'c8'
    +
    +
    +class DoubleComplex(Complex):
    +    """
    +    Handle doubleComplex datatype.  Pair of double-precision IEEE
    +    floating-point numbers.
    +    """
    +    format = 'c16'
    +
    +
    +class BitArray(NumericArray):
    +    """
    +    Handles an array of bits.
    +    """
    +    vararray_type = ArrayVarArray
    +
    +    def __init__(self, field, base, arraysize, config={}, pos=None):
    +        NumericArray.__init__(self, field, base, arraysize, config, pos)
    +
    +        self._bytes = ((self._items - 1) // 8) + 1
    +
    +    @staticmethod
    +    def _splitter_pedantic(value, config={}, pos=None):
    +        return list(re.sub('\s', '', value))
    +
    +    @staticmethod
    +    def _splitter_lax(value, config={}, pos=None):
    +        if ',' in value:
    +            vo_warn(W01, (), config, pos)
    +        return list(re.sub('\s|,', '', value))
    +
    +    def output(self, value, mask):
    +        value = np.asarray(value)
    +        mapping = {False: '0', True: '1'}
    +        return ''.join(mapping[x] for x in value.flat)
    +
    +    def binparse(self, read):
    +        data = read(self._bytes)
    +        results = []
    +        for byte in data:
    +            if not IS_PY3K:
    +                byte = ord(byte)
    +            for bit_no in range(7, -1, -1):
    +                bit = byte & (1 << bit_no)
    +                bit = (bit != 0)
    +                results.append(bit)
    +                if len(results) == self._items:
    +                    break
    +            if len(results) == self._items:
    +                break
    +
    +        result = np.array(results, dtype='b1').reshape(self._arraysize)
    +        result_mask = np.zeros(self._arraysize, dtype='b1')
    +        return result, result_mask
    +
    +    def binoutput(self, value, mask):
    +        if np.any(mask):
    +            vo_warn(W39)
    +
    +        x = value
    +        value = value.flat
    +        bit_no = 7
    +        byte = 0
    +        bytes = []
    +        for v in value:
    +            if v:
    +                byte |= 1 << bit_no
    +            if bit_no == 0:
    +                bytes.append(byte)
    +                bit_no = 7
    +                byte = 0
    +            else:
    +                bit_no -= 1
    +        if bit_no != 7:
    +            bytes.append(byte)
    +
    +        assert len(bytes) == self._bytes
    +
    +        return struct_pack("%sB" % len(bytes), *bytes)
    +
    +
    +class Bit(Converter):
    +    """
    +    Handles the bit datatype.
    +    """
    +    format = 'b1'
    +    array_type = BitArray
    +    vararray_type = ScalarVarArray
    +    default = False
    +    binary_one = bytes(chr(0x8), 'ascii')
    +    binary_zero = bytes(chr(0), 'ascii')
    +
    +    def __init__(self, field, config={}, pos=None):
    +        Converter.__init__(self, field, config, pos)
    +
    +    def parse(self, value, config={}, pos=None):
    +        mapping = {'1': True, '0': False}
    +        if value is False or value.strip() == '':
    +            warn_or_raise(W49, W49, (), config, pos)
    +            return False, True
    +        else:
    +            try:
    +                return mapping[value], False
    +            except KeyError:
    +                vo_raise(E04, (value,), config, pos)
    +
    +    def output(self, value, mask):
    +        if mask:
    +            vo_warn(W39)
    +
    +        if value:
    +            return '1'
    +        else:
    +            return '0'
    +
    +    def binparse(self, read):
    +        data = read(1)
    +        return (ord(data) & 0x8) != 0, False
    +
    +    def binoutput(self, value, mask):
    +        if mask:
    +            vo_warn(W39)
    +
    +        if value:
    +            return self.binary_one
    +        return self.binary_zero
    +
    +
    +class BooleanArray(NumericArray):
    +    """
    +    Handles an array of boolean values.
    +    """
    +    vararray_type = VarArray
    +
    +    def __init__(self, field, base, arraysize, config={}, pos=None):
    +        NumericArray.__init__(self, field, base, arraysize, config, pos)
    +
    +    def binparse(self, read):
    +        data = read(self._items)
    +        binparse = self._base.binparse_value
    +        result = []
    +        result_mask = []
    +        for char in data:
    +            if not IS_PY3K:
    +                char = ord(char)
    +            value, mask = binparse(char)
    +            result.append(value)
    +            result_mask.append(mask)
    +        result = np.array(result, dtype='b1').reshape(
    +            self._arraysize)
    +        result_mask = np.array(result_mask, dtype='b1').reshape(
    +            self._arraysize)
    +        return result, result_mask
    +
    +    def binoutput(self, value, mask):
    +        binoutput = self._base.binoutput
    +        value = np.asarray(value)
    +        mask = np.asarray(mask)
    +        result = [binoutput(x, m)
    +                  for x, m in np.broadcast(value.flat, mask.flat)]
    +        return _empty_bytes.join(result)
    +
    +
    +class Boolean(Converter):
    +    """
    +    Handles the boolean datatype.
    +    """
    +    format = 'b1'
    +    array_type = BooleanArray
    +    vararray_type = VarArray
    +    default = False
    +    binary_question_mark = bytes('?', 'ascii')
    +    binary_true = bytes('T', 'ascii')
    +    binary_false = bytes('F', 'ascii')
    +
    +    def __init__(self, field, config={}, pos=None):
    +        Converter.__init__(self, field, config, pos)
    +
    +    def parse(self, value, config={}, pos=None):
    +        if value is False:
    +            return False, True
    +        mapping = {'TRUE'  : (True, False),
    +                   'FALSE' : (False, False),
    +                   '1'     : (True, False),
    +                   '0'     : (False, False),
    +                   'T'     : (True, False),
    +                   'F'     : (False, False),
    +                   '\0'    : (False, True),
    +                   ' '     : (False, True),
    +                   '?'     : (False, True),
    +                   ''      : (False, True)}
    +        try:
    +            return mapping[value.upper()]
    +        except KeyError:
    +            vo_raise(E05, (value,), config, pos)
    +
    +    def output(self, value, mask):
    +        if mask:
    +            return '?'
    +        if value:
    +            return 'T'
    +        return 'F'
    +
    +    def binparse(self, read):
    +        value = ord(read(1))
    +        return self.binparse_value(value)
    +
    +    _binparse_mapping = {
    +        ord('T')  : (True, False),
    +        ord('t')  : (True, False),
    +        ord('1')  : (True, False),
    +        ord('F')  : (False, False),
    +        ord('f')  : (False, False),
    +        ord('0')  : (False, False),
    +        ord('\0') : (False, True),
    +        ord(' ')  : (False, True),
    +        ord('?')  : (False, True)}
    +
    +    def binparse_value(self, value):
    +        try:
    +            return self._binparse_mapping[value]
    +        except KeyError:
    +            vo_raise(E05, (value,))
    +
    +    def binoutput(self, value, mask):
    +        if mask:
    +            return self.binary_question_mark
    +        if value:
    +            return self.binary_true
    +        return self.binary_false
    +
    +
    +converter_mapping = {
    +    'double'        : Double,
    +    'float'         : Float,
    +    'bit'           : Bit,
    +    'boolean'       : Boolean,
    +    'unsignedByte'  : UnsignedByte,
    +    'short'         : Short,
    +    'int'           : Int,
    +    'long'          : Long,
    +    'floatComplex'  : FloatComplex,
    +    'doubleComplex' : DoubleComplex,
    +    'char'          : Char,
    +    'unicodeChar'   : UnicodeChar }
    +
    +
    +
    [docs]def get_converter(field, config={}, pos=None): + """ + Factory function to get an appropriate converter instance for a + given field. + + Parameters + ---------- + field : astropy.io.vo.tree.Field + + config : dict, optional + Parser configuration dictionary + + pos : tuple + Position in the input XML file. Used for error messages. + + Returns + ------- + converter : astropy.io.vo.converters.Converter + """ + if field.datatype not in converter_mapping: + vo_raise(E06, (field.datatype, field.ID), config) + + cls = converter_mapping[field.datatype] + converter = cls(field, config, pos) + + arraysize = field.arraysize + + # With numeric datatypes, special things need to happen for + # arrays. + if (field.datatype not in ('char', 'unicodeChar') and + arraysize is not None): + if arraysize[-1] == '*': + arraysize = arraysize[:-1] + last_x = arraysize.rfind('x') + if last_x == -1: + arraysize = '' + else: + arraysize = arraysize[:last_x] + fixed = False + else: + fixed = True + + if arraysize != '': + arraysize = [int(x) for x in arraysize.split("x")] + arraysize.reverse() + else: + arraysize = [] + + if arraysize != []: + converter = converter.array_type( + field, converter, arraysize, config) + + if not fixed: + converter = converter.vararray_type( + field, converter, arraysize, config) + + return converter
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/exceptions.html b/_modules/astropy/io/vo/exceptions.html new file mode 100644 index 00000000..06968ead --- /dev/null +++ b/_modules/astropy/io/vo/exceptions.html @@ -0,0 +1,1489 @@ + + + + + + + + + + astropy.io.vo.exceptions — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.exceptions

    +# -*- coding: utf-8 -*-
    +u"""
    +.. _warnings:
    +
    +Warnings
    +--------
    +
    +.. note::
    +    Most of the following warnings indicate violations of the VOTable
    +    specification.  They should be reported to the authors of the
    +    tools that produced the VOTable file.
    +
    +    To control the warnings emitted, use the standard Python
    +    :mod:`warnings` module.  Most of these are of the type
    +    `VOTableSpecWarning`.
    +
    +{warnings}
    +
    +.. _exceptions:
    +
    +Exceptions
    +----------
    +
    +.. note::
    +
    +    This is a list of many of the fatal exceptions emitted by vo.table
    +    when the file does not conform to spec.  Other exceptions may be
    +    raised due to unforeseen cases or bugs in vo.table itself.
    +
    +{exceptions}
    +"""
    +
    +from __future__ import division, absolute_import
    +
    +# STDLIB
    +import io
    +import re
    +import sys
    +from warnings import warn
    +
    +# LOCAL
    +from .util import IS_PY3K
    +
    +
    +__all__ = [
    +    'warn_or_raise', 'vo_raise', 'vo_reraise', 'vo_warn',
    +    'warn_unknown_attrs', 'parse_vowarning', 'VOWarning'
    +    'VOTableChangeWarning', 'VOTableSpecWarning',
    +    'UnimplementedWarning', 'IOWarning', 'VOTableSpecError']
    +
    +
    +MAX_WARNINGS = 10
    +
    +
    +def _format_message(message, name, config={}, pos=None):
    +    if pos is None:
    +        pos = ('?', '?')
    +    filename = config.get('filename', '?')
    +    return '%s:%s:%s: %s: %s' % (filename, pos[0], pos[1], name, message)
    +
    +
    +def _suppressed_warning(warning, config):
    +    warning_class = type(warning)
    +    config.setdefault('_warning_counts', {}).setdefault(warning_class, 0)
    +    config['_warning_counts'][warning_class] += 1
    +    message_count = config['_warning_counts'][warning_class]
    +    if message_count <= MAX_WARNINGS:
    +        if message_count == MAX_WARNINGS:
    +            warning.formatted_message += \
    +                ' (suppressing further warnings of this type...)'
    +        warn(warning)
    +
    +
    +
    [docs]def warn_or_raise(warning_class, exception_class=None, args=(), config={}, + pos=None): + """ + Warn or raise an exception, depending on the pedantic setting. + """ + if config.get('pedantic'): + if exception_class is None: + exception_class = warning_class + vo_raise(exception_class, args, config, pos) + else: + vo_warn(warning_class, args, config, pos) + +
    +
    [docs]def vo_raise(exception_class, args=(), config={}, pos=None): + """ + Raise an exception, with proper position information if available. + """ + raise exception_class(args, config, pos) + +
    +
    [docs]def vo_reraise(exc, config={}, pos=None, additional=''): + """ + Raise an exception, with proper position information if available. + + Restores the original traceback of the exception, and should only + be called within an "except:" block of code. + """ + message = _format_message(str(exc), exc.__class__.__name__, config, pos) + if message.split()[0] == str(exc).split()[0]: + message = str(exc) + if len(additional): + message += ' ' + additional + exc.args = (message,) + raise exc + +
    +
    [docs]def vo_warn(warning_class, args=(), config={}, pos=None): + """ + Warn, with proper position information if available. + """ + warning = warning_class(args, config, pos) + _suppressed_warning(warning, config) + +
    +def warn_unknown_attrs(element, attrs, config, pos, good_attr=[]): + for attr in attrs: + if attr not in good_attr: + vo_warn(W48, (attr, element), config, pos) + + +_warning_pat = re.compile( + (r":?(?P<nline>[0-9?]+):(?P<nchar>[0-9?]+): " + + r"((?P<warning>[WE]\d+): )?(?P<rest>.*)$")) + + +
    [docs]def parse_vowarning(line): + """ + Parses the vo warning string back into its parts. + """ + result = {} + match = _warning_pat.search(line) + if match: + result['warning'] = warning = match.group('warning') + if warning is not None: + result['is_warning'] = (warning[0].upper() == 'W') + result['is_exception'] = (warning[0].upper() == 'E') + result['number'] = int(match.group('warning')[1:]) + result['doc_url'] = "vo/api_exceptions.html#%s" % warning.lower() + else: + result['is_warning'] = False + result['is_exception'] = False + result['is_other'] = True + result['number'] = None + result['doc_url'] = None + result['nline'] = int(match.group('nline')) + result['nchar'] = int(match.group('nchar')) + result['message'] = match.group('rest') + result['is_something'] = True + else: + result['warning'] = None + result['is_warning'] = False + result['is_exception'] = False + result['is_other'] = False + result['is_something'] = False + + return result + +
    +
    [docs]class VOWarning(Warning): + """ + The base class of all VO warnings and exceptions. Handles the + formatting of the message with a warning or exception code, + filename, line and column number. + """ + default_args = () + + def __init__(self, args, config={}, pos=None): + msg = self.message % args + self.formatted_message = _format_message( + msg, self.__class__.__name__, config, pos) + + def __str__(self): + return self.formatted_message + + @classmethod + def get_short_name(cls): + if len(cls.default_args): + return cls.message % cls.default_args + return cls.message + +
    +
    [docs]class VOTableChangeWarning(VOWarning, SyntaxWarning): + """ + Warning emitted when a change has been made to the input XML file. + """ + pass + +
    +
    [docs]class VOTableSpecWarning(VOWarning, SyntaxWarning): + """ + Warning emitted when the input XML file violates the spec, but + there is an obvious workaround. + """ + pass + +
    +
    [docs]class UnimplementedWarning(VOWarning, SyntaxWarning): + """ + Warning emitted when the a feature of VOTABLE is not implemented. + """ + pass + +
    +
    [docs]class IOWarning(VOWarning, RuntimeWarning): + """ + Warning emitted when a network or IO error occurred, but the + system is able to recover using a cached copy of the data or some + other fallback. + """ + pass + +
    +
    [docs]class VOTableSpecError(VOWarning, ValueError): + """ + Error raised when the input XML file violates the spec and there + is no good workaround. + """ + pass + +
    +class W01(VOTableSpecWarning): + """ + The VOTable spec states: + + If a cell contains an array or complex number, it should be + encoded as multiple numbers separated by whitespace. + + Many VOTable files in the wild use commas as a separator instead, + and ``vo.table`` supports this convention when not in + :ref:`pedantic-mode`. + + `vo.table` always outputs files using only spaces, regardless of + how they were input. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#toc-header-35>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:TABLEDATA>`__ + """ + + message = "Array uses commas rather than whitespace" + + +class W02(VOTableSpecWarning): + """ + XML ids must match the following regular expression:: + + ^[A-Za-z_][A-Za-z0-9_\.\-]*$ + + The VOTable 1.1 says the following: + + According to the XML standard, the attribute ``ID`` is a + string beginning with a letter or underscore (``_``), followed + by a sequence of letters, digits, or any of the punctuation + characters ``.`` (dot), ``-`` (dash), ``_`` (underscore), or + ``:`` (colon). + + However, this is in conflict with the XML standard, which says + colons may not be used. VOTable 1.1's own schema does not allow a + colon here. Therefore, ``vo.table`` disallows the colon. + + VOTable 1.2 corrects this error in the specification. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, + `XML Names <http://www.w3.org/TR/REC-xml/#NT-Name>`__ + """ + + message = "%s attribute '%s' is invalid. Must be a standard XML id" + default_args = ('x', 'y') + + +class W03(VOTableChangeWarning): + """ + The VOTable 1.1 spec says the following about ``name`` vs. ``ID`` + on ``FIELD`` and ``VALUE`` elements: + + ``ID`` and ``name`` attributes have a different role in + VOTable: the ``ID`` is meant as a *unique identifier* of an + element seen as a VOTable component, while the ``name`` is + meant for presentation purposes, and need not to be unique + throughout the VOTable document. The ``ID`` attribute is + therefore required in the elements which have to be + referenced, but in principle any element may have an ``ID`` + attribute. ... In summary, the ``ID`` is different from the + ``name`` attribute in that (a) the ``ID`` attribute is made + from a restricted character set, and must be unique throughout + a VOTable document whereas names are standard XML attributes + and need not be unique; and (b) there should be support in the + parsing software to look up references and extract the + relevant element with matching ``ID``. + + It is further recommended in the VOTable 1.2 spec: + + While the ``ID`` attribute has to be unique in a VOTable + document, the ``name`` attribute need not. It is however + recommended, as a good practice, to assign unique names within + a ``TABLE`` element. This recommendation means that, between a + ``TABLE`` and its corresponding closing ``TABLE`` tag, + ``name`` attributes of ``FIELD``, ``PARAM`` and optional + ``GROUP`` elements should be all different. + + Since ``vo.table`` requires a unique identifier for each of its + columns, ``ID`` is used for the column name when present. + However, when ``ID`` is not present, (since it is not required by + the specification) ``name`` is used instead. However, ``name`` + must be cleansed by replacing invalid characters (such as + whitespace) with underscores. + + .. note:: + This warning does not indicate that the input file is invalid + with respect to the VOTable specification, only that the + column names in the record array may not match exactly the + ``name`` attributes specified in the file. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ + """ + + message = "Implictly generating an ID from a name '%s' -> '%s'" + default_args = ('x', 'y') + + +class W04(VOTableSpecWarning): + """ + The ``content-type`` attribute must use MIME content-type syntax as + defined in `RFC 2046 <http://tools.ietf.org/html/rfc2046>`__. + + The current check for validity is somewhat over-permissive. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:link>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:link>`__ + """ + + message = "content-type '%s' must be a valid MIME content type" + default_args = ('x',) + + +class W05(VOTableSpecWarning): + """ + The attribute must be a valid URI as defined in `RFC 2396 + <http://www.ietf.org/rfc/rfc2396.txt>`_. + """ + + message = "'%s' is not a valid URI" + default_args = ('x',) + + +class W06(VOTableSpecWarning): + """ + This warning is emitted when a ``ucd`` attribute does not match + the syntax of a `unified content descriptor + <http://vizier.u-strasbg.fr/doc/UCD.htx>`__. + + If the VOTable version is 1.2 or later, the UCD will also be + checked to ensure it conforms to the controlled vocabulary defined + by UCD1+. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:ucd>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:ucd>`__ + """ + + message = "Invalid UCD '%s': %s" + default_args = ('x', 'explanation') + + +class W07(VOTableSpecWarning): + """ + As astro year field is a Besselian or Julian year matching the + regular expression:: + + ^[JB]?[0-9]+([.][0-9]*)?$ + + Defined in this XML Schema snippet:: + + <xs:simpleType name="astroYear"> + <xs:restriction base="xs:token"> + <xs:pattern value="[JB]?[0-9]+([.][0-9]*)?"/> + </xs:restriction> + </xs:simpleType> + """ + + message = "Invalid astroYear in %s: '%s'" + default_args = ('x', 'y') + + +class W08(VOTableSpecWarning): + """ + To avoid local-dependent number parsing differences, ``vo.table`` + may require a string or unicode string where a numeric type may + make more sense. + """ + + if IS_PY3K: + message = "'%s' must be a str or bytes object" + else: + message = "'%s' must be a str or unicode object" + default_args = ('x',) + + +class W09(VOTableSpecWarning): + """ + The VOTable specification uses the attribute name ``ID`` (with + uppercase letters) to specify unique identifiers. Some + VOTable-producing tools use the more standard lowercase ``id`` + instead. ``vo.table`` accepts ``id`` and emits this warning when + not in ``pedantic`` mode. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ + """ + + message = "ID attribute not capitalized" + + +class W10(VOTableSpecWarning): + """ + The parser has encountered an element that does not exist in the + specification, or appears in an invalid context. Check the file + against the VOTable schema (with a tool such as `xmllint + <http://xmlsoft.org/xmllint.html>`__. If the file validates + against the schema, and you still receive this warning, this may + indicate a bug in ``vo.table``. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ + """ + + message = "Unknown tag '%s'. Ignoring" + default_args = ('x',) + + +class W11(VOTableSpecWarning): + """ + Earlier versions of the VOTable specification used a ``gref`` + attribute on the ``LINK`` element to specify a `GLU reference + <http://simbad3.u-strasbg.fr/glu/glu.htx>`__. New files should + specify a ``glu:`` protocol using the ``href`` attribute. + + Since ``vo.table`` does not currently support GLU references, it + likewise does not automatically convert the ``gref`` attribute to + the new form. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:link>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:link>`__ + """ + + message = "The gref attribute on LINK is deprecated in VOTable 1.1" + + +class W12(VOTableChangeWarning): + """ + In order to name the columns of the Numpy record array, each + ``FIELD`` element must have either an ``ID`` or ``name`` attribute + to derive a name from. Strictly speaking, according to the + VOTable schema, the ``name`` attribute is required. However, if + ``name`` is not present by ``ID`` is, and *pedantic mode* is off, + ``vo.table`` will continue without a ``name`` defined. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ + """ + + message = ( + "'%s' element must have at least one of 'ID' or 'name' attributes") + default_args = ('x',) + + +class W13(VOTableSpecWarning): + """ + Some VOTable files in the wild use non-standard datatype names. These + are mapped to standard ones using the following mapping:: + + string -> char + unicodeString -> unicodeChar + int16 -> short + int32 -> int + int64 -> long + float32 -> float + float64 -> double + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ + """ + + message = "'%s' is not a valid VOTable datatype, should be '%s'" + default_args = ('x', 'y') + + +# W14: Deprecated + + +class W15(VOTableSpecWarning): + """ + The ``name`` attribute is required on every ``FIELD`` element. + However, many VOTable files in the wild omit it and provide only + an ``ID`` instead. In this case, when *pedantic mode* is off, + ``vo.table`` will copy the ``name`` attribute to a new ``ID`` + attribute. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ + """ + + message = "%s element missing required 'name' attribute" + default_args = ('x',) + +# W16: Deprecated + + +class W17(VOTableSpecWarning): + """ + A ``DESCRIPTION`` element can only appear once within its parent + element. + + According to the schema, it may only occur once (`1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__) + + However, it is a `proposed extension + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:addesc>`__ + to VOTable 1.2. + """ + + message = "%s element contains more than one DESCRIPTION element" + default_args = ('x',) + + +class W18(VOTableSpecWarning): + """ + The number of rows explicitly specified in the ``nrows`` attribute + does not match the actual number of rows (``TR`` elements) present + in the ``TABLE``. This may indicate truncation of the file, or an + internal error in the tool that produced it. If *pedantic mode* + is off, parsing will proceed, with the loss of some performance. + + **References:** `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC10>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC10>`__ + """ + + message = 'TABLE specified nrows=%s, but table contains %s rows' + default_args = ('x', 'y') + + +class W19(VOTableSpecWarning): + """ + The column fields as defined using ``FIELD`` elements do not match + those in the headers of the embedded FITS file. If *pedantic + mode* is off, the embedded FITS file will take precedence. + """ + + message = ( + 'The fields defined in the VOTable do not match those in the ' + + 'embedded FITS file') + + +class W20(VOTableSpecWarning): + """ + If no version number is explicitly given in the VOTable file, the + parser assumes it is written to the VOTable 1.1 specification. + """ + + message = 'No version number specified in file. Assuming %s' + default_args = ('1.1',) + + +class W21(UnimplementedWarning): + """ + Unknown issues may arise using ``vo.table`` with VOTable files + from a version other than 1.1 or 1.2. + """ + + message = ( + 'vo.table is designed for VOTable version 1.1 and 1.2, but ' + + 'this file is %s') + default_args = ('x',) + + +class W22(VOTableSpecWarning): + """ + Version 1.0 of the VOTable specification used the ``DEFINITIONS`` + element to define coordinate systems. Version 1.1 now uses + ``COOSYS`` elements throughout the document. + + **References:** `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:definitions>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:definitions>`__ + """ + + message = 'The DEFINITIONS element is deprecated in VOTable 1.1. Ignoring' + + +class W23(IOWarning): + """ + Raised when the VO service database can not be updated (possibly + due to a network outage). This is only a warning, since an older + and possible out-of-date VO service database was available + locally. + """ + + message = "Unable to update service information for '%s'" + default_args = ('x',) + + +class W24(VOWarning, FutureWarning): + """ + The VO catalog database retrieved from the www is designed for a + newer version of vo.table. This may cause problems or limited + features performing service queries. Consider upgrading vo.table + to the latest version. + """ + + message = "The VO catalog database is for a later version of vo.table" + + +class W25(IOWarning): + """ + A VO service query failed due to a network error or malformed + arguments. Another alternative service may be attempted. If all + services fail, an exception will be raised. + """ + + message = "'%s' failed with: %s" + default_args = ('service', '...') + + +class W26(VOTableSpecWarning): + """ + The given element was not supported inside of the given element + until the specified VOTable version, however the version declared + in the file is for an earlier version. These attributes may not + be written out to the file. + """ + + message = "'%s' inside '%s' added in VOTable %s" + default_args = ('child', 'parent', 'X.X') + + +class W27(VOTableSpecWarning): + """ + The ``COOSYS`` element was deprecated in VOTABLE version 1.2 in + favor of a reference to the Space-Time Coordinate (STC) data + model (see `utype + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:utype>`__ + and the IVOA note `referencing STC in VOTable + <http://ivoa.net/Documents/latest/VOTableSTC.html>`__. + """ + + message = "COOSYS deprecated in VOTable 1.2" + + +class W28(VOTableSpecWarning): + """ + The given attribute was not supported on the given element until the + specified VOTable version, however the version declared in the file is + for an earlier version. These attributes may not be written out to + the file. + """ + + message = "'%s' on '%s' added in VOTable %s" + default_args = ('attribute', 'element', 'X.X') + + +class W29(VOTableSpecWarning): + """ + Some VOTable files specify their version number in the form "v1.0", + when the only supported forms in the spec are "1.0". + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ + """ + + message = "Version specified in non-standard form '%s'" + default_args = ('v1.0',) + + +class W30(VOTableSpecWarning): + """ + Some VOTable files write missing floating-point values in non-standard + ways, such as "null" and "-". In non-pedantic mode, any non-standard + floating-point literals are treated as missing values. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ + """ + + message = "Invalid literal for float '%s'. Treating as empty." + default_args = ('x',) + + +class W31(VOTableSpecWarning): + """ + Since NaN's can not be represented in integer fields directly, a null + value must be specified in the FIELD descriptor to support reading + NaN's from the tabledata. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ + """ + + message = "NaN given in an integral field without a specified null value" + + +class W32(VOTableSpecWarning): + """ + Each field in a table must have a unique ID. If two or more fields + have the same ID, some will be renamed to ensure that all IDs are + unique. + + From the VOTable 1.2 spec: + + The ``ID`` and ``ref`` attributes are defined as XML types + ``ID`` and ``IDREF`` respectively. This means that the + contents of ``ID`` is an identifier which must be unique + throughout a VOTable document, and that the contents of the + ``ref`` attribute represents a reference to an identifier + which must exist in the VOTable document. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ + """ + + message = "Duplicate ID '%s' renamed to '%s' to ensure uniqueness" + default_args = ('x', 'x_2') + + +class W33(VOTableChangeWarning): + """ + Each field in a table must have a unique name. If two or more + fields have the same name, some will be renamed to ensure that all + names are unique. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ + """ + + message = "Column name '%s' renamed to '%s' to ensure uniqueness" + default_args = ('x', 'x_2') + + +class W34(VOTableSpecWarning): + """ + The attribute requires the value to be a valid XML token, as + defined by `XML 1.0 + <http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-Nmtoken>`__. + """ + + message = "'%s' is an invalid token for attribute '%s'" + default_args = ('x', 'y') + + +class W35(VOTableSpecWarning): + """ + The ``name`` and ``value`` attributes are required on all ``INFO`` + elements. + + **References:** `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC32>` + """ + + message = "'%s' attribute required for INFO elements" + default_args = ('x',) + + +class W36(VOTableSpecWarning): + """ + If the field specifies a ``null`` value, that value must conform + to the given ``datatype``. + + **References:** `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>` + """ + + message = "null value '%s' does not match field datatype, setting to 0" + default_args = ('x',) + + +class W37(UnimplementedWarning): + """ + The 3 datatypes defined in the VOTable specification and supported by + vo.table are ``TABLEDATA``, ``BINARY`` and ``FITS``. + + **References:** `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:data>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:data>` + """ + + message = "Unsupported data format '%s'" + default_args = ('x',) + + +class W38(VOTableSpecWarning): + """ + The only encoding for local binary data supported by the VOTable + specification is base64. + """ + + message = "Inline binary data must be base64 encoded, got '%s'" + default_args = ('x',) + + +class W39(VOTableSpecWarning): + """ + Bit values do not support masking. This warning is raised upon + setting masked data in a bit column. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ + """ + + message = "Bit values can not be masked" + + +class W40(VOTableSpecWarning): + """ + This is a terrible hack to support Simple Image Access Protocol + results from `<archive.noao.edu>`__. It creates a field for the + coordinate projection type of type "double", which + actually contains character data. We have to hack the field + to store character data, or we can't read it in. A warning + will be raised when this happens. + """ + + message = "'cprojection' datatype repaired" + + +class W41(VOTableSpecWarning): + """ + An XML namespace was specified on the ``VOTABLE`` element, but the + namespace does not match what is expected for a ``VOTABLE`` file. + + The ``VOTABLE`` namespace is:: + + http://www.ivoa.net/xml/VOTable/vX.X + + where "X.X" is the version number. + + Some files in the wild set the namespace to the location of the + VOTable schema, which is not correct and will not pass some + validating parsers. + """ + + message = ( + "An XML namespace is specified, but is incorrect. Expected " + + "'%s', got '%s'") + default_args = ('x', 'y') + + +class W42(VOTableSpecWarning): + """ + The root element should specify a namespace. + + The ``VOTABLE`` namespace is:: + + http://www.ivoa.net/xml/VOTable/vX.X + + where "X.X" is the version number. + """ + + message = "No XML namespace specified" + + +class W43(VOTableSpecWarning): + """ + Referenced elements should be defined before referees. From the + VOTable 1.2 spec: + + In VOTable1.2, it is further recommended to place the ID + attribute prior to referencing it whenever possible. + """ + + message = "%s ref='%s' which has not already been defined" + default_args = ('element', 'x',) + + +class W44(VOTableSpecWarning): + """ + ``VALUES`` elements that reference another element should not have + their own content. + + From the VOTable 1.2 spec: + + The ``ref`` attribute of a ``VALUES`` element can be used to + avoid a repetition of the domain definition, by referring to a + previously defined ``VALUES`` element having the referenced + ``ID`` attribute. When specified, the ``ref`` attribute + defines completely the domain without any other element or + attribute, as e.g. ``<VALUES ref="RAdomain"/>`` + """ + + message = "VALUES element with ref attribute has content ('%s')" + default_args = ('element',) + + +class W45(VOWarning, ValueError): + """ + The ``content-role`` attribute on the ``LINK`` element must be one of + the following:: + + query, hints, doc, location + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ + """ + + message = "content-role attribute '%s' invalid" + default_args = ('x',) + + +class W46(VOTableSpecWarning): + """ + The given char or unicode string is too long for the specified + field length. + """ + + message = "%s value is too long for specified length of %s" + default_args = ('char or unicode', 'x') + + +class W47(VOTableSpecWarning): + """ + If no arraysize is specified on a char field, the default of '1' + is implied, but this is rarely what is intended. + """ + + message = "Missing arraysize indicates length 1" + + +class W48(VOTableSpecWarning): + """ + The attribute is not defined in the specification. + """ + + message = "Unknown attribute '%s' on %s" + default_args = ('attribute', 'element') + + +class W49(VOTableSpecWarning): + """ + Empty cell illegal for integer fields. + + If a \"null\" value was specified for the cell, it will be used + for the value, otherwise, 0 will be used. + """ + + message = "Empty cell illegal for integer fields." + + +class W50(VOTableSpecWarning): + """ + Invalid unit string as defined in the `Standards for Astronomical + Catalogues, Version 2.0 + <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_. + """ + + message = "Invalid unit string '%s'" + default_args = ('x',) + + +class E01(VOWarning, ValueError): + """ + The size specifier for a ``char`` or ``unicode`` field must be + only a number followed, optionally, by an asterisk. + Multi-dimensional size specifiers are not supported for these + datatypes. + + Strings, which are defined as a set of characters, can be + represented in VOTable as a fixed- or variable-length array of + characters:: + + <FIELD name="unboundedString" datatype="char" arraysize="*"/> + + A 1D array of strings can be represented as a 2D array of + characters, but given the logic above, it is possible to define a + variable-length array of fixed-length strings, but not a + fixed-length array of variable-length strings. + """ + + message = "Invalid size specifier '%s' for a %s field (in field '%s')" + default_args = ('x', 'char/unicode', 'y') + + +class E02(VOWarning, ValueError): + """ + The number of array elements in the data does not match that specified + in the FIELD specifier. + """ + + message = ( + "Incorrect number of elements in array. " + + "Expected multiple of %s, got %s") + default_args = ('x', 'y') + + +class E03(VOWarning, ValueError): + """ + Complex numbers should be two values separated by whitespace. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ + """ + + message = "'%s' does not parse as a complex number" + default_args = ('x',) + + +class E04(VOWarning, ValueError): + """ + A ``bit`` array should be a string of '0's and '1's. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ + """ + + message = "Invalid bit value '%s'" + default_args = ('x',) + + +class E05(VOWarning, ValueError): + """ + A ``boolean`` value should be one of the following strings (case + insensitive) in the ``TABLEDATA`` format:: + + 'TRUE', 'FALSE', '1', '0', 'T', 'F', '\\0', ' ', '?' + + and in ``BINARY`` format:: + + 'T', 'F', '1', '0', '\\0', ' ', '?' + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ + """ + + message = "Invalid boolean value '%s'" + default_args = ('x',) + + +class E06(VOWarning, ValueError): + """ + The supported datatypes are:: + + double, float, bit, boolean, unsignedByte, short, int, long, + floatComplex, doubleComplex, char, unicodeChar + + The following non-standard aliases are also supported, but in + these case :ref:`W13 <W13>` will be raised:: + + string -> char + unicodeString -> unicodeChar + int16 -> short + int32 -> int + int64 -> long + float32 -> float + float64 -> double + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ + """ + + message = "Unknown datatype '%s' on field '%s'" + default_args = ('x', 'y') + +# E07: Deprecated + + +class E08(VOWarning, ValueError): + """ + The ``type`` attribute on the ``VALUES`` element must be either + ``legal`` or ``actual``. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`__ + """ + + message = "type must be 'legal' or 'actual', but is '%s'" + default_args = ('x',) + + +class E09(VOWarning, ValueError): + """ + The ``MIN``, ``MAX`` and ``OPTION`` elements must always have a + ``value`` attribute. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`__ + """ + + message = "'%s' must have a value attribute" + default_args = ('x',) + + +class E10(VOWarning, ValueError): + """ + From VOTable 1.1 and later, ``FIELD`` and ``PARAM`` elements must have + a ``datatype`` field. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:FIELD>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#elem:FIELD>`__ + """ + + message = "'datatype' attribute required on all '%s' elements" + default_args = ('FIELD',) + + +class E11(VOWarning, ValueError): + """ + The precision attribute is meant to express the number of significant + digits, either as a number of decimal places (e.g. ``precision="F2"`` or + equivalently ``precision="2"`` to express 2 significant figures + after the decimal point), or as a number of significant figures + (e.g. ``precision="E5"`` indicates a relative precision of 10-5). + + It is validated using the following regular expression:: + + [EF]?[1-9][0-9]* + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:form>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:form>`__ + """ + + message = "precision '%s' is invalid" + default_args = ('x',) + + +class E12(VOWarning, ValueError): + """ + The width attribute is meant to indicate to the application the + number of characters to be used for input or output of the + quantity. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:form>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:form>`__ + """ + + message = "width must be a positive integer, got '%s'" + default_args = ('x',) + + +class E13(VOWarning, ValueError): + u""" + From the VOTable 1.2 spec: + + A table cell can contain an array of a given primitive type, + with a fixed or variable number of elements; the array may + even be multidimensional. For instance, the position of a + point in a 3D space can be defined by the following:: + + <FIELD ID="point_3D" datatype="double" arraysize="3"/> + + and each cell corresponding to that definition must contain + exactly 3 numbers. An asterisk (\*) may be appended to + indicate a variable number of elements in the array, as in:: + + <FIELD ID="values" datatype="int" arraysize="100*"/> + + where it is specified that each cell corresponding to that + definition contains 0 to 100 integer numbers. The number may + be omitted to specify an unbounded array (in practice up to + =~2×10⁹ elements). + + A table cell can also contain a multidimensional array of a + given primitive type. This is specified by a sequence of + dimensions separated by the ``x`` character, with the first + dimension changing fastest; as in the case of a simple array, + the last dimension may be variable in length. As an example, + the following definition declares a table cell which may + contain a set of up to 10 images, each of 64×64 bytes:: + + <FIELD ID="thumbs" datatype="unsignedByte" arraysize="64×64×10*"/> + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:dim>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:dim>`__ + """ + + message = "Invalid arraysize attribute '%s'" + default_args = ('x',) + + +class E14(VOWarning, ValueError): + """ + All ``PARAM`` elements must have a ``value`` attribute. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:FIELD>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#elem:FIELD>`__ + """ + + message = "value attribute is required for all PARAM elements" + + +class E15(VOWarning, ValueError): + """ + All ``COOSYS`` elements must have an ``ID`` attribute. + + Note that the VOTable 1.1 specification says this attribute is + optional, but its corresponding schema indicates it is required. + + In VOTable 1.2, the ``COOSYS`` element is deprecated. + """ + + message = "ID attribute is required for all COOSYS elements" + + +class E16(VOTableSpecWarning): + """ + The ``system`` attribute on the ``COOSYS`` element must be one of the + following:: + + 'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic', + 'supergalactic', 'xy', 'barycentric', 'geo_app' + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:COOSYS>`__ + """ + + message = "Invalid system attribute '%s'" + default_args = ('x',) + + +class E17(VOWarning, ValueError): + """ + ``extnum`` attribute must be a positive integer. + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ + """ + + message = "extnum must be a positive integer" + + +class E18(VOWarning, ValueError): + """ + The ``type`` attribute of the ``RESOURCE`` element must be one of + "results" or "meta". + + **References**: `1.1 + <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, + `1.2 + <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ + """ + + message = "type must be 'results' or 'meta', not '%s'" + default_args = ('x',) + + +class E19(VOWarning, ValueError): + """ + Raised either when the file doesn't appear to be XML, or the root + element is not VOTABLE. + """ + + message = "File does not appear to be a VOTABLE" + + +class E20(VOTableSpecError): + """ + The table had only *x* fields defined, but the data itself has more + columns than that. + """ + + message = "Data has more columns than are defined in the header (%s)" + default_args = ('x',) + + +class E21(VOWarning, ValueError): + """ + The table had *x* fields defined, but the data itself has only *y* + columns. + """ + + message = "Data has fewer columns (%s) than are defined in the header (%s)" + default_args = ('x', 'y') + + +def _get_warning_and_exception_classes(prefix): + classes = [] + for key, val in globals().iteritems(): + if re.match(prefix + "[0-9]{2}", key): + classes.append((key, val)) + classes.sort() + return classes + + +def _build_doc_string(): + from textwrap import dedent + + def generate_set(prefix): + classes = _get_warning_and_exception_classes(prefix) + + out = io.StringIO() + + for name, cls in classes: + out.write(u".. _%s:\n\n" % name) + msg = "%s: %s" % (cls.__name__, cls.get_short_name()) + if not isinstance(msg, unicode): + msg = msg.decode('utf-8') + out.write(msg) + out.write(u'\n') + out.write(u'~' * len(msg)) + out.write(u'\n\n') + doc = cls.__doc__ + if not isinstance(doc, unicode): + doc = doc.decode('utf-8') + out.write(dedent(doc)) + out.write(u'\n\n') + + return out.getvalue() + + warnings = generate_set(u'W') + exceptions = generate_set(u'E') + + return {u'warnings': warnings, + u'exceptions': exceptions} + +__doc__ = __doc__.format(**_build_doc_string()) + +__all__.extend([x[0] for x in _get_warning_and_exception_classes(u'W')]) +__all__.extend([x[0] for x in _get_warning_and_exception_classes(u'E')]) +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/table.html b/_modules/astropy/io/vo/table.html new file mode 100644 index 00000000..2b26f90e --- /dev/null +++ b/_modules/astropy/io/vo/table.html @@ -0,0 +1,340 @@ + + + + + + + + + + astropy.io.vo.table — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.table

    +"""
    +This file contains a contains the high-level functions to read a
    +VOTable file.
    +"""
    +
    +from __future__ import division, absolute_import
    +
    +# STDLIB
    +import io
    +import sys
    +import warnings
    +
    +# LOCAL
    +from . import exceptions
    +from . import tree
    +from . import util
    +from ...utils.xml import iterparser
    +from ...config import ConfigurationItem
    +
    +
    +__all__ = ['parse', 'parse_single_table', 'validate']
    +
    +
    +PEDANTIC = ConfigurationItem(
    +    'pedantic',
    +    True,
    +    'When True, treat fixable violations of the VOTable spec as exceptions.')
    +
    +
    +
    [docs]def parse(source, columns=None, invalid='exception', pedantic=None, + chunk_size=tree.DEFAULT_CHUNK_SIZE, table_number=None, + filename=None, + _debug_python_based_parser=False): + """ + Parses a VOTABLE_ xml file (or file-like object), and returns a + `~astropy.io.vo.tree.VOTable` object, with nested + `~astropy.io.vo.tree.Resource` instances and + `~astropy.io.vo.tree.Table` instances. + + Parameters + ---------- + source : str or readable file-like object + Path or file object containing a VOTABLE_ xml file. + + columns : sequence of str, optional + List of field names to include in the output. The default is + to include all fields. + + invalid : str, optional + One of the following values: + + - 'exception': throw an exception when an invalid value is + encountered (default) + + - 'mask': mask out invalid values + + pedantic : bool, optional + When `True`, raise an error when the file violates the spec, + otherwise issue a warning. Warnings may be controlled using + the standard Python mechanisms. See the `warnings` + module in the Python standard library for more information. + When not provided, uses the configuration setting + `astropy.io.vo.pedantic`, which defaults to True. + + chunk_size : int, optional + The number of rows to read before converting to an array. + Higher numbers are likely to be faster, but will consume more + memory. + + table_number : int, optional + The number of table in the file to read in. If `None`, all + tables will be read. If a number, 0 refers to the first table + in the file, and only that numbered table will be parsed and + read in. + + filename : str, optional + A filename, URL or other identifier to use in error messages. + If *filename* is None and *source* is a string (i.e. a path), + then *source* will be used as a filename for error messages. + Therefore, *filename* is only required when source is a + file-like object. + + Returns + ------- + votable : `astropy.io.vo.tree.VOTableFile` object + + See also + -------- + astropy.io.vo.exceptions : The exceptions this function may raise. + """ + invalid = invalid.lower() + assert invalid in ('exception', 'mask') + + if pedantic is None: + pedantic = PEDANTIC() + + config = { + 'columns' : columns, + 'invalid' : invalid, + 'pedantic' : pedantic, + 'chunk_size' : chunk_size, + 'table_number' : table_number, + 'filename' : filename} + + if filename is None and isinstance(source, basestring): + config['filename'] = source + + with iterparser.get_xml_iterator( + source, + _debug_python_based_parser=_debug_python_based_parser) as iterator: + return tree.VOTableFile( + config=config, pos=(1, 1)).parse(iterator, config) + +
    +
    [docs]def parse_single_table(source, **kwargs): + """ + Parses a VOTABLE_ xml file (or file-like object), reads only the + first TABLE_ element, and returns a `~astropy.io.vo.tree.Table` + instance. + + See `parse` for a description of the keyword arguments. + + Returns + ------- + votable : `astropy.io.vo.tree.Table` object + """ + if kwargs.get('table_number') is None: + kwargs['table_number'] = 0 + + votable = parse(source, **kwargs) + + return votable.get_first_table() + +
    +
    [docs]def validate(filename, output=sys.stdout, xmllint=False): + """ + Prints a validation report for the given file. + + Parameters + ---------- + filename : str path + Path to a VOTABLE_ xml file. + + output : writable file-like object, optional + Where to output the report. Defaults to `sys.stdout`. + If `None`, the output will be returned as a string. + + xmllint : bool, optional + When `True`, also send the file to `xmllint` for schema and + DTD validation. Requires that `xmllint` is installed. The + default is `False`. + + Returns + ------- + is_valid : bool or str + Returns `True` if no warnings were found. If `output` is + `None`, the return value will be a string. + """ + import textwrap + from ...utils.console import print_code_line, color_print + + return_as_str = False + if output is None: + output = io.StringIO() + + lines = [] + votable = None + + # This is a special variable used by the Python warnings + # infrastructure to keep track of warnings that have already been + # seen. Since we want to get every single warning out of this, we + # have to delete it first. + if hasattr(exceptions, '__warningregistry__'): + del exceptions.__warningregistry__ + + with io.open(filename, 'rb') as input: + with warnings.catch_warnings(record=True) as warning_lines: + warnings.resetwarnings() + warnings.simplefilter("always", append=True) + try: + votable = parse(input, pedantic=False, filename=filename) + except ValueError as e: + lines.append(str(e)) + lines = [str(x.message) for x in warning_lines] + lines + + output.write(u"Validation report for {0}\n\n".format(filename)) + + if len(lines): + xml_lines = iterparser.xml_readlines(filename) + + for warning in lines: + w = exceptions.parse_vowarning(warning) + + if not w['is_something']: + output.write(warning) + output.write(u'\n\n') + else: + line = xml_lines[w['nline'] - 1] + warning = w['warning'] + if warning.startswith('W'): + color = 'yellow' + else: + color = 'red' + color_print( + u'{0:d}: '.format(w['nline']), '', + warning, color, + u': ', '', + textwrap.fill( + w['message'], + initial_indent=u' ', + subsequent_indent=u' ').lstrip(), + file=output) + print_code_line(line, w['nchar'], file=output) + output.write(u'\n') + else: + output.write(u'astropy.io.vo found no violations.\n\n') + + success = 0 + if xmllint: + if votable is None: + version = "1.1" + else: + version = votable.version + success, stdout, stderr = xmlutil.validate_schema( + filename, version) + + if success != 0: + output.write( + u'xmllint schema violations:\n\n') + output.write(stderr) + else: + output.write(u'xmllint passed\n') + + if return_as_str: + return output.getvalue() + return len(lines) == 0 and success == 0 +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/tree.html b/_modules/astropy/io/vo/tree.html new file mode 100644 index 00000000..72fc8485 --- /dev/null +++ b/_modules/astropy/io/vo/tree.html @@ -0,0 +1,3178 @@ + + + + + + + + + + astropy.io.vo.tree — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.tree

    +# TODO: Test FITS parsing
    +
    +from __future__ import division, absolute_import
    +
    +from .util import IS_PY3K
    +
    +# STDLIB
    +import base64
    +import codecs
    +import io
    +from math import ceil
    +from operator import attrgetter
    +import re
    +import sys
    +import urllib2
    +if IS_PY3K:
    +    string_types = (str, bytes)
    +else:
    +    string_types = (str, unicode)
    +
    +# THIRD-PARTY
    +import numpy as np
    +try:
    +    import pyfits
    +    _has_pyfits = True
    +except ImportError:
    +    _has_pyfits = False
    +
    +# LOCAL
    +from ... import __version__ as astropy_version
    +from ...utils.collections import HomogeneousList
    +from ...utils.xml.writer import XMLWriter
    +
    +from . import converters
    +from .exceptions import (warn_or_raise, vo_warn, vo_raise, vo_reraise,
    +    warn_unknown_attrs, UnimplementedWarning, VOTableChangeWarning,
    +    W06, W07, W08, W09, W10, W11, W12, W13, W15, W17, W18, W19, W20,
    +    W21, W22, W26, W27, W28, W29, W32, W33, W35, W36, W37, W38, W40,
    +    W41, W42, W43, W44, W45, W48, E06, E08, E09, E10, E11, E12, E13,
    +    E14, E15, E16, E17, E18, E19, E20, E21)
    +from . import ucd as ucd_mod
    +from .unit import check_unit
    +from . import util
    +from . import xmlutil
    +
    +try:
    +    from . import tablewriter
    +    _has_c_tabledata_writer = True
    +except ImportError:
    +    _has_c_tabledata_writer = False
    +
    +
    +__all__ = [
    +    'Link', 'Info', 'Values', 'Field', 'Param', 'CooSys',
    +    'FieldRef', 'ParamRef', 'Group', 'Table', 'Resource',
    +    'VOTableFile'
    +    ]
    +
    +
    +# The default number of rows to read in each chunk before converting
    +# to an array.
    +DEFAULT_CHUNK_SIZE = 256
    +RESIZE_AMOUNT = 1.5
    +
    +######################################################################
    +# FACTORY FUNCTIONS
    +
    +
    +def _lookup_by_id_factory(iterator, element_name, doc):
    +    """
    +    Creates a function useful for looking up an element by ID.
    +
    +    Parameters
    +    ----------
    +    iterator : generator
    +        A generator that iterates over some arbitrary set of elements
    +
    +    element_name : str
    +        The XML element name of the elements being iterated over (used
    +        for error messages only).
    +
    +    doc : str
    +        A docstring to apply to the generated function.
    +
    +    Returns
    +    -------
    +    factory : function
    +        A function that looks up an element by ID
    +    """
    +    def lookup_by_id(self, ref, before=None):
    +        """
    +        Given an XML id *ref*, finds the first element in the iterator
    +        with the attribute ID == *ref*.  If *before* is provided, will
    +        stop searching at the object *before*.  This is important,
    +        since "forward references" are not allowed in the VOTABLE
    +        format.
    +        """
    +        for element in getattr(self, iterator)():
    +            if element is before:
    +                if element.ID == ref:
    +                    vo_raise(
    +                        "%s references itself" % element_name,
    +                        element._config, element._pos, KeyError)
    +                break
    +            if element.ID == ref:
    +                return element
    +        raise KeyError(
    +            "No %s with ID '%s' found before the referencing %s" %
    +            (element_name, ref, element_name))
    +
    +    lookup_by_id.__doc__ = doc
    +    return lookup_by_id
    +
    +
    +def _lookup_by_id_or_name_factory(iterator, element_name, doc):
    +    """
    +    Like `_lookup_by_id_factory`, but also looks in the "name" attribute.
    +    """
    +    def lookup_by_id(self, ref, before=None):
    +        """
    +        Given an key *ref*, finds the first element in the iterator
    +        with the attribute ID == *ref* or name == *ref*.  If *before*
    +        is provided, will stop searching at the object *before*.  This
    +        is important, since "forward references" are not allowed in
    +        the VOTABLE format.
    +        """
    +        for element in getattr(self, iterator)():
    +            if element is before:
    +                if ref in (element.ID, element.name):
    +                    vo_raise(
    +                        "%s references itself" % element_name,
    +                        element._config, element._pos, KeyError)
    +                break
    +            if ref in (element.ID, element.name):
    +                return element
    +        raise KeyError(
    +            "No %s with ID or name '%s' found before the referencing %s" %
    +            (element_name, ref, element_name))
    +
    +    lookup_by_id.__doc__ = doc
    +    return lookup_by_id
    +
    +
    +######################################################################
    +# ATTRIBUTE CHECKERS
    +def check_astroyear(year, field, config={}, pos=None):
    +    """
    +    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if *year* is
    +    not a valid astronomical year as defined by the VOTABLE standard.
    +
    +    Parameters
    +    ----------
    +    year : str
    +        An astronomical year string
    +
    +    field : str
    +        The name of the field this year was found in (used for error
    +        message)
    +
    +    config, pos : optional
    +        Information about the source of the value
    +    """
    +    if (year is not None and
    +        re.match(r"^[JB]?[0-9]+([.][0-9]*)?$", year) is None):
    +        warn_or_raise(W07, W07, (field, year), config, pos)
    +        return False
    +    return True
    +
    +
    +def check_string(string, attr_name, config={}, pos=None):
    +    """
    +    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if
    +    *string* is not a string or Unicode string.
    +
    +    Parameters
    +    ----------
    +    string : str
    +        An astronomical year string
    +
    +    field : str
    +        The name of the field this year was found in (used for error
    +        message)
    +
    +    config, pos : optional
    +        Information about the source of the value
    +    """
    +    if string is not None and not isinstance(string, string_types):
    +        warn_or_raise(W08, W08, attr_name, config, pos)
    +        return False
    +    return True
    +
    +
    +def resolve_id(ID, id, config={}, pos=None):
    +    if ID is None and id is not None:
    +        warn_or_raise(W09, W09, (), config, pos)
    +        return id
    +    return ID
    +
    +
    +def check_ucd(ucd, config={}, pos=None):
    +    """
    +    Warns or raises a `~astropy.io.vo.exceptions.VOTableSpecError`
    +    if *ucd* is not a valid `unified content descriptor`_ string as
    +    defined by the VOTABLE standard.
    +
    +    Parameters
    +    ----------
    +    ucd : str
    +        A UCD string.
    +
    +    config, pos : optional
    +        Information about the source of the value
    +    """
    +    if config.get('version_1_1_or_later'):
    +        try:
    +            ucd_mod.parse_ucd(
    +                ucd,
    +                check_controlled_vocabulary=config.get(
    +                    'version_1_2_or_later', False),
    +                has_colon=config.get('version_1_2_or_later', False))
    +        except ValueError as e:
    +            # This weird construction is for Python 3 compatibility
    +            if config.get('pedantic'):
    +                vo_raise(W06, (ucd, unicode(e)), config, pos)
    +            else:
    +                vo_warn(W06, (ucd, unicode(e)), config, pos)
    +                return False
    +    return True
    +
    +
    +######################################################################
    +# PROPERTY MIXINS
    +class _IDProperty(object):
    +    @property
    +    def ID(self):
    +        """
    +        The XML ID_ of the element.  May be ``None`` or a string
    +        conforming to XML ID_ syntax.
    +        """
    +        return self._ID
    +
    +    @ID.setter
    +    def ID(self, ID):
    +        xmlutil.check_id(ID, 'ID', self._config, self._pos)
    +        self._ID = ID
    +
    +    @ID.deleter
    +    def ID(self):
    +        self._ID = None
    +
    +
    +class _NameProperty(object):
    +    @property
    +    def name(self):
    +        """An optional name for the element."""
    +        return self._name
    +
    +    @name.setter
    +    def name(self, name):
    +        xmlutil.check_token(name, 'name', self._config, self._pos)
    +        self._name = name
    +
    +    @name.deleter
    +    def name(self):
    +        self._name = None
    +
    +
    +class _XtypeProperty(object):
    +    @property
    +    def xtype(self):
    +        """Extended data type information."""
    +        return self._xtype
    +
    +    @xtype.setter
    +    def xtype(self, xtype):
    +        if xtype is not None and not self._config.get('version_1_2_or_later'):
    +            warn_or_raise(
    +                W28, W28, ('xtype', self._element_name, '1.2'),
    +                self._config, self._pos)
    +        check_string(xtype, 'xtype', self._config, self._pos)
    +        self._xtype = xtype
    +
    +    @xtype.deleter
    +    def xtype(self):
    +        self._xtype = None
    +
    +
    +class _UtypeProperty(object):
    +    _utype_in_v1_2 = False
    +
    +    @property
    +    def utype(self):
    +        """The usage-specific or `unique type`_ of the element."""
    +        return self._utype
    +
    +    @utype.setter
    +    def utype(self, utype):
    +        if (self._utype_in_v1_2 and
    +            utype is not None and
    +            not self._config.get('version_1_2_or_later')):
    +            warn_or_raise(
    +                W28, W28, ('utype', self._element_name, '1.2'),
    +                config, pos)
    +        check_string(utype, 'utype', self._config, self._pos)
    +        self._utype = utype
    +
    +    @utype.deleter
    +    def utype(self):
    +        self._utype = None
    +
    +
    +class _UcdProperty(object):
    +    _ucd_in_v1_2 = False
    +
    +    @property
    +    def ucd(self):
    +        """The `unified content descriptor`_ for the element."""
    +        return self._ucd
    +
    +    @ucd.setter
    +    def ucd(self, ucd):
    +        if ucd is not None and ucd.strip() == '':
    +            ucd = None
    +        if ucd is not None:
    +            if (self._ucd_in_v1_2 and
    +                not self._config.get('version_1_2_or_later')):
    +                warn_or_raise(
    +                    W28, W28, ('ucd', self._element_name, '1.2'),
    +                    config, pos)
    +            check_ucd(ucd, self._config, self._pos)
    +        self._ucd = ucd
    +
    +    @ucd.deleter
    +    def ucd(self):
    +        self._ucd = None
    +
    +
    +class _DescriptionProperty(object):
    +    @property
    +    def description(self):
    +        """
    +        An optional string describing the element.  Corresponds to the
    +        DESCRIPTION_ element.
    +        """
    +        return self._description
    +
    +    @description.setter
    +    def description(self, description):
    +        self._description = description
    +
    +    @description.deleter
    +    def description(self):
    +        self._description = None
    +
    +
    +######################################################################
    +# ELEMENT CLASSES
    +
    [docs]class Element(object): + """ + A base class for all classes that represent XML elements in the + VOTABLE file. + """ + def _add_unknown_tag(self, iterator, tag, data, config, pos): + warn_or_raise(W10, W10, tag, config, pos) + + def _ignore_add(self, iterator, tag, data, config, pos): + warn_unknown_attrs(tag, data.iterkeys(), config, pos) + + def _add_definitions(self, iterator, tag, data, config, pos): + if config.get('version_1_1_or_later'): + warn_or_raise(W22, W22, (), config, pos) + warn_unknown_attrs(tag, data.iterkeys(), config, pos) + +
    +
    [docs]class SimpleElement(Element): + """ + A base class for simple elements, such as FIELD, PARAM and INFO + that don't require any special parsing or outputting machinery. + """ + def __init__(self): + Element.__init__(self) + +
    [docs] def parse(self, iterator, config): + for start, tag, data, pos in iterator: + if start and tag != self._element_name: + self._add_unknown_tag(iterator, tag, data, config, pos) + elif tag == self._element_name: + break + + return self +
    +
    [docs] def to_xml(self, w, **kwargs): + w.element(self._element_name, + attrib=w.object_attrs(self, self._attr_list)) + +
    +
    [docs]class SimpleElementWithContent(SimpleElement): + """ + A base class for simple elements, such as FIELD, PARAM and INFO + that don't require any special parsing or outputting machinery. + """ + def __init__(self): + SimpleElement.__init__(self) + + self._content = None + +
    [docs] def to_xml(self, w, **kwargs): + w.element(self._element_name, self._content, + attrib=w.object_attrs(self, self._attr_list)) +
    + @property + def content(self): + """The content of the element.""" + return self._content + + @content.setter + def content(self, content): + check_string(content, 'content', self._config, self._pos) + self._content = content + + @content.deleter +
    [docs] def content(self): + self._content = None + +
    + +
    [docs]class Info(SimpleElementWithContent, _IDProperty, _XtypeProperty, + _UtypeProperty): + """ + A class for storing INFO elements, which contain arbitrary + key-value pairs for extensions to the standard. + + The keyword arguments correspond to setting members of the same + name, documented below. + """ + _element_name = 'INFO' + _attr_list_11 = ['ID', 'name', 'value'] + _attr_list_12 = _attr_list_11 + ['xtype', 'ref', 'unit', 'ucd', 'utype'] + _utype_in_v1_2 = True + + def __init__(self, ID=None, name=None, value=None, id=None, xtype=None, + ref=None, unit=None, ucd=None, utype=None, + config={}, pos=None, **extra): + self._config = config + self._pos = pos + + SimpleElementWithContent.__init__(self) + + self.ID = (resolve_id(ID, id, config, pos) or + xmlutil.fix_id(name, config, pos)) + self.name = name + self.value = value + self.xtype = xtype + self.ref = ref + self.unit = unit + self.ucd = ucd + self.utype = utype + + if config.get('version_1_2_or_later'): + self._attr_list = self._attr_list_12 + else: + self._attr_list = self._attr_list_11 + if xtype is not None: + warn_unknown_attrs('INFO', ['xtype'], config, pos) + if ref is not None: + warn_unknown_attrs('INFO', ['ref'], config, pos) + if unit is not None: + warn_unknown_attrs('INFO', ['unit'], config, pos) + if ucd is not None: + warn_unknown_attrs('INFO', ['ucd'], config, pos) + if utype is not None: + warn_unknown_attrs('INFO', ['utype'], config, pos) + + warn_unknown_attrs('INFO', extra.iterkeys(), config, pos) + + @property + def name(self): + """[*required*] The key of the key-value pair.""" + return self._name + + @name.setter +
    [docs] def name(self, name): + if name is None: + warn_or_raise(W35, W35, ('name'), self._config, self._pos) + xmlutil.check_token(name, 'name', self._config, self._pos) + self._name = name +
    + @property + def value(self): + """ + [*required*] The value of the key-value pair. (Always stored + as a string or unicode string). + """ + return self._value + + @value.setter +
    [docs] def value(self, value): + if value is None: + warn_or_raise(W35, W35, ('value'), self._config, self._pos) + check_string(value, 'value', self._config, self._pos) + self._value = value +
    + @property + def content(self): + """The content inside the INFO element.""" + return self._content + + @content.setter + def content(self, content): + check_string(content, 'content', self._config, self._pos) + self._content = content + + @content.deleter +
    [docs] def content(self): + self._content = None +
    + @property + def ref(self): + """ + Refer to another INFO_ element by ID_, defined previously in + the document. + """ + return self._ref + + @ref.setter + def ref(self, ref): + if ref is not None and not self._config.get('version_1_2_or_later'): + warn_or_raise(W28, W28, ('ref', 'INFO', '1.2'), config, pos) + xmlutil.check_id(ref, 'ref', self._config, self._pos) + # TODO: actually apply the reference + # if ref is not None: + # try: + # other = self._votable.get_values_by_id(ref, before=self) + # except KeyError: + # vo_raise( + # "VALUES ref='%s', which has not already been defined." % + # self.ref, self._config, self._pos, KeyError) + # self.null = other.null + # self.type = other.type + # self.min = other.min + # self.min_inclusive = other.min_inclusive + # self.max = other.max + # self.max_inclusive = other.max_inclusive + # self._options[:] = other.options + self._ref = ref + + @ref.deleter +
    [docs] def ref(self): + self._ref = None +
    + @property + def unit(self): + """A string specifying the units_ for the INFO_.""" + return self._unit + + @unit.setter + def unit(self, unit): + if unit is not None and not self._config.get('version_1_2_or_later'): + warn_or_raise(W28, W28, ('unit', 'INFO', '1.2'), config, pos) + check_unit(unit, 'unit', self._config, self._pos) + self._unit = unit + + @unit.deleter +
    [docs] def unit(self): + self._unit = None + +
    +
    [docs]class Values(Element, _IDProperty): + """ + A class to represent the VALUES_ element, used within FIELD_ and + PARAM_ elements to define the domain of values. + + The keyword arguments correspond to setting members of the same + name, documented below. + """ + def __init__(self, votable, field, ID=None, null=None, ref=None, + type="legal", id=None, config={}, pos=None, **extras): + self._config = config + self._pos = pos + + Element.__init__(self) + + self._votable = votable + self._field = field + self.ID = resolve_id(ID, id, config, pos) + self.null = null + self._ref = ref + self.type = type + + self.min = None + self.max = None + self.min_inclusive = True + self.max_inclusive = True + self._options = [] + + warn_unknown_attrs('VALUES', extras.iterkeys(), config, pos) + + @property + def null(self): + """ + For integral datatypes, *null* is used to define the value + used for missing values. + """ + return self._null + + @null.setter + def null(self, null): + if null is not None and isinstance(null, string_types): + try: + null_val = self._field.converter.parse_scalar( + null, self._config, self._pos)[0] + except: + warn_or_raise(W36, W36, null, self._config, self._pos) + null_val = self._field.converter.parse_scalar( + '0', self._config, self._pos)[0] + else: + null_val = null + self._null = null_val + + @null.deleter +
    [docs] def null(self): + self._null = None +
    + @property + def type(self): + """ + [*required*] Defines the applicability of the domain defined + by this VALUES_ element. Must be one of the following + strings: + + - 'legal': The domain of this column applies in general to + this datatype. (default) + + - 'actual': The domain of this column applies only to the + data enclosed in the parent table. + """ + return self._type + + @type.setter +
    [docs] def type(self, type): + if type not in ('legal', 'actual'): + vo_raise(E08, type, self._config, self._pos) + self._type = type +
    + @property + def ref(self): + """ + Refer to another VALUES_ element by ID_, defined previously in + the document, for MIN/MAX/OPTION information. + """ + return self._ref + + @ref.setter + def ref(self, ref): + xmlutil.check_id(ref, 'ref', self._config, self._pos) + if ref is not None: + try: + other = self._votable.get_values_by_id(ref, before=self) + except KeyError: + warn_or_raise(W43, W43, ('VALUES', self.ref), self._config, + self._pos) + ref = None + else: + self.null = other.null + self.type = other.type + self.min = other.min + self.min_inclusive = other.min_inclusive + self.max = other.max + self.max_inclusive = other.max_inclusive + self._options[:] = other.options + self._ref = ref + + @ref.deleter +
    [docs] def ref(self): + self._ref = None +
    + @property + def min(self): + """ + The minimum value of the domain. See :attr:`min_inclusive`. + """ + return self._min + + @min.setter + def min(self, min): + if hasattr(self._field, 'converter') and min is not None: + self._min = self._field.converter.parse(min)[0] + else: + self._min = min + + @min.deleter +
    [docs] def min(self): + self._min = None +
    + @property + def min_inclusive(self): + """When `True`, the domain includes the minimum value.""" + return self._min_inclusive + + @min_inclusive.setter + def min_inclusive(self, inclusive): + if inclusive == 'yes': + self._min_inclusive = True + elif inclusive == 'no': + self._min_inclusive = False + else: + self._min_inclusive = bool(inclusive) + + @min_inclusive.deleter +
    [docs] def min_inclusive(self): + self._min_inclusive = True +
    + @property + def max(self): + """ + The maximum value of the domain. See :attr:`max_inclusive`. + """ + return self._max + + @max.setter + def max(self, max): + if hasattr(self._field, 'converter') and max is not None: + self._max = self._field.converter.parse(max)[0] + else: + self._max = max + + @max.deleter +
    [docs] def max(self): + self._max = None +
    + @property + def max_inclusive(self): + """When `True`, the domain includes the maximum value.""" + return self._max_inclusive + + @max_inclusive.setter + def max_inclusive(self, inclusive): + if inclusive == 'yes': + self._max_inclusive = True + elif inclusive == 'no': + self._max_inclusive = False + else: + self._max_inclusive = bool(inclusive) + + @max_inclusive.deleter +
    [docs] def max_inclusive(self): + self._max_inclusive = True +
    + @property +
    [docs] def options(self): + """ + A list of string key-value tuples defining other OPTION + elements for the domain. All options are ignored -- they are + stored for round-tripping purposes only. + """ + return self._options +
    +
    [docs] def parse(self, iterator, config): + if self.ref is not None: + for start, tag, data, pos in iterator: + if start: + warn_or_raise(W44, W44, tag, config, pos) + else: + if tag != 'VALUES': + warn_or_raise(W44, W44, tag, config, pos) + break + else: + for start, tag, data, pos in iterator: + if start: + if tag == 'MIN': + if 'value' not in data: + vo_raise(E09, 'MIN', config, pos) + self.min = data['value'] + self.min_inclusive = data.get('inclusive', 'yes') + warn_unknown_attrs( + 'MIN', data.iterkeys(), config, pos, + ['value', 'inclusive']) + elif tag == 'MAX': + if 'value' not in data: + vo_raise(E09, 'MAX', config, pos) + self.max = data['value'] + self.max_inclusive = data.get('inclusive', 'yes') + warn_unknown_attrs( + 'MAX', data.iterkeys(), config, pos, + ['value', 'inclusive']) + elif tag == 'OPTION': + if 'value' not in data: + vo_raise(E09, 'OPTION', config, pos) + xmlutil.check_token( + data.get('name'), 'name', config, pos) + self.options.append( + (data.get('name'), data.get('value'))) + warn_unknown_attrs( + 'OPTION', data.iterkeys(), config, pos, + ['data', 'name']) + elif tag == 'VALUES': + break + + return self +
    +
    [docs] def is_defaults(self): + # If there's nothing meaningful or non-default to write, + # don't write anything. + return (self.ref is None and self.null is None and self.ID is None and + self.max is None and self.min is None and self.options == []) +
    +
    [docs] def to_xml(self, w, **kwargs): + def yes_no(value): + if value: + return 'yes' + return 'no' + + if self.is_defaults(): + return + + if self.ref is not None: + w.element('VALUES', attrib=w.object_attrs(self, ['ref'])) + else: + with w.tag('VALUES', + attrib=w.object_attrs( + self, ['ID', 'null', 'ref'])): + if self.min is not None: + w.element( + 'MIN', + value=self._field.converter.output(self.min, False), + inclusive=yes_no(self.min_inclusive)) + if self.max is not None: + w.element( + 'MAX', + value=self._field.converter.output(self.max, False), + inclusive=yes_no(self.max_inclusive)) + for name, value in self.options: + w.element( + 'OPTION', + name=name, + value=value) + +
    +
    [docs]class Field(SimpleElement, _IDProperty, _NameProperty, _XtypeProperty, + _UtypeProperty, _UcdProperty): + """ + A class that represents the FIELD_ element, which describes the + datatype of a particular column of data. + + The keyword arguments correspond to setting members of the same + name, documented below. + + If *ID* is provided, it is used for the column name in the + resulting recarray of the table. If no *ID* is provided, *name* + is used instead. If neither is provided, an exception will be + raised. + """ + _attr_list_11 = ['ID', 'name', 'datatype', 'arraysize', 'ucd', + 'unit', 'width', 'precision', 'utype', 'ref'] + _attr_list_12 = _attr_list_11 + ['xtype'] + _element_name = 'FIELD' + + def __init__(self, votable, ID=None, name=None, datatype=None, + arraysize=None, ucd=None, unit=None, width=None, + precision=None, utype=None, ref=None, type=None, id=None, + xtype=None, + config={}, pos=None, **extra): + self._config = config + self._pos = pos + + SimpleElement.__init__(self) + + if config.get('version_1_2_or_later'): + self._attr_list = self._attr_list_12 + else: + self._attr_list = self._attr_list_11 + if xtype is not None: + warn_unknown_attrs(self._element_name, ['xtype'], config, pos) + + # TODO: REMOVE ME ---------------------------------------- + # This is a terrible hack to support Simple Image Access + # Protocol results from archive.noao.edu. It creates a field + # for the coordinate projection type of type "double", which + # actually contains character data. We have to hack the field + # to store character data, or we can't read it in. A warning + # will be raised when this happens. + if (not config.get('pedantic') and name == 'cprojection' and + ID == 'cprojection' and ucd == 'VOX:WCS_CoordProjection' and + datatype == 'double'): + datatype = 'char' + arraysize = '3' + vo_warn(W40, (), config, pos) + # ---------------------------------------- + + self.description = None + self._votable = votable + + self.ID = (resolve_id(ID, id, config, pos) or + xmlutil.fix_id(name, config, pos)) + self.name = name + if name is None: + if (self._element_name == 'PARAM' and + not config.get('version_1_1_or_later')): + pass + else: + warn_or_raise(W15, W15, self._element_name, config, pos) + self.name = self.ID + + if self._ID is None and name is None: + vo_raise(W12, self._element_name, config, pos) + + datatype_mapping = { + 'string' : 'char', + 'unicodeString' : 'unicodeChar', + 'int16' : 'short', + 'int32' : 'int', + 'int64' : 'long', + 'float32' : 'float', + 'float64' : 'double'} + + if datatype in datatype_mapping: + warn_or_raise(W13, W13, (datatype, datatype_mapping[datatype]), + config, pos) + datatype = datatype_mapping[datatype] + + self.ref = ref + self.datatype = datatype + self.arraysize = arraysize + self.ucd = ucd + self.unit = unit + self.width = width + self.precision = precision + self.utype = utype + self.type = type + self._links = HomogeneousList(Link) + self.title = self.name + self.values = Values(self._votable, self) + self.xtype = xtype + + self._setup(config, pos) + + warn_unknown_attrs(self._element_name, extra.iterkeys(), config, pos) + + @classmethod +
    [docs] def uniqify_names(cls, fields): + """ + Make sure that all names and titles in a list of fields are + unique, by appending numbers if necessary. + """ + unique = {} + for field in fields: + i = 2 + new_id = field.ID + while new_id in unique: + new_id = field.ID + "_%d" % i + i += 1 + if new_id != field.ID: + vo_warn(W32, (field.ID, new_id), field._config, field._pos) + field.ID = new_id + unique[new_id] = field.ID + + for field in fields: + i = 2 + if field.name is None: + new_name = field.ID + implicit = True + else: + new_name = field.name + implicit = False + if new_name != field.ID: + while new_name in unique: + new_name = field.name + " %d" % i + i += 1 + + if (not implicit and + new_name != field.name): + vo_warn(W33, (field.name, new_name), field._config, field._pos) + field._unique_name = new_name + unique[new_name] = field.name +
    + def _setup(self, config, pos): + if self.values._ref is not None: + self.values.ref = self.values._ref + self.converter = converters.get_converter(self, config, pos) + + @property + def datatype(self): + """ + [*required*] The datatype of the column. Valid values (as + defined by the spec) are: + + 'boolean', 'bit', 'unsignedByte', 'short', 'int', 'long', + 'char', 'unicodeChar', 'float', 'double', 'floatComplex', or + 'doubleComplex' + + Many VOTABLE files in the wild use 'string' instead of 'char', + so that is also a valid option, though 'string' will always be + converted to 'char' when writing the file back out. + """ + return self._datatype + + @datatype.setter +
    [docs] def datatype(self, datatype): + if datatype is None: + if self._config.get('version_1_1_or_later'): + vo_raise(E10, self._element_name, self._config, self._pos) + else: + datatype = 'char' + if datatype not in converters.converter_mapping: + vo_raise(E06, (datatype, self.ID), self._config, self._pos) + self._datatype = datatype +
    + @property + def precision(self): + """ + Along with :attr:`width`, defines the `numerical accuracy`_ + associated with the data. These values are used to limit the + precision when writing floating point values back to the XML + file. Otherwise, it is purely informational -- the Numpy + recarray containing the data itself does not use this + information. + """ + return self._precision + + @precision.setter + def precision(self, precision): + if precision is not None and not re.match("^[FE]?[0-9]+$", precision): + vo_raise(E11, precision, self._config, self._pos) + self._precision = precision + + @precision.deleter +
    [docs] def precision(self): + self._precision = None +
    + @property + def width(self): + """ + Along with :attr:`precision`, defines the `numerical + accuracy`_ associated with the data. These values are used to + limit the precision when writing floating point values back to + the XML file. Otherwise, it is purely informational -- the + Numpy recarray containing the data itself does not use this + information. + """ + return self._width + + @width.setter + def width(self, width): + if width is not None: + width = int(width) + if width <= 0: + vo_raise(E12, width, self._config, self._pos) + self._width = width + + @width.deleter +
    [docs] def width(self): + self._width = None + + # ref on FIELD and PARAM behave differently than elsewhere -- here + # they're just informational, such as to refer to a coordinate + # system.
    + @property + def ref(self): + """ + On FIELD_ elements, ref is used only for informational + purposes, for example to refer to a COOSYS_ element. + """ + return self._ref + + @ref.setter + def ref(self, ref): + xmlutil.check_id(ref, 'ref', self._config, self._pos) + self._ref = ref + + @ref.deleter +
    [docs] def ref(self): + self._ref = None +
    + @property + def unit(self): + """A string specifying the units_ for the FIELD_.""" + return self._unit + + @unit.setter + def unit(self, unit): + check_unit(unit, 'unit', self._config, self._pos) + self._unit = unit + + @unit.deleter +
    [docs] def unit(self): + self._unit = None +
    + @property + def arraysize(self): + """ + Specifies the size of the multidimensional array if this + FIELD_ contains more than a single value. + + See `multidimensional arrays`_. + """ + return self._arraysize + + @arraysize.setter + def arraysize(self, arraysize): + if (arraysize is not None and + not re.match("^([0-9]+x)*[0-9]*[*]?(s\W)?$", arraysize)): + vo_raise(E13, arraysize, self._config, self._pos) + self._arraysize = arraysize + + @arraysize.deleter +
    [docs] def arraysize(self): + self._arraysize = None +
    + @property + def type(self): + """ + The type attribute on FIELD_ elements is reserved for future + extensions. + """ + return self._type + + @type.setter + def type(self, type): + self._type = type + + @type.deleter +
    [docs] def type(self): + self._type = None +
    + @property + def values(self): + """ + A :class:`Values` instance (or ``None``) defining the domain + of the column. + """ + return self._values + + @values.setter + def values(self, values): + assert values is None or isinstance(values, Values) + self._values = values + + @values.deleter +
    [docs] def values(self): + self._values = None +
    + @property + +
    [docs] def parse(self, iterator, config): + for start, tag, data, pos in iterator: + if start: + if tag == 'VALUES': + self.values.__init__( + self._votable, self, config=config, pos=pos, **data) + self.values.parse(iterator, config) + elif tag == 'LINK': + link = Link(config=config, pos=pos, **data) + self.links.append(link) + link.parse(iterator, config) + elif tag == 'DESCRIPTION': + warn_unknown_attrs( + 'DESCRIPTION', data.iterkeys(), config, pos) + elif tag != self._element_name: + self._add_unknown_tag(iterator, tag, data, config, pos) + else: + if tag == 'DESCRIPTION': + if self.description is not None: + warn_or_raise( + W17, W17, self._element_name, config, pos) + self.description = data or None + elif tag == self._element_name: + break + + if self.description is not None: + self.title = " ".join(x.strip() for x in + self.description.split("\n")) + else: + self.title = self.name + + self._setup(config, pos) + + return self +
    +
    [docs] def to_xml(self, w, **kwargs): + with w.tag(self._element_name, + attrib=w.object_attrs(self, self._attr_list)): + if self.description is not None: + w.element("DESCRIPTION", self.description, wrap=True) + if not self.values.is_defaults(): + self.values.to_xml(w, **kwargs) + for link in self.links: + link.to_xml(w, **kwargs) + +
    +
    [docs]class Param(Field): + """ + A class to represent the PARAM_ element, which are constant-valued + columns in the data. + + :class:`Param` objects are a subclass of :class:`Field`, and have + all of its methods and members. Additionally, it defines :attr:`value`. + """ + _attr_list_11 = Field._attr_list_11 + ['value'] + _attr_list_12 = Field._attr_list_12 + ['value'] + _element_name = 'PARAM' + + def __init__(self, votable, ID=None, name=None, value=None, datatype=None, + arraysize=None, ucd=None, unit=None, width=None, + precision=None, utype=None, type=None, id=None, config={}, + pos=None, **extra): + self._value = value + Field.__init__(self, votable, ID=ID, name=name, datatype=datatype, + arraysize=arraysize, ucd=ucd, unit=unit, + precision=precision, utype=utype, type=type, + id=id, config=config, pos=pos, **extra) + + @property + def value(self): + """ + [*required*] The constant value of the parameter. Its type is + determined by the :attr:`~Field.datatype` member. + """ + return self._value + + @value.setter +
    [docs] def value(self, value): + if value is None: + vo_raise(E14, (), self._config, self._pos) + if ((IS_PY3K and isinstance(value, unicode)) or + (not IS_PY3K and isinstance(value, string_types))): + self._value = self.converter.parse( + value, self._config, self._pos)[0] + else: + self._value = value +
    + def _setup(self, config, pos): + Field._setup(self, config, pos) + self.value = self._value + +
    [docs] def to_xml(self, w, **kwargs): + tmp_value = self._value + self._value = self.converter.output(tmp_value, False) + # We must always have a value + if self._value in (None, ''): + self._value = " " + Field.to_xml(self, w, **kwargs) + self._value = tmp_value + +
    +
    [docs]class CooSys(SimpleElement): + """ + A class representing the COOSYS_ element, which defines a + coordinate system. + + The keyword arguments correspond to setting members of the same + name, documented below. + """ + _attr_list = ['ID', 'equinox', 'epoch', 'system'] + _element_name = 'COOSYS' + + def __init__(self, ID=None, equinox=None, epoch=None, system=None, id=None, + config={}, pos=None, **extra): + self._config = config + self._pos = pos + + if config.get('version_1_2_or_later'): + warn_or_raise(W27, W27, (), config, pos) + + SimpleElement.__init__(self) + + self.ID = resolve_id(ID, id, config, pos) + self.equinox = equinox + self.epoch = epoch + self.system = system + + warn_unknown_attrs('COOSYS', extra.iterkeys(), config, pos) + + @property + def ID(self): + """ + [*required*] The XML ID of the COOSYS_ element, used for + cross-referencing. May be ``None`` or a string conforming to + XML ID_ syntax. + """ + return self._ID + + @ID.setter +
    [docs] def ID(self, ID): + if self._config.get('version_1_1_or_later'): + if ID is None: + vo_raise(E15, (), self._config, self._pos) + xmlutil.check_id(ID, 'ID', self._config, self._pos) + self._ID = ID +
    + @property + def system(self): + """ + Specifies the type of coordinate system. Valid choices are: + + 'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic', + 'supergalactic', 'xy', 'barycentric', or 'geo_app' + """ + return self._system + + @system.setter + def system(self, system): + if system not in ('eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', + 'galactic', 'supergalactic', 'xy', 'barycentric', + 'geo_app'): + warn_or_raise(E16, E16, system, self._config, self._pos) + self._system = system + + @system.deleter +
    [docs] def system(self): + self._system = None +
    + @property + def equinox(self): + """ + A parameter required to fix the equatorial or ecliptic systems + (as e.g. "J2000" as the default "eq_FK5" or "B1950" as the + default "eq_FK4"). + """ + return self._equinox + + @equinox.setter + def equinox(self, equinox): + check_astroyear(equinox, 'equinox', self._config, self._pos) + self._equinox = equinox + + @equinox.deleter +
    [docs] def equinox(self): + self._equinox = None +
    + @property + def epoch(self): + """ + Specifies the epoch of the positions. It must be a string + specifying an astronomical year. + """ + return self._epoch + + @epoch.setter + def epoch(self, epoch): + check_astroyear(epoch, 'epoch', self._config, self._pos) + self._epoch = epoch + + @epoch.deleter +
    [docs] def epoch(self): + self._epoch = None + +
    +
    [docs]class FieldRef(SimpleElement, _UtypeProperty, _UcdProperty): + """ + A class representing the FIELDref_ element, which is used inside + of GROUP_ elements to refer to FIELD_ elements defined elsewhere. + """ + _attr_list_11 = ['ref'] + _attr_list_12 = _attr_list_11 + ['ucd', 'utype'] + _element_name = "FIELDref" + _utype_in_v1_2 = True + _ucd_in_v1_2 = True + + def __init__(self, table, ref, ucd=None, utype=None, config={}, pos=None, + **extra): + """ + *table* is the :class:`Table` object that this :class:`FieldRef` + is a member of. + + *ref* is the ID to reference a :class:`Field` object defined + elsewhere. + """ + self._config = config + self._pos = pos + + SimpleElement.__init__(self) + self._table = table + self.ref = ref + self.ucd = ucd + self.utype = utype + + if config.get('version_1_2_or_later'): + self._attr_list = self._attr_list_12 + else: + self._attr_list = self._attr_list_11 + if ucd is not None: + warn_unknown_attrs(self._element_name, ['ucd'], config, pos) + if utype is not None: + warn_unknown_attrs(self._element_name, ['utype'], config, pos) + + @property + def ref(self): + """The ID_ of the FIELD_ that this FIELDref_ references.""" + return self._ref + + @ref.setter + def ref(self, ref): + xmlutil.check_id(ref, 'ref', self._config, self._pos) + self._ref = ref + + @ref.deleter +
    [docs] def ref(self): + self._ref = None +
    +
    [docs] def get_ref(self): + """ + Lookup the :class:`Field` instance that this :class:`FieldRef` + references. + """ + for field in self._table._votable.iter_fields_and_params(): + if isinstance(field, Field) and field.ID == self.ref: + return field + vo_raise( + "No field named '%s'" % self.ref, + self._config, self._pos, KeyError) + +
    +
    [docs]class ParamRef(SimpleElement, _UtypeProperty, _UcdProperty): + """ + A class representing the PARAMref_ element, which is used inside + of GROUP_ elements to refer to PARAM_ elements defined elsewhere. + + The keyword arguments correspond to setting members of the same + name, documented below. + + It contains the following publicly-accessible members: + + *ref*: An XML ID refering to a <PARAM> element. + """ + _attr_list_11 = ['ref'] + _attr_list_12 = _attr_list_11 + ['ucd', 'utype'] + _element_name = "PARAMref" + _utype_in_v1_2 = True + _ucd_in_v1_2 = True + + def __init__(self, table, ref, ucd=None, utype=None, config={}, pos=None): + self._config = config + self._pos = pos + + Element.__init__(self) + self._table = table + self.ref = ref + self.ucd = ucd + self.utype = utype + + if config.get('version_1_2_or_later'): + self._attr_list = self._attr_list_12 + else: + self._attr_list = self._attr_list_11 + if ucd is not None: + warn_unknown_attrs(self._element_name, ['ucd'], config, pos) + if utype is not None: + warn_unknown_attrs(self._element_name, ['utype'], config, pos) + + @property + def ref(self): + """The ID_ of the PARAM_ that this PARAMref_ references.""" + return self._ref + + @ref.setter + def ref(self, ref): + xmlutil.check_id(ref, 'ref', self._config, self._pos) + self._ref = ref + + @ref.deleter +
    [docs] def ref(self): + self._ref = None +
    +
    [docs] def get_ref(self): + """ + Lookup the :class:`Param` instance that this :class:`PARAMref` + references. + """ + for param in self._table._votable.iter_fields_and_params(): + if isinstance(param, Param) and param.ID == self.ref: + return param + vo_raise( + "No params named '%s'" % self.ref, + self._config, self._pos, KeyError) + +
    +
    [docs]class Group(Element, _IDProperty, _NameProperty, _UtypeProperty, + _UcdProperty, _DescriptionProperty): + """ + Stores information about the grouping of FIELD_ and PARAM_ + elements. + + This information is currently ignored by the vo package---that is + the columns in the recarray are always flat---but the grouping + information is stored so that it can be written out again to the + XML file. + + The keyword arguments correspond to setting members of the same + name, documented below. + """ + + def __init__(self, table, ID=None, name=None, ref=None, ucd=None, + utype=None, id=None, config={}, pos=None, **extra): + self._config = config + self._pos = pos + + Element.__init__(self) + self._table = table + + self.ID = (resolve_id(ID, id, config, pos) + or xmlutil.fix_id(name, config, pos)) + self.name = name + self.ref = ref + self.ucd = ucd + self.utype = utype + self.description = None + + self._entries = HomogeneousList( + (FieldRef, ParamRef, Group, Param)) + + warn_unknown_attrs('GROUP', extra.iterkeys(), config, pos) + + @property + def ref(self): + """ + Currently ignored, as it's not clear from the spec how this is + meant to work. + """ + return self._ref + + @ref.setter + def ref(self, ref): + xmlutil.check_id(ref, 'ref', self._config, self._pos) + self._ref = ref + + @ref.deleter +
    [docs] def ref(self): + self._ref = None +
    + @property +
    [docs] def entries(self): + """ + [read-only] A list of members of the GROUP_. This list may + only contain objects of type :class:`Param`, :class:`Group`, + :class:`ParamRef` and :class:`FieldRef`. + """ + return self._entries +
    + def _add_fieldref(self, iterator, tag, data, config, pos): + fieldref = FieldRef(self._table, config=config, pos=pos, **data) + self.entries.append(fieldref) + + def _add_paramref(self, iterator, tag, data, config, pos): + paramref = ParamRef(self._table, config=config, pos=pos, **data) + self.entries.append(paramref) + + def _add_param(self, iterator, tag, data, config, pos): + if isinstance(self._table, VOTableFile): + votable = self._table + else: + votable = self._table._votable + param = Param(votable, config=config, pos=pos, **data) + self.entries.append(param) + param.parse(iterator, config) + + def _add_group(self, iterator, tag, data, config, pos): + group = Group(self._table, config=config, pos=pos, **data) + self.entries.append(group) + group.parse(iterator, config) + +
    [docs] def parse(self, iterator, config): + tag_mapping = { + 'FIELDref' : self._add_fieldref, + 'PARAMref' : self._add_paramref, + 'PARAM' : self._add_param, + 'GROUP' : self._add_group, + 'DESCRIPTION' : self._ignore_add} + + for start, tag, data, pos in iterator: + if start: + tag_mapping.get(tag, self._add_unknown_tag)( + iterator, tag, data, config, pos) + else: + if tag == 'DESCRIPTION': + if self.description is not None: + warn_or_raise(W17, W17, 'GROUP', config, pos) + self.description = data or None + elif tag == 'GROUP': + break + return self +
    +
    [docs] def to_xml(self, w, **kwargs): + with w.tag( + 'GROUP', + attrib=w.object_attrs( + self, ['ID', 'name', 'ref', 'ucd', 'utype'])): + if self.description is not None: + w.element("DESCRIPTION", self.description, wrap=True) + for entry in self.entries: + entry.to_xml(w, **kwargs) +
    +
    [docs] def iter_fields_and_params(self): + """ + Recursively iterate over all :class:`Param` elements in this + :class:`Group`. + """ + for entry in self.entries: + if isinstance(entry, Param): + yield entry + elif isinstance(entry, Group): + for field in entry.iter_fields_and_params(): + yield field +
    +
    [docs] def iter_groups(self): + """ + Recursively iterate over all sub-:class:`Group` instances in + this :class:`Group`. + """ + for entry in self.entries: + if isinstance(entry, Group): + yield entry + for group in entry.iter_groups(): + yield group + +
    +
    [docs]class Table(Element, _IDProperty, _NameProperty, _UcdProperty, + _DescriptionProperty): + """ + A class to store a TABLE_ element, which optionally contains data. + + It contains the following publicly-accessible members, all of + which are mutable: + + *array*: A Numpy recarray of the data itself, where each row + is a row of votable data, and columns are named and typed + based on the <FIELD> elements of the table. + + *mask*: A Numpy recarray of only boolean values, set to *True* + wherever a value is undefined. + + If the Table contains no data, (for example, its enclosing + :class:`Resource` has :attr:`~Resource.type` == 'meta') *array* + and *mask* will be zero-length arrays. + + .. note:: + In a future version of the vo package, the *array* and *mask* + elements will likely be combined into a single Numpy masked + record array. However, there are a number of deficiencies the + current implementation of Numpy that prevent this. + + The keyword arguments correspond to setting members of the same + name, documented below. + """ + def __init__(self, votable, ID=None, name=None, ref=None, ucd=None, + utype=None, nrows=None, id=None, config={}, pos=None, + **extra): + self._config = config + self._pos = pos + self._empty = False + + Element.__init__(self) + self._votable = votable + + self.ID = (resolve_id(ID, id, config, pos) + or xmlutil.fix_id(name, config, pos)) + self.name = name + xmlutil.check_id(ref, 'ref', config, pos) + self._ref = ref + self.ucd = ucd + self.utype = utype + if nrows is not None: + nrows = int(nrows) + assert nrows >= 0 + self._nrows = nrows + self.description = None + self.format = 'tabledata' + + self._fields = HomogeneousList(Field) + self._params = HomogeneousList(Param) + self._groups = HomogeneousList(Group) + self._links = HomogeneousList(Link) + self._infos = HomogeneousList(Info) + + self.array = np.array([]) + self.mask = np.array([]) + + warn_unknown_attrs('TABLE', extra.iterkeys(), config, pos) + + @property + def ref(self): + return self._ref + + @ref.setter + def ref(self, ref): + """ + Refer to another TABLE, previously defined, by the *ref* ID_ + for all metadata (FIELD_, PARAM_ etc.) information. + """ + # When the ref changes, we want to verify that it will work + # by actually going and looking for the referenced table. + # If found, set a bunch of properties in this table based + # on the other one. + xmlutil.check_id(ref, 'ref', self._config, self._pos) + if ref is not None: + try: + table = self._votable.get_table_by_id(ref, before=self) + except KeyError: + warn_or_raise( + W43, W43, ('TABLE', self.ref), self._config, self._pos) + ref = None + else: + self._fields = table.fields + self._params = table.params + self._groups = table.groups + self._links = table.links + else: + del self._fields[:] + del self._params[:] + del self._groups[:] + del self._links[:] + self._ref = ref + + @ref.deleter +
    [docs] def ref(self): + self._ref = None +
    + @property + def format(self): + """ + [*required*] The serialization format of the table. Must be + one of: + + 'tabledata' (TABLEDATA_), 'binary' (BINARY_), 'fits' (FITS_). + + Note that the 'fits' format, since it requires an external + file, can not be written out. Any file read in with 'fits' + format will be read out, by default, in 'tabledata' format. + """ + return self._format + + @format.setter +
    [docs] def format(self, format): + format = format.lower() + if format == 'fits': + vo_raise("fits format can not be written out, only read.", + self._config, self._pos, NotImplementedError) + if format not in ('tabledata', 'binary'): + vo_raise("Invalid format '%s'" % format, + self._config, self._pos) + self._format = format +
    + @property +
    [docs] def nrows(self): + """ + [*immutable*] The number of rows in the table, as specified in + the XML file. + """ + return self._nrows +
    + @property +
    [docs] def fields(self): + """ + A list of :class:`Field` objects describing the types of each + of the data columns. + """ + return self._fields +
    + @property +
    [docs] def params(self): + """ + A list of parameters (constant-valued columns) for the + table. Must contain only :class:`Param` objects. + """ + return self._params +
    + @property +
    [docs] def groups(self): + """ + A list of :class:`Group` objects describing how the columns + and parameters are grouped. Currently this information is + only kept around for round-tripping and informational + purposes. + """ + return self._groups +
    + @property + + @property +
    [docs] def infos(self): + """ + A list of :class:`Info` objects for the table. Allows for + post-operational diagnostics. + """ + return self._infos +
    +
    [docs] def is_empty(self): + """ + Returns True if this table doesn't contain any real data + because it was skipped over by the parser (through use of the + `table_number` kwarg). + """ + return self._empty +
    +
    [docs] def create_arrays(self, nrows=0, config={}): + """ + Create new arrays to hold the data based on the current set of + fields, and store them in the *array* and *mask* member + variables. Any data in existing arrays will be lost. + + *nrows*, if provided, is the number of rows to allocate. + """ + if nrows is None: + nrows = 0 + + fields = self.fields + + if len(fields) == 0: + array = np.recarray((nrows,), dtype='O') + mask = np.zeros((nrows,), dtype='b') + else: + # for field in fields: field._setup(config) + Field.uniqify_names(fields) + + dtype = [] + for x in fields: + if x._unique_name == x.ID: + id = x.ID + else: + id = (x._unique_name, x.ID) + dtype.append((id, x.converter.format)) + + array = np.recarray((nrows,), dtype=dtype) + descr_mask = [] + for d in array.dtype.descr: + new_type = (d[1][1] == 'O' and 'O') or 'bool' + if len(d) == 2: + descr_mask.append((d[0], new_type)) + elif len(d) == 3: + descr_mask.append((d[0], new_type, d[2])) + mask = np.zeros((nrows,), dtype=descr_mask) + + self.array = array + self.mask = mask +
    + def _resize_strategy(self, size): + """ + Return a new (larger) size based on size, used for + reallocating an array when it fills up. This is in its own + function so the resizing strategy can be easily replaced. + """ + # Once we go beyond 0, make a big step -- after that use a + # factor of 1.5 to help keep memory usage compact + if size == 0: + return 512 + return int(ceil(size * RESIZE_AMOUNT)) + + def _add_field(self, iterator, tag, data, config, pos): + field = Field(self._votable, config=config, pos=pos, **data) + self.fields.append(field) + field.parse(iterator, config) + + def _add_param(self, iterator, tag, data, config, pos): + param = Param(self._votable, config=config, pos=pos, **data) + self.params.append(param) + param.parse(iterator, config) + + def _add_group(self, iterator, tag, data, config, pos): + group = Group(self, config=config, pos=pos, **data) + self.groups.append(group) + group.parse(iterator, config) + + def _add_link(self, iterator, tag, data, config, pos): + link = Link(config=config, pos=pos, **data) + self.links.append(link) + link.parse(iterator, config) + +
    [docs] def parse(self, iterator, config): + columns = config.get('columns') + + # If we've requested to read in only a specific table, skip + # all others + table_number = config.get('table_number') + current_table_number = config.get('_current_table_number') + skip_table = False + if current_table_number is not None: + config['_current_table_number'] += 1 + if (table_number is not None and + table_number != current_table_number): + skip_table = True + self._empty = True + + if self.ref is not None: + # This table doesn't have its own datatype descriptors, it + # just references those from another table. + + # This is to call the property setter to go and get the + # referenced information + self.ref = self.ref + + for start, tag, data, pos in iterator: + if start: + if tag == 'DATA': + warn_unknown_attrs( + 'DATA', data.iterkeys(), config, pos) + break + else: + if tag == 'TABLE': + return self + elif tag == 'DESCRIPTION': + if self.description is not None: + warn_or_raise(W17, W17, 'RESOURCE', config, pos) + self.description = data or None + else: + tag_mapping = { + 'FIELD' : self._add_field, + 'PARAM' : self._add_param, + 'GROUP' : self._add_group, + 'LINK' : self._add_link, + 'DESCRIPTION' : self._ignore_add} + + for start, tag, data, pos in iterator: + if start: + if tag == 'DATA': + warn_unknown_attrs( + 'DATA', data.iterkeys(), config, pos) + break + + tag_mapping.get(tag, self._add_unknown_tag)( + iterator, tag, data, config, pos) + else: + if tag == 'DESCRIPTION': + if self.description is not None: + warn_or_raise(W17, W17, 'RESOURCE', config, pos) + self.description = data or None + elif tag == 'TABLE': + # For error checking purposes + Field.uniqify_names(self.fields) + return self + + self.create_arrays(nrows=self._nrows, config=config) + fields = self.fields + names = [x.ID for x in fields] + # Deal with a subset of the columns, if requested. + if not columns: + colnumbers = range(len(fields)) + else: + if isinstance(columns, string_types): + columns = [columns] + columns = np.asarray(columns) + if issubclass(columns.dtype.type, np.integer): + if np.any(columns < 0) or np.any(columns > len(fields)): + raise ValueError( + "Some specified column numbers out of range") + colnumbers = columns + elif issubclass(columns.dtype.type, np.character): + try: + colnumbers = [names.index(x) for x in columns] + except ValueError: + raise ValueError( + "Columns '%s' not found in fields list" % columns) + else: + raise TypeError("Invalid columns list") + + if not skip_table: + for start, tag, data, pos in iterator: + if start: + if tag == 'TABLEDATA': + warn_unknown_attrs( + 'TABLEDATA', data.iterkeys(), config, pos) + self.array, self.mask = self._parse_tabledata( + iterator, colnumbers, fields, config) + break + elif tag == 'BINARY': + warn_unknown_attrs( + 'BINARY', data.iterkeys(), config, pos) + self.array, self.mask = self._parse_binary( + iterator, colnumbers, fields, config) + break + elif tag == 'FITS': + warn_unknown_attrs( + 'FITS', data.iterkeys(), config, pos, ['extnum']) + try: + extnum = int(data.get('extnum', 0)) + if extnum < 0: + raise ValueError() + except ValueError: + vo_raise(E17, (), config, pos) + self.array, self.mask = self._parse_fits( + iterator, extnum, config) + break + else: + warn_or_raise(W37, W37, tag, config, pos) + break + + for start, tag, data, pos in iterator: + if not start and tag == 'DATA': + break + + for start, tag, data, pos in iterator: + if tag == 'INFO': + if start: + if not config.get('version_1_2_or_later'): + warn_or_raise( + W26, W26, ('INFO', 'TABLE', '1.2'), config, pos) + info = Info(config=config, pos=pos, **data) + self.infos.append(info) + info.parse(iterator, config) + else: + info.content = data + elif not start and tag == 'TABLE': + break + + return self +
    + def _parse_tabledata(self, iterator, colnumbers, fields, config): + # Since we don't know the number of rows up front, we'll + # reallocate the record array to make room as we go. This + # prevents the need to scan through the XML twice. The + # allocation is by factors of 1.5. + invalid = config.get('invalid', 'exception') + + array = self.array + mask = self.mask + # Need to have only one reference so that we can resize the + # array + del self.array + del self.mask + + parsers = [field.converter.parse for field in fields] + binparsers = [field.converter.binparse for field in fields] + + numrows = 0 + alloc_rows = len(array) + colnumbers_bits = [i in colnumbers for i in range(len(fields))] + row_default = [x.converter.default for x in fields] + mask_default = [True] * len(fields) + array_chunk = [] + mask_chunk = [] + chunk_size = config.get('chunk_size', DEFAULT_CHUNK_SIZE) + for start, tag, data, pos in iterator: + if tag == 'TR': + # Now parse one row + row = row_default[:] + row_mask = mask_default[:] + i = 0 + for start, tag, data, pos in iterator: + if start: + binary = (data.get('encoding', None) == 'base64') + warn_unknown_attrs( + tag, data.iterkeys(), config, pos, ['encoding']) + else: + if tag == 'TD': + if i >= len(fields): + vo_raise(E20, len(fields), config, pos) + + if colnumbers_bits[i]: + try: + if binary: + if IS_PY3K: + rawdata = base64.b64decode( + data.encode('ascii')) + else: + rawdata = data.decode('base64') + buf = io.BytesIO(rawdata) + buf.seek(0) + try: + value, mask_value = binparsers[i]( + buf.read) + except Exception as e: + vo_reraise( + e, config, pos, + "(in row %d, col '%s')" % + (len(array_chunk), + fields[i].ID)) + else: + try: + value, mask_value = parsers[i]( + data, config, pos) + except Exception as e: + vo_reraise( + e, config, pos, + "(in row %d, col '%s')" % + (len(array_chunk), + fields[i].ID)) + except Exception as e: + if invalid == 'exception': + vo_reraise(e, config, pos) + else: + row[i] = value + row_mask[i] = mask_value + elif tag == 'TR': + break + else: + self._add_unknown_tag( + iterator, tag, data, config, pos) + i += 1 + + if i < len(fields): + vo_raise(E21, (i, len(fields)), config, pos) + + array_chunk.append(tuple(row)) + mask_chunk.append(tuple(row_mask)) + + if len(array_chunk) == chunk_size: + while numrows + chunk_size > alloc_rows: + alloc_rows = self._resize_strategy(alloc_rows) + if alloc_rows != len(array): + array.resize((alloc_rows,)) + mask.resize((alloc_rows,)) + array[numrows:numrows + chunk_size] = array_chunk + mask[numrows:numrows + chunk_size] = mask_chunk + numrows += chunk_size + array_chunk = [] + mask_chunk = [] + + elif not start and tag == 'TABLEDATA': + break + + # Now, resize the array to the exact number of rows we need and + # put the last chunk values in there. + if len(array_chunk): + alloc_rows = numrows + len(array_chunk) + array.resize((alloc_rows,)) + mask.resize((alloc_rows,)) + array[numrows:] = array_chunk + mask[numrows:] = mask_chunk + numrows += len(array_chunk) + + if (self.nrows is not None and + self.nrows >= 0 and + self.nrows != numrows): + warn_or_raise(W18, W18, (self.nrows, numrows), config, pos) + self._nrows = numrows + + return array, mask + + def _parse_binary(self, iterator, colnumbers, fields, config): + fields = self.fields + + have_local_stream = False + for start, tag, data, pos in iterator: + if tag == 'STREAM': + if start: + warn_unknown_attrs( + 'STREAM', data.iterkeys(), config, pos, + ['type', 'href', 'actuate', 'encoding', 'expires', + 'rights']) + if 'href' not in data: + have_local_stream = True + if data.get('encoding', None) != 'base64': + warn_or_raise( + W38, W38, data.get('encoding', None), + config, pos) + else: + href = data['href'] + xmlutil.check_anyuri(href, config, pos) + encoding = data.get('encoding', None) + else: + buffer = data + break + + if have_local_stream: + buffer = base64.b64decode(buffer.encode('ascii')) + string_io = io.BytesIO(buffer) + string_io.seek(0) + read = string_io.read + else: + if not (href.startswith('http') or + href.startswith('ftp') or + href.startswith('file')): + vo_raise( + "The vo package only supports remote data through http, " + + "ftp or file", + self._config, self._pos, NotImplementedError) + fd = urllib2.urlopen(href) + if encoding is not None: + if encoding == 'gzip': + from ...utils.compat import gzip + fd = gzip.GzipFile(href, 'rb', fileobj=fd) + elif encoding == 'base64': + fd = codecs.EncodedFile(fd, 'base64') + else: + vo_raise( + "Unknown encoding type '%s'" % encoding, + self._config, self._pos, NotImplementedError) + read = fd.read + + def careful_read(length): + result = read(length) + if len(result) != length: + raise EOFError + return result + + array = self.array + mask = self.mask + # Need to have only one reference so that we can resize the + # array + del self.array + del self.mask + + binparsers = [field.converter.binparse for field in fields] + + numrows = 0 + alloc_rows = len(array) + while True: + # Resize result arrays if necessary + if numrows >= alloc_rows: + alloc_rows = self._resize_strategy(alloc_rows) + array.resize((alloc_rows,)) + mask.resize((alloc_rows,)) + + row_data = [] + row_mask_data = [] + try: + for i, binparse in enumerate(binparsers): + try: + value, value_mask = binparse(careful_read) + except EOFError: + raise + except Exception as e: + vo_reraise(e, config, pos, + "(in row %d, col '%s')" % + (numrows, fields[i].ID)) + row_data.append(value) + row_mask_data.append(value_mask) + except EOFError: + break + + row = [x.converter.default for x in fields] + row_mask = [False] * len(fields) + for i in colnumbers: + row[i] = row_data[i] + row_mask[i] = row_mask_data[i] + + array[numrows] = tuple(row) + mask[numrows] = tuple(row_mask) + numrows += 1 + + array = np.resize(array, (numrows,)) + mask = np.resize(mask, (numrows,)) + + return array, mask + + def _parse_fits(self, iterator, extnum, config): + if not _has_pyfits: + vo_raise( + "Input file contains FITS data, but pyfits is not installed.", + config, None, ImportError) + + for start, tag, data, pos in iterator: + if tag == 'STREAM': + if start: + warn_unknown_attrs( + 'STREAM', data.iterkeys(), config, pos, + ['type', 'href', 'actuate', 'encoding', 'expires', + 'rights']) + href = data['href'] + encoding = data.get('encoding', None) + else: + break + + if not (href.startswith('http') or + href.startswith('ftp') or + href.startswith('file')): + vo_raise( + "The vo package only supports remote data through http, " + "ftp or file", + self._config, self._pos, NotImplementedError) + + fd = urllib2.urlopen(href) + if encoding is not None: + if encoding == 'gzip': + from ...utils.compat import gzip + fd = gzip.GzipFile(href, 'r', fileobj=fd) + elif encoding == 'base64': + fd = codecs.EncodedFile(fd, 'base64') + else: + vo_raise( + "Unknown encoding type '%s'" % encoding, + self._config, self._pos, NotImplementedError) + + fits = pyfits.open(fd) + + array = fits[int(extnum)].data + if array.dtype != self.array.dtype: + warn_or_raise(W19, W19, (), self._config, self._pos) + + return array, self.mask + +
    [docs] def to_xml(self, w, **kwargs): + with w.tag( + 'TABLE', + attrib=w.object_attrs( + self, + ('ID', 'name', 'ref', 'ucd', 'utype', 'nrows'))): + + if self.description is not None: + w.element("DESCRIPTION", self.description, wrap=True) + + for element_set in (self.fields, self.params): + for element in element_set: + element._setup({}, None) + + if self.ref is None: + for element_set in (self.fields, self.params, self.groups, + self.links): + for element in element_set: + element.to_xml(w, **kwargs) + + if len(self.array): + with w.tag('DATA'): + if self.format == 'fits': + self.format = 'tabledata' + + if self.format == 'tabledata': + self._write_tabledata(w, **kwargs) + elif self.format == 'binary': + self._write_binary(w, **kwargs) + + if self.ref is None and kwargs['version_1_2_or_later']: + for element in self._infos: + element.to_xml(w, **kwargs) +
    + def _write_tabledata(self, w, **kwargs): + fields = self.fields + array = self.array + mask = self.mask + + write_null_values = kwargs.get('write_null_values', False) + with w.tag('TABLEDATA'): + w._flush() + if (_has_c_tabledata_writer and + not kwargs.get('_debug_python_based_parser')): + fields = [field.converter.output for field in fields] + indent = len(w._tags) - 1 + tablewriter.write_tabledata(w.write, array, mask, fields, + write_null_values, indent, 1 << 8) + else: + write = w.write + indent_spaces = w.get_indentation_spaces() + if not IS_PY3K: + indent_spaces = indent_spaces.encode('ascii') + tr_start = indent_spaces + "<TR>\n" + tr_end = indent_spaces + "</TR>\n" + td = indent_spaces + " <TD>%s</TD>\n" + td_empty = indent_spaces + " <TD/>\n" + fields = [(i, field.converter.output) + for i, field in enumerate(fields)] + for row in xrange(len(array)): + write(tr_start) + array_row = array[row] + mask_row = mask[row] + for i, output in fields: + masked = mask_row[i] + if not np.all(masked) or write_null_values: + try: + val = output(array_row[i], masked) + except Exception as e: + vo_reraise(e, config, pos, + "(in row %d, col '%s')" % + (row, fields[i].ID)) + write(td % val) + else: + write(td_empty) + write(tr_end) + + def _write_binary(self, w, **kwargs): + fields = self.fields + array = self.array + mask = self.mask + + with w.tag('BINARY'): + with w.tag('STREAM', encoding='base64'): + fields = [(i, field.converter.binoutput) + for (i, field) in enumerate(fields)] + + data = io.BytesIO() + for row in xrange(len(array)): + array_row = array[row] + array_mask = mask[row] + for i, converter in fields: + try: + chunk = converter(array_row[i], array_mask[i]) + except Exception as e: + vo_reraise(e, config, pos, + "(in row %d, col '%s')" % + (row, fields[i].ID)) + data.write(chunk) + + w._flush() + if IS_PY3K: + w.write(base64.b64encode(data.getvalue()).decode('ascii')) + else: + w.write(data.getvalue().encode('base64')) + +
    [docs] def iter_fields_and_params(self): + """ + Recursively iterate over all FIELD and PARAM elements in the + TABLE. + """ + for param in self.params: + yield param + for field in self.fields: + yield field + for group in self.groups: + for field in group.iter_fields_and_params(): + yield field +
    + get_field_by_id = _lookup_by_id_factory( + 'iter_fields_and_params', 'FIELD or PARAM', + """ + Looks up a FIELD or PARAM element by the given ID. + """) + + get_field_by_id_or_name = _lookup_by_id_or_name_factory( + 'iter_fields_and_params', 'FIELD or PARAM', + """ + Looks up a FIELD or PARAM element by the given ID or name. + """) + +
    [docs] def iter_groups(self): + """ + Recursively iterate over all GROUP elements in the TABLE. + """ + for group in self.groups: + yield group + for g in group.iter_groups(): + yield g +
    + get_group_by_id = _lookup_by_id_factory( + 'iter_groups', 'GROUP', + """ + Looks up a GROUP element by the given ID. Used by the group's + "ref" attribute + """) + +
    +
    [docs]class Resource(Element, _IDProperty, _NameProperty, _UtypeProperty, + _DescriptionProperty): + """ + A class to store the information in a RESOURCE_ element. Each + resource may contain zero-or-more TABLE_ elements and zero-or-more + nested RESOURCE_ elements. + + The keyword arguments correspond to setting members of the same + name, documented below. + """ + def __init__(self, name=None, ID=None, utype=None, type='results', + id=None, config={}, pos=None, **kwargs): + self._config = config + self._pos = pos + + Element.__init__(self) + self.name = name + self.ID = resolve_id(ID, id, config, pos) + self.utype = utype + self.type = type + self._extra_attributes = kwargs + self.description = None + + self._coordinate_systems = HomogeneousList(CooSys) + self._params = HomogeneousList(Param) + self._infos = HomogeneousList(Info) + self._links = HomogeneousList(Link) + self._tables = HomogeneousList(Table) + self._resources = HomogeneousList(Resource) + + warn_unknown_attrs('RESOURCE', kwargs.iterkeys(), config, pos) + + @property + def type(self): + """ + [*required*] The type of the resource. Must be either: + + - 'results': This resource contains actual result values + (default) + + - 'meta': This resource contains only datatype descriptions + (FIELD_ elements), but no actual data. + """ + return self._type + + @type.setter +
    [docs] def type(self, type): + if type not in ('results', 'meta'): + vo_raise(E18, type, self._config, self._pos) + self._type = type +
    + @property +
    [docs] def extra_attributes(self): + """ + A dictionary of string keys to string values containing any + extra attributes of the RESOURCE_ element that are not defined + in the specification. (The specification explicitly allows + for extra attributes here, but nowhere else.) + """ + return self._extra_attributes +
    + @property +
    [docs] def coordinate_systems(self): + """ + A list of coordinate system definitions (COOSYS_ elements) for + the RESOURCE_. Must contain only `CooSys` objects. + """ + return self._coordinate_systems +
    + @property +
    [docs] def infos(self): + """ + A list of informational parameters (key-value pairs) for the + resource. Must only contain `Info` objects. + """ + return self._infos +
    + @property +
    [docs] def params(self): + """ + A list of parameters (constant-valued columns) for the + resource. Must contain only `Param` objects. + """ + return self._params +
    + @property + + @property +
    [docs] def tables(self): + """ + A list of tables in the resource. Must contain only + `Table` objects. + """ + return self._tables +
    + @property +
    [docs] def resources(self): + """ + A list of nested resources inside this resource. Must contain + only `Resource` objects. + """ + return self._resources +
    + def _add_table(self, iterator, tag, data, config, pos): + table = Table(self._votable, config=config, pos=pos, **data) + self.tables.append(table) + table.parse(iterator, config) + + def _add_info(self, iterator, tag, data, config, pos): + info = Info(config=config, pos=pos, **data) + self.infos.append(info) + info.parse(iterator, config) + + def _add_param(self, iterator, tag, data, config, pos): + param = Param(self._votable, config=config, pos=pos, **data) + self.params.append(param) + param.parse(iterator, config) + + def _add_coosys(self, iterator, tag, data, config, pos): + coosys = CooSys(config=config, pos=pos, **data) + self.coordinate_systems.append(coosys) + coosys.parse(iterator, config) + + def _add_resource(self, iterator, tag, data, config, pos): + resource = Resource(config=config, pos=pos, **data) + self.resources.append(resource) + resource.parse(self._votable, iterator, config) + + def _add_link(self, iterator, tag, data, config, pos): + link = Link(config=config, pos=pos, **data) + self.links.append(link) + link.parse(iterator, config) + +
    [docs] def parse(self, votable, iterator, config): + self._votable = votable + + tag_mapping = { + 'TABLE' : self._add_table, + 'INFO' : self._add_info, + 'PARAM' : self._add_param, + 'COOSYS' : self._add_coosys, + 'RESOURCE' : self._add_resource, + 'LINK' : self._add_link, + 'DESCRIPTION' : self._ignore_add + } + + for start, tag, data, pos in iterator: + if start: + tag_mapping.get(tag, self._add_unknown_tag)( + iterator, tag, data, config, pos) + elif tag == 'DESCRIPTION': + if self.description is not None: + warn_or_raise(W17, W17, 'RESOURCE', config, pos) + self.description = data or None + elif tag == 'INFO': + self.infos[-1].content = data + + del self._votable + + return self +
    +
    [docs] def to_xml(self, w, **kwargs): + attrs = w.object_attrs(self, ('ID', 'type', 'utype')) + attrs.update(self.extra_attributes) + with w.tag('RESOURCE', attrib=attrs): + if self.description is not None: + w.element("DESCRIPTION", self.description, wrap=True) + for element_set in (self.coordinate_systems, self.params, + self.infos, self.links, self.tables, + self.resources): + for element in element_set: + element.to_xml(w, **kwargs) +
    +
    [docs] def iter_tables(self): + """ + Recursively iterates over all tables in the resource and + nested resources. + """ + for table in self.tables: + yield table + for resource in self.resources: + for table in resource.iter_tables(): + yield table +
    +
    [docs] def iter_fields_and_params(self): + """ + Recursively iterates over all FIELD_ and PARAM_ elements in + the resource, its tables and nested resources. + """ + for param in self.params: + yield param + for table in self.tables: + for param in table.iter_fields_and_params(): + yield param + for resource in self.resources: + for param in resource.iter_fields_and_params(): + yield param +
    +
    [docs] def iter_coosys(self): + """ + Recursively iterates over all the COOSYS_ elements in the + resource and nested resources. + """ + for coosys in self.coordinate_systems: + yield coosys + for resource in self.resources: + for coosys in resource.iter_coosys(): + yield coosys + +
    +
    [docs]class VOTableFile(Element, _IDProperty, _DescriptionProperty): + """ + A class to represent the top-level VOTABLE_ element. + + The keyword arguments correspond to setting members of the same + name, documented below. + + *version* is settable at construction time only, since conformance + tests for building the rest of the structure depend on it. + """ + + def __init__(self, ID=None, id=None, config={}, pos=None, version="1.2"): + self._config = config + self._pos = pos + + Element.__init__(self) + self.ID = resolve_id(ID, id, config, pos) + self.description = None + + self._coordinate_systems = HomogeneousList(CooSys) + self._params = HomogeneousList(Param) + self._infos = HomogeneousList(Info) + self._resources = HomogeneousList(Resource) + self._groups = HomogeneousList(Group) + + version = str(version) + assert version in ("1.0", "1.1", "1.2") + self._version = version + + @property +
    [docs] def version(self): + """ + The version of the VOTable specification that the file uses. + """ + return self._version +
    + @property +
    [docs] def coordinate_systems(self): + """ + A list of coordinate system descriptions for the file. Must + contain only `CooSys` objects. + """ + return self._coordinate_systems +
    + @property +
    [docs] def params(self): + """ + A list of parameters (constant-valued columns) that apply to + the entire file. Must contain only `Param` objects. + """ + return self._params +
    + @property +
    [docs] def infos(self): + """ + A list of informational parameters (key-value pairs) for the + entire file. Must only contain `Info` objects. + """ + return self._infos +
    + @property +
    [docs] def resources(self): + """ + A list of resources, in the order they appear in the file. + Must only contain `Resource` objects. + """ + return self._resources +
    + @property +
    [docs] def groups(self): + """ + A list of groups, in the order they appear in the file. Only + supported as a child of the VOTABLE element in VOTable 1.2 or + later. + """ + return self._groups +
    + def _add_param(self, iterator, tag, data, config, pos): + param = Param(self, config=config, pos=pos, **data) + self.params.append(param) + param.parse(iterator, config) + + def _add_resource(self, iterator, tag, data, config, pos): + resource = Resource(config=config, pos=pos, **data) + self.resources.append(resource) + resource.parse(self, iterator, config) + + def _add_coosys(self, iterator, tag, data, config, pos): + coosys = CooSys(config=config, pos=pos, **data) + self.coordinate_systems.append(coosys) + coosys.parse(iterator, config) + + def _add_info(self, iterator, tag, data, config, pos): + info = Info(config=config, pos=pos, **data) + self.infos.append(info) + info.parse(iterator, config) + + def _add_group(self, iterator, tag, data, config, pos): + if not config.get('version_1_2_or_later'): + warn_or_raise(W26, W26, ('GROUP', 'VOTABLE', '1.2'), config, pos) + group = Group(self, config=config, pos=pos, **data) + self.groups.append(group) + group.parse(iterator, config) + +
    [docs] def parse(self, iterator, config): + config['_current_table_number'] = 0 + + for start, tag, data, pos in iterator: + if start: + if tag == 'xml': + pass + elif tag == 'VOTABLE': + if 'version' not in data: + warn_or_raise(W20, W20, self.version, config, pos) + config['version'] = self.version + else: + config['version'] = self._version = data['version'] + if config['version'].lower().startswith('v'): + warn_or_raise( + W29, W29, config['version'], config, pos) + self._version = config['version'] = \ + config['version'][1:] + if config['version'] not in ('1.1', '1.2'): + vo_warn(W21, config['version'], config, pos) + + if 'xmlns' in data: + correct_ns = ('http://www.ivoa.net/xml/VOTable/v%s' % + config['version']) + if data['xmlns'] != correct_ns: + vo_warn( + W41, (correct_ns, data['xmlns']), config, pos) + else: + vo_warn(W42, (), config, pos) + + break + else: + vo_raise(E19, (), config, pos) + config['version_1_1_or_later'] = \ + util.version_compare(config['version'], '1.1') >= 0 + config['version_1_2_or_later'] = \ + util.version_compare(config['version'], '1.2') >= 0 + + tag_mapping = { + 'PARAM' : self._add_param, + 'RESOURCE' : self._add_resource, + 'COOSYS' : self._add_coosys, + 'INFO' : self._add_info, + 'DEFINITIONS' : self._add_definitions, + 'DESCRIPTION' : self._ignore_add, + 'GROUP' : self._add_group} + + for start, tag, data, pos in iterator: + if start: + tag_mapping.get(tag, self._add_unknown_tag)( + iterator, tag, data, config, pos) + elif tag == 'DESCRIPTION': + if self.description is not None: + warn_or_raise(W17, W17, 'VOTABLE', config, pos) + self.description = data or None + elif tag == 'INFO': + self.infos[-1].content = data + return self +
    +
    [docs] def to_xml(self, fd, write_null_values=False, + _debug_python_based_parser=False, + _astropy_version=None): + """ + Write to an XML file. + + Parameters + ---------- + fd : str path or writable file-like object + Where to write the file. + + write_null_values : bool + When `True`, write the 'null' value (specified in the null + attribute of the VALUES element for each FIELD) for empty + values. When False (default), simply write no value. + """ + kwargs = { + 'write_null_values': write_null_values, + 'version': self.version, + 'version_1_1_or_later': + util.version_compare(self.version, '1.1') >= 0, + 'version_1_2_or_later': + util.version_compare(self.version, '1.2') >= 0, + '_debug_python_based_parser': _debug_python_based_parser} + + with util.convert_to_writable_filelike(fd) as fd: + w = XMLWriter(fd) + version = self.version + if _astropy_version is None: + lib_version = astropy_version + else: + lib_version = _astropy_version + + xml_header = """ +<?xml version="1.0" encoding="utf-8"?> +<!-- Produced with astropy.io.vo version %(lib_version)s + http://www.astropy.org/ -->\n""" + w.write(xml_header.lstrip() % locals()) + + with w.tag('VOTABLE', + {'version': version, + 'xmlns:xsi': + "http://www.w3.org/2001/XMLSchema-instance", + 'xsi:noNamespaceSchemaLocation': + "http://www.ivoa.net/xml/VOTable/v%s" % version, + 'xmlns': + "http://www.ivoa.net/xml/VOTable/v%s" % version}): + if self.description is not None: + w.element("DESCRIPTION", self.description, wrap=True) + element_sets = [self.coordinate_systems, self.params, + self.infos, self.resources] + if kwargs['version_1_2_or_later']: + element_sets[0] = self.groups + for element_set in element_sets: + for element in element_set: + element.to_xml(w, **kwargs) +
    +
    [docs] def iter_tables(self): + """ + Iterates over all tables in the VOTable file in a "flat" way, + ignoring the nesting of resources etc. + """ + for resource in self.resources: + for table in resource.iter_tables(): + yield table +
    +
    [docs] def get_first_table(self): + """ + Often, you know there is only one table in the file, and + that's all you need. This method returns that first table. + """ + for table in self.iter_tables(): + if not table.is_empty(): + return table + raise IndexError("No table found in VOTABLE file.") +
    + get_table_by_id = _lookup_by_id_factory( + 'iter_tables', 'TABLE', + """ + Looks up a TABLE element by the given ID. Used by the table + "ref" attribute. + """) + +
    [docs] def get_table_by_index(self, idx): + """ + Get a table by its ordinal position in the file. + """ + for i, table in enumerate(self.iter_tables()): + if i == idx: + return table + raise IndexError("No table at index %d found in VOTABLE file." % idx) +
    +
    [docs] def iter_fields_and_params(self): + """ + Recursively iterate over all FIELD and PARAM elements in the + VOTABLE file. + """ + for resource in self.resources: + for field in resource.iter_fields_and_params(): + yield field +
    + get_field_by_id = _lookup_by_id_factory( + 'iter_fields_and_params', 'FIELD', + """ + Looks up a FIELD element by the given ID. Used by the field's + "ref" attribute. + """) + + get_field_by_id_or_name = _lookup_by_id_or_name_factory( + 'iter_fields_and_params', 'FIELD', + """ + Looks up a FIELD element by the given ID or name. + """) + +
    [docs] def iter_values(self): + """ + Recursively iterate over all VALUES_ elements in the VOTABLE + file. + """ + for field in self.iter_fields_and_params(): + yield field.values +
    + get_values_by_id = _lookup_by_id_factory( + 'iter_values', 'VALUES', + """ + Looks up a VALUES element by the given ID. Used by the values + "ref" attribute. + """) + +
    [docs] def iter_groups(self): + """ + Recursively iterate over all GROUP elements in the VOTABLE + file. + """ + for table in self.iter_tables(): + for group in table.iter_groups(): + yield group +
    + get_group_by_id = _lookup_by_id_factory( + 'iter_groups', 'GROUP', + """ + Looks up a GROUP element by the given ID. Used by the group's + "ref" attribute + """) + +
    [docs] def iter_coosys(self): + """ + Recursively iterate over all COOSYS elements in the VOTABLE + file. + """ + for coosys in self.coordinate_systems: + yield coosys + for resource in self.resources: + for coosys in resource.iter_coosys(): + yield coosys +
    + get_coosys_by_id = _lookup_by_id_factory( + 'iter_coosys', 'COOSYS', + """Looks up a COOSYS element by the given ID.""") + +
    [docs] def set_all_tables_format(self, format): + """ + Set the output storage format of all tables in the file. + """ + for table in self.iter_tables(): + table.format = format
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/ucd.html b/_modules/astropy/io/vo/ucd.html new file mode 100644 index 00000000..84a9b9d3 --- /dev/null +++ b/_modules/astropy/io/vo/ucd.html @@ -0,0 +1,296 @@ + + + + + + + + + + astropy.io.vo.ucd — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.ucd

    +"""
    +This file contains routines to verify the correctness of UCD strings.
    +"""
    +
    +from __future__ import with_statement, absolute_import
    +
    +#STDLIB
    +import os
    +import re
    +import sys
    +
    +#LOCAL
    +from ... import config
    +
    +__all__ = ['parse_ucd', 'check_ucd']
    +
    +
    +class UCDWords:
    +    """
    +    A class to manage the list of acceptable UCD words.  Works by
    +    reading in a data file exactly as provided by IVOA.  This file
    +    resides in data/ucd1p-words.txt.
    +    """
    +    def __init__(self):
    +        self._primary = set()
    +        self._secondary = set()
    +        self._descriptions = {}
    +        self._capitalization = {}
    +
    +        with config.get_data_fileobj("data/ucd1p-words.txt") as fd:
    +            for line in fd.readlines():
    +                if sys.version_info[0] >= 3:
    +                    type, name, descr = [
    +                        x.strip().decode('ascii') for x in line.split(b'|')]
    +                else:
    +                    type, name, descr = [x.strip() for x in line.split('|')]
    +                name_lower = name.lower()
    +                if type in 'QPEV':
    +                    self._primary.add(name_lower)
    +                if type in 'QSEV':
    +                    self._secondary.add(name_lower)
    +                self._descriptions[name_lower] = descr
    +                self._capitalization[name_lower] = name
    +
    +    def is_primary(self, name):
    +        """
    +        Returns True if *name* is a valid primary name.
    +        """
    +        return name.lower() in self._primary
    +
    +    def is_secondary(self, name):
    +        """
    +        Returns True if *name* is a valid secondary name.
    +        """
    +        return name.lower() in self._secondary
    +
    +    def get_description(self, name):
    +        """
    +        Returns the official English description of the given UCD
    +        *name*.
    +        """
    +        return self._descriptions[name.lower()]
    +
    +    def normalize_capitalization(self, name):
    +        """
    +        Returns the standard capitalization form of the given name.
    +        """
    +        return self._capitalization[name.lower()]
    +
    +_ucd_singleton = None
    +
    +
    +
    [docs]def parse_ucd(ucd, check_controlled_vocabulary=False, has_colon=False): + """ + Parse the UCD into its component parts. + + Parameters + ---------- + ucd : str + The UCD string + + check_controlled_vocabulary : bool, optional + If `True`, then each word in the UCD will be verified against + the UCD1+ controlled vocabulary, (as required by the VOTable + specification version 1.2), otherwise not. + + has_colon : bool, optional + If `True`, the UCD may contain a colon (as defined in earlier + versions of the standard). + + Returns + ------- + parts : list + The result is a list of tuples of the form: + + (*namespace*, *word*) + + If no namespace was explicitly specified, *namespace* will be + returned as ``'ivoa'`` (i.e., the default namespace). + + Raises + ------ + ValueError : *ucd* is invalid + """ + global _ucd_singleton + if _ucd_singleton is None: + _ucd_singleton = UCDWords() + + if has_colon: + m = re.search('[^A-Za-z0-9_.:;\-]', ucd) + else: + m = re.search('[^A-Za-z0-9_.;\-]', ucd) + if m is not None: + raise ValueError("UCD has invalid character '%s' in '%s'" % + (m.group(0), ucd)) + + word_component_re = '[A-Za-z0-9][A-Za-z0-9\-_]*' + word_re = '%s(\.%s)*' % (word_component_re, word_component_re) + + parts = ucd.split(';') + words = [] + for i, word in enumerate(parts): + colon_count = word.count(':') + if colon_count == 1: + ns, word = word.split(':', 1) + if not re.match(word_component_re, ns): + raise ValueError("Invalid namespace '%s'" % ns) + ns = ns.lower() + elif colon_count > 1: + raise ValueError("Too many colons in '%s'" % word) + else: + ns = 'ivoa' + + if not re.match(word_re, word): + raise ValueError("Invalid word '%s'" % word) + + if ns == 'ivoa' and check_controlled_vocabulary: + if i == 0: + if not _ucd_singleton.is_primary(word): + if _ucd_singleton.is_secondary(word): + raise ValueError( + "Secondary word '%s' is not valid as a primary " + "word" % word) + else: + raise ValueError("Unknown word '%s'" % word) + else: + if not _ucd_singleton.is_secondary(word): + if _ucd_singleton.is_primary(word): + raise ValueError( + "Primary word '%s' is not valid as a secondary " + "word" % word) + else: + raise ValueError("Unknown word '%s'" % word) + + try: + normalized_word = _ucd_singleton.normalize_capitalization(word) + except KeyError: + normalized_word = word + words.append((ns, normalized_word)) + + return words + +
    +
    [docs]def check_ucd(ucd, check_controlled_vocabulary=False, has_colon=False): + """ + Returns False if *ucd* is not a valid `unified content + descriptor`_. + + Parameters + ---------- + ucd : str + The UCD string + + check_controlled_vocabulary : bool, optional + If `True`, then each word in the UCD will be verified against + the UCD1+ controlled vocabulary, (as required by the VOTable + specification version 1.2), otherwise not. + + Returns + ------- + valid : bool + """ + if ucd is None: + return True + + try: + parse_ucd(ucd, + check_controlled_vocabulary=check_controlled_vocabulary, + has_colon=has_colon) + except ValueError as e: + return False + return True
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/unit.html b/_modules/astropy/io/vo/unit.html new file mode 100644 index 00000000..7b8a414f --- /dev/null +++ b/_modules/astropy/io/vo/unit.html @@ -0,0 +1,164 @@ + + + + + + + + + + astropy.io.vo.unit — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.unit

    +"""
    +Tools to verify the syntax of unit attributes according to the
    +`Standards for Astronomical Catalogues, Version 2.0
    +<http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_
    +"""
    +
    +# STDLIB
    +import re
    +
    +# LOCAL
    +from .exceptions import warn_or_raise, W50
    +
    +
    +__all__ = ['unit_names', 'unit_prefixes', 'is_unit', 'check_unit']
    +
    +
    +unit_names = """
    +    - % a A AU arcmin arcsec barn bit byte C cd ct D d deg eV F g h H
    +    Hz J Jy K lm lx m mag mas min mol N Ohm Pa pc pix rad Ry s S
    +    solLum solMass solRad Sun sr T V W Wb yr
    +    """.split()
    +
    +
    +unit_prefixes = """
    +    d c m u n p f a z y da h k M G T P E Z Y
    +    """.split()
    +
    +
    +_unit_name_regex = '|'.join('(?:{0})'.format(x) for x in unit_names)
    +_unit_prefix_regex = '|'.join('(?:{0})'.format(x) for x in unit_prefixes)
    +
    +
    +
    [docs]def is_unit(s): + """ + Returns `True` if *s* is a valid unit string as defined by + `Standards for Astronomical Catalogues, Version 2.0 + <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_ + """ + number = r'[+\-]?[0-9]+(?:\.[0-9]*)?(?:[+\-][0-9]+)?' + factor = r'{0}(?:x{0})?'.format(number) + unit = r'(?:{0})?(?:{1})'.format(_unit_prefix_regex, _unit_name_regex) + bracketed_unit = r'(?:{0})|(?:\[{0}\])'.format(unit) + expression = ( + r'^(?P<factor>{0})?(?P<unit>{1})(?P<subunit>[/.]{1})?(?P<power>{2})?$'.format( + factor, bracketed_unit, number)) + + match = re.match(expression, s) + return match is not None + +
    +
    [docs]def check_unit(unit, attr_name, config={}, pos=None): + """ + Raises a `ValueError` if *unit* is not a valid unit as defined by + `Standards for Astronomical Catalogues, Version 2.0 + <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_ + """ + if (unit is not None and not is_unit(unit)): + warn_or_raise(W50, W50, unit, config, pos) + return False + return True +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/util.html b/_modules/astropy/io/vo/util.html new file mode 100644 index 00000000..d4345d3a --- /dev/null +++ b/_modules/astropy/io/vo/util.html @@ -0,0 +1,326 @@ + + + + + + + + + + astropy.io.vo.util — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.util

    +"""
    +Various utilities and cookbook-like things.
    +"""
    +
    +from __future__ import division, with_statement, absolute_import
    +
    +# STDLIB
    +import collections
    +import contextlib
    +from distutils import version
    +import io
    +import re
    +import sys
    +import time
    +
    +
    +__all__ = [
    +    'convert_to_writable_filelike',
    +    'stc_reference_frames',
    +    'coerce_range_list_param',
    +    'is_callable'
    +    ]
    +
    +
    +IS_PY3K = sys.hexversion >= 0x03000000
    +
    +
    +@contextlib.contextmanager
    +
    [docs]def convert_to_writable_filelike(fd): + """ + Returns a writable file-like object suitable for streaming output. + + Parameters + ---------- + fd : file path string or writable file-like object + May be: + + - a file path, in which case it is opened, and the file + object is returned. + + - an object with a :meth:`write` method, in which case that + object. + + Returns + ------- + fd : writable file-like object + """ + if isinstance(fd, basestring): + if IS_PY3K: + if fd.endswith('.gz'): + from ...utils.compat import gzip + with gzip.GzipFile(fd, 'wb') as real_fd: + encoded_fd = io.TextIOWrapper(real_fd, encoding='utf8') + yield encoded_fd + encoded_fd.flush() + real_fd.flush() + return + else: + with io.open(fd, 'w', encoding='utf8') as real_fd: + yield real_fd + return + else: + if fd.endswith('.gz'): + from ...utils.compat import gzip + with gzip.GzipFile(fd, 'wb') as real_fd: + yield real_fd + real_fd.flush() + return + else: + with open(fd, 'wb') as real_fd: + yield real_fd + return + elif hasattr(fd, 'write'): + assert is_callable(fd.write) + yield fd + return + else: + raise TypeError("Can not be coerced to writable file-like object") + + +# <http://www.ivoa.net/Documents/REC/DM/STC-20071030.html>
    +stc_reference_frames = set([ + 'FK4', 'FK5', 'ECLIPTIC', 'ICRS', 'GALACTIC', 'GALACTIC_I', 'GALACTIC_II', + 'SUPER_GALACTIC', 'AZ_EL', 'BODY', 'GEO_C', 'GEO_D', 'MAG', 'GSE', 'GSM', + 'SM', 'HGC', 'HGS', 'HEEQ', 'HRTN', 'HPC', 'HPR', 'HCC', 'HGI', + 'MERCURY_C', 'VENUS_C', 'LUNA_C', 'MARS_C', 'JUPITER_C_III', + 'SATURN_C_III', 'URANUS_C_III', 'NEPTUNE_C_III', 'PLUTO_C', 'MERCURY_G', + 'VENUS_G', 'LUNA_G', 'MARS_G', 'JUPITER_G_III', 'SATURN_G_III', + 'URANUS_G_III', 'NEPTUNE_G_III', 'PLUTO_G', 'UNKNOWNFrame']) + + +
    [docs]def coerce_range_list_param(p, frames=None, numeric=True): + """ + Coerces and/or verifies the object *p* into a valid + range-list-format parameter as defined in `Section 8.7.2 of Simple + Spectral Access Protocol + <http://www.ivoa.net/Documents/REC/DAL/SSA-20080201.html>`_. + + Parameters + ---------- + p : str or sequence + May be a string as passed verbatim to the service expecting a + range-list, or a sequence. If a sequence, each item must be + either: + + - a numeric value + + - a named value, such as, for example, 'J' for named + spectrum (if the *numeric* kwarg is False) + + - a 2-tuple indicating a range + + - the last item my be a string indicating the frame of + reference + + frames : sequence of str, optional + A sequence of acceptable frame of reference keywords. If not + provided, the default set in `set_reference_frames` will be + used. + + numeric : bool, optional + TODO + + Returns + ------- + parts : tuple + The result is a tuple: + - a string suitable for passing to a service as a range-list + argument + + - an integer counting the number of elements + """ + def str_or_none(x): + if x is None: + return '' + if numeric: + x = float(x) + return str(x) + + def numeric_or_range(x): + if isinstance(x, tuple) and len(x) == 2: + return '%s/%s' % (str_or_none(x[0]), str_or_none(x[1])) + else: + return str_or_none(x) + + def is_frame_of_reference(x): + return isinstance(x, basestring) + + if p is None: + return None, 0 + + elif isinstance(p, (tuple, list)): + has_frame_of_reference = len(p) > 1 and is_frame_of_reference(p[-1]) + if has_frame_of_reference: + points = p[:-1] + else: + points = p[:] + + out = ','.join([numeric_or_range(x) for x in points]) + length = len(points) + if has_frame_of_reference: + if frames is not None and p[-1] not in frames: + raise ValueError( + "'%s' is not a valid frame of reference" % p[-1]) + out += ';' + p[-1] + length += 1 + + return out, length + + elif isinstance(p, basestring): + number = r'([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)?' + if not numeric: + number = r'(' + number + ')|([A-Z_]+)' + match = re.match( + '^' + number + r'([,/]' + number + + r')+(;(?P<frame>[<A-Za-z_0-9]+))?$', + p) + + if match is None: + raise ValueError("'%s' is not a valid range list" % p) + + frame = match.groupdict()['frame'] + if frames is not None and frame is not None and frame not in frames: + raise ValueError( + "'%s' is not a valid frame of reference" % frame) + return p, p.count(',') + p.count(';') + 1 + + try: + float(p) + return str(p), 1 + except TypeError: + raise ValueError("'%s' is not a valid range list" % p) + +
    +def version_compare(a, b): + """ + Compare two VOTable version identifiers. + """ + def version_to_tuple(v): + if v[0].lower() == 'v': + v = v[1:] + return version.StrictVersion(v) + av = version_to_tuple(a) + bv = version_to_tuple(b) + # Can't use cmp because it was removed from Python 3.x + return (av > bv) - (av < bv) + + +if IS_PY3K: + def is_callable(o): + """ + Abstracts away the different ways to test for a callable object in + Python 2.x and 3.x. + """ + return isinstance(o, collections.Callable) +else: +
    [docs] def is_callable(o): + """ + Abstracts away the different ways to test for a callable object in + Python 2.x and 3.x. + """ + return callable(o) +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/validator/main.html b/_modules/astropy/io/vo/validator/main.html new file mode 100644 index 00000000..d128f4d5 --- /dev/null +++ b/_modules/astropy/io/vo/validator/main.html @@ -0,0 +1,267 @@ + + + + + + + + + + astropy.io.vo.validator.main — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.validator.main

    +"""
    +Validates a large collection of web-accessible VOTable files,
    +and generates a report as a directory tree of HTML files.
    +"""
    +from __future__ import print_function
    +
    +# STDLIB
    +import os
    +import sys
    +
    +# LOCAL
    +from ....config import get_data_filename
    +from . import html
    +from . import result
    +
    +
    +__all__ = ['make_validation_report']
    +
    +
    +
    +def get_srcdir():
    +    return os.path.dirname(__file__)
    +
    +
    +def get_urls(destdir, s):
    +    import gzip
    +
    +    types = ['good', 'broken', 'incorrect']
    +
    +    seen = set()
    +    urls = []
    +    for type in types:
    +        filename = get_data_filename(
    +            'astropy/io/vo/validator/urls/cone.{0}.dat.gz'.format(type))
    +        with gzip.open(filename, 'rb') as fd:
    +            for url in fd.readlines():
    +                s.next()
    +                url = url.strip()
    +                if url not in seen:
    +                    with result.Result(url, root=destdir) as r:
    +                        r['expected'] = type
    +                    urls.append(url)
    +                seen.add(url)
    +
    +    return urls
    +
    +
    +def download(args):
    +    url, destdir = args
    +    with result.Result(url, root=destdir) as r:
    +        r.download_xml_content()
    +
    +
    +def validate_vo(args):
    +    url, destdir = args
    +    with result.Result(url, root=destdir) as r:
    +        r.validate_vo()
    +
    +
    +def votlint_validate(args):
    +    path_to_stilts_jar, url, destdir = args
    +    with result.Result(url, root=destdir) as r:
    +        if r['network_error'] is None:
    +            r.validate_with_votlint(path_to_stilts_jar)
    +
    +
    +def write_html_result(args):
    +    url, destdir = args
    +    with result.Result(url, root=destdir) as r:
    +        html.write_result(r)
    +
    +
    +def write_subindex(args):
    +    subset, destdir, total = args
    +    html.write_index_table(destdir, *subset, total=total)
    +
    +
    +
    [docs]def make_validation_report( + urls=None, destdir='astropy.io.vo.validator.results', multiprocess=True, + stilts=None): + """ + Validates a large collection of web-accessible VOTable files, + and generates a report as a directory tree of HTML files. + + Parameters + ---------- + urls : list of strings, optional + If provided, is a list of HTTP urls to download VOTable files + from. If not provided, a built-in set of ~22,000 urls + compiled by HEASARC will be used. + + destdir : path, optional + The directory to write the report to. By default, this is a + directory called `astropy.io.vo.validator.results` in the + current directory. If the directory does not exist, it will + be created. + + multiprocess : bool, optional + If `True` (default), perform validations in parallel using all + of the cores on this machine. + + stilts : path, optional + To perform validation with `votlint` from the the Java-based + `STILTS <http://www.star.bris.ac.uk/~mbt/stilts/>`_ VOTable + parser, in addition to `astropy.io.vo`, set this to the path + of the `stilts.jar` file. `java` on the system shell path + will be used to run it. + + Notes + ----- + Downloads of each given URL will be performed only once and cached + locally in *destdir*. To refresh the cache, remove *destdir* + first. + """ + from ....utils.console import (color_print, ProgressBar, Spinner) + + if stilts is not None: + if not os.path.exists(stilts): + raise ValueError( + '{0} does not exist.'.format(stilts)) + + destdir = os.path.abspath(destdir) + + if urls is None: + with Spinner('Loading URLs', 'green') as s: + urls = get_urls(destdir, s) + else: + color_print('Marking URLs', 'green') + for url in ProgressBar.iterate(urls): + with result.Result(url, root=destdir) as r: + r['expected'] = type + + args = [(url, destdir) for url in urls] + + color_print('Downloading VO files', 'green') + ProgressBar.map( + download, args, multiprocess=multiprocess) + + color_print('Validating VO files', 'green') + ProgressBar.map( + validate_vo, args, multiprocess=multiprocess) + + if stilts is not None: + color_print('Validating with votlint', 'green') + votlint_args = [(stilts, x, destdir) for x in urls] + ProgressBar.map( + votlint_validate, votlint_args, multiprocess=multiprocess) + + + color_print('Generating HTML files', 'green') + ProgressBar.map( + write_html_result, args, multiprocess=multiprocess) + + with Spinner('Grouping results', 'green') as s: + subsets = result.get_result_subsets(urls, destdir, s) + + color_print('Generating index', 'green') + html.write_index(subsets, urls, destdir) + + color_print('Generating subindices', 'green') + subindex_args = [(subset, destdir, len(urls)) for subset in subsets] + ProgressBar.map( + write_subindex, subindex_args, multiprocess=multiprocess)
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/io/vo/xmlutil.html b/_modules/astropy/io/vo/xmlutil.html new file mode 100644 index 00000000..f6f4aed8 --- /dev/null +++ b/_modules/astropy/io/vo/xmlutil.html @@ -0,0 +1,229 @@ + + + + + + + + + + astropy.io.vo.xmlutil — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.io.vo.xmlutil

    +"""
    +Various XML-related utilities
    +"""
    +
    +from __future__ import division, absolute_import
    +
    +# STDLIB
    +import io
    +import os
    +
    +# ASTROPY
    +from ...utils.xml import check as xml_check
    +from ...utils.xml import validate
    +
    +# LOCAL
    +from . import util
    +from .util import IS_PY3K
    +from .exceptions import (warn_or_raise, vo_warn, vo_raise,
    +     VOTableChangeWarning, W02, W03, W04, W05, W34)
    +from ... import config
    +
    +
    +__all__ = [
    +    'check_id', 'fix_id', 'check_token', 'check_mime_content_type',
    +    'check_anyuri', 'validate_schema'
    +    ]
    +
    +
    +
    [docs]def check_id(ID, name='ID', config={}, pos=None): + """ + Raises a `astropy.io.vo.exceptions.VOTableSpecError` if *ID* is not a + valid XML ID_. *name* is the name of the attribute being checked + (used only for error messages). + """ + if (ID is not None and not xml_check.check_id(ID)): + warn_or_raise(W02, W02, (name, ID), config, pos) + return False + return True + +
    +
    [docs]def fix_id(ID, config={}, pos=None): + """ + Given an arbitrary string, create one that can be used as an xml + id. This is rather simplistic at the moment, since it just + replaces non-valid characters with underscores. + """ + if ID is None: + return None + corrected = xml_check.fix_id(ID) + if corrected != ID: + vo_warn(W03, (ID, corrected), config, pos) + return corrected + +
    +_token_regex = r"(?![\r\l\t ])[^\r\l\t]*(?![\r\l\t ])" + + +
    [docs]def check_token(token, attr_name, config={}, pos=None): + """ + Raises a `ValueError` if *token* is not a valid XML token, as + defined by XML Schema Part 2. + """ + if (token is not None and not xml_check.check_token(token)): + return False + return True + +
    +
    [docs]def check_mime_content_type(content_type, config={}, pos=None): + """ + Raises a `astropy.io.vo.exceptions.VOTableSpecError` if + *content_type* is not a valid MIME content type (syntactically at + least), as defined by RFC 2045. + """ + if (content_type is not None and + not xml_check.check_mime_content_type(content_type)): + warn_or_raise(W04, W04, content_type, config, pos) + return False + return True + +
    +
    [docs]def check_anyuri(uri, config={}, pos=None): + """ + Raises a `astropy.io.vo.exceptions.VOTableSpecError` if *uri* is + not a valid URI as defined in RFC 2396. + """ + if (uri is not None and not xml_check.check_anyuri(uri)): + warn_or_raise(W05, W05, uri, config, pos) + return False + return True + +
    +
    [docs]def validate_schema(filename, version='1.2'): + """ + Validates the given file against the appropriate VOTable schema. + + Parameters + ---------- + filename : str + The path to the XML file to validate + + version : str + The VOTABLE version to check, which must be a string \"1.0\", + \"1.1\", or \"1.2\". + + For version \"1.0\", it is checked against a DTD, since that + version did not have an XML Schema. + + Returns + ------- + returncode, stdout, stderr : int, str, str + Returns the returncode from xmllint and the stdout and stderr + as strings + """ + import subprocess + + assert version in ('1.0', '1.1', '1.2') + + if version in ('1.1', '1.2'): + schema_path = config.get_data_filename( + 'data/VOTable.v{0}.xsd'.format(version)) + else: + schema_path = config.get_data_filename( + 'data/VOTable.dtd') + + return validate.validate_schema(filename, schema_path)
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/tools/misc.html b/_modules/astropy/tools/misc.html new file mode 100644 index 00000000..eaf2e21d --- /dev/null +++ b/_modules/astropy/tools/misc.html @@ -0,0 +1,211 @@ + + + + + + + + + + astropy.tools.misc — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.tools.misc

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""
    +This module contains simple algorithmic functionality common in astronomy or
    +used in multiple places throughout Astropy, but are not complex enough to
    +necessarily warrant their own module.
    +
    +This package should generally not be used directly.  Everything in `__all__` is
    +imported into `astropy.tools`, and hence that package should be used for
    +access.
    +"""
    +
    +import numpy as np  # needed for some defaults
    +
    +__all__ = ['sigma_clip']
    +
    +
    +
    [docs]def sigma_clip(data, sig=3, iters=1, cenfunc=np.median, varfunc=np.var, + maout=False): + """ Perform sigma-clipping on the provided data. + + This performs the sigma clipping algorithm - i.e. the data will be iterated + over, each time rejecting points that are more than a specified number of + standard deviations discrepant. + + Parameters + ---------- + data : array-like + The data to be sigma-clipped (any shape). + sig : float + The number of standard deviations (*not* variances) to use as the + clipping limit. + iters : int or None + The number of iterations to perform clipping for, or None to clip until + convergence is achieved (i.e. continue until the last iteration clips + nothing). + cenfunc : callable + The technique to compute the center for the clipping. Must be a + callable that takes in a 1D data array and outputs the central value. + Defaults to the median. + varfunc : callable + The technique to compute the variance about the center. Must be a + callable that takes in a 1D data array and outputs the width estimator + that will be interpreted as a variance. Defaults to the variance. + maout : bool or 'copy' + If True, a masked array will be returned. If the special string + 'inplace', the masked array will contain the same array as `data`, + otherwise the array data will be copied. + + Returns + ------- + filtereddata : `numpy.ndarray` or `numpy.masked.MaskedArray` + If `maout` is True, this is a masked array with a shape matching the + input that is masked where the algorithm has rejected those values. + Otherwise, a 1D array of values including only those that are not + clipped. + mask : boolean array + Only present if `maout` is False. A boolean array with a shape matching + the input `data` that is False for rejected values and True for all + others. + + Examples + -------- + + This will generate random variates from a Gaussian distribution and return + only the points that are within 2 *sample* standard deviation from the + median:: + + >>> from astropy.tools.alg import sigma_clip + >>> from numpy.random import randn + >>> randvar = randn(10000) + >>> data,mask = sigma_clip(randvar,2,1) + + This will clipping on a similar distribution, but for 3 sigma relative to + the sample *mean*, will clip until converged, and produces a + `numpy.masked.MaskedArray`:: + + >>> from astropy.tools.alg import sigma_clip + >>> from numpy.random import randn + >>> from numpy import mean + >>> randvar = randn(10000) + >>> maskedarr = sigma_clip(randvar,3,None,mean,maout=True) + + """ + data = np.array(data, copy=False) + oldshape = data.shape + data = data.ravel() + + mask = np.ones(data.size, bool) + if iters is None: + i = -1 + lastrej = sum(mask) + 1 + while(sum(mask) != lastrej): + i += 1 + lastrej = sum(mask) + do = data - cenfunc(data[mask]) + mask = do * do <= varfunc(data[mask]) * sig ** 2 + iters = i + 1 + #TODO: ?print iters to the log if iters was None? + else: + for i in range(iters): + do = data - cenfunc(data[mask]) + mask = do * do <= varfunc(data[mask]) * sig ** 2 + + if maout: + return np.ma.MaskedArray(data, ~mask, copy=maout != 'inplace') + else: + return data[mask], mask.reshape(oldshape)
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/utils/collections.html b/_modules/astropy/utils/collections.html new file mode 100644 index 00000000..05c27d81 --- /dev/null +++ b/_modules/astropy/utils/collections.html @@ -0,0 +1,156 @@ + + + + + + + + + + astropy.utils.collections — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.utils.collections

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""
    +A number of specialized collection classes.
    +"""
    +
    +
    +
    [docs]class HomogeneousList(list): + """ + A subclass of list that contains only elements of a given type or + types. If an item that is not of the specified type is added to + the list, a `TypeError` is raised. + """ +
    [docs] def __init__(self, types, values=[]): + """ + Parameters + ---------- + types : sequence of types + The types to accept. + + values : sequence, optional + An initial set of values. + """ + self._types = types + list.__init__(self, values) +
    + def _assert(self, x): + if not isinstance(x, self._types): + raise TypeError( + "homogeneous list must contain only objects of type '%s'" % + (self._types)) + +
    [docs] def __iadd__(self, other): + for x in other: + self._assert(x) + return list.__iadd__(self, other) +
    +
    [docs] def __setitem__(self, x): + self._assert(x) + return list.__setitem__(self, x) +
    +
    [docs] def append(self, x): + self._assert(x) + return list.append(self, x) +
    +
    [docs] def insert(self, i, x): + self._assert(x) + return list.insert(self, i, x) +
    +
    [docs] def extend(self, x): + for item in x: + self._assert(item) + return list.extend(self, x)
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/utils/console.html b/_modules/astropy/utils/console.html new file mode 100644 index 00000000..99012bf3 --- /dev/null +++ b/_modules/astropy/utils/console.html @@ -0,0 +1,706 @@ + + + + + + + + + + astropy.utils.console — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.utils.console

    +# -*- coding: utf-8 -*-
    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""
    +Utilities for prettifying output to the console.
    +"""
    +from __future__ import division, print_function
    +
    +import io
    +import re
    +import math
    +import sys
    +import time
    +
    +
    +from ..config.configs import ConfigurationItem
    +
    +
    +__all__ = [
    +    'isatty', 'color_print', 'human_time', 'ProgressBar', 'Spinner',
    +    'print_code_line', 'ProgressBarOrSpinner']
    +
    +
    +USE_COLOR = ConfigurationItem(
    +    'use_color', True,
    +    'When True, use ANSI color escape sequences when writing to the console.')
    +USE_UNICODE = ConfigurationItem(
    +    'use_unicode', True,
    +    'Use Unicode characters when drawing progress bars etc. at the console.')
    +
    +
    +
    [docs]def isatty(file): + """ + Returns `True` if `file` is a tty. + + Most built-in Python file-like objects have an `isatty` member, + but some user-defined types may not, so this assumes those are not + ttys. + """ + if hasattr(file, 'isatty'): + return file.isatty() + return False + +
    +
    [docs]def color_print(*args, **kwargs): + """ + Prints colors and styles to the terminal uses ANSI escape + sequences:: + + color_print('This is the color ', 'default', 'GREEN', 'green') + + Parameters + ---------- + positional args : strings + The positional arguments come in pairs (*msg*, *color*), where + *msg* is the string to display and *color* is the color to + display it in. + + *color* is an ANSI terminal color name. Must be one of: + black, red, green, brown, blue, magenta, cyan, lightgrey, + default, darkgrey, lightred, lightgreen, yellow, lightblue, + lightmagenta, lightcyan, white, or '' (the empty string). + + file : writeable file-like object, optional + Where to write to. Defaults to `sys.stdout`. If file is not + a tty (as determined by calling its `isatty` member, if one + exists), no coloring will be included. + + end : str, optional + The ending of the message. Defaults to ``\\n``. The end will + be printed after resetting any color or font state. + """ + color_mapping = { + 'black': '0;30', + 'red': '0;31', + 'green': '0;32', + 'brown': '0;33', + 'blue': '0;34', + 'magenta': '0;35', + 'cyan': '0;36', + 'lightgrey': '0;37', + 'default': '0;39', + 'darkgrey': '1;30', + 'lightred': '1;31', + 'lightgreen': '1;32', + 'yellow': '1;33', + 'lightblue': '1;34', + 'lightmagenta': '1;35', + 'lightcyan': '1;36', + 'white': '1;37'} + + file = kwargs.get('file', sys.stdout) + end = kwargs.get('end', u'\n') + + write = file.write + if isatty(file) and USE_COLOR(): + for i in xrange(0, len(args), 2): + msg = args[i] + if i + 1 == len(args): + color = '' + else: + color = args[i + 1] + + if isinstance(msg, bytes): + msg = msg.decode('ascii') + + if color == u'' or color is None: + write(msg) + else: + color_code = color_mapping.get(color, '0;39') + write(u'\033[{0}m{1}\033[0m'.format( + color_code, msg)) + + write(end) + else: + for i in xrange(0, len(args), 2): + msg = args[i] + if isinstance(msg, bytes): + msg = msg.decode('ascii') + write(msg) + write(end) + +
    +def strip_ansi_codes(s): + """ + Remove ANSI color codes from the string. + """ + return re.sub('\033\[([0-9]+)(;[0-9]+)*m', '', s) + + +
    [docs]def human_time(seconds): + """ + Returns a human-friendly time string that is always exactly 6 + characters long. + + Depending on the number of seconds given, can be one of:: + + 1w 3d + 2d 4h + 1h 5m + 1m 4s + 15s + + Will be in color if console coloring is turned on. + + Parameters + ---------- + seconds : int + The number of seconds to represent + + Returns + ------- + time : str + A human-friendly representation of the given number of seconds + that is always exactly 6 characters. + """ + units = [ + (u'y', 60 * 60 * 24 * 7 * 52), + (u'w', 60 * 60 * 24 * 7), + (u'd', 60 * 60 * 24), + (u'h', 60 * 60), + (u'm', 60), + (u's', 1), + ] + + seconds = int(seconds) + + if seconds < 60: + return u' {0:02d}s'.format(seconds) + for i in xrange(len(units) - 1): + unit1, limit1 = units[i] + unit2, limit2 = units[i + 1] + if seconds >= limit1: + return u'{0:02d}{1}{2:02d}{3}'.format( + seconds // limit1, unit1, + (seconds % limit1) // limit2, unit2) + return u' ~inf' + +
    +
    [docs]class ProgressBar: + """ + A class to display a progress bar in the terminal. + + It is designed to be used with the `with` statement:: + + with ProgressBar(len(items)) as bar: + for item in enumerate(items): + bar.update() + """ +
    [docs] def __init__(self, total, file=sys.stdout): + """ + Parameters + ---------- + total : int + The number of increments in the process being tracked. + + file : writable file-like object, optional + The file to write the progress bar to. Defaults to + `sys.stdout`. If `file` is not a tty (as determined by + calling its `isatty` member, if any), the scrollbar will + be completely silent. + """ + if not isatty(file): + self.update = self._silent_update + self._silent = True + else: + self._silent = False + + self._total = total + self._file = file + self._start_time = time.time() + terminal_width = 78 + if sys.platform.startswith('linux'): + import subprocess + p = subprocess.Popen( + 'stty size', + shell=True, + stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + parts = stdout.split() + if len(parts) == 2: + rows, cols = parts + terminal_width = int(cols) + self._bar_length = terminal_width - 36 + num_scale = int(math.floor(math.log(self._total) / math.log(1000))) + if num_scale > 7: + self._suffix = '?' + else: + suffixes = u' kMGTPEH' + self._suffix = suffixes[num_scale] + self._num_scale = int(math.pow(1000, num_scale)) + self.update(0) +
    +
    [docs] def __enter__(self): + return self +
    +
    [docs] def __exit__(self, exc_type, exc_value, traceback): + if not self._silent: + if exc_type is None: + self.update(self._total) + self._file.write('\n') + self._file.flush() +
    +
    [docs] def update(self, value=None): + """ + Update the progress bar to the given value (out of the total + given to the constructor. + """ + if value is None: + value = self._current_value = self._current_value + 1 + else: + self._current_value = value + if self._total == 0: + frac = 1.0 + else: + frac = float(value) / float(self._total) + + file = self._file + write = file.write + + bar_fill = int(float(self._bar_length) * frac) + write(u'\r|') + color_print(u'=' * bar_fill, 'blue', file=file, end=u'') + if bar_fill < self._bar_length: + color_print(u'>', 'green', file=file, end=u'') + write(u'-' * (self._bar_length - bar_fill - 1)) + write(u'|') + + if value >= self._total: + t = time.time() - self._start_time + prefix = u' ' + elif value <= 0: + t = None + prefix = u'' + else: + t = ((time.time() - self._start_time) * (1.0 - frac)) / frac + prefix = u' ETA ' + write(u' {0:>3d}/{1:>3d}{2}'.format( + value // self._num_scale, + self._total // self._num_scale, + self._suffix)) + write(u' ({0:>6s}%)'.format(u'{0:.2f}'.format(frac * 100.0))) + write(prefix) + if t is not None: + write(human_time(t)) + self._file.flush() +
    + def _silent_update(self, value=None): + pass + + @classmethod +
    [docs] def map(cls, function, items, multiprocess=False, file=sys.stdout): + """ + Does a `map` operation while displaying a progress bar with + percentage complete:: + + def work(i): + print(i) + + ProgressBar.map(work, range(50)) + + Parameters + ---------- + function : function + Function to call for each step + + items : sequence + Sequence where each element is a tuple of arguments to pass to + *function*. + + multiprocess : bool, optional + If `True`, use the `multiprocessing` module to distribute each + task to a different processor core. + + file : writeable file-like object, optional + The file to write the progress bar to. Defaults to + `sys.stdout`. If `file` is not a tty (as determined by + calling its `isatty` member, if any), the scrollbar will + be completely silent. + """ + with cls(len(items), file=file) as bar: + step_size = max(200, bar._bar_length) + steps = max(int(float(len(items)) / step_size), 1) + if not multiprocess: + for i, item in enumerate(items): + function(item) + if (i % steps) == 0: + bar.update(i) + else: + import multiprocessing + p = multiprocessing.Pool() + for i, _ in enumerate( + p.imap_unordered(function, items, steps)): + bar.update(i) +
    + @classmethod +
    [docs] def iterate(cls, items, file=sys.stdout): + """ + Iterate over a sequence while indicating progress with a progress + bar in the terminal:: + + for item in ProgressBar.iterate(items): + pass + + Parameters + ---------- + items : sequence + A sequence of items to iterate over + + file : writeable file-like object, optional + The file to write the progress bar to. Defaults to + `sys.stdout`. If `file` is not a tty (as determined by + calling its `isatty` member, if any), the scrollbar will + be completely silent. + + Returns + ------- + generator : + A generator over `items` + """ + with cls(len(items), file=file) as bar: + for item in items: + yield item + bar.update() + +
    +
    [docs]class Spinner(): + """ + A class to display a spinner in the terminal. + + It is designed to be used with the `with` statement:: + + with Spinner("Reticulating splines", "green") as s: + for item in enumerate(items): + s.next() + """ + _default_unicode_chars = u"◓◑◒◐" + _default_ascii_chars = u"-/|\\" + +
    [docs] def __init__(self, msg, color='default', file=sys.stdout, step=1, chars=None): + """ + Parameters + ---------- + msg : str + The message to print + + color : str, optional + An ANSI terminal color name. Must be one of: black, red, + green, brown, blue, magenta, cyan, lightgrey, default, + darkgrey, lightred, lightgreen, yellow, lightblue, + lightmagenta, lightcyan, white. + + file : writeable file-like object, optional + The file to write the spinner to. Defaults to + `sys.stdout`. If `file` is not a tty (as determined by + calling its `isatty` member, if any), the scrollbar will + be completely silent. + + step : int, optional + Only update the spinner every *step* steps + + chars : str, optional + The character sequence to use for the spinner + """ + self._msg = msg + self._color = color + self._file = file + self._step = step + if chars is None: + if USE_UNICODE: + chars = self._default_unicode_chars + else: + chars = self._default_ascii_chars + self._chars = chars + + self._silent = not isatty(file) +
    + def _iterator(self): + chars = self._chars + index = 0 + file = self._file + write = file.write + flush = file.flush + + while True: + write(u'\r') + color_print(self._msg, self._color, file=file, end=u'') + write(u' ') + write(chars[index]) + flush() + yield + + for i in xrange(self._step): + yield + + index += 1 + if index == len(chars): + index = 0 + +
    [docs] def __enter__(self): + if self._silent: + return self._silent_iterator() + else: + return self._iterator() +
    +
    [docs] def __exit__(self, exc_type, exc_value, traceback): + file = self._file + write = file.write + flush = file.flush + + if not self._silent: + write(u'\r') + color_print(self._msg, self._color, file=file, end=u'') + if exc_type is None: + color_print(u' [Done]', 'green', file=file) + else: + color_print(u' [Failed]', 'red', file=file) + flush() +
    + def _silent_iterator(self): + color_print(self._msg, self._color, file=self._file, end=u'') + self._file.flush() + + while True: + yield + +
    +
    [docs]class ProgressBarOrSpinner: + """ + A class that displays either a `ProgressBar` or `Spinner` + depending on whether the total size of the operation is + known or not. + + It is designed to be used with the `with` statement:: + + if file.has_length(): + length = file.get_length() + else: + length = None + bytes_read = 0 + with ProgressBarOrSpinner(length) as bar: + while file.read(blocksize): + bytes_read += blocksize + bar.update(bytes_read) + """ + +
    [docs] def __init__(self, total, msg, color='default', file=sys.stdout): + """ + Parameters + ---------- + total : int or None + If an int, the number of increments in the process being + tracked and a `ProgressBar` is displayed. If `None`, a + `Spinner` is displayed. + + msg : str + The message to display above the `ProgressBar` or + alongside the `Spinner`. + + color : str, optional + The color of `msg`, if any. Must be an ANSI terminal + color name. Must be one of: black, red, green, brown, + blue, magenta, cyan, lightgrey, default, darkgrey, + lightred, lightgreen, yellow, lightblue, lightmagenta, + lightcyan, white. + + file : writable file-like object, optional + The file to write the to. Defaults to `sys.stdout`. If + `file` is not a tty (as determined by calling its `isatty` + member, if any), only `msg` will be displayed: the + `ProgressBar` or `Spinner` will be silent. + """ + if total is None or not isatty(file): + self._is_spinner = True + self._obj = Spinner(msg, color=color, file=file) + else: + self._is_spinner = False + color_print(msg, color, file=file) + self._obj = ProgressBar(total, file=file) +
    +
    [docs] def __enter__(self): + self._iter = self._obj.__enter__() + return self +
    +
    [docs] def __exit__(self, exc_type, exc_value, traceback): + return self._obj.__exit__(exc_type, exc_value, traceback) +
    +
    [docs] def update(self, value): + """ + Update the progress bar to the given value (out of the total + given to the constructor. + """ + if self._is_spinner: + self._iter.next() + else: + self._obj.update(value) + +
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/_modules/astropy/utils/misc.html b/_modules/astropy/utils/misc.html new file mode 100644 index 00000000..2c24a4c9 --- /dev/null +++ b/_modules/astropy/utils/misc.html @@ -0,0 +1,313 @@ + + + + + + + + + + astropy.utils.misc — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.utils.misc

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""
    +This package contains smallish general-purpose utilities that don't have a
    +clear other module to live in.
    +
    +This module should not be used directly, as everything in `__all__`` is
    +imported into `astropy.utils`
    +"""
    +from __future__ import absolute_import
    +
    +__all__ = ['find_current_module', 'fnpickle', 'fnunpickle']
    +
    +
    +
    [docs]def find_current_module(depth=1, finddiff=False): + """ Determines the module/package this function is called from. + + Parameters + ---------- + depth : int + Specifies how far back to go in the call stack (0-indexed, so that + passing in 0 gives back `astropy.utils.misc`). + finddiff : bool + If True, once the module at `depth` is determined, a search will be + performed up the call stack until a *different* module is found + from the one at `depth`. + + Returns + ------- + mod : module or None + The module object or None if the package cannot be found. The name of + the module is available as the ``__name__`` attribute of the returned + object (if it isn't None). + + Examples + -------- + The examples below assume that there are two modules in a package named + `pkg`. ``mod1.py``:: + + def find1(): + from astropy.utils import find_current_module + print find_current_module(1).__name__ + def find2(): + from astropy.utils import find_current_module + cmod = find_current_module(2) + if cmod is None: + print 'None' + else: + print cmod.__name__ + def find_diff(): + from astropy.utils import find_current_module + print find_current_module(0,True).__name__ + + ``mod2.py``:: + + def find(): + from .mod1 import find2 + find2() + + With these modules in place, the following occurs:: + + >>> from pkg import mod1, mod2 + >>> from astropy.utils import find_current_module + >>> mod1.find1() + pkg.mod1 + >>> mod1.find2() + None + >>> mod2.find() + pkg.mod2 + >>> find_current_module(0) + <module 'astropy.utils.misc' from 'astropy/utils/misc.py'> + >>> mod1.find_diff() + pkg.mod1 + + """ + from inspect import currentframe + + # using a patched version of getmodule because the py 3.1 and 3.2 stdlib + # is broken if the list of modules changes during import + from .compat import inspect_getmodule + + frm = currentframe() + for i in range(depth): + frm = frm.f_back + if frm is None: + return None + + if finddiff: + currmod = inspect_getmodule(frm) + while frm: + frmb = frm.f_back + modb = inspect_getmodule(frmb) + if modb is not currmod: + return modb + frm = frmb + else: + return inspect_getmodule(frm) + +
    +
    [docs]def fnunpickle(fileorname, number=0, usecPickle=True): + """ Unpickle pickled objects from a specified file and return the contents. + + Parameters + ---------- + fileorname : str or `file`-like + The file name or file from which to unpickle objects. If a file object, + it should have been opened in binary mode. + number : int + If 0, a single object will be returned (the first in the file). If >0, + this specifies the number of objects to be unpickled, and a list will be + returned with exactly that many objects. If <0, all objects in the file + will be unpickled and returned as a list. + usecPickle : bool + If True, the :mod:`cPickle` module is to be used in place of + :mod:`pickle` (cPickle is faster). This only applies for python 2.x. + + Raises + ------ + EOFError + If `number` is >0 and there are fewer than `number` objects in the + pickled file. + + Returns + ------- + contents : obj or list + If `number` is 0, this is a individual object - the first one unpickled + from the file. Otherwise, it is a list of objects unpickled from the + file. + + """ + import sys + + if usecPickle and sys.version_info[0] < 3: + import cPickle as pickle + else: + import pickle + + if isinstance(fileorname, basestring): + f = open(fileorname, 'rb') + close = True + else: + f = fileorname + close = False + + try: + if number > 0: # get that number + res = [] + for i in range(number): + res.append(pickle.load(f)) + elif number < 0: # get all objects + res = [] + eof = False + while not eof: + try: + res.append(pickle.load(f)) + except EOFError: + eof = True + else: # number==0 + res = pickle.load(f) + finally: + if close: + f.close() + + return res + +
    +
    [docs]def fnpickle(object, fileorname, usecPickle=True, protocol=None, append=False): + """Pickle an object to a specified file. + + Parameters + ---------- + object + The python object to pickle. + fileorname : str or `file`-like + The filename or file into which the `object` should be pickled. If a + file object, it should have been opened in binary mode. + usecPickle : bool + If True (default), the :mod:`cPickle` module is to be used in place of + :mod:`pickle` (cPickle is faster). This only applies for python 2.x. + protocol : int or None + Pickle protocol to use - see the :mod:`pickle` module for details on + these options. If None, the most recent protocol will be used. + append : bool + If True, the object is appended to the end of the file, otherwise the + file will be overwritten (if a file object is given instead of a + file name, this has no effect). + + """ + import sys + + if usecPickle and sys.version_info[0] < 3: + import cPickle as pickle + else: + import pickle + + if protocol is None: + protocol = pickle.HIGHEST_PROTOCOL + + if isinstance(fileorname, basestring): + f = open(fileorname, 'ab' if append else 'wb') + close = True + else: + f = fileorname + close = False + + try: + pickle.dump(object, f, protocol=protocol) + finally: + if close: + f.close()
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/utils/xml/check.html b/_modules/astropy/utils/xml/check.html new file mode 100644 index 00000000..e0cefee4 --- /dev/null +++ b/_modules/astropy/utils/xml/check.html @@ -0,0 +1,178 @@ + + + + + + + + + + astropy.utils.xml.check — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.utils.xml.check

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""
    +A collection of functions for checking various XML-related strings for
    +standards compliance.
    +"""
    +
    +import re
    +import urlparse
    +
    +
    +
    [docs]def check_id(ID): + """ + Returns `True` if *ID* is a valid XML ID. + """ + return re.match(r"^[A-Za-z_][A-Za-z0-9_\.\-]*$", ID) is not None + +
    +
    [docs]def fix_id(ID): + """ + Given an arbitrary string, create one that can be used as an xml + id. This is rather simplistic at the moment, since it just + replaces non-valid characters with underscores. + """ + if re.match(r"^[A-Za-z_][A-Za-z0-9_\.\-]*$", ID): + return ID + if len(ID): + corrected = ID + if not len(corrected) or re.match('^[^A-Za-z_]$', corrected[0]): + corrected = '_' + corrected + corrected = (re.sub(r"[^A-Za-z_]", '_', corrected[0]) + + re.sub(r"[^A-Za-z0-9_\.\-]", "_", corrected[1:])) + return corrected + return '' +
    +_token_regex = r"(?![\r\l\t ])[^\r\l\t]*(?![\r\l\t ])" + + +
    [docs]def check_token(token): + """ + Returns `True` if *token* is a valid XML token, as defined by XML + Schema Part 2. + """ + return (token == '' or + re.match( + "[^\r\n\t ]?([^\r\n\t ]| [^\r\n\t ])*[^\r\n\t ]?$", token) + is not None) + +
    +
    [docs]def check_mime_content_type(content_type): + """ + Returns `True` if *content_type* is a valid MIME content type + (syntactically at least), as defined by RFC 2045. + """ + ctrls = ''.join(chr(x) for x in xrange(0, 0x20)) + token_regex = '[^()<>@,;:\\\"/[\]?= %s\x7f]+' % ctrls + return re.match( + r'(?P<type>%s)/(?P<subtype>%s)$' % (token_regex, token_regex), + content_type) is not None + +
    +
    [docs]def check_anyuri(uri): + """ + Returns `True` if *uri* is a valid URI as defined in RFC 2396. + """ + if (re.match( + (r"(([a-zA-Z][0-9a-zA-Z+\-\.]*:)?/{0,2}[0-9a-zA-Z;" + + r"/?:@&=+$\.\-_!~*'()%]+)?(#[0-9a-zA-Z;/?:@&=+$\.\-_!~*'()%]+)?"), + uri) is None): + return False + try: + urlparse.urlparse(uri) + except: + return False + return True
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/utils/xml/iterparser.html b/_modules/astropy/utils/xml/iterparser.html new file mode 100644 index 00000000..3c7a8d27 --- /dev/null +++ b/_modules/astropy/utils/xml/iterparser.html @@ -0,0 +1,344 @@ + + + + + + + + + + astropy.utils.xml.iterparser — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.utils.xml.iterparser

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""
    +This module includes a fast iterator-based XML parser.
    +"""
    +
    +# STDLIB
    +import collections
    +import contextlib
    +import io
    +import sys
    +
    +
    +__all__ = ['get_xml_iterator', 'get_xml_encoding', 'xml_readlines']
    +
    +
    +############################################################
    +# TODO: Refactor this into a py3k compatibility module
    +IS_PY3K = (sys.version_info[0] >= 3)
    +
    +if IS_PY3K:
    +    def is_callable(o):
    +        """
    +        Abstracts away the different ways to test for a callable object in
    +        Python 2.x and 3.x.
    +        """
    +        return isinstance(o, collections.Callable)
    +else:
    +    def is_callable(o):
    +        """
    +        Abstracts away the different ways to test for a callable object in
    +        Python 2.x and 3.x.
    +        """
    +        return callable(o)
    +############################################################
    +
    +
    +@contextlib.contextmanager
    +def _convert_to_fd_or_read_function(fd):
    +    """
    +    Returns a function suitable for streaming input, or a file object.
    +
    +    This function is only useful if passing off to C code where:
    +
    +       - If it's a real file object, we want to use it as a real
    +         C file object to avoid the Python overhead.
    +
    +       - If it's not a real file object, it's much handier to just
    +         have a Python function to call.
    +
    +    Parameters
    +    ----------
    +    fd : object
    +        May be:
    +
    +            - a file object, in which case it is returned verbatim.
    +
    +            - a function that reads from a stream, in which case it is
    +              returned verbatim.
    +
    +            - a file path, in which case it is opened.  If it ends in
    +              `.gz`, it is assumed to be a gzipped file, and the
    +              :meth:`read` method on the file object is returned.
    +              Otherwise, the raw file object is returned.
    +
    +           - an object with a :meth:`read` method, in which case that
    +             method is returned.
    +
    +    Returns
    +    -------
    +    fd : context-dependent
    +        See above.
    +    """
    +    if not sys.platform.startswith('win'):
    +        if IS_PY3K:
    +            if isinstance(fd, io.IOBase):
    +                yield fd
    +                return
    +        else:
    +            if isinstance(fd, file):
    +                yield fd
    +                return
    +    if is_callable(fd):
    +        yield fd
    +        return
    +    elif isinstance(fd, basestring):
    +        if fd.endswith('.gz'):
    +            from ...utils.compat import gzip
    +            with gzip.GzipFile(fd, 'rb') as real_fd:
    +                yield real_fd.read
    +                return
    +        else:
    +            with open(fd, 'rb') as real_fd:
    +                if sys.platform.startswith('win'):
    +                    # On Windows, we can't pass a real file descriptor
    +                    # to the C level, so we pass the read method
    +                    yield real_fd.read
    +                    return
    +                yield real_fd
    +                return
    +    elif hasattr(fd, 'read'):
    +        assert is_callable(fd.read)
    +        yield fd.read
    +        return
    +    else:
    +        raise TypeError("Can not be coerced to read function")
    +
    +
    +def _fast_iterparse(fd, buffersize=2 ** 10):
    +    from xml.parsers import expat
    +
    +    if not is_callable(fd):
    +        read = fd.read
    +    else:
    +        read = fd
    +
    +    queue = []
    +    text = []
    +
    +    def start(name, attr):
    +        queue.append((True, name, attr,
    +                      (parser.CurrentLineNumber, parser.CurrentColumnNumber)))
    +        del text[:]
    +
    +    def end(name):
    +        queue.append((False, name, ''.join(text).strip(),
    +                      (parser.CurrentLineNumber, parser.CurrentColumnNumber)))
    +
    +    parser = expat.ParserCreate()
    +    if not IS_PY3K:
    +        parser.returns_unicode = False
    +    parser.specified_attributes = True
    +    parser.StartElementHandler = start
    +    parser.EndElementHandler = end
    +    parser.CharacterDataHandler = text.append
    +    Parse = parser.Parse
    +
    +    data = read(buffersize)
    +    while data:
    +        Parse(data, False)
    +        for elem in queue:
    +            yield elem
    +        del queue[:]
    +        data = read(buffersize)
    +
    +    Parse('', True)
    +    for elem in queue:
    +        yield elem
    +
    +
    +# Try to import the C version of the iterparser, otherwise fall back
    +# to the Python implementation above.
    +_slow_iterparse = _fast_iterparse
    +try:
    +    from . import _iterparser
    +    _fast_iterparse = _iterparser.IterParser
    +except ImportError:
    +    pass
    +
    +
    +@contextlib.contextmanager
    +
    [docs]def get_xml_iterator(source, _debug_python_based_parser=False): + """ + Returns an iterator over the elements of an XML file. + + The iterator doesn't ever build a tree, so it is much more memory + and time efficient than the alternative in `cElementTree`. + + Parameters + ---------- + fd : readable file-like object or read function + + Returns + ------- + parts : iterator + + The iterator returns 4-tuples (*start*, *tag*, *data*, *pos*): + + - *start*: when `True` is a start element event, otherwise + an end element event. + + - *tag*: The name of the element + + - *data*: Depends on the value of *event*: + + - if *start* == `True`, data is a dictionary of + attributes + + - if *start* == `False`, data is a string containing + the text content of the element + + - *pos*: Tuple (*line*, *col*) indicating the source of the + event. + """ + with _convert_to_fd_or_read_function(source) as fd: + if _debug_python_based_parser: + context = _slow_iterparse(fd) + else: + context = _fast_iterparse(fd) + yield iter(context) + +
    +
    [docs]def get_xml_encoding(source): + """ + Determine the encoding of an XML file by reading its header. + + Parameters + ---------- + source : readable file-like object, read function or str path + + Returns + ------- + encoding : str + """ + with get_xml_iterator(source) as iterator: + start, tag, data, pos = iterator.next() + if not start or tag != 'xml': + raise IOError('Invalid XML file') + + return data['encoding'] + +
    +
    [docs]def xml_readlines(source): + """ + Get the lines from a given XML file. Correctly determines the + encoding and always returns unicode. + + Parameters + ---------- + source : readable file-like object, read function or str path + + Returns + ------- + lines : list of unicode + """ + encoding = get_xml_encoding(source) + + with io.open(source, 'rt', encoding=encoding) as input: + xml_lines = input.readlines() + + return xml_lines
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/utils/xml/validate.html b/_modules/astropy/utils/xml/validate.html new file mode 100644 index 00000000..03e452c9 --- /dev/null +++ b/_modules/astropy/utils/xml/validate.html @@ -0,0 +1,153 @@ + + + + + + + + + + astropy.utils.xml.validate — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.utils.xml.validate

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""
    +Functions to do XML schema and DTD validation.  At the moment, this
    +makes a subprocess call to xmllint.  This could use a Python-based
    +library at some point in the future, if something appropriate could be
    +found.
    +"""
    +
    +import os
    +
    +
    +
    [docs]def validate_schema(filename, schema_file): + """ + Validates an XML file against a schema or DTD. + + Parameters + ---------- + filename : str + The path to the XML file to validate + + schema : str + The path to the XML schema or DTD + + Returns + ------- + returncode, stdout, stderr : int, str, str + Returns the returncode from xmllint and the stdout and stderr + as strings + """ + import subprocess + + base, ext = os.path.splitext(schema_file) + if ext == '.xsd': + schema_part = '--schema ' + schema_file + elif ext == '.dtd': + schema_part = '--dtdvalid ' + schema_file + else: + raise TypeError("schema_file must be a path to an XML Schema or DTD") + + p = subprocess.Popen( + "xmllint --noout --nonet %s %s" % (schema_part, filename), + shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + + if p.returncode == 127: + raise OSError( + "xmllint not found, so can not validate schema") + + return p.returncode, stdout, stderr
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/utils/xml/writer.html b/_modules/astropy/utils/xml/writer.html new file mode 100644 index 00000000..511a3461 --- /dev/null +++ b/_modules/astropy/utils/xml/writer.html @@ -0,0 +1,383 @@ + + + + + + + + + + astropy.utils.xml.writer — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.utils.xml.writer

    +# Licensed under a 3-clause BSD style license - see LICENSE.rst
    +"""
    +Contains a class that makes it simple to stream out well-formed and
    +nicely-indented XML.
    +"""
    +
    +# STDLIB
    +import contextlib
    +import textwrap
    +
    +
    +
    [docs]def xml_escape_cdata(s): + """ + Escapes &, < and > in an XML CDATA string. + """ + s = s.replace(u"&", u"&amp;") + s = s.replace(u"<", u"&lt;") + s = s.replace(u">", u"&gt;") + return s + +
    +
    [docs]def xml_escape(s): + """ + Escapes &, ', ", < and > in an XML attribute value. + """ + s = s.replace(u"&", u"&amp;") + s = s.replace(u"'", u"&apos;") + s = s.replace(u"\"", u"&quot;") + s = s.replace(u"<", u"&lt;") + s = s.replace(u">", u"&gt;") + return s + +
    +
    [docs]class XMLWriter: + """ + A class to write well-formed and nicely indented XML. + + Use like this:: + + w = XMLWriter(fh) + with w.tag('html'): + with w.tag('body'): + w.data('This is the content') + + Which produces:: + + <html> + <body> + This is the content + </body> + </html> + """ + +
    [docs] def __init__(self, file): + """ + Parameters + ---------- + file : writable file-like object. + """ + self.write = file.write + if hasattr(file, "flush"): + self.flush = file.flush + self._open = 0 # true if start tag is open + self._tags = [] + self._data = [] + self._indentation = u" " * 64 + + try: + from astropy.io.vo import iterparser + self.xml_escape_cdata = iterparser.escape_xml_cdata + self.xml_escape = iterparser.escape_xml + except ImportError: + self.xml_escape_cdata = xml_escape_cdata + self.xml_escape = xml_escape +
    + def _flush(self, indent=True, wrap=False): + """ + Flush internal buffers. + """ + if self._open: + if indent: + self.write(u">\n") + else: + self.write(u">") + self._open = 0 + if self._data: + data = u''.join(self._data) + if wrap: + indent = self.get_indentation_spaces(1) + data = textwrap.fill( + data, + initial_indent=indent, + subsequent_indent=indent) + self.write('\n') + self.write(self.xml_escape_cdata(data)) + self.write('\n') + self.write(self.get_indentation_spaces()) + else: + self.write(self.xml_escape_cdata(data)) + self._data = [] + +
    [docs] def start(self, tag, attrib={}, **extra): + """ + Opens a new element. Attributes can be given as keyword + arguments, or as a string/string dictionary. The method + returns an opaque identifier that can be passed to the + :meth:`close` method, to close all open elements up to and + including this one. + + Parameters + ---------- + tag : str + The element name + + attrib : dict of str -> str + Attribute dictionary. Alternatively, attributes can + be given as keyword arguments. + + Returns + ------- + id : int + Returns an element identifier. + """ + self._flush() + # This is just busy work -- we know our tag names are clean + # tag = xml_escape_cdata(tag) + self._data = [] + self._tags.append(tag) + self.write(self.get_indentation_spaces(-1)) + self.write(u"<%s" % tag) + if attrib or extra: + attrib = attrib.copy() + attrib.update(extra) + attrib = attrib.items() + attrib.sort() + for k, v in attrib: + if not v == '' and v is not None: + # This is just busy work -- we know our keys are clean + # k = xml_escape_cdata(k) + v = self.xml_escape(v) + self.write(u" %s=\"%s\"" % (k, v)) + self._open = 1 + + return len(self._tags) +
    + @contextlib.contextmanager +
    [docs] def tag(self, tag, attrib={}, **extra): + """ + A convenience method for use with the `with` statement:: + + with writer.tag('foo'): + writer.element('bar') + # </foo> is implicitly closed here + + Parameters are the same as to `start`. + """ + self.start(tag, attrib, **extra) + yield + self.end(tag) +
    +
    [docs] def comment(self, comment): + """ + Adds a comment to the output stream. + + Parameters + ---------- + comment : str + Comment text, as a Unicode string. + """ + self._flush() + self.write(self.get_indentation_spaces()) + self.write(u"<!-- %s -->\n" % self.xml_escape_cdata(comment)) +
    +
    [docs] def data(self, text): + """ + Adds character data to the output stream. + + Parameters + ---------- + text : str + Character data, as a Unicode string. + """ + self._data.append(text) +
    +
    [docs] def end(self, tag=None, indent=True, wrap=False): + """ + Closes the current element (opened by the most recent call to + `start`). + + Parameters + ---------- + tag : str + Element name. If given, the tag must match the start tag. + If omitted, the current element is closed. + """ + if tag: + assert self._tags, "unbalanced end(%s)" % tag + assert tag == self._tags[-1],\ + "expected end(%s), got %s" % (self._tags[-1], tag) + else: + assert self._tags, "unbalanced end()" + tag = self._tags.pop() + if self._data: + self._flush(indent, wrap) + elif self._open: + self._open = 0 + self.write(u"/>\n") + return + if indent: + self.write(self.get_indentation_spaces()) + self.write(u"</%s>\n" % tag) +
    +
    [docs] def close(self, id): + """ + Closes open elements, up to (and including) the element identified + by the given identifier. + + Parameters + ---------- + id : int + Element identifier, as returned by the `start` method. + """ + while len(self._tags) > id: + self.end() +
    +
    [docs] def element(self, tag, text=None, wrap=False, attrib={}, **extra): + """ + Adds an entire element. This is the same as calling `start`, + `data`, and `end` in sequence. The `text` argument + can be omitted. + """ + self.start(tag, attrib, **extra) + if text: + self.data(text) + self.end(indent=False, wrap=wrap) +
    +
    [docs] def flush(self): + pass # replaced by the constructor +
    +
    [docs] def get_indentation(self): + """ + Returns the number of indentation levels the file is currently + in. + """ + return len(self._tags) +
    +
    [docs] def get_indentation_spaces(self, offset=0): + """ + Returns a string of spaces that matches the current + indentation level. + """ + return self._indentation[:len(self._tags) + offset] +
    + @staticmethod +
    [docs] def object_attrs(obj, attrs): + """ + Converts an object with a bunch of attributes on an object + into a dictionary for use by the `XMLWriter`. + + Parameters + ---------- + obj : object + Any Python object + + attrs : sequence of str + Attribute names to pull from the object + + Returns + ------- + attrs : dict + Maps attribute names to the values retrieved from + `obj.attr`. If any of the attributes is `None`, it will + not appear in the output dictionary. + """ + d = {} + for attr in attrs: + if getattr(obj, attr) is not None: + d[attr.replace('_', '-')] = str(getattr(obj, attr)) + return d
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/astropy/wcs.html b/_modules/astropy/wcs.html new file mode 100644 index 00000000..3c58fd9f --- /dev/null +++ b/_modules/astropy/wcs.html @@ -0,0 +1,159 @@ + + + + + + + + + + astropy.wcs — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +

    Source code for astropy.wcs

    +"""
    +.. _wcslib: http://www.atnf.csiro.au/~mcalabre/WCS/
    +.. _pyfits: http://www.stsci.edu/resources/software_hardware/pyfits
    +.. _Paper IV: http://www.atnf.csiro.au/people/mcalabre/WCS/index.html
    +.. _SIP: http://irsa.ipac.caltech.edu/data/SPITZER/docs/files/spitzer/shupeADASS.pdf
    +.. _ds9: http://hea-www.harvard.edu/RD/ds9/
    +
    +astropy.wcs provides transformations following the `SIP`_ conventions,
    +`Paper IV`_ table lookup distortion, and the core WCS functionality
    +provided by `wcslib`_.  Each of these transformations can be used
    +independently or together in a standard pipeline.
    +
    +The basic workflow is as follows:
    +
    +    1. ``from astropy import wcs``
    +
    +    2. Call the `wcs.WCS` constructor with a `pyfits`_ header
    +       and/or hdulist object.
    +
    +    3. Optionally, if the FITS file uses any deprecated or
    +       non-standard features, you may need to call one of the
    +       `~astropy.wcs.WCS.fix` methods on the object.
    +
    +    4. Use one of the following transformation methods:
    +
    +       - `~WCS.all_pix2sky`: Perform all three transformations from
    +         pixel to sky coordinates.
    +
    +       - `~WCS.wcs_pix2sky`: Perform just the core WCS transformation
    +         from pixel to sky coordinates.
    +
    +       - `~WCS.wcs_sky2pix`: Perform just the core WCS transformation
    +         from sky to pixel coordinates.
    +
    +       - `~WCS.sip_pix2foc`: Convert from pixel to focal plane
    +         coordinates using the `SIP`_ polynomial coefficients.
    +
    +       - `~WCS.sip_foc2pix`: Convert from focal plane to pixel
    +         coordinates using the `SIP`_ polynomial coefficients.
    +
    +       - `~WCS.p4_pix2foc`: Convert from pixel to focal plane
    +         coordinates using the table lookup distortion method
    +         described in `Paper IV`_.
    +
    +       - `~WCS.det2im`: Convert from detector coordinates to image
    +         coordinates.  Commonly used for narrow column correction.
    +"""
    +
    +from __future__ import division  # confidence high
    +
    +from .wcs import *
    +
    +
    +
    [docs]class Wcsprm(Wcsprm): + pass
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 00000000..53d853a6 --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,123 @@ + + + + + + + + + + Overview: module code — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_sources/configs.txt b/_sources/configs.txt new file mode 100644 index 00000000..95e92ddf --- /dev/null +++ b/_sources/configs.txt @@ -0,0 +1,100 @@ +Configuration system Documentation +================================== + +The astropy configuration system is designed to give users control of various +parameters used in astropy or affiliated packages without delving into the +source code to make those changes. + +.. todo:: + Move this portion of the documentation to a more appropriate place when a + doc reorg happens + +For Users +--------- + +To see the configuration options, look for your astropy configuration file. +You can find it by doing:: + + from astropy.config import get_config_dir + + print get_config_dir() + +And you should see the location of your configuration directory. The standard +scheme generally puts your configuration directory in ``$HOME/.astropy/config``, +but if you've set the environment variable `XDG_CONFIG_HOME` and the +``$XDG_CONFIG_HOME/astropy`` directory exists, it will instead be there. + +Once you've found the configuration file, open it with your favorite editor. +It should have all of the sections you might want, with descriptions and the +type of the value that is accepted. Feel free to edit this as you wish, and +any of these changes will be reflected when you next start Astropy. Or, if you +want to see your changes immediately in your current Astropy session, just do:: + + from astropy.config import reload_config() + + reload_config() + +.. warning:: + The above is not true yet, because the setup doesn't automatically + populate the configuration files. Hopefully it will be true soon, though. + The :func:`astropy.config.configs._generate_all_config_items` function will + already do this, basically, but there has to be some thought about how to + make driver scripts that actually do this for each user, and coordinate + when they get run so that everything is already built. + + + + +For Developers +-------------- +The Reference guide below describes the full interface - this is a summary of +typical practices. The most common way to use the configuration system is as +follows:: + + """ This is the docstring at the beginning of a module + """ + from astropy.config import ConfigurationItem + + SOME_OPTION = ConfigurationItem('some_opt',1,'A description.') + ANOTHER_OPTION = ConfigurationItem('anno_opt','a string val', + 'A longer description of what this does.') + + ... implementation ... + def some_func(): + #to get the value of these options, I might do: + something = SOME_OPTION()+2 + return ANOTHER_OPTION()+' Also, I added text.' + +It is highly recommended that any configuration items be placed at the top of a +module like this, as they can then be easily found when viewing the source code +and the automated tools to generate the default configuration files can also +locate these items. + + + +Reference/API +------------- +Below are the reference documentation for the three main config sub-packages: +`astropy.config.paths`, `astropy.config.configs`, and `astropy.config.data`. +Note that all the public classes and functions in these sub-packages are +imported into `astropy.config`, so the recommended usage is simply +``from astropy.config import foo``. + +`astropy.config.paths` +^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: astropy.config.paths + :members: + +`astropy.config.configs` +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: astropy.config.configs + :members: + + +`astropy.config.data` +^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: astropy.config.data + :members: \ No newline at end of file diff --git a/_sources/development/building_packaging.txt b/_sources/development/building_packaging.txt new file mode 100644 index 00000000..45b31e82 --- /dev/null +++ b/_sources/development/building_packaging.txt @@ -0,0 +1,135 @@ +=============================================== +Building, Cython/C Extensions, and Distribution +=============================================== + +The build process currently uses the +`Distribute `_ package to build and +install the astropy core (and any affiliated packages that use the template). +The user doesn't necessarily need to have `distribute` installed, as it will +automatically bootstrap itself using the ``distribute_setup.py`` file in the +source distribution if it isn't installed for the user. + +Customizing setup/build for subpackages +--------------------------------------- + +As is typical, there is a single ``setup.py`` file that's used for the whole +`astropy` package. To customize setup parameters for a given sub-package, a +``setup_package.py`` file can be defined inside a package, and if it is present, +the setup process will look for the following functions to customize the build +process: + +* :func:`get_package_data` + This function, if defined, should return a dictionary mapping the name of + the subpackage(s) that need package data to a list of data file paths + (possibly including wildcards) relative to the path of the package's source + code. e.g. if the source distribution has a needed data file + ``astropy/wcs/tests/data/3d_cd.hdr``, this function should return + ``{'astropy.wcs.tests:'['data/3d_cd.hdr']}``. See the ``package_data`` + option of the :func:`distutils.core.setup` function. + + It is recommended that all such data be in a directory named "data" inside + the package within which it is supposed to be used, and package data should + be accessed via the `astropy.config.data.get_data_filename` and + `astropy.config.data.get_data_fileobj` functions. + +* :func:`get_extensions` + This provides information for building C or Cython extensions. If defined, + it should return a list of `distutils.core.Extension` objects controlling + the Cython/C build process (see below for more detail). + +* :func:`get_legacy_alias` + This function allows for the creation of `shims` that allow a + subpackage to be imported under another name. For example, + `astropy.io.fits` used to be available under the namespace + `pyfits`. For backward compatibility, it is helpful to have it + still importable under the old name. Under most circumstances, + this function should call `astropy.setup_helpers.add_legacy_alias` + to generate a legacy module and then return what it returns. + +The `astropy.setup_helpers` modules includes a :func:`update_package_files` +function which automatically searches the given source path for +``setup_package.py`` modules and calls each of the above functions, if they +exist. This makes it easy for affiliated packages to use this machinery in +their own ``setup.py``. + +.. _building-c-or-cython-extensions: + +C or Cython Extensions +---------------------- + +Astropy supports using C extensions for wrapping C libraries and Cython for +speeding up computationally-intensive calculations. Both Cython and C extension +building can be customized using the :func:`get_extensions` function of the +``setup_package.py`` file. If defined, this function must return a list of +`distutils.core.Extension` objects. The creation process is left to the +subpackage designer, and can be customized however is relevant for the +extensions in the subpackage. + +While C extensions must always be defined through the :func:`get_extensions` +mechanism, Cython files (ending in ``.pyx``) are automatically located and +loaded in separate extensions if they are not in :func:`get_extensions`. For +Cython extensions located in this way, headers for numpy C functions are +included in the build, but no other external headers are included. ``.pyx`` +files present in the extensions returned by :func:`get_extensions` are not +included in the list of extensions automatically generated extensions. Note +that this allows disabling a Cython file by providing an extension that +includes the Cython file, but giving it the special `name` 'cython_skip'. Any +extension with this package name will not be built by ``setup.py``. + +.. note:: + + If an :class:`~distutils.core.Extension` object is provided for Cython + source files using the :func:`get_extensions` mechanism, it is very + important that the ``.pyx`` files be given as the `source`, rather than the + ``.c`` files generated by Cython. + +Installing C header files +````````````````````````` + +If your C extension needs to be linked from other third-party C code, +you probably want to install its header files along side the Python module. + + 1) Create an `include` directory inside of your package for + all of the header files. + + 2) Use the :func:`get_package_data` hook in `setup_package.py` to + install those header files. For example, the `astropy.wcs` + package has this:: + + def get_package_data(): + return {'astropy.wcs': ['include/*.h']} + +Release +------- + +There have been no releases of the core package yet, so this isn't fully +defined. Some important items that are expected to be involved: + +* The release process should be done by automated script. +* Documentation is currently hosted at http://readthedocs.org/docs/astropy, + and tested at https://jenkins.shiningpanda.com/astropy/job/astropy-doc/, + automatically updated with every commit to github master. +* c files generated by Cython should never be stored in source, but instead + generated during the release process. The setup script will always use these + generated c files for release versions (instead of the .pyx Cython file). + +There is a central `setup.py`. It defines which Python packages to +install. Each package does not have its own standalone `setup.py`. + +Each package that needs to build C extensions has a module +`setup_package.py` that contains a function `get_extensions()` which +returns a list of `distutils.core.Extension` objects defining any +extensions to be built. + +There are a set of helper functions for commonly occurring things when +building C extensions (e.g. finding the Numpy headers and library) in +`astropy.setup_helpers`. + +Future directions +----------------- + +We plan to switch to a newer packaging scheme when it's more stable, the +upcoming standard library `packaging` module, derived from the +`distutils2 `_ +project. Until it's working right, however, we will be using `distribute` and +`distutils`. diff --git a/_sources/development/codeguide.txt b/_sources/development/codeguide.txt index 1451740c..91dae5ec 100644 --- a/_sources/development/codeguide.txt +++ b/_sources/development/codeguide.txt @@ -1,6 +1,6 @@ -=========================== -Coding Guidelines (Draft 3) -=========================== +========================= +Coding Guidelines (Draft) +========================= .. warning:: This document is currently in Draft form and is subject to change. @@ -29,6 +29,11 @@ Interface and Dependencies and Matplotlib_ (versions for these packages will be specified in the Astropy ``setup.py`` file and on PyPI_). +* The package should be importable from the source tree at build time. + This means that, for example, if the package relies on C extensions + that have yet to be built, the Python code is still importable, even + if none of its functionality will work. + * Additional dependencies are allowed for sub-modules or in function calls, but they must be noted in the package documentation and should only affect the relevant component. @@ -52,17 +57,24 @@ Documentation and Testing Data and Configuration ---------------------- -* Packages can include data in ``path TBD`` as long as it is less than about - 100 kb. These data should be accessed via the - :func:`astropy.config.[funcname TBD]` mechanism. If the data exceeds this - size, it should be hosted outside the source code repository and downloaded - using the :func:`astropy.config.[funcname TBD]` mechanism. Exceptions to - this size limit may be allowed if there are version dependencies between - data and code. - -* All persistent configuration should be stored using the functions in - :mod:`astropy.config`, which make use of the :class:`ConfigObj` class and - associated file format (http://www.voidspace.org.uk/python/configobj.html. +* Packages can include data in a directory named `data` inside a subpackage + source directory as long as it is less than about 100 kb. These data should + always be accessed via the :func:`astropy.config.get_data_fileobj` or + :func:`astropy.config.get_data_filename` functions. If the data exceeds this + size, it should be hosted outside the source code repository, either at a + third-party location on the internet or the astropy data server. In either + case, it should always be downloaded using the + :func:`astropy.config.get_data_fileobj` or + :func:`astropy.config.get_data_filename` functions. If a specific version of + a data file is needed, the hash mechanism described in :doc:`/configs` should + be used. + +* All persistent configuration should use the + `astropy.config.ConfigurationItem` mechanism. Such configuration items + should be placed at the top of the module or package that makes use of them, + and supply a description sufficient for users to understand what the setting + changes. + Coding Style/Conventions ------------------------ @@ -77,47 +89,79 @@ Coding Style/Conventions syntax. This is primarily due to improved relative import support since PEP8 was developed, and to simplify the process of moving modules. -.. note:: A pep8.py checker script is available at - http://pypi.python.org/pypi/pep8. +.. note:: There are multiple options for testing PEP8 compliance of code, + see :doc:`testguide` for more information. See :doc:`codeguide_emacs` for some configuration options for Emacs that helps in ensuring conformance to PEP8. + +* Astropy source code should contain a comment at the beginning of the file (or + imppediately after the ``#!/usr/bin env python`` command, if relevant) + pointing to the license for the Astropy source code. This line should say:: + + # Licensed under a 3-clause BSD style license - see LICENSE.rst * The ``import numpy as np``, ``import matplotlib as mpl``, and ``import matplotlib.pyplot as plt`` naming conventions should be used wherever relevant. ``from packagename import *`` should never be used, except as a tool to flatten the namespace of a module. An example of the allowed usage - is given below. + is given in :ref:`import-star-example`. * Classes should either use direct variable access, or python’s property mechanism for setting object instance variables. ``get_value``/``set_value`` style methods should be used only when getting and setting the values - requires a computationally-expensive operation. The example below - illustrates this guideline. - -* Classes are discouraged from using the builtin python :func:`super` - function, unless absolutely needed. If used, it should be used - consistentently by all subclasses, and noted in the class’s docstrings. An - example illustrating why this is important (and alternative solutions) is - included below. + requires a computationally-expensive operation. :ref:`prop-get-set-example` + below illustrates this guideline. + +* All new classes should be new-style classes inheriting from :class:`object` + (in Python 3 this is a non-issue as all classes are new-style by default). + The one exception to this rule is older classes in third-party libraries such + the Python standard library or numpy. + +* Classes should use the builtin :func:`super` function when making calls to + methods in their super-class(es) unless there are specific reasons not to. + :func:`super` should be used consistently in all subclasses since it does not + work otherwise. :ref:`super-vs-direct-example` illustrates why this is + important. + +* Multiple inheritance should be avoided in general without good reason. + Mulitple inheritance is complicated to implement well, which is why many + object-oriented languages, like Java, do not allow it at all. Python does + enable multiple inheritance through use of the + `C3 Linearization `_ + algorithm, which provides a consistent method resolution ordering. + Non-trivial multiple-inheritance schemes should not be attempted without + good justification, or without understanding how C3 is used to determine + method resolution order. However, trivial multiple inheritance using + orthogonal base classes, known as the 'mixin' pattern, may be used. + +* ``__init__.py`` files for modules should not contain any significant + implementation code. ``__init__.py`` can contain docstrings and code for + organizing the module layout, however (e.g. ``from submodule import *`` + in accord with the guideline above). If a module is small enough that + it fits in one file, it should simple be a single file, rather than a + directory with an ``__init__.py`` file. + +* When try...except blocks are used to catch exceptions, the ``as`` syntax + should always be used, because this is available in all supported versions of + python and is less ambiguous syntax (see :ref:`try-except-as-example`). * Affiliated packages are required to follow the layout and documentation form of the template package included in the core package source distribution. -.. note:: For more info on the pros and cons of using super, see - http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ - or http://keithdevens.com/weblog/archive/2011/Mar/16/Python.super) +* Command-line scripts should follow the form outlined in the :doc:`scripts` + document. -Including C code +Including C Code ---------------- * C extensions are only allowed when they provide a significant performance enhancement over pure python, or a robust C library already exists to provided the needed functionality. When C extensions are used, the Python - interface must meet interface guidelines. + interface must meet the aforementioned python interface guidelines. * The use of Cython_ is strongly recommended for C extensions, as per the - example in the template package. Cython extensions should store ``.pyx`` + example in the template package. Cython_ extensions should store ``.pyx`` files in the source code repository, but they should be compiled to ``.c`` files that are updated in the repository when important changes are made to the ``.pyx`` file. @@ -128,11 +172,15 @@ Including C code Additionally, the package must be compatible with using a system-installed library in place of the library included in Astropy. -* In cases where C extensions are needed but Cython cannot be used, the `PEP 7 +* In cases where C extensions are needed but Cython_ cannot be used, the `PEP 7 Style Guide for C Code `_ is recommended. + +* C extensions (Cython_ or otherwise) should provide the necessary information + for building the extension via the mechanisms described in + :ref:`building-c-or-cython-extensions`. -Requirements specific to Affiliated Packages +Requirements Specific to Affiliated Packages -------------------------------------------- * Affiliated packages must be registered on the `Python Package Index @@ -151,6 +199,8 @@ This section shows a few examples (not all of which are correct!) to illustrate points from the guidelines. These will be moved into the template project once it has been written. +.. _prop-get-set-example: + Properties vs. get\_/set\_ ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,14 +229,17 @@ a get/set method. For lengthy or complex calculations, however, use a method:: >>> print s.compute_color(5800, age=5e9) 0.4 + +.. _super-vs-direct-example: -super() vs. direct calling +super() vs. Direct Calling ^^^^^^^^^^^^^^^^^^^^^^^^^^ -This example shows why the use of :func:`super` can be confusing for -subclasses, and gives an alternative syntax:: +This example shows why the use of :func:`super` leads to a more consistent +method resolution order than manually calling methods of the super classes in a +multiple inheritance case:: - #This is dangerous and bug-prone! + # This is dangerous and bug-prone! class A(object): def method(self): @@ -195,20 +248,20 @@ subclasses, and gives an alternative syntax:: class B(A): def method(self): - super(B, self).method() print 'Doing B' + A.method(self) class C(A): def method(self): - A.method(self) print 'Doing C' - + A.method(self) class D(C, B): def method(self): - super(D, self).method() print 'Doing D' + C.method(self) + B.method(self) if you then do:: @@ -217,49 +270,77 @@ if you then do:: you will see:: - Doing A Doing B + Doing A which is what you expect, and similarly for C. However, if you do:: >>> d = D() >>> d.method() -you might expect to have it call both method in the order A,C,B,D. But it -doesn't - instead you see:: +you might expect to see the methods called in the order D, B, C, A but instead +you see:: - Doing A - Doing C Doing D + Doing C + Doing A + Doing B + Doing A -because the the ``A.method(self)`` in C effectively short-circuits the super -mechanism. Thus, it's crucial that all classes in an inheritance hierarchy -consistently use super and not mix super with the direct syntax. The simplest -approach is to explicitly call each class' method and avoid super completely:: - #This is safer - class A(object): - def __init__(self, a): - self.a = 1 +because both ``B.method()`` and ``C.method()`` call ``A.method()`` unaware of +the fact that they're being called as part of a chain in a hierarchy. When +``C.method()`` is called it is unaware that it's being called from a subclass +that inherts from both ``B`` and ``C``, and that ``B.method()`` should be +called next. By calling :func:`super` the entire method resolution order for +``D`` is precomputed, enabling each superclass to cooperatively determine which +class should be handed control in the next :func:`super` call:: + # This is safer + + class A(object): + def method(self): + print 'Doing A' class B(A): - def __init__(self, a, b): - A.__init__(self, a) - self.b = b + def method(self): + print 'Doing B' + super(B, self).method() class C(A): - def __init__(self, a, c): - A.__init__(self, a) - self.c = c - + def method(self): + print 'Doing C' + super(C, self).method() class D(C, B): - def __init__(self, a, b, c, d): - B.__init__(self, a, b) - C.__init__(self, a, c) - self.d = d + def method(self): + print 'Doing D' + super(D, self).method() + +:: + + >>> d = D() + >>> d.method() + Doing D + Doing C + Doing B + Doing A + +As you can see, each superclass's method is entered only once. For this to +work it is very important that each method in a class that calls its +superclass's version of that method use :func:`super` instead of calling the +method directly. In the most common case of single-inheritance, using +``super()`` is functionally equivalent to calling the superclass's method +directly. But as soon as a class is used in a multiple-inheritance +hierarchy it must use ``super()`` in order to cooperate with other classes in +the hierarchy. + +.. note:: For more info on the pros and cons of using super, see + http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ + or http://keithdevens.com/weblog/archive/2011/Mar/16/Python.super) + +.. _import-star-example: Acceptable use of ``from module import *`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -303,6 +384,31 @@ might read:: This ensures that ``from submodule import *`` only imports :func:`foo` and :class:`AClass`, but not :class:`numpy.array` or :func:`numpy.linspace`. +.. _try-except-as-example: + +try...except block "as" syntax +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Catching of exceptions should always use this syntax:: + + try: + ... some code that might produce a variety of exceptions ... + except ImportError as e: + if 'somemodule' in e.args[0]" + #for whatever reason, failed import of somemodule is ok + pass + else: + raise + except ValueError, TypeError as e: + msg = 'Hit an input problem, which is ok,' + msg2 = 'but we're printing it here just so you know:' + print msg, msg2, e + +This avoids the old style syntax of ``except ImportError, e`` or +``except (ValueError,TypeError), e``, which is dangerous because it's easy to +instead accidentally do something like ``except ValueError,TypeError``, which +won't catch `TypeError`. + Additional Resources -------------------- diff --git a/_sources/development/codeguide_emacs.txt b/_sources/development/codeguide_emacs.txt index b71de549..0a071a31 100644 --- a/_sources/development/codeguide_emacs.txt +++ b/_sources/development/codeguide_emacs.txt @@ -6,7 +6,7 @@ .. _pyflakes: http://pypi.python.org/pypi/pyflakes .. _pep8: http://pypi.python.org/pypi/pep8 -The AstroPy coding guidelines are listed in :doc:`codeguide`. This +The Astropy coding guidelines are listed in :doc:`codeguide`. This document will describe some configuration options for Emacs, that will help in ensuring that Python code satisfies the guidelines. Emacs can be configured in several different ways. So instead of providing a drop diff --git a/_sources/development/docguide.txt b/_sources/development/docguide.txt index 56d8f9eb..83b6800a 100644 --- a/_sources/development/docguide.txt +++ b/_sources/development/docguide.txt @@ -1,16 +1,19 @@ -================================== -Documentation Guidelines (Draft 2) -================================== +================================ +Documentation Guidelines (Draft) +================================ .. warning:: This document is currently in Draft form and is subject to change. -AstroPy Documentation Rules and Recommendations +TODO: Detailed information about building the documentation should be +added here. + +Astropy Documentation Rules and Recommendations ----------------------------------------------- This section describes the standards for documentation format affiliated packages that must follow for consideration of integration into the core -module, as well as the standard AstroPy docstring format. +module, as well as the standard Astropy docstring format. * Documentation shall use the Sphinx documentation tool. @@ -20,7 +23,7 @@ module, as well as the standard AstroPy docstring format. * Docstrings must be provided for all public classes, methods, and functions. * Docstrings will be incorporated into the documentation using a version of - numpydoc included with AstroPy, and should follow the NumPy_/SciPy_ + numpydoc included with Astropy, and should follow the NumPy_/SciPy_ docstring standards, included below. * Examples and/or tutorials are strongly encouraged for typical use-cases of a @@ -39,7 +42,7 @@ The original source for these docstring standards is the NumPy_ project, and the associated numpydoc_ tools. The most up-to-date version of these standards can be found at `numpy's github site `_. The -guidelines below have been adapted to the AstroPy pacakge. +guidelines below have been adapted to the Astropy pacakge. .. _NumPy: http://numpy.scipy.org/ .. _numpydoc: http://pypi.python.org/pypi/numpydoc/0.3.1 @@ -65,7 +68,7 @@ Use a code checker: * `pyflakes `_ * `pep8.py `_ -The following import conventions are used throughout the AstroPy source +The following import conventions are used throughout the Astropy source and documentation:: import numpy as np @@ -102,7 +105,7 @@ triple double quotes, i.e.:: NumPy_ and SciPy_ have defined a common convention for docstrings that provides for consistency, while also allowing our toolchain to produce -well-formatted reference guides. This format should be used for AstroPy +well-formatted reference guides. This format should be used for Astropy docstrings. This docstring standard uses `re-structured text (reST) @@ -154,7 +157,7 @@ The sections of the docstring are: A section (use if applicable) to warn users that the object is deprecated. Section contents should include: - * In what AstroPy version the object was deprecated, and when it will + * In what Astropy version the object was deprecated, and when it will be removed. * Reason for deprecation if this is useful information (e.g., object @@ -167,8 +170,8 @@ The sections of the docstring are: :: - .. note:: Deprecated in AstroPy 1.2 - `ndobj_old` will be removed in AstroPy 2.0, it is replaced by + .. note:: Deprecated in Astropy 1.2 + `ndobj_old` will be removed in Astropy 2.0, it is replaced by `ndobj_new` because the latter works also with array subclasses. 3. **Extended summary** @@ -405,8 +408,8 @@ The sections of the docstring are: Documenting classes ^^^^^^^^^^^^^^^^^^^ -Class docstring -``````````````` +Class docstrings +```````````````` Use the same sections as outlined above (all except ``Returns`` are applicable). The constructor (``__init__``) should also be documented here, @@ -478,7 +481,7 @@ put brief summary and See Also sections in the method docstring. Documenting class instances ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Instances of classes that are part of the AstroPy API may require some care. +Instances of classes that are part of the Astropy API may require some care. To give these instances a useful docstring, we do the following: * Single instance: If only a single instance of a class is exposed, document @@ -576,7 +579,7 @@ Conclusion `An example `_ of the format shown here is available. Refer to `How to Build API/Reference Documentation -`_ +`_ on how to use Sphinx_ to build the manual. .. _SciPy: http://www.scipy.org diff --git a/_sources/development/index.txt b/_sources/development/index.txt index fc40daa2..5775acb7 100644 --- a/_sources/development/index.txt +++ b/_sources/development/index.txt @@ -1,7 +1,11 @@ +.. _developer-docs: + Documentation for Developers ============================ -The information in the following pages are relevant for anyone interesting in contributing to AstroPy: +The information in the following pages are relevant for anyone interesting in +contributing to Astropy. In addition, the :doc:`../overview` is a useful guide +to the layout of the `astropy` package. .. toctree:: :maxdepth: 1 @@ -11,3 +15,5 @@ The information in the following pages are relevant for anyone interesting in co codeguide docguide testguide + building_packaging + scripts diff --git a/_sources/development/scripts.txt b/_sources/development/scripts.txt new file mode 100644 index 00000000..88301ee9 --- /dev/null +++ b/_sources/development/scripts.txt @@ -0,0 +1,63 @@ +============================ +Writing Command-Line Scripts +============================ + +Command-line scripts in Astropy should follow a consistent scheme to promote +readability and compatibility. + +The actual script should be in the ``/scripts`` directory of the Astropy +source distribution, and should do nothing aside from importing a ``main`` +function from astropy and execute it. This is partly necessary because the +"2to3" utility that converts python 2.x code to 3.x does not convert scripts. +These scripts should be executable, include ``#!/usr/bin/env python`` at the +top, and should *not* end in ``.py``. + +The ``main`` functions these scripts call should accept an optional single +argument that holds the ``sys.argv`` list, except for the script name +(e.g., ``argv[1:]``). This function can live in its own module, or be part of a +larger module that implements a class or function for astropy library use. The +``main`` function should do very little actual work - it should only parse the +arguments and pass those arguments on to some library function so that the +library function can be used programmatically when needed. +Command-line options can be parsed however desired, but the :mod:`argparse` +module is recommended when possible, due to its simpler and more flexible +interface relative to the older :mod:`optparse`. :mod:`argparse` is only +available in python >=2.7 and >=3.2, however, so it should be imported as +``from astropy.util.compat import argparse`` . + + +Example +------- + +Contents of ``/scripts/cmdlinescript`` :: + + #!/usr/bin/env python + # -*- coding: utf-8 -*- + """An astropy command-line script""" + + import astropy.somepackage.somemod + + astropy.somepackage.somemod.main() + +Contents of ``/astropy/somepackage/somemod.py`` :: + + def do_something(args, option=False): + for a in args: + if option: + ...do something... + else: + ...do something else... + + def main(args=None): + from astropy.utils.compat import argparse + + parser = argparse.ArgumentParser(description='Process some integers.') + parser.add_argument('-o', '--option', dest='op',action='store_true', + help='Some option that turns something on.') + parser.add_argument('stuff', metavar='S', nargs='+', + help='Some input I should be able to get lots of.') + + res = parser.parse_args(args) + + do_something(res.stuff,res.op) + diff --git a/_sources/development/testguide.txt b/_sources/development/testguide.txt index 53e9c6a4..89c8770d 100644 --- a/_sources/development/testguide.txt +++ b/_sources/development/testguide.txt @@ -1,10 +1,444 @@ +.. _testing-guidelines: + ========================== Testing Guidelines (Draft) ========================== -.. warning:: - This document is currently in Draft form and is subject to change. +.. warning:: + This document is currently in Draft form and is subject to change. Not all + described functionality may be implemented. + +This section describes the testing framework and format standards for tests in +Astropy core packages (this also serves as recommendations for affiliated +packages). + +Testing Framework +================= + +The testing framework used by Astropy is the `py.test `_ +framework. + +.. _running-tests: + +Running Tests +============= + +There are currently three different ways to invoke Astropy tests. Each method +invokes py.test to run the tests but offers different options when calling. + +In addition to running the Astropy tests, these methods can also be called so +that they check Python source code for +`PEP8 compliance `_. All of the PEP8 +testing options require the +`pytest-pep8 plugin `_, which must be +installed separately. + +setup.py test +------------- + +The safest way to run the astropy test suite is via the setup command ``test``. +This is invoked by running ``python setup.py test`` while in the astropy source +code directory. Run ``python setup.py test --help`` to see the options to the +test command. + +Turn on PEP8 checking by passing ``--pep8`` to the ``test`` command. This will +turn off regular testing and enable PEP8 testing. + +.. note:: + This method of running the tests defaults to the version of `py.test` that + is bundled with Astropy. To use the locally-installed version, you should + either change the `use_system_pytest` configuration option to "True" + (see :doc:`../../configs`) or the `py.test` method describe below. + +py.test +------- + +An alternative way to run tests from the command line is to switch to the source +code directory of astropy and simply type:: + + py.test + +``py.test`` will look for files that `look like tests +`_ +in the currect directory and all recursive directories then run all the code that +`looks like tests +`_ +within those files. + +.. note:: + To test any compiled C/Cython extensions, you must either have run + ``python setup.py test`` or ``python setup.py develop`` prior to running + the py.test command-line script. Otherwise, any tests that make use of + these extensions will not succeed. Similarly, in python 3, these tests + will not run correctly in the source code, because they need the ``2to3`` + tool to be run on them. + + +You may specify a specific test file or directory at the command line:: + + py.test test_file.py + +To run a specific test within a file use the ``-k`` option:: + + py.test test_file.py -k "test_function" + +You may also use the ``-k`` option to not run tests py putting a ``-`` in front +of the matching string:: + + py.test test_file.py -k "-test_function" + +py.test has a number of `command line usage options. +`_ + +Turn on PEP8 testing by adding the ``--pep8`` flag to the ``py.test`` call. By +default regular tests will also be run but these can be turned off by adding +``-k pep8``:: + + py.test some_dir --pep8 -k pep8 + +.. note:: + This method of running the tests uses the locally-installed version of + `py.test` rather than the bundled one, and hence will fail if the local + version it is not up-to-date enough (`py.test` 2.2 as of this writing). + +astropy.test() +-------------- + +AstroPy includes a standalone version of py.test that allows to tests +to be run even if py.test is not installed. Tests can be run from within +AstroPy with:: + + import astropy + astropy.test() + +This will run all the default tests for AstroPy. + +Tests for a specific package can be run by specifying the package in the call +to the ``test()`` function:: + + astropy.test('io.fits') + +This method works only with package names that can be mapped to Astropy +directories. As an alternative you can test a specific directory or file +with the ``test_path`` option:: + + astropy.test(test_path='wcs/tests/test_wcs.py') + +The ``test_path`` must be specified either relative to the working directory +or absolutely. + +By default ``astropy.test()`` will skip tests which retrieve data from the +internet. To turn these tests on use the ``remote_data`` flag:: + + astropy.test('io.fits',remote_data=True) + +In addition, the ``test`` function supports any of the options that can be +passed to `pytest.main() `_, +and convenience options ``verbose=`` and ``pastebin=``. + +Enable PEP8 compliance testing with ``pep8=True`` in the call to +``astropy.test``. This will enable PEP8 checking and disable regular tests. + +.. note:: + This method of running the tests defaults to the version of `py.test` that + is bundled with Astropy. To use the locally-installed version, you should + either change the `use_system_pytest` configuration option to "True" + (see :doc:`../../configs`) or the `py.test` method describe above. + +Regression tests +================ + +Any time a bug is fixed, and wherever possible, one or more regression tests +should be added to ensure that the bug is not introduced in future. Regression +tests should include the ticket URL where the bug was reported. + +Where to put tests +================== + +Package-specific tests +---------------------- + +Each package should include a suite of unit tests, covering as many of the +public methods/functions as possible. These tests should be included inside +each sub-package, either in a `tests` directory, or in a test.py file, e.g:: + + astropy/io/fits/tests/ + +or:: + + astropy/io/fits/test.py + +``tests`` directories should contain an ``__init__.py`` file so that the tests +can be imported and so that they can use relative imports. + +Interoperability tests +---------------------- + +Tests involving two or more sub-packages should be included in:: + + astropy/tests/ + +and using:: + + astropy.test() + +then runs both these interoperability tests, and all the unit tests in the +sub-packages. This functionality is especially important for people who install +packages through bundles and package managers, where the original source code +for the tests is not immediately available. + + +Writing tests +============= + +``py.test`` has the following test discovery rules: + + * ``test_*.py`` or ``*_test.py`` files + * ``Test`` prefixed classes (without an ``__init__`` method) + * ``test_`` prefixed functions and methods + +Consult the `test discovery rules +`_ +for detailed information on how to name files and tests so that they are +automatically discovered by ``py.test``. + +Simple example +-------------- + +The following example shows a simple function and a test to test this +function:: + + def func(x): + return x + 1 + + def test_answer(): + assert func(3) == 5 + +If we place this in a ``test.py`` file and then run:: + + py.test test.py + +The result is:: + + ============================= test session starts ============================== + python: platform darwin -- Python 2.7.2 -- pytest-1.1.1 + test object 1: /Users/tom/tmp/test.py + + test.py F + + =================================== FAILURES =================================== + _________________________________ test_answer __________________________________ + + def test_answer(): + > assert func(3) == 5 + E assert 4 == 5 + E + where 4 = func(3) + + test.py:5: AssertionError + =========================== 1 failed in 0.07 seconds =========================== + +Working with data files +----------------------- + +Tests that need to make use of a data file should use the +`~astropy.config.data.get_data_fileobj` or +`~astropy.config.data.get_data_filename` functions. These functions search +locally first, and then on the astropy data server or an arbitrary URL, and +return a file-like object or a local filename, respectively. They automatically +cache the data locally if remote data is obtained, and from then on the local +copy will be used transparently. + +They also support the use of an MD5 hash to get a specific version of a data +file. This hash can be obtained prior to submitting a file to the astropy +data server by using the `~astropy.config.data.compute_hash` function on a +local copy of the file. + +Tests that may retrieve remote data should be marked with the ``@remote_data`` +decorator. Tests marked with this decorator will be skipped by default by +``astropy.test()`` to prevent test runs from taking too long. These tests can +be run by ``astropy.test()`` by adding the ``remote_data=True`` flag. +Turn on the remote data tests at the command line with +``py.test --remote-data``. + +Examples +^^^^^^^^ +:: + + from ...config import get_data_filename + from ...tests.helper import remote_data + + def test_1(): + #if filename.fits is a local file in the source distribution + datafile = get_data_filename('filename.fits') + # do the test + + @remote_data + def test_2(): + #this is the hash for a particular version of a file stored on the + #astropy data server. + datafile = get_data_filename('hash/94935ac31d585f68041c08f87d1a19d4') + # do the test + +The ``get_remote_test_data`` will place the files in a temporary directory +indicated by the ``tempfile`` module, so that the test files will eventually +get removed by the system. In the long term, once test data files become too +large, we will need to design a mechanism for removing test data immediately. + +Tests that create files +----------------------- + +Tests may often be run from directories where users do not have write permissions +so tests which create files should always do so in temporary directories. This +can be done with the `py.test tmpdir function argument +`_ +or with Python's built-in `tempfile module +`_. + +Setting up/Tearing down tests +----------------------------- + +In some cases, it can be useful to run a series of tests requiring something +to be set up first. There are four ways to do this: + +Module-level setup/teardown +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the ``setup_module`` and ``teardown_module`` functions are specified in a +file, they are called before and after all the tests in the file respectively. +These functions take one argument, which is the module itself, which makes it +very easy to set module-wide variables:: + + def setup_module(module): + module.NUM = 11 + + def add_num(x): + return x + NUM + + def test_42(): + added = add_num(42) + assert added == 53 + +We can use this for example to download a remote test data file and have all +the functions in the file access it:: + + import os + + def setup_module(module): + module.DATAFILE = get_remote_test_data('94935ac31d585f68041c08f87d1a19d4') + + def test(): + f = open(DATAFILE, 'rb') + # do the test + + def teardown_module(module): + os.remove(DATAFILE) + +Class-level +^^^^^^^^^^^ + +Tests can be organized into classes that have their own setup/teardown +functions. In the following :: + + def add_nums(x, y): + return x + y + + class TestAdd42(object): + + def setup_class(self): + self.NUM = 42 + + def test_1(self): + added = add_nums(11, self.NUM) + assert added == 53 + + def test_2(self): + added = add_nums(13, self.NUM) + assert added == 55 + + def teardown_class(self): + pass + +In the above example, the ``setup_class`` method is called first, then all the +tests in the class, and finally the ``teardown_class`` is called. + +Method-level +^^^^^^^^^^^^ + +There are cases where one might want setup and teardown methods to be run +before and after *each* test. For this, use the ``setup_method`` and +``teardown_method`` methods:: + + def add_nums(x, y): + return x + y + + class TestAdd42(object): + + def setup_method(self, method): + self.NUM = 42 + + def test_1(self): + added = add_nums(11, self.NUM) + assert added == 53 + + def test_2(self): + added = add_nums(13, self.NUM) + assert added == 55 + + def teardown_method(self, method): + pass + +Function-level +^^^^^^^^^^^^^^ + +Finally, one can use ``setup_function`` and ``teardown_function`` to define a +setup/teardown mechanism to be run before and after each function in a module. +These take one argument, which is the function being tested:: + + def setup_function(function): + pass + + def test_1(self): + # do test + + def test_2(self): + # do test + + def teardown_method(function): + pass + +Using py.test helper functions +------------------------------ + +If your tests need to use `py.test helper functions +`_, such as ``pytest.raises``, +import ``pytest`` into your test module like so:: + + from ...tests.helper import pytest + +You may need to adjust the relative import to work for the depth of your module. +``tests.helper`` imports ``pytest`` either from the user's system or ``extern.pytest`` +if the user does not have py.test installed. This is so that users need not +install py.test to run AstroPy's tests. + + +Using data in tests +=================== + +Tests can include very small datafiles, but any files significantly larger +than the source code should be placed on a remote server. The base URL for the +test files will be:: + + http://data.astropy.org/ + +and files will be accessed by their MD5 hash, for example:: + + http://data.astropy.org/94935ac31d585f68041c08f87d1a19d4 -This section describes the testing framework and format standards for tests in Astropy core modules (this also serves as recommendations for affiliated packages). +Tests then retrieve data via this URL. This implicitly allows versioning, +since different versions of data files will have different hashes. Old data +files should not be removed, so that tests can be run in any version of +AstroPy. -* Guidelines will be filled in following a discussion on the astropy mailing list. \ No newline at end of file +The details of the server implementation have yet to be decided, but using +these static hash-based URLs ensures that even if we change the backend, the +URL will remain the same. diff --git a/_sources/development/vision.txt b/_sources/development/vision.txt index 0ef1f6a8..82f9bd84 100644 --- a/_sources/development/vision.txt +++ b/_sources/development/vision.txt @@ -1,50 +1,110 @@ .. _vision: -Vision for a common Astronomy Python package +============================================ +Vision for a Common Astronomy Python Package ============================================ -The following document summarizes a vision for a common Astronomy Python package, and how we can best all work together to achieve this. In the following document, this common package will be referred to as the core package. This vision is not set in stone, and we are committed to adapting it to whatever process and guidelines work in practice. +The following document summarizes a vision for a common Astronomy Python +package, and how we can best all work together to achieve this. In the +following document, this common package will be referred to as the core +package. This vision is not set in stone, and we are committed to adapting it +to whatever process and guidelines work in practice. -The ultimate goal that we seek is a package that would contain much of the core functionality and some common tools required across Astronomy, but not *everything* Astronomers will ever need. The aim is primarily to avoid duplication for common core tasks, and to provide a robust framework upon which to build more complex tools. +The ultimate goal that we seek is a package that would contain much of the core +functionality and some common tools required across Astronomy, but not +*everything* Astronomers will ever need. The aim is primarily to avoid +duplication for common core tasks, and to provide a robust framework upon which +to build more complex tools. -Such a common package should not preclude any other Astronomy package from existing, because there will always be more complex and/or specialized tools required. These tools will be able to rely on a single core library for many tasks, and thus reduce the number of dependencies, reduce duplication of functionality, and increase consistency of their interfaces. +Such a common package should not preclude any other Astronomy package from +existing, because there will always be more complex and/or specialized tools +required. These tools will be able to rely on a single core library for many +tasks, and thus reduce the number of dependencies, reduce duplication of +functionality, and increase consistency of their interfaces. Procedure --------- -With the help of the community, the coordination committee will start by identifying a few of key areas where initial development/consolidation will be needed (such as FITS, WCS, coordinates, tables, photometry, spectra, etc.) and will encourage teams to be formed to build standalone packages implementing this functionality. These packages will be referred to as affiliated packages (meaning that they are intended for future integration in the core package). - -A set of requirements will be set out concerning the interfaces and classes/methods that affiliated packages will need to make available in order to ensure consistency between the different components. As the core package grows, new potential areas/components for the core package will be identified. Competition cannot be avoided, and will not be actively discouraged, but whenever possible, developers should strive to work as a team to provide a single and robust affiliated package, for the benefit of the community. - -The affiliated packages will be developed outside the core package in independent repositories, which will allow the teams the choice of tool and organization. Once an affiliated package has implemented the desired functionality, and satisfies quality criteria for coding style, documentation, and testing, it will be considered for inclusion in the core package, and further development will be done directly in the core package either via direct access to the repository, or via patches/pull requests (exactly how this will be done will be decided later). - -To ensure uniformity across affiliated packages, and to facilitate integration with the core package, developers who wish to submit their affiliated packages for inclusion in the core will need to follow the layout of a ‘template’ package that will be provided before development starts. +With the help of the community, the coordination committee will start by +identifying a few of key areas where initial development/consolidation will be +needed (such as FITS, WCS, coordinates, tables, photometry, spectra, etc.) and +will encourage teams to be formed to build standalone packages implementing +this functionality. These packages will be referred to as affiliated packages +(meaning that they are intended for future integration in the core package). + +A set of requirements will be set out concerning the interfaces and +classes/methods that affiliated packages will need to make available in order +to ensure consistency between the different components. As the core package +grows, new potential areas/components for the core package will be identified. +Competition cannot be avoided, and will not be actively discouraged, but +whenever possible, developers should strive to work as a team to provide a +single and robust affiliated package, for the benefit of the community. + +The affiliated packages will be developed outside the core package in +independent repositories, which will allow the teams the choice of tool and +organization. Once an affiliated package has implemented the desired +functionality, and satisfies quality criteria for coding style, documentation, +and testing, it will be considered for inclusion in the core package, and +further development will be done directly in the core package either via direct +access to the repository, or via patches/pull requests (exactly how this will +be done will be decided later). + +To ensure uniformity across affiliated packages, and to facilitate integration +with the core package, developers who wish to submit their affiliated packages +for inclusion in the core will need to follow the layout of a ‘template’ +package that will be provided before development starts. Dependencies ------------ -Affiliated packages should be able to be imported with only the following dependencies: +Affiliated packages should be able to be imported with only the following +dependencies: -* The Python Standard Library -* NumPy, SciPy, and Matplotlib -* Components already in the core Astronomy package +* The Python Standard Library NumPy, SciPy, and Matplotlib Components already + * in the core Astronomy package -Other packages may be used, but must be imported as needed rather than during the initial import of the package. +Other packages may be used, but must be imported as needed rather than during +the initial import of the package. -If a dependency is needed, but is an affiliated package, the dependent package will need to wait until the dependency is integrated into the core package before being itself considered for inclusion. In the mean time, it can make use of the other affiliated package in its current form, or other packages, so as not to stall development. Thus, the first packages to be included in the core will be those only requiring the standard library, NumPy, SciPy, and Matplotlib. +If a dependency is needed, but is an affiliated package, the dependent package +will need to wait until the dependency is integrated into the core package +before being itself considered for inclusion. In the mean time, it can make use +of the other affiliated package in its current form, or other packages, so as +not to stall development. Thus, the first packages to be included in the core +will be those only requiring the standard library, NumPy, SciPy, and +Matplotlib. -If the required dependency will never be part of a main package, then by default the dependency can be included but should be imported as needed (meaning that it only prevents the importing of that component, not the entire core package), unless a strong case is made and a general consensus is reached by the community that this dependency is important enough to be required at a higher level. +If the required dependency will never be part of a main package, then by +default the dependency can be included but should be imported as needed +(meaning that it only prevents the importing of that component, not the entire +core package), unless a strong case is made and a general consensus is reached +by the community that this dependency is important enough to be required at a +higher level. -This system means that packages will be integrated into the core package in an order depending on the dependency tree, and also ensures that the interfaces of packages being integrated into the core package are consistent with those already in the core package. +This system means that packages will be integrated into the core package in an +order depending on the dependency tree, and also ensures that the interfaces of +packages being integrated into the core package are consistent with those +already in the core package. -Initially, no dependency on GUI toolkits will be allowed in the core package. If the community reaches agrees on a single toolkit that could be used, then this toolkit will be allowed (but will only be imported as needed). +Initially, no dependency on GUI toolkits will be allowed in the core package. +If the community reaches agrees on a single toolkit that could be used, then +this toolkit will be allowed (but will only be imported as needed). Keeping track of affiliated packages ------------------------------------ -Affiliated packages will be listed in a central location (in addition to PyPI) that will allow an easy installation of all the affiliated packages, for example with a script that will seamlessly download and install all the affiliated packages. The core package will also include mechanisms to facilitate this installation process. +Affiliated packages will be listed in a central location (in addition to PyPI) +that will allow an easy installation of all the affiliated packages, for +example with a script that will seamlessly download and install all the +affiliated packages. The core package will also include mechanisms to +facilitate this installation process. Existing Packages ----------------- -Developers who already have existing packages will be encouraged to continue supporting them for the benefit of users until the core library is considered stable, contains this functionality, and is released to the community. Thereafter, developers should encourage users to transition to using the functionality in the core package, and eventually phase out their own packages, unless they provide added value over the core package. \ No newline at end of file +Developers who already have existing packages will be encouraged to continue +supporting them for the benefit of users until the core library is considered +stable, contains this functionality, and is released to the community. +Thereafter, developers should encourage users to transition to using the +functionality in the core package, and eventually phase out their own packages, +unless they provide added value over the core package. diff --git a/_sources/development/workflow/development_workflow_advanced.txt b/_sources/development/workflow/development_workflow_advanced.txt index 0ae99a66..5e57d4c9 100644 --- a/_sources/development/workflow/development_workflow_advanced.txt +++ b/_sources/development/workflow/development_workflow_advanced.txt @@ -4,7 +4,7 @@ Development Workflow (Advanced) =============================== -In the present document, we refer to the AstroPy ``master`` branch, as the +In the present document, we refer to the Astropy ``master`` branch, as the *trunk*. .. _forking: diff --git a/_sources/index.txt b/_sources/index.txt index c72f8fa2..0672d6b8 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -3,21 +3,26 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to Astropy's documentation! +Welcome to Astropy's Documentation! =================================== -The current AstroPy documentation is limited, as no code has yet been developed. -For more information, see the `github wiki `_ page of the project. - -Contents: +The current Astropy documentation is limited, as not much code has yet been +developed. For more information, see the `github wiki +`_ page of the project. .. toctree:: :maxdepth: 2 - - development/index + overview + install + configs + wcs/index + vo/index + tools + utils/index + development/index -Indices and tables +Indices and Tables ================== * :ref:`genindex` diff --git a/_sources/install.txt b/_sources/install.txt new file mode 100644 index 00000000..e14d9e7a --- /dev/null +++ b/_sources/install.txt @@ -0,0 +1,111 @@ +Installation +============ + +Requirements +------------ + +Astropy has the following strict requirements: + +- `Python `_ 2.6, 2.7, 3.1 or 3.2 + +- `Numpy `_ 1.4 or later + +Astropy also depends on other projects for optional features. + +- `xmllint `_: To validate VOTABLE XML files. + +TODO: Link to the planned dependency checker/installer tool. + +Installing Astropy +------------------ + +Using `pip` +``````````` + +TODO: Write once we’re up on PyPI. + +Binary installers +````````````````` + +TODO: Write about where to obtain binary packages (.dmg, .msi etc.) + +Building from source +-------------------- + +Prerequisites +````````````` + +You will need a compiler suite and the development headers for Python +and Numpy in order to build Astropy. Using the package manager for +your platform will usually be the easiest route. + +The `instructions for building Numpy from source +`_ are also a good +resource for setting up your environment to build Python packages. + +Obtaining the source +```````````````````` + +Source packages +^^^^^^^^^^^^^^^ + +Source tarballs of past releases and the current development branch of +astropy can be downloaded from here: + + https://github.com/astropy/astropy/downloads + +Development repository +^^^^^^^^^^^^^^^^^^^^^^ + +The latest development version of Astropy can be cloned from github +using this command:: + + git clone git://github.com/astropy/astropy.git + +.. note:: + + If you wish to participate in the development of Astropy, see + :ref:`developer-docs`. This document covers only the basics + necessary to install Astropy. + +Building and Installing +``````````````````````` + +Astropy uses the Python `distutils framework +`_ for building and +installing. + +To build Astropy (from the root of the source tree):: + + python setup.py build + +To install Astropy (from the root of the source tree):: + + python setup.py install + +Building documentation +`````````````````````` + +Building the documentation requires some additional packages: + + - `Sphinx `_ (and its dependencies) 1.0 or later + + - `Graphviz `_ + +To build the Astropy documentation (from the root of the source tree):: + + python setup.py build_sphinx + +The documentation tree will be built in the `docs/_build/html` +directory. + +Testing Astropy +``````````````` + +The easiest way to test that your Astropy built correctly is to run +(from the root of the source tree):: + + python setup.py test + +There are also alternative methods of :ref:`running-tests`. + diff --git a/_sources/overview.txt b/_sources/overview.txt new file mode 100644 index 00000000..3ff9e1f4 --- /dev/null +++ b/_sources/overview.txt @@ -0,0 +1,56 @@ +Overview +======== + +Here we describe a broad overview of the astropy project and its associated +modules and packages. + + +`astropy` Package Layout +------------------------ + +Astropy contains the following base-level subpackages: + + +* :mod:`~astropy.config` + This subpackage contains configuration and setup utilities, including the + affiliated package install tools. +* :mod:`~astropy.utils` + This subpackage contains utilities of general use for multiple modules or + affiliated packages. +* :mod:`~astropy.version` + This subpackage contains the version number information for the package. + Note that the version is also available at the base level of the package as + :attr:`astropy.__version__`. +* :mod:`~astropy.extern` + This subpackage contains small python packages that are not unique to + astropy but are convinient to include as part of the astropy source code. +* :mod:`~astropy.tests` + This subpackage contains utilities to run the astropy test suite (the + simplest method is to just call :meth:`astropy.test`), tools for writing + tests, and general tests that are not associated with a particular package. +* :mod:`~astropy.wcs` + This subpackage contains a python wrapper around the + `wcslib `_ library for + managing FITS world coordinate systems (WCS). + +Affiliated Packages +------------------- + +Astropy also includes the concept of "affiliated packages." An affiliated +package is an astronomy-related python package that is not included as part of +the Astropy source code, but has officially requested to be included in the +Astropy community. Such a package may be a candidate for eventual inclusion in +the main `astropy` package. Astropy comes with a tool to install a affiliated +packages by name, and a single official index with a list and description of +each package. See the :mod:`~astropy.config` module documentation for details +regarding this install tool. + +Affiliated packages do not use the `astropy` namespace, but rather either use +their package name directly, or `awastropy.packagename` ("affiliated with +astropy"). These packages may later be merged into the `astropy` package, in +which case the original package may still be used, but it is recommended that +users switch to the `astropy.packagename` version as soon as possible. +Alternatively, some affiliated packages may not wish to ever be merged with the +`astropy` source code, but rather remain as separate packages that make use of +other astropy modules or affiliated packages. + diff --git a/_sources/tools.txt b/_sources/tools.txt new file mode 100644 index 00000000..e1c540ff --- /dev/null +++ b/_sources/tools.txt @@ -0,0 +1,27 @@ +============================= +`astropy.tools` documentation +============================= + +The `~astropy.tools` package holds general astronomy functions or algorithms +that are likely of use to users, but either not related to functionality in +an existing package or of general use across multiple packages. + +.. note:: + For functions and classes that are more developer-oriented, the correct + package is `astropy.utils`. `astropy.tools` is intended primarily for + functionality that is astronomy-specific and/or of use to users. + + +Reference/API +------------- +Below are the reference documentation for the tools sub-packages. All public +functions and classes in these packages will be imported into the +`astropy.tools` package, so the recommended usage is e.g. +``from astropy.tools import sigma_clip`` or ``import astropy.tools`` instead of +``from astropy.tools.misc import sigma_clip`` or similar. + +`astropy.tools.misc` +^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: astropy.tools.misc + :members: \ No newline at end of file diff --git a/_sources/utils/api_collections.txt b/_sources/utils/api_collections.txt new file mode 100644 index 00000000..7b44d78f --- /dev/null +++ b/_sources/utils/api_collections.txt @@ -0,0 +1,8 @@ +`astropy.utils.collections`: Specialized collection classes +=========================================================== + +.. automodule:: astropy.utils.collections + :members: + :undoc-members: + :show-inheritance: + :special-members: diff --git a/_sources/utils/api_console.txt b/_sources/utils/api_console.txt new file mode 100644 index 00000000..80ebcba2 --- /dev/null +++ b/_sources/utils/api_console.txt @@ -0,0 +1,8 @@ +`astropy.utils.console`: Utilities for console output +===================================================== + +.. automodule:: astropy.utils.console + :members: + :undoc-members: + :show-inheritance: + :special-members: diff --git a/_sources/utils/api_misc.txt b/_sources/utils/api_misc.txt new file mode 100644 index 00000000..054c57f3 --- /dev/null +++ b/_sources/utils/api_misc.txt @@ -0,0 +1,8 @@ +`astropy.utils.misc`: Miscellaneous/uncategorized Utilities +=========================================================== + +.. automodule:: astropy.utils.misc + :members: + :undoc-members: + :show-inheritance: + :special-members: diff --git a/_sources/utils/api_xml.txt b/_sources/utils/api_xml.txt new file mode 100644 index 00000000..8c186810 --- /dev/null +++ b/_sources/utils/api_xml.txt @@ -0,0 +1,38 @@ +`astropy.utils.xml`: Utilities related to XML +============================================= + +`astropy.utils.xml.check` +------------------------- + +.. automodule:: astropy.utils.xml.check + :members: + :undoc-members: + :show-inheritance: + :special-members: + +`astropy.utils.xml.iterparser` +------------------------------ + +.. automodule:: astropy.utils.xml.iterparser + :members: + :undoc-members: + :show-inheritance: + :special-members: + +`astropy.utils.xml.validate` +---------------------------- + +.. automodule:: astropy.utils.xml.validate + :members: + :undoc-members: + :show-inheritance: + :special-members: + +`astropy.utils.xml.writer` +-------------------------- + +.. automodule:: astropy.utils.xml.writer + :members: + :undoc-members: + :show-inheritance: + :special-members: diff --git a/_sources/utils/index.txt b/_sources/utils/index.txt new file mode 100644 index 00000000..4c9ceb0e --- /dev/null +++ b/_sources/utils/index.txt @@ -0,0 +1,14 @@ +============================= +`astropy.utils` documentation +============================= + +API documentation +================= + +.. toctree:: + :maxdepth: 2 + + api_collections + api_console + api_xml + api_misc diff --git a/_sources/vo/api.txt b/_sources/vo/api.txt new file mode 100644 index 00000000..1efd735b --- /dev/null +++ b/_sources/vo/api.txt @@ -0,0 +1,30 @@ +================= +API documentation +================= + +Public API +---------- + +.. toctree:: + :maxdepth: 2 + + api_table.rst + api_tree.rst + api_converters.rst + api_exceptions.rst + api_ucd.rst + api_unit.rst + api_util.rst + api_validator.rst + api_xmlutil.rst + +Private API +----------- + +These classes are not designed for public use. + +.. toctree:: + :maxdepth: 2 + + api_converters.rst + diff --git a/_sources/vo/api_converters.txt b/_sources/vo/api_converters.txt new file mode 100644 index 00000000..e99baae3 --- /dev/null +++ b/_sources/vo/api_converters.txt @@ -0,0 +1,13 @@ +.. include:: references.txt + +`astropy.io.vo.converters`: Conversions between XML and Numpy datatypes +======================================================================= + +.. inheritance-diagram:: astropy.io.vo.converters + :parts: 1 + +.. automodule:: astropy.io.vo.converters + :members: + :undoc-members: + :show-inheritance: + diff --git a/_sources/vo/api_exceptions.txt b/_sources/vo/api_exceptions.txt new file mode 100644 index 00000000..af725a71 --- /dev/null +++ b/_sources/vo/api_exceptions.txt @@ -0,0 +1,39 @@ +`astropy.io.vo.exceptions` +========================== + +.. contents:: + +.. automodule:: astropy.io.vo.exceptions + +Exception utilities +------------------- + +.. currentmodule:: astropy.io.vo.exceptions + +.. autofunction:: warn_or_raise + +.. autofunction:: vo_raise + +.. autofunction:: vo_reraise + +.. autofunction:: vo_warn + +.. autofunction:: parse_vowarning + +.. autoclass:: VOWarning + :show-inheritance: + +.. autoclass:: VOTableChangeWarning + :show-inheritance: + +.. autoclass:: VOTableSpecWarning + :show-inheritance: + +.. autoclass:: UnimplementedWarning + :show-inheritance: + +.. autoclass:: IOWarning + :show-inheritance: + +.. autoclass:: VOTableSpecError + :show-inheritance: diff --git a/_sources/vo/api_table.txt b/_sources/vo/api_table.txt new file mode 100644 index 00000000..cf9b2dd8 --- /dev/null +++ b/_sources/vo/api_table.txt @@ -0,0 +1,9 @@ +.. include:: references.txt + +`astropy.io.vo.table`: Loading entire VOTable files +=================================================== + +.. automodule:: astropy.io.vo.table + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/vo/api_tree.txt b/_sources/vo/api_tree.txt new file mode 100644 index 00000000..11ee8aee --- /dev/null +++ b/_sources/vo/api_tree.txt @@ -0,0 +1,13 @@ +.. include:: references.txt + +`astropy.io.vo.tree`: Accessing and modifying the individual parts of VOTable files +=================================================================================== + +.. inheritance-diagram:: astropy.io.vo.tree + :parts: 1 + +.. automodule:: astropy.io.vo.tree + :members: Element, SimpleElement, SimpleElementWithContent, VOTableFile, Resource, Table, Group, Info, Field, Param, Link, CooSys, FieldRef, ParamRef, Values + :undoc-members: + :show-inheritance: + diff --git a/_sources/vo/api_ucd.txt b/_sources/vo/api_ucd.txt new file mode 100644 index 00000000..142fc7a6 --- /dev/null +++ b/_sources/vo/api_ucd.txt @@ -0,0 +1,10 @@ +.. include:: references.txt + +`astropy.io.vo.ucd`: Functions to parse and verify unified content descriptors +============================================================================== + +.. automodule:: astropy.io.vo.ucd + :members: + :undoc-members: + :show-inheritance: + diff --git a/_sources/vo/api_unit.txt b/_sources/vo/api_unit.txt new file mode 100644 index 00000000..780e3e50 --- /dev/null +++ b/_sources/vo/api_unit.txt @@ -0,0 +1,10 @@ +.. include:: references.txt + +`astropy.io.vo.unit`: Verification of units as defined in the VOTable standard +============================================================================== + +.. automodule:: astropy.io.vo.unit + :members: + :undoc-members: + :show-inheritance: + diff --git a/_sources/vo/api_util.txt b/_sources/vo/api_util.txt new file mode 100644 index 00000000..8ae20f42 --- /dev/null +++ b/_sources/vo/api_util.txt @@ -0,0 +1,10 @@ +.. include:: references.txt + +`astropy.io.vo.util`: Low-level utilities used by the library +============================================================= + +.. automodule:: astropy.io.vo.util + :members: + :undoc-members: + :show-inheritance: + diff --git a/_sources/vo/api_validator.txt b/_sources/vo/api_validator.txt new file mode 100644 index 00000000..b5a71980 --- /dev/null +++ b/_sources/vo/api_validator.txt @@ -0,0 +1,11 @@ +.. include:: references.txt + +`astropy.io.vo.validator`: Generates HTML validation reports +============================================================ + +.. automodule:: astropy.io.vo.validator + :members: + :undoc-members: + :show-inheritance: + +.. autofunction:: astropy.io.vo.validator.main.make_validation_report diff --git a/_sources/vo/api_xmlutil.txt b/_sources/vo/api_xmlutil.txt new file mode 100644 index 00000000..94d6de53 --- /dev/null +++ b/_sources/vo/api_xmlutil.txt @@ -0,0 +1,9 @@ +.. include:: references.txt + +`astropy.io.vo.xmlutil`: XML-related utilities used by the library +================================================================== + +.. automodule:: astropy.io.vo.xmlutil + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/vo/index.txt b/_sources/vo/index.txt new file mode 100644 index 00000000..dc672bdd --- /dev/null +++ b/_sources/vo/index.txt @@ -0,0 +1,10 @@ +astropy.io.vo Documentation +=========================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + intro_table.rst + api.rst diff --git a/_sources/vo/intro_table.txt b/_sources/vo/intro_table.txt new file mode 100644 index 00000000..cc4adcc3 --- /dev/null +++ b/_sources/vo/intro_table.txt @@ -0,0 +1,282 @@ +Introduction to ``astropy.io.vo.table`` +======================================= + +`astropy.io.vo.table` is a Python package to read and write VOTable +files into Numpy record arrays. + +Standard compliance +------------------- + +`astropy.io.vo.table` supports the `VOTable Format Definition Version +1.1 +`_ +and `Version 1.2 +`_. +Some flexibility is provided to support the 1.0 draft version and +other non-standard usage in the wild. To support these cases, set the +keyword argument ``pedantic`` to ``False`` when parsing. + +.. note:: + + Each warning and VOTABLE-specific exception emitted has a number and + is documented in more detail in :ref:`warnings` and + :ref:`exceptions`. + +Output always conforms to the 1.1 or 1.2 spec, depending on the input. + +Using `astropy.io.vo.table` +--------------------------- + +Reading a VOTable file +~~~~~~~~~~~~~~~~~~~~~~ + +To read in a VOTable file, pass a file path to +`astropy.io.vo.table.parse`:: + + from astropy.io.vo.table import parse + votable = parse("votable.xml") + +``votable`` is a `~astropy.io.vo.tree.VOTableFile` object, which can +be used to retrieve and manipulate the data and save it back out to +disk. + +VOTable files are made up of nested ``RESOURCE`` elements, each of +which may contain one or more ``TABLE`` elements. The ``TABLE`` +elements contain the arrays of data. + +To get at the ``TABLE`` elements, one can write a loop over the +resources in the ``VOTABLE`` file:: + + for resource in votable.resources: + for table in resource.tables: + # ... do something with the table ... + pass + +However, if the nested structure of the resources is not important, +one can use `~astropy.io.vo.tree.VOTable.iter_tables` to return a flat +list of all tables:: + + for table in votable.iter_tables(): + # ... do something with the table ... + pass + +Finally, if there is expected to be only one table in the file, it +might be simplest to just use +`~astropy.io.vo.tree.VOTable.get_first_table`:: + + table = votable.get_first_table() + +Even easier, there is a convenience method to parse a VOTable file and +return the first table all in one step:: + + from astropy.io.vo.table import parse_single_table + table = parse_single_table("votable.xml") + +From a `~astropy.io.vo.tree.Table` object, one can get the data itself +in the ``array`` member variable:: + + data = table.array + +This data is a Numpy record array. The columns get their names from +both the ``ID`` and ``name`` attributes of the ``FIELD`` elements in +the ``VOTABLE`` file. For example, suppose we had a ``FIELD`` +specified as follows: + +.. code-block:: xml + + + + representing the ICRS declination of the center of the image. + + + +This column of data can be extracted from the record array using:: + + >>> table.array['dec_targ'] + array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826, + 17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136, + 17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055, + 17.1553884541, 17.15539736932, 17.15539752176, + 17.25736014763, + # ... + 17.2765703], dtype=object) + +or equivalently:: + + >>> table.array['Dec'] + array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826, + 17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136, + 17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055, + 17.1553884541, 17.15539736932, 17.15539752176, + 17.25736014763, + # ... + 17.2765703], dtype=object) + +.. _pedantic-mode: + +Pedantic mode +````````````` + +Many VOTABLE files in the wild do not conform to the VOTABLE +specification. If reading one of these files causes exceptions, you +may turn off pedantic mode in `astropy.io.vo` by passing +``pedantic=False`` to the `~astropy.io.vo.table.parse` or +`~astropy.io.vo.table.parse_single_table` functions:: + + from astropy.io.vo.table import parse + votable = parse("votable.xml", pedantic=False) + +Note, however, that it is good practice to report these errors to the +author of the application that generated the VOTABLE file to bring the +file into compliance with the specification. + +Even with ``pedantic`` turned off, many warnings may still be omitted. +These warnings are all of the type +`~astropy.io.vo.exceptions.VOTableSpecWarning` and can be turned off +using the standard Python `warnings` module. + +Building a new table from scratch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is also possible to build a new table, define some field datatypes +and populate it with data:: + + from astropy.io.vo.tree import VOTableFile, Resource, Table, Field + + # Create a new VOTable file... + votable = VOTableFile() + + # ...with one resource... + resource = Resource() + votable.resources.append(resource) + + # ... with one table + table = Table(votable) + resource.tables.append(table) + + # Define some fields + table.fields.extend([ + Field(votable, ID="filename", datatype="char"), + Field(votable, ID="matrix", datatype="double", arraysize="2x2")]) + + # Now, use those field definitions to create the numpy record arrays, with + # the given number of rows + table.create_arrays(2) + + # Now table.array can be filled with data + table.array[0] = ('test1.xml', [[1, 0], [0, 1]]) + table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]]) + + # Now write the whole thing to a file. + # Note, we have to use the top-level votable file object + votable.to_xml("new_votable.xml") + +Missing values +~~~~~~~~~~~~~~ + +Any value in the table may be "missing". `astropy.io.vo.table` stores +a parallel array in each `~astropy.io.vo.tree.Table` instance called +`~astropy.io.vo.tree.Table.mask` to keep track of missing values. +This array is ``False`` anywhere the value is missing. + +.. note:: + In the future, the ``array`` and ``mask`` members will likely be + combined into a single masked record array. There are + implementation bugs in current versions of Numpy that prevent this + at the moment. + +Datatype mappings +~~~~~~~~~~~~~~~~~ + +The datatype specified by a ``FIELD`` element is mapped to a Numpy +type according to the following table: + + ================================ ======================================================================== + VOTABLE type Numpy type + ================================ ======================================================================== + boolean b1 + -------------------------------- ------------------------------------------------------------------------ + bit b1 + -------------------------------- ------------------------------------------------------------------------ + unsignedByte u1 + -------------------------------- ------------------------------------------------------------------------ + char (*variable length*) O - In Python 2.x, a `str` object; in 3.x, a `bytes` object. + -------------------------------- ------------------------------------------------------------------------ + char (*fixed length*) S + -------------------------------- ------------------------------------------------------------------------ + unicodeChar (*variable length*) O - In Python 2.x, a `unicode` object, in utf-16; in 3.x a `str` object + -------------------------------- ------------------------------------------------------------------------ + unicodeChar (*fixed length*) U + -------------------------------- ------------------------------------------------------------------------ + short i2 + -------------------------------- ------------------------------------------------------------------------ + int i4 + -------------------------------- ------------------------------------------------------------------------ + long i8 + -------------------------------- ------------------------------------------------------------------------ + float f4 + -------------------------------- ------------------------------------------------------------------------ + double f8 + -------------------------------- ------------------------------------------------------------------------ + floatComplex c8 + -------------------------------- ------------------------------------------------------------------------ + doubleComplex c16 + ================================ ======================================================================== + +If the field is a fixed size array, the data is stored as a Numpy +fixed-size array. + +If the field is a variable size array (that is ``arraysize`` contains +a '*'), the cell will contain a Python list of Numpy values. Each +value may be either an array or scalar depending on the ``arraysize`` +specifier. + +Examining field types +~~~~~~~~~~~~~~~~~~~~~ + +To look up more information about a field in a table, one can use the +`~astropy.io.vo.tree.Table.get_field_or_param_by_id` method, which +returns the `~astropy.io.vo.tree.Field` object with the given ID. For +example:: + + >>> field = table.get_field_or_param_by_id('Dec') + >>> field.datatype + 'char' + >>> field.unit + 'deg' + +.. note:: + Field descriptors should not be mutated -- they will have no effect + on the record arrays storing the data. This shortcoming will be + addressed in a future version of `astropy.io.vo`. + +Outputting a VOTable file +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To save a VOTable file, simply call the +`~astropy.io.vo.tree.VOTableFile.to_xml` method. It accepts either a +string or unicode path, or a Python file-like object:: + + votable.to_xml('output.xml') + +There are currently two data storage formats supported by +`astropy.io.vo`. The ``TABLEDATA`` format is XML-based and stores +values as strings representing numbers. The ``BINARY`` format is more +compact, and stores numbers in base64-encoded binary. The storage +format can be set on a per-table basis using the +`~astropy.io.vo.tree.Table.format` attribute, or globally using the +`~astropy.io.vo.tree.VOTableFile.set_all_tables_format` method:: + + votable.get_first_table().format = 'binary' + votable.set_all_tables_format('binary') + votable.to_xml('binary.xml') + +Performance considerations +-------------------------- + +File reads will be moderately faster if the ``TABLE`` element includes +an nrows_ attribute. If the number of rows is not specified, the +record array must be resized repeatedly during load. + +.. _nrows: http://www.ivoa.net/Documents/REC/VOTable/VOTable-20040811.html#ToC10 diff --git a/_sources/wcs/api.txt b/_sources/wcs/api.txt new file mode 100644 index 00000000..3aaa4ec5 --- /dev/null +++ b/_sources/wcs/api.txt @@ -0,0 +1,23 @@ +.. include:: references.txt + +API Documentation +================= + +:mod:`astropy.wcs` +------------------ + +.. automodule:: astropy.wcs.wcs + +Classes +------- + +.. toctree:: + :maxdepth: 2 + + api_wcs.rst + api_wcsprm.rst + api_distortion.rst + api_sip.rst + api_units.rst + relax.rst + diff --git a/_sources/wcs/api_distortion.txt b/_sources/wcs/api_distortion.txt new file mode 100644 index 00000000..2171e91d --- /dev/null +++ b/_sources/wcs/api_distortion.txt @@ -0,0 +1,10 @@ +.. include:: references.txt + +`DistortionLookupTable` +``````````````````````` + +.. autoclass:: astropy.wcs.DistortionLookupTable + :members: + :inherited-members: + :undoc-members: + diff --git a/_sources/wcs/api_sip.txt b/_sources/wcs/api_sip.txt new file mode 100644 index 00000000..164708f4 --- /dev/null +++ b/_sources/wcs/api_sip.txt @@ -0,0 +1,10 @@ +.. include:: references.txt + +`Sip` +````` + +.. autoclass:: astropy.wcs.Sip + :members: + :inherited-members: + :undoc-members: + diff --git a/_sources/wcs/api_units.txt b/_sources/wcs/api_units.txt new file mode 100644 index 00000000..8007e295 --- /dev/null +++ b/_sources/wcs/api_units.txt @@ -0,0 +1,299 @@ +.. include:: references.txt + +`UnitConverter` +``````````````` + +.. autoclass:: astropy.wcs.UnitConverter + :members: + :inherited-members: + :undoc-members: + +.. _fits-unit: + +FITS unit specification +``````````````````````` + +Supported units +--------------- + +The following units are supported by the FITS standard: + +**SI base & supplementary units** + +====================== ============ ================= +Quantity Unit String Meaning +====================== ============ ================= +length m metre +mass kg kilogram +time s second of time +plane angle rad radian +solid angle sr steradian +temperature K kelvin +electric current A ampere +amount of substance mol mole +luminous intensity cd candela +====================== ============ ================= + +**IAU-recognized derived units** + +====================== ============ ================= ================== +Quantity Unit String Meaning Equivalence +====================== ============ ================= ================== +frequency Hz hertz s\ :sup:`-1` +energy J joule N m +power W watt J s\ :sup:`-1` +electric potential V volts J C\ :sup:`-1` +force N newton kg m s\ :sup:`-2` +pressure, stress Pa pascal N m\ :sup:`-2` +electric charge C coulomb A s +electric resistance ohm ohm (Ω) V A\ :sup:`-1` +electric conductance S siemens A V\ :sup:`-1` +electric capacitance F farad C V\ :sup:`-1` +magnetic flux Wb weber V s +magnetic flux density T tesla Wb m\ :sup:`-2` +inductance H henry Wb A\ :sup:`-1` +luminous flux lm lumen cd sr +illuminance lx lux lm m\ :sup:`-2` +====================== ============ ================= ================== + +**Additional units** + +====================== ============ ======================== ============================================ +Quantity Unit String Meaning Equivalence +====================== ============ ======================== ============================================ +mass u unified atomic mass unit 1.6605387 x 10\ :sup:`-27` kg +mass solMass solar mass 1.9891 x 10\ :sup:`30` kg +plane angle deg degree of arc 1.745533 x 10\ :sup:`-2` rad +plane angle arcsec second of arc 4.848137 x 10\ :sup:`-6` rad +plane angle arcmin minute of arc 2.90888 x 10\ :sup:`-4` rad +time min minute +time h hour +time d day 8.64 x 10\ :sup:`4` s +time yr year (Julian) 3.15576 x10\ :sup:`-7` s (365.25 d) +energy eV electron volt 1.602177 x 10\ :sup:`-19` J +energy erg erg 10\ :sup:`-7` J +energy Ry Rydberg 13.605692 eV +length angstrom angstrom 10\ :sup:`-10` m +length AU astronomical unit 1.49598 x 10\ :sup:`11` m +length lyr light year 9.460530 x 10\ :sup:`-15` m +length pc parsec 3.0857 x 10\ :sup:`-16` m +length solRad solar radius 6.9599 x 10\ :sup:`8` m +events count counts +events photon photons +flux density Jy jansky 10\ :sup:`-16` W m\ :sup:`-2` Hz\ :sup:`-1` +flux density mag (stellar) magnitude +flux density Crab 'crab' +flux density beam beam Jy/beam +flux density solLum solar luminosity +magnetic field G gauss 10\ :sup:`-4` T +area pixel (image/detector) pixel +area voxel 3-d analog of pixel +area barn barn 10\ :sup:`-28` m\ :sup:`2` +device chan (detector) channel +device byte (computer) byte +device bit (computer) bits +device adu A/D converter units +misc bin numerous applications +misc Sun wrt. sun +====================== ============ ======================== ============================================ + +Potentially unsafe translations of ``"D"``, ``"H"``, and ``"S"``, are +optional, using the *translate_units* parameter. + +.. _unit-aliases: + +Unit aliases +------------ + +When converting non-standard units to standard ones, a case-sensitive +match is required for the aliases listed below, in particular the only +recognized aliases with metric prefixes are ``"KM"``, ``"KHZ"``, +``"MHZ"``, and ``"GHZ"``. + +========== ============================================================= +Unit Recognized aliases +========== ============================================================= +Angstrom angstrom +arcmin arcmins, ARCMIN, ARCMINS +arcsec arcsecs, ARCSEC, ARCSECS +beam BEAM +byte Byte +count ct +d day, days, (D), DAY, DAYS +deg degree, degrees, DEG, DEGREE, DEGREES +GHz GHZ +h hr, (H), HR +Hz hz, HZ +kHz KHZ +Jy JY +K kelvin, kelvins, Kelvin, Kelvins, KELVIN, KELVINS +km KM +m metre, meter, metres, meters, M, METRE, METER, METRES, METERS +min MIN +MHz MHZ +Ohm ohm +Pa pascal, pascals, Pascal, Pascals, PASCAL, PASCALS +photon ph +pixel pixels, PIXEL, PIXELS, pix +rad radian, radians, RAD, RADIAN, RADIANS +s sec, second, seconds, (S), SEC, SECOND, SECONDS +V volt, volts, Volt, Volts, VOLT, VOLTS +yr year, years, YR, YEAR, YEARS +========== ============================================================= + +The aliases ``"angstrom"``, ``"ohm"``, and ``"Byte"`` for (Angstrom, +Ohm, and byte) are recognized by astropy.wcs/wcslib itself as an +unofficial extension of the standard, but they are converted to the +standard form here. + +Prefixes +-------- + +The following metric prefixes are supported: + +======= ======= =================== +Prefix String Magnitude +======= ======= =================== +yocto y 10\ :sup:`-24` +zepto z 10\ :sup:`-21` +atto a 10\ :sup:`-18` +femto f 10\ :sup:`-15` +pico p 10\ :sup:`-12` +nano n 10\ :sup:`-9` +micro u 10\ :sup:`-6` +milli m 10\ :sup:`-3` +centi c 10\ :sup:`-2` +deci d 10\ :sup:`-1` +deka da 10\ :sup:`1` +hecto h 10\ :sup:`2` +kilo k 10\ :sup:`3` +Mega M 10\ :sup:`6` +Giga G 10\ :sup:`9` +Tera T 10\ :sup:`12` +Peta P 10\ :sup:`15` +Exa E 10\ :sup:`18` +Zetta Z 10\ :sup:`21` +Yotta Y 10\ :sup:`24` +======= ======= =================== + +Table 6 of WCS Paper I lists eleven units for which metric prefixes +are allowed. However, in this implementation only prefixes greater +than unity are allowed for ``"a"`` (annum), ``"yr"`` (year), ``"pc"`` +(parsec), ``"bit"``, and ``"byte"``, and only prefixes less than unity +are allowed for ``"mag"`` (stellar magnitude). + +Metric prefix ``"P"`` (peta) is specifically forbidden for ``"a"`` +(annum) to avoid confusion with ``"Pa"`` (Pascal, not peta-annum). +Note that metric prefixes are specifically disallowed for ``"h"`` +(hour) and ``"d"`` (day) so that ``"ph"`` (photons) cannot be +interpreted as pico-hours, nor ``"cd"`` (candela) as centi-days. + +Operators +--------- + +A compound unit is considered to be formed by a series of sub-strings +of component units & mathematical operations. Each of these +sub-strings must be separated by at least one space or a mathematical +operator (``*`` or ``/``). + +Multiplication +============== + +Multiplicative units can be specified either: + +- by simply using one or more preceding spaces, e.g. ``str1 str2`` + (The recommended method). + +- by the use of a single asterisk (``*``) with optional whitespace, + e.g. ``str1 * str2``. + +Division +======== + +Units which form the denominator of a compound expression can be +specified either: + +- by using a slash (``/``) with optional whitespace, e.g. ``str1 / + str2``. If such a syntax is used, it is recommended that no space + is included between the slash and the unit string. + +- by raising a multiplicative unit to a negative power (see below). + +It should be stressed that the slash character only effects the +sub-string it immediately precedes. Thus, unless brackets are used, +subsequent sub-strings which also form part of the denominator of the +compound expression must also be preceded by a slash. For example, +``str1 /str2 str3`` is equivalent to ``str1 str3 /str2`` whilst ``str1 +/str2 /str3`` is equivalent to ``str1 /(str2 * str3)``. + +Raising to Powers +================= + +A unit string raised to the power *y* is specified: + +- by using two asterisks (``**``) followed by the index enclosed + within round brackets and with no preceding or intervening spaces, + e.g. ``str1**(y)`` or ``str1**(-y)``. + +However, if *y* is positive, then the brackets need not be included, +but a following space is recommended if additional sub-strings follow. + +Use of brackets +=============== + +Any number of pairs of round brackets (``()``) may be used within the +string for a compound unit in order to prevent ambiguities. As +described within this section, a number of rules always/often require +their use. However, it is suggested that conservative use is made of +such pairs of brackets in order to minimize the total length of +compound strings. (It should be remembered that a maximum of 68 +characters are allowed in the card image of keywords.) + +Avoidance of underflows & overflows +=================================== + +The inclusion of numerical factors within the unit string should +generally be avoided (by the use of multiples and/or submultiples of +component basic units). + +However, occasionally it may be preferable to include such factors on +the grounds of user-friendliness and/or to minimize the risk of +computer under- or overflows. In such cases, the numerical factor can +simply be considered a basic unit string. + +The following additional guidelines are suggested: + +- the numerical factor should precede any unit strings + +- only powers of 10 are used as numerical factors + +Mathematical Operations & Functions +=================================== + +A number of mathematical operations are supported. It should be noted +that the (round) brackets are mandatory in all cases in which they are +included in the table. + +=============== ================================================== +String Meaning +=============== ================================================== +``str1*str2`` Multiplication +``str1 /str2`` Division +``str1**(y)`` Raised to the power *y* +``log(str1)`` Common Logarithm (to base 10) +``ln(str1)`` Natural Logarithm +``exp(str1)`` Exponential (exp\ :sup:`str1`\ ) +``sqrt(str1)`` Square root +``sin(str1)`` Sine +``cos(str1)`` Cosine +``tan(str1)`` Tangent +``asin(str1)`` Arc Sine +``acos(str1)`` Arc Cosine +``atan(str1)`` Arc Tangent +``sinh(str1)`` Hyperbolic Sine +``cosh(str1)`` Hyperbolic Cosine +``tanh(str1)`` Hyperbolic Tangent +=============== ================================================== + +Function types ``log()``, ``ln()`` and ``exp()`` may only occur at the +start of the units specification. diff --git a/_sources/wcs/api_wcs.txt b/_sources/wcs/api_wcs.txt new file mode 100644 index 00000000..5c77a0c0 --- /dev/null +++ b/_sources/wcs/api_wcs.txt @@ -0,0 +1,14 @@ +.. include:: references.txt + +`WCS` +````` + +.. autoclass:: astropy.wcs.WCS + :members: + :inherited-members: + :undoc-members: + +functions +````````` + +.. autofunction:: astropy.wcs.find_all_wcs diff --git a/_sources/wcs/api_wcsprm.txt b/_sources/wcs/api_wcsprm.txt new file mode 100644 index 00000000..24701620 --- /dev/null +++ b/_sources/wcs/api_wcsprm.txt @@ -0,0 +1,26 @@ +.. include:: references.txt + +`Wcsprm` +```````` + +.. autoclass:: astropy.wcs.Wcsprm + :members: + :inherited-members: + :undoc-members: + +`Tabprm` +```````` + +.. autoclass:: astropy.wcs._wcs.Tabprm + :members: + :inherited-members: + :undoc-members: + +.. `Wtbarr` +.. ```````` + +.. .. autoclass:: pywcs._pywcs.Wtbarr +.. :members: +.. :inherited-members: +.. :undoc-members: + diff --git a/_sources/wcs/examples.txt b/_sources/wcs/examples.txt new file mode 100644 index 00000000..7c430094 --- /dev/null +++ b/_sources/wcs/examples.txt @@ -0,0 +1,22 @@ +Example Usage +============= + +Loading WCS information from a FITS file +---------------------------------------- + +This example loads a FITS file (supplied on the commandline) and uses +the WCS cards in its primary header to transform. + +.. literalinclude:: examples/from_file.py + :language: python + +Building a WCS structure programmatically +----------------------------------------- + +This example, rather than starting from a FITS header, sets WCS values +programmatically, uses those settings to transform some points, and then +saves those settings to a new FITS header. + +.. literalinclude:: examples/programmatic.py + :language: python + diff --git a/_sources/wcs/history.txt b/_sources/wcs/history.txt new file mode 100644 index 00000000..0caa082d --- /dev/null +++ b/_sources/wcs/history.txt @@ -0,0 +1,90 @@ +astropy.wcs History +=================== + +`astropy.wcs` began life as `pywcs`. Earlier version numbers refer to +that package. + +pywcs Version 1.11 +------------------ + +- Updated to wcslib version 4.8, which gives much more detailed error + messages. + +- Added functions get_pc() and get_cdelt(). These provide a way to + always get the canonical representation of the linear transformation + matrix, whether the header specified it in PC, CD or CROTA form. + +- Long-running process will now release the Python GIL to better + support Python multithreading. + +- The dimensions of the `~astropy.wcs.Wcsprm.cd` and + `~astropy.wcs.Wcsprm.pc` matrices were always returned as 2x2. They + now are sized according to naxis. + +- Supports Python 3.x + +- Builds on Microsoft Windows without severely patching wcslib. + +- Lots of new unit tests + +- `pywcs` will now run without `pyfits`, though the SIP and distortion + lookup table functionality is unavailable. + +- Setting `~astropy.wcs.Wcsprm.cunit` will now verify that the values + are valid unit strings. + +pywcs Version 1.10 +------------------ + +- Adds a `UnitConversion` class, which gives access to wcslib's unit + conversion functionality. Given two convertible unit strings, pywcs + can convert arrays of values from one to the other. + +- Now uses wcslib 4.7 + +- Changes to some wcs values would not always calculate secondary values. + +pywcs Version 1.9 +----------------- + +- Support binary image arrays and pixel list format WCS by presenting + a way to call wcslib's `wcsbth()` + +- Updated underlying wcslib to version 4.5, which fixes the following: + + - Fixed the interpretation of VELREF when translating + AIPS-convention spectral types. Such translation is now handled + by a new special- purpose function, spcaips(). The wcsprm + struct has been augmented with an entry for velref which is + filled by wcspih() and wcsbth(). Previously, selection by + VELREF of the radio or optical velocity convention for type VELO + was not properly handled. + +Bugs +```` + +- The `~astropy.wcs.Wcsprm.pc` member is now available with a default + raw `~astropy.wcs.Wcsprm` object. + +- Make properties that return arrays read-only, since modifying a + (mutable) array could result in secondary values not being + recomputed based on those changes. + +- `float` properties can now be set using `int` values + +pywcs Version 1.3a1 +------------------- + +Earlier versions of pywcs had two versions of every conversion method:: + + X(...) -- treats the origin of pixel coordinates at (0, 0) + X_fits(...) -- treats the origin of pixel coordinates at (1, 1) + +From version 1.3 onwards, there is only one method for each +conversion, with an 'origin' argument: + + - 0: places the origin at (0, 0), which is the C/Numpy convention. + + - 1: places the origin at (1, 1), which is the Fortran/FITS + convention. + diff --git a/_sources/wcs/index.txt b/_sources/wcs/index.txt new file mode 100644 index 00000000..5cc32c98 --- /dev/null +++ b/_sources/wcs/index.txt @@ -0,0 +1,31 @@ +.. astropy.wcs documentation master file, created by + sphinx-quickstart on Thu Sep 17 12:58:53 2009. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +========================= +astropy.wcs Documentation +========================= + +Python wrappers, SIP, Paper IV support (BSD License): + + `Michael Droettboom `_, Nadia Dencheva + + Space Telescope Science Institute + +wcslib (LGPL License): + + Mark Calabretta + + Australia Telescope National Facility, CSIRO (wcslib) + +.. automodule:: astropy.wcs + +Contents: + +.. toctree:: + :maxdepth: 2 + + examples.rst + api.rst + history.rst diff --git a/_sources/wcs/relax.txt b/_sources/wcs/relax.txt new file mode 100644 index 00000000..a958ff90 --- /dev/null +++ b/_sources/wcs/relax.txt @@ -0,0 +1,365 @@ +.. include:: references.txt + +.. _relax: + +Relax constants +``````````````` + +.. _relaxread: + +Header-reading relaxation constants +----------------------------------- + +`~astropy.wcs.WCS`, `~astropy.wcs.Wcsprm` and +`~astropy.wcs.find_all_wcs` have a *relax* argument, which may be +either `True`, `False` or an `int`. + +- If `True`, all non-standard WCS extensions recognized by the parser + will be handled. + +- If `False` (default), none of the extensions (even those in the + errata) will be handled. Non-conformant keywords will be handled in + the same way as non-WCS keywords in the header, i.e. by simply + ignoring them. + +- If an `int`, is is a bit field to provide fine-grained control over + what non-standard WCS keywords to accept. The flag bits are subject + to change in future and should be set by using the constants + beginning with ``WCSHDR_`` in the `astropy.wcs` module. + + For example, to accept ``CD00i00j`` and ``PC00i00j`` use:: + + relax = astropy.wcs.WCSHDR_CD00i00j | astropy.wcs.WCSHDR_PC00i00j + + The parser always treats ``EPOCH`` as subordinate to ``EQUINOXa`` if + both are present, and ``VSOURCEa`` is always subordinate to + ``ZSOURCEa``. + + Likewise, ``VELREF`` is subordinate to the formalism of WCS Paper + III. + +The flag bits are: + +- `WCSHDR_none`: Don't accept any extensions (not even those in the + errata). Treat non-conformant keywords in the same way as non-WCS + keywords in the header, i.e. simply ignore them. (This is + equivalent to the default behavior or passing `False`) + +- `WCSHDR_all`: Accept all extensions recognized by the parser. (This + is equivalent to passing `True`). + +- `WCSHDR_CROTAia`: Accept ``CROTAia``, ``iCROTna``, ``TCROTna`` +- `WCSHDR_EPOCHa`: Accept ``EPOCHa``. +- `WCSHDR_VELREFa`: Accept ``VELREFa``. + + The constructor always recognizes the AIPS-convention + keywords, ``CROTAn``, ``EPOCH``, and ``VELREF`` for the + primary representation ``(a = ' ')`` but alternates are + non-standard. + + The constructor accepts ``EPOCHa`` and ``VELREFa`` only if + `WCSHDR_AUXIMG` is also enabled. + +- `WCSHDR_CD00i00j`: Accept ``CD00i00j``. +- `WCSHDR_PC00i00j`: Accept ``PC00i00j``. +- `WCSHDR_PROJPn`: Accept ``PROJPn`` + + These appeared in early drafts of WCS Paper I+II (before they + were split) and are equivalent to ``CDi_ja``, ``PCi_ja``, and + ``PVi_ma`` for the primary representation ``(a = ' ')``. + ``PROJPn`` is equivalent to ``PVi_ma`` with ``m`` = ``n`` <= + 9, and is associated exclusively with the latitude axis. + +- `WCSHDR_RADECSYS`: Accept ``RADECSYS``. This appeared in early + drafts of WCS Paper I+II and was subsequently replaced by + ``RADESYSa``. The construtor accepts ``RADECSYS`` only if + `WCSHDR_AUXIMG` is also enabled. + +- `WCSHDR_VSOURCE`: Accept ``VSOURCEa`` or ``VSOUna``. This appeared + in early drafts of WCS Paper III and was subsequently dropped in + favour of ``ZSOURCEa`` and ``ZSOUna``. The constructor accepts + ``VSOURCEa`` only if `WCSHDR_AUXIMG` is also enabled. + +- `WCSHDR_DOBSn`: Allow ``DOBSn``, the column-specific analogue of + ``DATE-OBS``. By an oversight this was never formally defined in + the standard. + +- `WCSHDR_LONGKEY`: Accept long forms of the alternate binary table + and pixel list WCS keywords, i.e. with "a" non- blank. + Specifically:: + + jCRPXna TCRPXna : jCRPXn jCRPna TCRPXn TCRPna CRPIXja + - TPCn_ka : - ijPCna - TPn_ka PCi_ja + - TCDn_ka : - ijCDna - TCn_ka CDi_ja + iCDLTna TCDLTna : iCDLTn iCDEna TCDLTn TCDEna CDELTia + iCUNIna TCUNIna : iCUNIn iCUNna TCUNIn TCUNna CUNITia + iCTYPna TCTYPna : iCTYPn iCTYna TCTYPn TCTYna CTYPEia + iCRVLna TCRVLna : iCRVLn iCRVna TCRVLn TCRVna CRVALia + iPVn_ma TPVn_ma : - iVn_ma - TVn_ma PVi_ma + iPSn_ma TPSn_ma : - iSn_ma - TSn_ma PSi_ma + + where the primary and standard alternate forms together with the + image-header equivalent are shown rightwards of the colon. + + The long form of these keywords could be described as quasi- + standard. ``TPCn_ka``, ``iPVn_ma``, and ``TPVn_ma`` appeared by + mistake in the examples in WCS Paper II and subsequently these and + also ``TCDn_ka``, ``iPSn_ma`` and ``TPSn_ma`` were legitimized by + the errata to the WCS papers. + + Strictly speaking, the other long forms are non-standard and in fact + have never appeared in any draft of the WCS papers nor in the + errata. However, as natural extensions of the primary form they are + unlikely to be written with any other intention. Thus it should be + safe to accept them provided, of course, that the resulting keyword + does not exceed the 8-character limit. + + If ``WCSHDR_CNAMn`` is enabled then also accept:: + + iCNAMna TCNAMna : --- iCNAna --- TCNAna CNAMEia + iCRDEna TCRDEna : --- iCRDna --- TCRDna CRDERia + iCSYEna TCSYEna : --- iCSYna --- TCSYna CSYERia + + Note that ``CNAMEia``, ``CRDERia``, ``CSYERia``, and their variants + are not used by `astropy.wcs` but are stored as auxiliary information. + +- `WCSHDR_CNAMn`: Accept ``iCNAMn``, ``iCRDEn``, ``iCSYEn``, + ``TCNAMn``, ``TCRDEn``, and ``TCSYEn``, i.e. with ``a`` blank. + While non-standard, these are the obvious analogues of ``iCTYPn``, + ``TCTYPn``, etc. + +- `WCSHDR_AUXIMG`: Allow the image-header form of an auxiliary WCS + keyword with representation-wide scope to provide a default value + for all images. This default may be overridden by the + column-specific form of the keyword. + + For example, a keyword like ``EQUINOXa`` would apply to all image + arrays in a binary table, or all pixel list columns with alternate + representation ``a`` unless overridden by ``EQUIna``. + + Specifically the keywords are:: + + LATPOLEa for LATPna + LONPOLEa for LONPna + RESTFREQ for RFRQna + RESTFRQa for RFRQna + RESTWAVa for RWAVna + + whose keyvalues are actually used by WCSLIB, and also keywords that + provide auxiliary information that is simply stored in the wcsprm + struct:: + + EPOCH - ... (No column-specific form.) + EPOCHa - ... Only if WCSHDR_EPOCHa is set. + EQUINOXa for EQUIna + RADESYSa for RADEna + RADECSYS for RADEna ... Only if WCSHDR_RADECSYS is set. + SPECSYSa for SPECna + SSYSOBSa for SOBSna + SSYSSRCa for SSRCna + VELOSYSa for VSYSna + VELANGLa for VANGna + VELREF - ... (No column-specific form.) + VELREFa - ... Only if WCSHDR_VELREFa is set. + VSOURCEa for VSOUna ... Only if WCSHDR_VSOURCE is set. + WCSNAMEa for WCSNna ... Or TWCSna (see below). + ZSOURCEa for ZSOUna + + DATE-AVG for DAVGn + DATE-OBS for DOBSn + MJD-AVG for MJDAn + MJD-OBS for MJDOBn + OBSGEO-X for OBSGXn + OBSGEO-Y for OBSGYn + OBSGEO-Z for OBSGZn + + where the image-header keywords on the left provide default values + for the column specific keywords on the right. + + Keywords in the last group, such as ``MJD-OBS``, apply to all + alternate representations, so ``MJD-OBS`` would provide a default + value for all images in the header. + + This auxiliary inheritance mechanism applies to binary table image + arrays and pixel lists alike. Most of these keywords have no + default value, the exceptions being ``LONPOLEa`` and ``LATPOLEa``, + and also ``RADESYSa`` and ``EQUINOXa`` which provide defaults for + each other. Thus the only potential difficulty in using + `WCSHDR_AUXIMG` is that of erroneously inheriting one of these four + keywords. + + Unlike `WCSHDR_ALLIMG`, the existence of one (or all) of these + auxiliary WCS image header keywords will not by itself cause a + `~astropy.wcs.Wcsprm` object to be created for alternate + representation ``a``. This is because they do not provide + sufficient information to create a non-trivial coordinate + representation when used in conjunction with the default values of + those keywords, such as ``CTYPEia``, that are parameterized by axis + number. + +- `WCSHDR_ALLIMG`: Allow the image-header form of *all* image header + WCS keywords to provide a default value for all image arrays in a + binary table (n.b. not pixel list). This default may be overridden + by the column-specific form of the keyword. + + For example, a keyword like ``CRPIXja`` would apply to all image + arrays in a binary table with alternate representation ``a`` + unless overridden by ``jCRPna``. + + Specifically the keywords are those listed above for `WCSHDR_AUXIMG` + plus:: + + WCSAXESa for WCAXna + + which defines the coordinate dimensionality, and the following + keywords which are parameterized by axis number:: + + CRPIXja for jCRPna + PCi_ja for ijPCna + CDi_ja for ijCDna + CDELTia for iCDEna + CROTAi for iCROTn + CROTAia - ... Only if WCSHDR_CROTAia is set. + CUNITia for iCUNna + CTYPEia for iCTYna + CRVALia for iCRVna + PVi_ma for iVn_ma + PSi_ma for iSn_ma + + CNAMEia for iCNAna + CRDERia for iCRDna + CSYERia for iCSYna + + where the image-header keywords on the left provide default values + for the column specific keywords on the right. + + This full inheritance mechanism only applies to binary table image + arrays, not pixel lists, because in the latter case there is no + well-defined association between coordinate axis number and column + number. + + Note that ``CNAMEia``, ``CRDERia``, ``CSYERia``, and their variants + are not used by pywcs but are stored in the `~astropy.wcs.Wcsprm` + object as auxiliary information. + + Note especially that at least one `~astropy.wcs.Wcsprm` object will + be returned for each ``a`` found in one of the image header keywords + listed above: + + - If the image header keywords for ``a`` **are not** inherited by + a binary table, then the struct will not be associated with any + particular table column number and it is up to the user to + provide an association. + + - If the image header keywords for ``a`` **are** inherited by a + binary table image array, then those keywords are considered to + be "exhausted" and do not result in a separate + `~astropy.wcs.Wcsprm` object. + +.. _relaxwrite: + +Header-writing relaxation constants +----------------------------------- + +`~astropy.wcs.WCS.to_header` and `~astropy.wcs.WCS.to_header_string` +has a *relax* argument which may be either `True`, `False` or an +`int`. + +- If `True`, write all recognized extensions. + +- If `False` (default), none of the extensions (even those in the + errata) will be written. + +- If an `int`, is is a bit field to provide fine-grained control over + what non-standard WCS keywords to accept. The flag bits are subject + to change in future and should be set by using the constants + beginning with ``WCSHDO_`` in the `astropy.wcs` module. + +The flag bits are: + +- `WCSHDO_none`: Don't use any extensions. + +- `WCSHDO_all`: Write all recognized extensions, equivalent to setting + each flag bit. + +- `WCSHDO_safe`: Write all extensions that are considered to be safe + and recommended. + +- `WCSHDO_DOBSn`: Write ``DOBSn``, the column-specific analogue of + ``DATE-OBS`` for use in binary tables and pixel lists. WCS Paper + III introduced ``DATE-AVG`` and ``DAVGn`` but by an oversight + ``DOBSn`` (the obvious analogy) was never formally defined by the + standard. The alternative to using ``DOBSn`` is to write + ``DATE-OBS`` which applies to the whole table. This usage is + considered to be safe and is recommended. + +- `WCSHDO_TPCn_ka`: WCS Paper I defined + + - ``TPn_ka`` and ``TCn_ka`` for pixel lists + + but WCS Paper II uses ``TPCn_ka`` in one example and subsequently + the errata for the WCS papers legitimized the use of + + - ``TPCn_ka`` and ``TCDn_ka`` for pixel lists + + provided that the keyword does not exceed eight characters. This + usage is considered to be safe and is recommended because of the + non-mnemonic terseness of the shorter forms. + +- `WCSHDO_PVn_ma`: WCS Paper I defined + + - ``iVn_ma`` and ``iSn_ma`` for bintables and + - ``TVn_ma`` and ``TSn_ma`` for pixel lists + + but WCS Paper II uses ``iPVn_ma`` and ``TPVn_ma`` in the examples + and subsequently the errata for the WCS papers legitimized the use + of + + - ``iPVn_ma`` and ``iPSn_ma`` for bintables and + - ``TPVn_ma`` and ``TPSn_ma`` for pixel lists + + provided that the keyword does not exceed eight characters. This + usage is considered to be safe and is recommended because of the + non-mnemonic terseness of the shorter forms. + +- `WCSHDO_CRPXna`: For historical reasons WCS Paper I defined + + - ``jCRPXn``, ``iCDLTn``, ``iCUNIn``, ``iCTYPn``, and ``iCRVLn`` for + bintables and + - ``TCRPXn``, ``TCDLTn``, ``TCUNIn``, ``TCTYPn``, and ``TCRVLn`` for + pixel lists + + for use without an alternate version specifier. However, because + of the eight-character keyword constraint, in order to accommodate + column numbers greater than 99 WCS Paper I also defined + + - ``jCRPna``, ``iCDEna``, ``iCUNna``, ``iCTYna`` and ``iCRVna`` for + bintables and + - ``TCRPna``, ``TCDEna``, ``TCUNna``, ``TCTYna`` and ``TCRVna`` for + pixel lists + + for use with an alternate version specifier (the ``a``). Like the + ``PC``, ``CD``, ``PV``, and ``PS`` keywords there is an obvious + tendency to confuse these two forms for column numbers up to 99. + It is very unlikely that any parser would reject keywords in the + first set with a non-blank alternate version specifier so this + usage is considered to be safe and is recommended. + +- `WCSHDO_CNAMna`: WCS Papers I and III defined + + - ``iCNAna``, ``iCRDna``, and ``iCSYna`` for bintables and + - ``TCNAna``, ``TCRDna``, and ``TCSYna`` for pixel lists + + By analogy with the above, the long forms would be + + - ``iCNAMna``, ``iCRDEna``, and ``iCSYEna`` for bintables and + - ``TCNAMna``, ``TCRDEna``, and ``TCSYEna`` for pixel lists + + Note that these keywords provide auxiliary information only, none + of them are needed to compute world coordinates. This usage is + potentially unsafe and is not recommended at this time. + +- `WCSHDO_WCSNna`: Write ``WCSNna`` instead of ``TWCSna`` for pixel + lists. While the constructor treats ``WCSNna`` and ``TWCSna`` as + equivalent, other parsers may not. Consequently, this usage is + potentially unsafe and is not recommended at this time. diff --git a/_static/ajax-loader.gif b/_static/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..61faf8cab23993bd3e1560bff0668bd628642330 GIT binary patch literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nno%(3)e{?)x>&1u}A`t?OF7Z|1gRivOgXi&7IyQd1Pl zGfOfQ60;I3a`F>X^fL3(@);C=vM_KlFfb_o=k{|A33hf2a5d61U}gjg=>Rd%XaNQW zW@Cw{|b%Y*pl8F?4B9 zlo4Fz*0kZGJabY|>}Okf0}CCg{u4`zEPY^pV?j2@h+|igy0+Kz6p;@SpM4s6)XEMg z#3Y4GX>Hjlml5ftdH$4x0JGdn8~MX(U~_^d!Hi)=HU{V%g+mi8#UGbE-*ao8f#h+S z2a0-5+vc7MU$e-NhmBjLIC1v|)9+Im8x1yacJ7{^tLX(ZhYi^rpmXm0`@ku9b53aN zEXH@Y3JaztblgpxbJt{AtE1ad1Ca>{v$rwwvK(>{m~Gf_=-Ro7Fk{#;i~+{{>QtvI yb2P8Zac~?~=sRA>$6{!(^3;ZP0TPFR(G_-UDU(8Jl0?(IXu$~#4A!880|o%~Al1tN literal 0 HcmV?d00001 diff --git a/_static/basic.css b/_static/basic.css index 32630d54..f0379f35 100644 --- a/_static/basic.css +++ b/_static/basic.css @@ -79,6 +79,14 @@ div.sphinxsidebar input { font-size: 1em; } +div.sphinxsidebar input[type="text"] { + width: 170px; +} + +div.sphinxsidebar input[type="submit"] { + width: 30px; +} + img { border: 0; } @@ -236,7 +244,6 @@ img.align-center, .figure.align-center, object.align-center { } .align-center { - clear: both; text-align: center; } @@ -440,6 +447,11 @@ dl.glossary dt { font-style: oblique; } +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + /* -- code displays --------------------------------------------------------- */ pre { @@ -525,4 +537,4 @@ span.eqno { #top-link { display: none; } -} +} \ No newline at end of file diff --git a/_static/comment-bright.png b/_static/comment-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..551517b8c83b76f734ff791f847829a760ad1903 GIT binary patch literal 3500 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 A2LJ#7 literal 0 HcmV?d00001 diff --git a/_static/comment.png b/_static/comment.png new file mode 100644 index 0000000000000000000000000000000000000000..92feb52b8824c6b0f59b658b1196c61de9162a95 GIT binary patch literal 3445 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 Xn!ZpXD%P(H00000NkvXXu0mjf' + _('Hide Search Matches') + '') - .appendTo($('.sidebar .this-page-menu')); + $('') + .appendTo($('#searchbox')); } }, @@ -213,7 +213,7 @@ var Documentation = { * helper function to hide the search marks again */ hideSearchWords : function() { - $('.sidebar .this-page-menu li.highlight-link').fadeOut(300); + $('#searchbox .highlight-link').fadeOut(300); $('span.highlighted').removeClass('highlighted'); }, diff --git a/_static/down-pressed.png b/_static/down-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..6f7ad782782e4f8e39b0c6e15c7344700cdd2527 GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6U4S$Y z{B+)352QE?JR*yM+OLB!qm#z$3ZNi+iKnkC`z>}Z23@f-Ava~9&<9T!#}JFtXD=!G zGdl{fK6ro2OGiOl+hKvH6i=D3%%Y^j`yIkRn!8O>@bG)IQR0{Kf+mxNd=_WScA8u_ z3;8(7x2){m9`nt+U(Nab&1G)!{`SPVpDX$w8McLTzAJ39wprG3p4XLq$06M`%}2Yk zRPPsbES*dnYm1wkGL;iioAUB*Or2kz6(-M_r_#Me-`{mj$Z%( literal 0 HcmV?d00001 diff --git a/_static/down.png b/_static/down.png new file mode 100644 index 0000000000000000000000000000000000000000..3003a88770de3977d47a2ba69893436a2860f9e7 GIT binary patch literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6U4S$Y z{B+)352QE?JR*yM+OLB!qm#z$3ZNi+iKnkC`z>}xaV3tUZ$qnrLa#kt978NlpS`ru z&)HFc^}^>{UOEce+71h5nn>6&w6A!ieNbu1wh)UGh{8~et^#oZ1# z>T7oM=FZ~xXWnTo{qnXm$ZLOlqGswI_m2{XwVK)IJmBjW{J3-B3x@C=M{ShWt#fYS9M?R;8K$~YwlIqwf>VA7q=YKcwf2DS4Zj5inDKXXB1zl=(YO3ST6~rDq)&z z*o>z)=hxrfG-cDBW0G$!?6{M<$@{_4{m1o%Ub!naEtn|@^frU1tDnm{r-UW|!^@B8 literal 0 HcmV?d00001 diff --git a/_static/searchtools.js b/_static/searchtools.js index dae92b5e..663be4c9 100644 --- a/_static/searchtools.js +++ b/_static/searchtools.js @@ -1,6 +1,6 @@ /* - * searchtools.js - * ~~~~~~~~~~~~~~ + * searchtools.js_t + * ~~~~~~~~~~~~~~~~ * * Sphinx JavaScript utilties for the full-text search. * @@ -36,10 +36,11 @@ jQuery.makeSearchSummary = function(text, keywords, hlwords) { return rv; } + /** * Porter Stemmer */ -var PorterStemmer = function() { +var Stemmer = function() { var step2list = { ational: 'ate', @@ -300,20 +301,20 @@ var Search = { }, query : function(query) { - var stopwords = ['and', 'then', 'into', 'it', 'as', 'are', 'in', - 'if', 'for', 'no', 'there', 'their', 'was', 'is', - 'be', 'to', 'that', 'but', 'they', 'not', 'such', - 'with', 'by', 'a', 'on', 'these', 'of', 'will', - 'this', 'near', 'the', 'or', 'at']; - - // stem the searchterms and add them to the correct list - var stemmer = new PorterStemmer(); + var stopwords = ["and","then","into","it","as","are","in","if","for","no","there","their","was","is","be","to","that","but","they","not","such","with","by","a","on","these","of","will","this","near","the","or","at"]; + + // Stem the searchterms and add them to the correct list + var stemmer = new Stemmer(); var searchterms = []; var excluded = []; var hlterms = []; var tmp = query.split(/\s+/); - var object = (tmp.length == 1) ? tmp[0].toLowerCase() : null; + var objectterms = []; for (var i = 0; i < tmp.length; i++) { + if (tmp[i] != "") { + objectterms.push(tmp[i].toLowerCase()); + } + if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) || tmp[i] == "") { // skip this "word" @@ -344,9 +345,6 @@ var Search = { var filenames = this._index.filenames; var titles = this._index.titles; var terms = this._index.terms; - var objects = this._index.objects; - var objtypes = this._index.objtypes; - var objnames = this._index.objnames; var fileMap = {}; var files = null; // different result priorities @@ -357,40 +355,19 @@ var Search = { $('#search-progress').empty(); // lookup as object - if (object != null) { - for (var prefix in objects) { - for (var name in objects[prefix]) { - var fullname = (prefix ? prefix + '.' : '') + name; - if (fullname.toLowerCase().indexOf(object) > -1) { - match = objects[prefix][name]; - descr = objnames[match[1]] + _(', in ') + titles[match[0]]; - // XXX the generated anchors are not generally correct - // XXX there may be custom prefixes - result = [filenames[match[0]], fullname, '#'+fullname, descr]; - switch (match[2]) { - case 1: objectResults.push(result); break; - case 0: importantResults.push(result); break; - case 2: unimportantResults.push(result); break; - } - } - } - } + for (var i = 0; i < objectterms.length; i++) { + var others = [].concat(objectterms.slice(0,i), + objectterms.slice(i+1, objectterms.length)) + var results = this.performObjectSearch(objectterms[i], others); + // Assume first word is most likely to be the object, + // other words more likely to be in description. + // Therefore put matches for earlier words first. + // (Results are eventually used in reverse order). + objectResults = results[0].concat(objectResults); + importantResults = results[1].concat(importantResults); + unimportantResults = results[2].concat(unimportantResults); } - // sort results descending - objectResults.sort(function(a, b) { - return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); - }); - - importantResults.sort(function(a, b) { - return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); - }); - - unimportantResults.sort(function(a, b) { - return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); - }); - - // perform the search on the required terms for (var i = 0; i < searchterms.length; i++) { var word = searchterms[i]; @@ -489,7 +466,7 @@ var Search = { listItem.slideDown(5, function() { displayNextItem(); }); - }); + }, "text"); } else { // no source available, just display title Search.output.append(listItem); @@ -510,9 +487,74 @@ var Search = { } } displayNextItem(); + }, + + performObjectSearch : function(object, otherterms) { + var filenames = this._index.filenames; + var objects = this._index.objects; + var objnames = this._index.objnames; + var titles = this._index.titles; + + var importantResults = []; + var objectResults = []; + var unimportantResults = []; + + for (var prefix in objects) { + for (var name in objects[prefix]) { + var fullname = (prefix ? prefix + '.' : '') + name; + if (fullname.toLowerCase().indexOf(object) > -1) { + var match = objects[prefix][name]; + var objname = objnames[match[1]][2]; + var title = titles[match[0]]; + // If more than one term searched for, we require other words to be + // found in the name/title/description + if (otherterms.length > 0) { + var haystack = (prefix + ' ' + name + ' ' + + objname + ' ' + title).toLowerCase(); + var allfound = true; + for (var i = 0; i < otherterms.length; i++) { + if (haystack.indexOf(otherterms[i]) == -1) { + allfound = false; + break; + } + } + if (!allfound) { + continue; + } + } + var descr = objname + _(', in ') + title; + anchor = match[3]; + if (anchor == '') + anchor = fullname; + else if (anchor == '-') + anchor = objnames[match[1]][1] + '-' + fullname; + result = [filenames[match[0]], fullname, '#'+anchor, descr]; + switch (match[2]) { + case 1: objectResults.push(result); break; + case 0: importantResults.push(result); break; + case 2: unimportantResults.push(result); break; + } + } + } + } + + // sort results descending + objectResults.sort(function(a, b) { + return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); + }); + + importantResults.sort(function(a, b) { + return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); + }); + + unimportantResults.sort(function(a, b) { + return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); + }); + + return [importantResults, objectResults, unimportantResults] } } $(document).ready(function() { Search.init(); -}); +}); \ No newline at end of file diff --git a/_static/sidebar.js b/_static/sidebar.js index e9ef491c..a45e1926 100644 --- a/_static/sidebar.js +++ b/_static/sidebar.js @@ -29,6 +29,9 @@ $(function() { var sidebar = $('.sphinxsidebar'); var sidebarwrapper = $('.sphinxsidebarwrapper'); + // for some reason, the document has no sidebar; do not run into errors + if (!sidebar.length) return; + // original margin-left of the bodywrapper and width of the sidebar // with the sidebar expanded var bw_margin_expanded = bodywrapper.css('margin-left'); diff --git a/_static/underscore.js b/_static/underscore.js index 9146e086..5d899143 100644 --- a/_static/underscore.js +++ b/_static/underscore.js @@ -1,3 +1,10 @@ +// Underscore.js 0.5.5 +// (c) 2009 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the terms of the MIT license. +// Portions of Underscore are inspired by or borrowed from Prototype.js, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore/ (function(){var j=this,n=j._,i=function(a){this._wrapped=a},m=typeof StopIteration!=="undefined"?StopIteration:"__break__",b=j._=function(a){return new i(a)};if(typeof exports!=="undefined")exports._=b;var k=Array.prototype.slice,o=Array.prototype.unshift,p=Object.prototype.toString,q=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;b.VERSION="0.5.5";b.each=function(a,c,d){try{if(a.forEach)a.forEach(c,d);else if(b.isArray(a)||b.isArguments(a))for(var e=0,f=a.length;e}Z1|5lxjZvvUp)Z~;jv*GO&raT- z#pEb(tbY1#Ey4dH;Y+=wAPPMA->(Ug=YM6W%tgKtA zI`O=0Laf#Y-Y4f~`^K_)D_mvj{B=4?=t!I41ZLNlI~j_4kE*^nvF$)|>mH^X%(>6c z8XimFvvIAOoRJf!>6jzIa5w(S%7lxdZ{*qJxhxpj6S#UB!oTuMX^Z^6%)IfT_v-!3 z=PEaM_iSh6_`s$!$NaEMP6gw}xaYa3wv(2tRq1T=+jv*GO&raUx z$K)u`w*Tuor>1}ySNCesuPuG-8#b%jw0sn-5fpk^!623V@1GR6+<`78?&Rhov&jx6 z*R7KttIVGJ=8yH~|HhI(uB&NIpYp$LXT}M`Z)D=?%dxpN#UiKM#HZsJK4DUm#Y3a5!dMF634rTxz_l%hvABb z(=Pc<$5*Xj@eE$@$89c0_oa>Y5;`&;INvn7C-9xQbH92`*_(~*lcvS}m5Z2pGdgKc z>;tJC%=6B^QS*>ubT+QGD)v`9z&&Y`y-xHu*7vDC$|9@xfdY)d)78&qol`;+01iQm A<^TWy literal 0 HcmV?d00001 diff --git a/_static/websupport.js b/_static/websupport.js new file mode 100644 index 00000000..e9bd1b85 --- /dev/null +++ b/_static/websupport.js @@ -0,0 +1,808 @@ +/* + * websupport.js + * ~~~~~~~~~~~~~ + * + * sphinx.websupport utilties for all documentation. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +(function($) { + $.fn.autogrow = function() { + return this.each(function() { + var textarea = this; + + $.fn.autogrow.resize(textarea); + + $(textarea) + .focus(function() { + textarea.interval = setInterval(function() { + $.fn.autogrow.resize(textarea); + }, 500); + }) + .blur(function() { + clearInterval(textarea.interval); + }); + }); + }; + + $.fn.autogrow.resize = function(textarea) { + var lineHeight = parseInt($(textarea).css('line-height'), 10); + var lines = textarea.value.split('\n'); + var columns = textarea.cols; + var lineCount = 0; + $.each(lines, function() { + lineCount += Math.ceil(this.length / columns) || 1; + }); + var height = lineHeight * (lineCount + 1); + $(textarea).css('height', height); + }; +})(jQuery); + +(function($) { + var comp, by; + + function init() { + initEvents(); + initComparator(); + } + + function initEvents() { + $('a.comment-close').live("click", function(event) { + event.preventDefault(); + hide($(this).attr('id').substring(2)); + }); + $('a.vote').live("click", function(event) { + event.preventDefault(); + handleVote($(this)); + }); + $('a.reply').live("click", function(event) { + event.preventDefault(); + openReply($(this).attr('id').substring(2)); + }); + $('a.close-reply').live("click", function(event) { + event.preventDefault(); + closeReply($(this).attr('id').substring(2)); + }); + $('a.sort-option').live("click", function(event) { + event.preventDefault(); + handleReSort($(this)); + }); + $('a.show-proposal').live("click", function(event) { + event.preventDefault(); + showProposal($(this).attr('id').substring(2)); + }); + $('a.hide-proposal').live("click", function(event) { + event.preventDefault(); + hideProposal($(this).attr('id').substring(2)); + }); + $('a.show-propose-change').live("click", function(event) { + event.preventDefault(); + showProposeChange($(this).attr('id').substring(2)); + }); + $('a.hide-propose-change').live("click", function(event) { + event.preventDefault(); + hideProposeChange($(this).attr('id').substring(2)); + }); + $('a.accept-comment').live("click", function(event) { + event.preventDefault(); + acceptComment($(this).attr('id').substring(2)); + }); + $('a.delete-comment').live("click", function(event) { + event.preventDefault(); + deleteComment($(this).attr('id').substring(2)); + }); + $('a.comment-markup').live("click", function(event) { + event.preventDefault(); + toggleCommentMarkupBox($(this).attr('id').substring(2)); + }); + } + + /** + * Set comp, which is a comparator function used for sorting and + * inserting comments into the list. + */ + function setComparator() { + // If the first three letters are "asc", sort in ascending order + // and remove the prefix. + if (by.substring(0,3) == 'asc') { + var i = by.substring(3); + comp = function(a, b) { return a[i] - b[i]; }; + } else { + // Otherwise sort in descending order. + comp = function(a, b) { return b[by] - a[by]; }; + } + + // Reset link styles and format the selected sort option. + $('a.sel').attr('href', '#').removeClass('sel'); + $('a.by' + by).removeAttr('href').addClass('sel'); + } + + /** + * Create a comp function. If the user has preferences stored in + * the sortBy cookie, use those, otherwise use the default. + */ + function initComparator() { + by = 'rating'; // Default to sort by rating. + // If the sortBy cookie is set, use that instead. + if (document.cookie.length > 0) { + var start = document.cookie.indexOf('sortBy='); + if (start != -1) { + start = start + 7; + var end = document.cookie.indexOf(";", start); + if (end == -1) { + end = document.cookie.length; + by = unescape(document.cookie.substring(start, end)); + } + } + } + setComparator(); + } + + /** + * Show a comment div. + */ + function show(id) { + $('#ao' + id).hide(); + $('#ah' + id).show(); + var context = $.extend({id: id}, opts); + var popup = $(renderTemplate(popupTemplate, context)).hide(); + popup.find('textarea[name="proposal"]').hide(); + popup.find('a.by' + by).addClass('sel'); + var form = popup.find('#cf' + id); + form.submit(function(event) { + event.preventDefault(); + addComment(form); + }); + $('#s' + id).after(popup); + popup.slideDown('fast', function() { + getComments(id); + }); + } + + /** + * Hide a comment div. + */ + function hide(id) { + $('#ah' + id).hide(); + $('#ao' + id).show(); + var div = $('#sc' + id); + div.slideUp('fast', function() { + div.remove(); + }); + } + + /** + * Perform an ajax request to get comments for a node + * and insert the comments into the comments tree. + */ + function getComments(id) { + $.ajax({ + type: 'GET', + url: opts.getCommentsURL, + data: {node: id}, + success: function(data, textStatus, request) { + var ul = $('#cl' + id); + var speed = 100; + $('#cf' + id) + .find('textarea[name="proposal"]') + .data('source', data.source); + + if (data.comments.length === 0) { + ul.html('
  • No comments yet.
  • '); + ul.data('empty', true); + } else { + // If there are comments, sort them and put them in the list. + var comments = sortComments(data.comments); + speed = data.comments.length * 100; + appendComments(comments, ul); + ul.data('empty', false); + } + $('#cn' + id).slideUp(speed + 200); + ul.slideDown(speed); + }, + error: function(request, textStatus, error) { + showError('Oops, there was a problem retrieving the comments.'); + }, + dataType: 'json' + }); + } + + /** + * Add a comment via ajax and insert the comment into the comment tree. + */ + function addComment(form) { + var node_id = form.find('input[name="node"]').val(); + var parent_id = form.find('input[name="parent"]').val(); + var text = form.find('textarea[name="comment"]').val(); + var proposal = form.find('textarea[name="proposal"]').val(); + + if (text == '') { + showError('Please enter a comment.'); + return; + } + + // Disable the form that is being submitted. + form.find('textarea,input').attr('disabled', 'disabled'); + + // Send the comment to the server. + $.ajax({ + type: "POST", + url: opts.addCommentURL, + dataType: 'json', + data: { + node: node_id, + parent: parent_id, + text: text, + proposal: proposal + }, + success: function(data, textStatus, error) { + // Reset the form. + if (node_id) { + hideProposeChange(node_id); + } + form.find('textarea') + .val('') + .add(form.find('input')) + .removeAttr('disabled'); + var ul = $('#cl' + (node_id || parent_id)); + if (ul.data('empty')) { + $(ul).empty(); + ul.data('empty', false); + } + insertComment(data.comment); + var ao = $('#ao' + node_id); + ao.find('img').attr({'src': opts.commentBrightImage}); + if (node_id) { + // if this was a "root" comment, remove the commenting box + // (the user can get it back by reopening the comment popup) + $('#ca' + node_id).slideUp(); + } + }, + error: function(request, textStatus, error) { + form.find('textarea,input').removeAttr('disabled'); + showError('Oops, there was a problem adding the comment.'); + } + }); + } + + /** + * Recursively append comments to the main comment list and children + * lists, creating the comment tree. + */ + function appendComments(comments, ul) { + $.each(comments, function() { + var div = createCommentDiv(this); + ul.append($(document.createElement('li')).html(div)); + appendComments(this.children, div.find('ul.comment-children')); + // To avoid stagnating data, don't store the comments children in data. + this.children = null; + div.data('comment', this); + }); + } + + /** + * After adding a new comment, it must be inserted in the correct + * location in the comment tree. + */ + function insertComment(comment) { + var div = createCommentDiv(comment); + + // To avoid stagnating data, don't store the comments children in data. + comment.children = null; + div.data('comment', comment); + + var ul = $('#cl' + (comment.node || comment.parent)); + var siblings = getChildren(ul); + + var li = $(document.createElement('li')); + li.hide(); + + // Determine where in the parents children list to insert this comment. + for(i=0; i < siblings.length; i++) { + if (comp(comment, siblings[i]) <= 0) { + $('#cd' + siblings[i].id) + .parent() + .before(li.html(div)); + li.slideDown('fast'); + return; + } + } + + // If we get here, this comment rates lower than all the others, + // or it is the only comment in the list. + ul.append(li.html(div)); + li.slideDown('fast'); + } + + function acceptComment(id) { + $.ajax({ + type: 'POST', + url: opts.acceptCommentURL, + data: {id: id}, + success: function(data, textStatus, request) { + $('#cm' + id).fadeOut('fast'); + $('#cd' + id).removeClass('moderate'); + }, + error: function(request, textStatus, error) { + showError('Oops, there was a problem accepting the comment.'); + } + }); + } + + function deleteComment(id) { + $.ajax({ + type: 'POST', + url: opts.deleteCommentURL, + data: {id: id}, + success: function(data, textStatus, request) { + var div = $('#cd' + id); + if (data == 'delete') { + // Moderator mode: remove the comment and all children immediately + div.slideUp('fast', function() { + div.remove(); + }); + return; + } + // User mode: only mark the comment as deleted + div + .find('span.user-id:first') + .text('[deleted]').end() + .find('div.comment-text:first') + .text('[deleted]').end() + .find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id + + ', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id) + .remove(); + var comment = div.data('comment'); + comment.username = '[deleted]'; + comment.text = '[deleted]'; + div.data('comment', comment); + }, + error: function(request, textStatus, error) { + showError('Oops, there was a problem deleting the comment.'); + } + }); + } + + function showProposal(id) { + $('#sp' + id).hide(); + $('#hp' + id).show(); + $('#pr' + id).slideDown('fast'); + } + + function hideProposal(id) { + $('#hp' + id).hide(); + $('#sp' + id).show(); + $('#pr' + id).slideUp('fast'); + } + + function showProposeChange(id) { + $('#pc' + id).hide(); + $('#hc' + id).show(); + var textarea = $('#pt' + id); + textarea.val(textarea.data('source')); + $.fn.autogrow.resize(textarea[0]); + textarea.slideDown('fast'); + } + + function hideProposeChange(id) { + $('#hc' + id).hide(); + $('#pc' + id).show(); + var textarea = $('#pt' + id); + textarea.val('').removeAttr('disabled'); + textarea.slideUp('fast'); + } + + function toggleCommentMarkupBox(id) { + $('#mb' + id).toggle(); + } + + /** Handle when the user clicks on a sort by link. */ + function handleReSort(link) { + var classes = link.attr('class').split(/\s+/); + for (var i=0; iThank you! Your comment will show up ' + + 'once it is has been approved by a moderator.'); + } + // Prettify the comment rating. + comment.pretty_rating = comment.rating + ' point' + + (comment.rating == 1 ? '' : 's'); + // Make a class (for displaying not yet moderated comments differently) + comment.css_class = comment.displayed ? '' : ' moderate'; + // Create a div for this comment. + var context = $.extend({}, opts, comment); + var div = $(renderTemplate(commentTemplate, context)); + + // If the user has voted on this comment, highlight the correct arrow. + if (comment.vote) { + var direction = (comment.vote == 1) ? 'u' : 'd'; + div.find('#' + direction + 'v' + comment.id).hide(); + div.find('#' + direction + 'u' + comment.id).show(); + } + + if (opts.moderator || comment.text != '[deleted]') { + div.find('a.reply').show(); + if (comment.proposal_diff) + div.find('#sp' + comment.id).show(); + if (opts.moderator && !comment.displayed) + div.find('#cm' + comment.id).show(); + if (opts.moderator || (opts.username == comment.username)) + div.find('#dc' + comment.id).show(); + } + return div; + } + + /** + * A simple template renderer. Placeholders such as <%id%> are replaced + * by context['id'] with items being escaped. Placeholders such as <#id#> + * are not escaped. + */ + function renderTemplate(template, context) { + var esc = $(document.createElement('div')); + + function handle(ph, escape) { + var cur = context; + $.each(ph.split('.'), function() { + cur = cur[this]; + }); + return escape ? esc.text(cur || "").html() : cur; + } + + return template.replace(/<([%#])([\w\.]*)\1>/g, function() { + return handle(arguments[2], arguments[1] == '%' ? true : false); + }); + } + + /** Flash an error message briefly. */ + function showError(message) { + $(document.createElement('div')).attr({'class': 'popup-error'}) + .append($(document.createElement('div')) + .attr({'class': 'error-message'}).text(message)) + .appendTo('body') + .fadeIn("slow") + .delay(2000) + .fadeOut("slow"); + } + + /** Add a link the user uses to open the comments popup. */ + $.fn.comment = function() { + return this.each(function() { + var id = $(this).attr('id').substring(1); + var count = COMMENT_METADATA[id]; + var title = count + ' comment' + (count == 1 ? '' : 's'); + var image = count > 0 ? opts.commentBrightImage : opts.commentImage; + var addcls = count == 0 ? ' nocomment' : ''; + $(this) + .append( + $(document.createElement('a')).attr({ + href: '#', + 'class': 'sphinx-comment-open' + addcls, + id: 'ao' + id + }) + .append($(document.createElement('img')).attr({ + src: image, + alt: 'comment', + title: title + })) + .click(function(event) { + event.preventDefault(); + show($(this).attr('id').substring(2)); + }) + ) + .append( + $(document.createElement('a')).attr({ + href: '#', + 'class': 'sphinx-comment-close hidden', + id: 'ah' + id + }) + .append($(document.createElement('img')).attr({ + src: opts.closeCommentImage, + alt: 'close', + title: 'close' + })) + .click(function(event) { + event.preventDefault(); + hide($(this).attr('id').substring(2)); + }) + ); + }); + }; + + var opts = { + processVoteURL: '/_process_vote', + addCommentURL: '/_add_comment', + getCommentsURL: '/_get_comments', + acceptCommentURL: '/_accept_comment', + deleteCommentURL: '/_delete_comment', + commentImage: '/static/_static/comment.png', + closeCommentImage: '/static/_static/comment-close.png', + loadingImage: '/static/_static/ajax-loader.gif', + commentBrightImage: '/static/_static/comment-bright.png', + upArrow: '/static/_static/up.png', + downArrow: '/static/_static/down.png', + upArrowPressed: '/static/_static/up-pressed.png', + downArrowPressed: '/static/_static/down-pressed.png', + voting: false, + moderator: false + }; + + if (typeof COMMENT_OPTIONS != "undefined") { + opts = jQuery.extend(opts, COMMENT_OPTIONS); + } + + var popupTemplate = '\ +
    \ +

    \ + Sort by:\ + best rated\ + newest\ + oldest\ +

    \ +
    Comments
    \ +
    \ + loading comments...
    \ +
      \ +
      \ +

      Add a comment\ + (markup):

      \ +
      \ + reStructured text markup: *emph*, **strong**, \ + ``code``, \ + code blocks: :: and an indented block after blank line
      \ +
      \ + \ +

      \ + \ + Propose a change ▹\ + \ + \ + Propose a change ▿\ + \ +

      \ + \ + \ + \ + \ +
      \ +
      \ +
      '; + + var commentTemplate = '\ +
      \ +
      \ +
      \ + \ + \ + \ + \ + \ + \ +
      \ +
      \ + \ + \ + \ + \ + \ + \ +
      \ +
      \ +
      \ +

      \ + <%username%>\ + <%pretty_rating%>\ + <%time.delta%>\ +

      \ +
      <#text#>
      \ +

      \ + \ + reply ▿\ + proposal ▹\ + proposal ▿\ + \ + \ +

      \ +
      \
      +<#proposal_diff#>\
      +        
      \ +
        \ +
        \ +
        \ +
        \ + '; + + var replyTemplate = '\ +
      • \ +
        \ +
        \ + \ + \ + \ + \ + \ +
        \ +
        \ +
      • '; + + $(document).ready(function() { + init(); + }); +})(jQuery); + +$(document).ready(function() { + // add comment anchors for all paragraphs that are commentable + $('.sphinx-has-comment').comment(); + + // highlight search words in search results + $("div.context").each(function() { + var params = $.getQueryParameters(); + var terms = (params.q) ? params.q[0].split(/\s+/) : []; + var result = $(this); + $.each(terms, function() { + result.highlightText(this.toLowerCase(), 'highlighted'); + }); + }); + + // directly open comment window if requested + var anchor = document.location.hash; + if (anchor.substring(0, 9) == '#comment-') { + $('#ao' + anchor.substring(9)).click(); + document.location.hash = '#s' + anchor.substring(9); + } +}); diff --git a/configs.html b/configs.html new file mode 100644 index 00000000..46c72dc3 --- /dev/null +++ b/configs.html @@ -0,0 +1,938 @@ + + + + + + + + + + Configuration system Documentation — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Configuration system Documentation

        +

        The astropy configuration system is designed to give users control of various +parameters used in astropy or affiliated packages without delving into the +source code to make those changes.

        +
        +

        For Users

        +

        To see the configuration options, look for your astropy configuration file. +You can find it by doing:

        +
        from astropy.config import get_config_dir
        +
        +print get_config_dir()
        +
        +
        +

        And you should see the location of your configuration directory. The standard +scheme generally puts your configuration directory in $HOME/.astropy/config, +but if you’ve set the environment variable XDG_CONFIG_HOME and the +$XDG_CONFIG_HOME/astropy directory exists, it will instead be there.

        +

        Once you’ve found the configuration file, open it with your favorite editor. +It should have all of the sections you might want, with descriptions and the +type of the value that is accepted. Feel free to edit this as you wish, and +any of these changes will be reflected when you next start Astropy. Or, if you +want to see your changes immediately in your current Astropy session, just do:

        +
        from astropy.config import reload_config()
        +
        +reload_config()
        +
        +
        +

        Warning

        +

        The above is not true yet, because the setup doesn’t automatically +populate the configuration files. Hopefully it will be true soon, though. +The astropy.config.configs._generate_all_config_items() function will +already do this, basically, but there has to be some thought about how to +make driver scripts that actually do this for each user, and coordinate +when they get run so that everything is already built.

        +
        +
        +
        +

        For Developers

        +

        The Reference guide below describes the full interface - this is a summary of +typical practices. The most common way to use the configuration system is as +follows:

        +
        """ This is the docstring at the beginning of a module
        +"""
        +from astropy.config import ConfigurationItem
        +
        +SOME_OPTION = ConfigurationItem('some_opt',1,'A description.')
        +ANOTHER_OPTION = ConfigurationItem('anno_opt','a string val',
        +                        'A longer description of what this does.')
        +
        +... implementation ...
        +def some_func():
        +    #to get the value of these options, I might do:
        +    something = SOME_OPTION()+2
        +    return ANOTHER_OPTION()+' Also, I added text.'
        +
        +
        +

        It is highly recommended that any configuration items be placed at the top of a +module like this, as they can then be easily found when viewing the source code +and the automated tools to generate the default configuration files can also +locate these items.

        +
        +
        +

        Reference/API

        +

        Below are the reference documentation for the three main config sub-packages: +astropy.config.paths, astropy.config.configs, and astropy.config.data. +Note that all the public classes and functions in these sub-packages are +imported into astropy.config, so the recommended usage is simply +from astropy.config import foo.

        +
        +

        astropy.config.paths

        +

        This module contains functions to determine where configuration and +data/cache files used by Astropy should be placed.

        +
        +
        +astropy.config.paths.get_config_dir(create=True)[source]
        +

        Determines the Astropy configuration directory name and creates the +directory if it doesn’t exist.

        +

        This directory is typically $HOME/.astropy/config, but if the +XDG_CONFIG_HOME environment variable is set and the +$XDG_CONFIG_HOME/astropy directory exists, it will be that directory. +If neither exists, the former will be created and symlinked to the latter.

        + +++ + + + +
        Returns :

        configdir : str

        +
        +

        The absolute path to the configuration directory.

        +
        +
        +
        + +
        +
        +astropy.config.paths.get_cache_dir()[source]
        +

        Determines the Astropy cache directory name and creates the directory if it +doesn’t exist.

        +

        This directory is typically $HOME/.astropy/cache, but if the +XDG_CACHE_HOME environment variable is set and the +$XDG_CACHE_HOME/astropy directory exists, it will be that directory. +If neither exists, the former will be created and symlinked to the latter.

        + +++ + + + +
        Returns :

        cachedir : str

        +
        +

        The absolute path to the cache directory.

        +
        +
        +
        + +
        +
        +

        astropy.config.configs

        +

        This module contains classes and functions to standardize access to +configuration files for Astropy and affiliated packages.

        +
        +

        Note

        +

        The configuration system makes use of the ‘configobj’ package, which stores +configuration in a text format like that used in the standard library +ConfigParser. More information and documentation for configobj can be +found at http://www.voidspace.org.uk/python/configobj.html.

        +
        +
        +
        +class astropy.config.configs.ConfigurationItem(name, defaultvalue='', description=None, cfgtype=None, module=None)[source]
        +

        A setting and associated value stored in the astropy configuration +files.

        +

        These objects are typically defined at the top of astropy subpackages +or affiliated packages, and store values or option settings that can be +modified by the user to

        + +++ + + + + + +
        Parameters :

        name : str

        +
        +

        The (case-sensitive) name of this parameter, as shown in the +configuration file.

        +
        +

        defaultvalue :

        +
        +

        The default value for this item. If this is a list of strings, this item +will be interpreted as an ‘options’ value - this item must be one of +those values, and the first in the list will be taken as the default +value.

        +
        +

        description : str or None

        +
        +

        A description of this item (will be shown as a comment in the +configuration file)

        +
        +

        cfgtype : str or None

        +
        +

        A type specifier like those used as the values of a particular key in +a configspec file of configobj. If None, the type will be inferred +from the default value.

        +
        +

        module : str or None

        +
        +

        The full module name that this item is associated with. The first +element (e.g. ‘astropy’ if this is ‘astropy.config.configs’) will be +used to determine the name of the configuration file, while the +remaining items determine the section. If None, the package will be +inferred from the package within whiich this object’s initializer is +called.

        +
        +
        Raises :

        RuntimeError :

        +
        +

        If module is None, but the module this item is created from cannot +be determined.

        +
        +
        +

        Examples

        +

        The following example will create an item ‘cfgoption = 42’ in the +‘[configs]’ section of astropy.cfg (located in the directory that +astropy.config.paths.get_config_dir returns), or if the option is already +set, it will take the value from the configuration file:

        +
        from astropy.config import ConfigurationItem
        +
        +CFG_OPTION = ConfigurationItem('cfgoption',42,module='astropy.configs')
        +
        +
        +

        If called as CFG_OPTION(), this will return the value 42, or some +other integer if the astropy.cfg file specifies a different value.

        +

        If this were in the astropy/configs/__init__.py file, the module +option would not be necessary, as it would automatically detect the correct +module.

        +
        +
        +reload()[source]
        +

        Reloads the value of this ConfigurationItem from the relevant +configuration file.

        + +++ + + + +
        Returns :

        val :

        +
        +

        The new value loaded from the configuration file.

        +
        +
        +
        + +
        +
        +save(value=None)[source]
        +

        Writes a value for this ConfigurationItem to the relevant +configuration file.

        +

        This also writes updated versions of the comments that give the +description and type information.

        +
        +

        Note

        +

        This only saves the value of this particular ConfigurationItem. +To save all configuration settings for this package at once, see +save_config.

        +
        + +++ + + + + + +
        Parameters :

        value :

        +
        +

        Save this value to the configuration file. If None, the current +value of this ConfigurationItem will be saved.

        +
        +
        Raises :

        TypeError :

        +
        +

        If the provided value is not valid for this ConfigurationItem.

        +
        +
        +
        + +
        +
        +set(value)[source]
        +

        Sets the current value of this ConfigurationItem.

        +

        This also updates the comments that give the description and type +information.

        +
        +

        Note

        +

        This does not save the value of this ConfigurationItem to the +configuration file. To do that, use ConfigurationItem.save or +save_config.

        +
        + +++ + + + + + +
        Parameters :

        value :

        +
        +

        The value this item should be set to.

        +
        +
        Raises :

        TypeError :

        +
        +

        If the provided value is not valid for this ConfigurationItem.

        +
        +
        +
        + +
        + +
        +
        +exception astropy.config.configs.InvalidConfigurationItemWarning[source]
        +

        A Warning that is issued when the configuration value specified in the +astropy configuration file does not match the type expected for that +configuration value.

        +
        + +
        +
        +astropy.config.configs.get_config(packageormod=None, reload=False)[source]
        +

        Gets the configuration object or section associated with a particular +package or module.

        + +++ + + + + + + + +
        Parameters :

        packageormod : str or None

        +
        +

        The package for which to retrieve the configuration object. If a string, +it must be a valid package name, or if None, the package from which this +function is called will be used.

        +
        +
        Returns :

        cfgobj : configobj.ConfigObj or configobj.Section

        +
        +

        If the requested package is a base package, this will be the +configobj.ConfigObj for that package, or if it is a subpackage or +module, it will return the relevant configobj.Section object.

        +
        +
        Raises :

        RuntimeError :

        +
        +

        If package is None, but the package this item is created from cannot +be determined.

        +
        +
        +
        + +
        +
        +astropy.config.configs.save_config(packageormod=None)[source]
        +

        Saves all configuration settings to the configuration file for the +root package of the requested package/module.

        +

        This overwrites any configuration items that have been changed in +ConfigurationItem objects that are based on the configuration file +determined by the root package of packageormod (e.g. ‘astropy.cfg’ for +the ‘astropy.config.configs’ module).

        +
        +

        Note

        +

        To save only a single item, use the ConfigurationItem.save method - +this will save all options in the current session that may have been +changed.

        +
        + +++ + + + +
        Parameters :

        packageormod : str or None

        +
        +

        The package or module name - see get_config for details.

        +
        +
        +
        + +
        +
        +astropy.config.configs.reload_config(packageormod=None)[source]
        +

        Reloads configuration settings from a configuration file for the root +package of the requested package/module.

        +

        This overwrites any changes that may have been made in ConfigurationItem +objects. This applies for any items that are based on this file, which is +determined by the root package of packageormod (e.g. ‘astropy.cfg’ for +the ‘astropy.config.configs’ module).

        + +++ + + + +
        Parameters :

        packageormod : str or None

        +
        +

        The package or module name - see get_config for details.

        +
        +
        +
        + +
        +
        +

        astropy.config.data

        +

        This module contains helper functions for accessing, downloading, and +caching data files.

        +
        +
        +astropy.config.data.get_data_fileobj(dataname, cache=True)[source]
        +

        Retrieves a data file from the standard locations and provides the file as +a file-like object.

        + +++ + + + + + + + +
        Parameters :

        dataname : str

        +
        +

        Name/location of the desired data file. One of the following:

        +
        +
          +
        • The name of a data file included in the source +distribution. The path is relative to the module +calling this function. For example, if calling from +astropy.pkname, use 'data/file.dat' to get the +file in astropy/pkgname/data/file.dat. Double-dots +can be used to go up a level. In the same example, use +'../data/file.dat' to get astropy/data/file.dat.
        • +
        • If a matching local file does not exist, the Astropy +data server will be queried for the file.
        • +
        • A hash like that produced by compute_hash can be +requested, prefixed by ‘hash/’ +e.g. ‘hash/395dd6493cc584df1e78b474fb150840’. The hash +will first be searched for locally, and if not found, +the Astropy data server will be queried.
        • +
        • A URL to some other file.
        • +
        +
        +
        +

        cache : bool

        +
        +

        If True, the file will be downloaded and saved locally or the +already-cached local copy will be accessed. If False, the file-like +object will directly access the resource (e.g. if a remote URL is +accessed, an object like that from urllib2.urlopen is returned).

        +
        +
        Returns :

        fileobj : file-like

        +
        +

        An object with the contents of the data file available via read(). +Can be used as part of a with statement, automatically closing +itself after the with block.

        +
        +
        Raises :

        urllib2.URLError :

        +
        +

        If a remote file cannot be found.

        +
        +

        IOError :

        +
        +

        If problems occur writing or reading a local file.

        +
        +
        +
        +

        See also

        +
        +
        get_data_contents
        +
        returns the contents of a file or url as a bytes object
        +
        get_data_filename
        +
        returns a local name for a file containing the data
        +
        +
        +

        Examples

        +

        This will retrieve a data file and its contents for the astropy.wcs +tests:

        +
        from astropy.config import get_data_fileobj
        +
        +with get_data_fileobj('data/3d_cd.hdr') as fobj:
        +    fcontents = fobj.read()
        +
        +
        +

        This downloads a data file and its contents from a specified URL, and does +not cache it remotely:

        +
        from astropy.config import get_data_fileobj
        +
        +vegaurl = 'ftp://ftp.stsci.edu/cdbs/grid/k93models/standards/vega.fits'
        +with get_data_fileobj(vegaurl,False) as fobj:
        +    fcontents = fobj.read()
        +
        +
        +
        + +
        +
        +astropy.config.data.get_data_filename(dataname)[source]
        +

        Retrieves a data file from the standard locations and provides the local +name of the file.

        +

        This function is similar to get_data_fileobj but returns the file name +instead of a readable file-like object. This means that this function must +always cache remote files locally, unlike get_data_fileobj.

        + +++ + + + + + + + +
        Parameters :

        dataname : str

        +
        +

        Name/location of the desired data file. One of the following:

        +
        +
          +
        • The name of a data file included in the source +distribution. The path is relative to the module +calling this function. For example, if calling from +astropy.pkname, use 'data/file.dat' to get the +file in astropy/pkgname/data/file.dat. Double-dots +can be used to go up a level. In the same example, use +'../data/file.dat' to get astropy/data/file.dat.
        • +
        • If a matching local file does not exist, the Astropy +data server will be queried for the file.
        • +
        • A hash like that produced by compute_hash can be +requested, prefixed by ‘hash/’ +e.g. ‘hash/395dd6493cc584df1e78b474fb150840’. The hash +will first be searched for locally, and if not found, +the Astropy data server will be queried.
        • +
        • A URL to some other file.
        • +
        +
        +
        +
        Returns :

        filename : str

        +
        +

        A file path on the local file system corresponding to the data +requested in dataname.

        +
        +
        Raises :

        urllib2.URLError :

        +
        +

        If a remote file cannot be found.

        +
        +

        IOError :

        +
        +

        If problems occur writing or reading a local file.

        +
        +
        +
        +

        See also

        +
        +
        get_data_contents
        +
        returns the contents of a file or url as a bytes object
        +
        get_data_fileobj
        +
        returns a file-like object with the data
        +
        +
        +

        Examples

        +

        This will retrieve the contents of the data file for the astropy.wcs +tests:

        +
        from astropy.config import get_data_filename
        +
        +fn = get_data_filename('data/3d_cd.hdr')
        +with open(fn) as f:
        +    fcontents = f.read()
        +
        +
        +

        This retrieves a data file by hash either locally or from the astropy data +server:

        +
        from astropy.config import get_data_filename
        +
        +fn = get_data_filename('hash/da34a7b07ef153eede67387bf950bb32')
        +with open(fn) as f:
        +    fcontents = f.read()
        +
        +
        +
        + +
        +
        +astropy.config.data.get_data_contents(dataname, cache=True)[source]
        +

        Retrieves a data file from the standard locations and returns its +contents as a bytes object.

        + +++ + + + + + + + +
        Parameters :

        dataname : str

        +
        +

        Name/location of the desired data file. One of the following:

        +
        +
          +
        • The name of a data file included in the source +distribution. The path is relative to the module +calling this function. For example, if calling from +astropy.pkname, use 'data/file.dat' to get the +file in astropy/pkgname/data/file.dat. Double-dots +can be used to go up a level. In the same example, use +'../data/file.dat' to get astropy/data/file.dat.
        • +
        • If a matching local file does not exist, the Astropy +data server will be queried for the file.
        • +
        • A hash like that produced by compute_hash can be +requested, prefixed by ‘hash/’ +e.g. ‘hash/395dd6493cc584df1e78b474fb150840’. The hash +will first be searched for locally, and if not found, +the Astropy data server will be queried.
        • +
        • A URL to some other file.
        • +
        +
        +
        +

        cache : bool

        +
        +

        If True, the file will be downloaded and saved locally or the +already-cached local copy will be accessed. If False, the file-like +object will directly access the resource (e.g. if a remote URL is +accessed, an object like that from urllib2.urlopen is returned).

        +
        +
        Returns :

        contents : bytes

        +
        +

        The complete contents of the file as a bytes object.

        +
        +
        Raises :

        urllib2.URLError :

        +
        +

        If a remote file cannot be found.

        +
        +

        IOError :

        +
        +

        If problems occur writing or reading a local file.

        +
        +
        +
        +

        See also

        +
        +
        get_data_fileobj
        +
        returns a file-like object with the data
        +
        get_data_filename
        +
        returns a local name for a file containing the data
        +
        +
        +
        + +
        +
        +astropy.config.data.get_data_fileobjs(datadir, pattern='*')[source]
        +

        Returns readable file objects for all of the data files in a given +directory that match a given glob pattern.

        + +++ + + + + + +
        Parameters :

        datadir : str

        +
        +

        Name/location of the desired data files. One of the following:

        +
        +
          +
        • The name of a directory included in the source +distribution. The path is relative to the module +calling this function. For example, if calling from +astropy.pkname, use 'data' to get the +files in astropy/pkgname/data
        • +
        • Remote URLs are not currently supported
        • +
        +
        +
        +

        pattern : str, optional

        +
        +

        A UNIX-style filename glob pattern to match files. See the +glob module in the standard library for more information. +By default, matches all files.

        +
        +
        Returns :

        fileobjs : iterator of file objects

        +
        +

        File objects for each of the files on the local filesystem in +datadir matching pattern.

        +
        +
        +

        Examples

        +

        This will retrieve the contents of the data file for the astropy.wcs +tests:

        +
        from astropy.config import get_data_filenames
        +
        +for fd in get_data_filename('maps', '*.hdr'):
        +    fcontents = fd.read()
        +
        +
        +
        + +
        +
        +astropy.config.data.get_data_filenames(datadir, pattern='*')[source]
        +

        Returns the path of all of the data files in a given directory +that match a given glob pattern.

        + +++ + + + + + +
        Parameters :

        datadir : str

        +
        +

        Name/location of the desired data files. One of the following:

        +
        +
          +
        • The name of a directory included in the source +distribution. The path is relative to the module +calling this function. For example, if calling from +astropy.pkname, use 'data' to get the +files in astropy/pkgname/data.
        • +
        • Remote URLs are not currently supported.
        • +
        +
        +
        +

        pattern : str, optional

        +
        +

        A UNIX-style filename glob pattern to match files. See the +glob module in the standard library for more information. +By default, matches all files.

        +
        +
        Returns :

        filenames : iterator of str

        +
        +

        Paths on the local filesystem in datadir matching pattern.

        +
        +
        +

        Examples

        +

        This will retrieve the contents of the data file for the astropy.wcs +tests:

        +
        from astropy.config import get_data_filenames
        +
        +for fn in get_data_filename('maps', '*.hdr'):
        +    with open(fn) as f:
        +        fcontents = f.read()
        +
        +
        +
        + +
        +
        +astropy.config.data.compute_hash(localfn)[source]
        +

        Computes the MD5 hash for a file.

        +

        The hash for a data file is used for looking up data files in a unique +fashion. This is of particular use for tests; a test may require a +particular version of a particular file, in which case it can be accessed +via hash to get the appropriate version.

        +

        Typically, if you wish to write a test that requires a particular data +file, you will want to submit that file to the astropy data servers, and +use e.g. get_data_filename('hash/a725fa6ba642587436612c2df0451956'), +but with the hash for your file in place of the hash in the example.

        + +++ + + + + + +
        Parameters :

        localfn : str

        +
        +

        The path to the file for which the hash should be generated.

        +
        +
        Returns :

        md5hash : str

        +
        +

        The hex digest of the MD5 hash for the contents of the localfn file.

        +
        +
        +
        + +
        +
        +astropy.config.data.clear_data_cache(hashorurl=None)[source]
        +

        Clears the data file cache by deleting the local file(s).

        + +++ + + + + + +
        Parameters :

        hashorurl : str or None

        +
        +

        If None, the whole cache is cleared. Otherwise, either specifies a hash +for the cached file that is supposed to be deleted, or a URL that has +previously been downloaded to the cache.

        +
        +
        Raises :

        OSEerror :

        +
        +

        If the requested filename is not present in the data directory.

        +
        +
        +
        + +
        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        Installation

        +

        Next topic

        +

        astropy.wcs Documentation

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/development/building_packaging.html b/development/building_packaging.html new file mode 100644 index 00000000..505b96c9 --- /dev/null +++ b/development/building_packaging.html @@ -0,0 +1,280 @@ + + + + + + + + + + Building, Cython/C Extensions, and Distribution — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Building, Cython/C Extensions, and Distribution

        +

        The build process currently uses the +Distribute package to build and +install the astropy core (and any affiliated packages that use the template). +The user doesn’t necessarily need to have distribute installed, as it will +automatically bootstrap itself using the distribute_setup.py file in the +source distribution if it isn’t installed for the user.

        +
        +

        Customizing setup/build for subpackages

        +

        As is typical, there is a single setup.py file that’s used for the whole +astropy package. To customize setup parameters for a given sub-package, a +setup_package.py file can be defined inside a package, and if it is present, +the setup process will look for the following functions to customize the build +process:

        +
          +
        • +
          get_package_data()
          +

          This function, if defined, should return a dictionary mapping the name of +the subpackage(s) that need package data to a list of data file paths +(possibly including wildcards) relative to the path of the package’s source +code. e.g. if the source distribution has a needed data file +astropy/wcs/tests/data/3d_cd.hdr, this function should return +{'astropy.wcs.tests:'['data/3d_cd.hdr']}. See the package_data +option of the distutils.core.setup() function.

          +

          It is recommended that all such data be in a directory named “data” inside +the package within which it is supposed to be used, and package data should +be accessed via the astropy.config.data.get_data_filename and +astropy.config.data.get_data_fileobj functions.

          +
          +
          +
        • +
        • +
          get_extensions()
          +

          This provides information for building C or Cython extensions. If defined, +it should return a list of distutils.core.Extension objects controlling +the Cython/C build process (see below for more detail).

          +
          +
          +
        • +
        • +
          get_legacy_alias()
          +

          This function allows for the creation of shims that allow a +subpackage to be imported under another name. For example, +astropy.io.fits used to be available under the namespace +pyfits. For backward compatibility, it is helpful to have it +still importable under the old name. Under most circumstances, +this function should call astropy.setup_helpers.add_legacy_alias +to generate a legacy module and then return what it returns.

          +
          +
          +
        • +
        +

        The astropy.setup_helpers modules includes a update_package_files() +function which automatically searches the given source path for +setup_package.py modules and calls each of the above functions, if they +exist. This makes it easy for affiliated packages to use this machinery in +their own setup.py.

        +
        +
        +

        C or Cython Extensions

        +

        Astropy supports using C extensions for wrapping C libraries and Cython for +speeding up computationally-intensive calculations. Both Cython and C extension +building can be customized using the get_extensions() function of the +setup_package.py file. If defined, this function must return a list of +distutils.core.Extension objects. The creation process is left to the +subpackage designer, and can be customized however is relevant for the +extensions in the subpackage.

        +

        While C extensions must always be defined through the get_extensions() +mechanism, Cython files (ending in .pyx) are automatically located and +loaded in separate extensions if they are not in get_extensions(). For +Cython extensions located in this way, headers for numpy C functions are +included in the build, but no other external headers are included. .pyx +files present in the extensions returned by get_extensions() are not +included in the list of extensions automatically generated extensions. Note +that this allows disabling a Cython file by providing an extension that +includes the Cython file, but giving it the special name ‘cython_skip’. Any +extension with this package name will not be built by setup.py.

        +
        +

        Note

        +

        If an Extension object is provided for Cython +source files using the get_extensions() mechanism, it is very +important that the .pyx files be given as the source, rather than the +.c files generated by Cython.

        +
        +
        +

        Installing C header files

        +

        If your C extension needs to be linked from other third-party C code, +you probably want to install its header files along side the Python module.

        +
        +
          +
        1. Create an include directory inside of your package for +all of the header files.

          +
        2. +
        3. Use the get_package_data() hook in setup_package.py to +install those header files. For example, the astropy.wcs +package has this:

          +
          def get_package_data():
          +    return {'astropy.wcs': ['include/*.h']}
          +
          +
          +
        4. +
        +
        +
        +
        +
        +

        Release

        +

        There have been no releases of the core package yet, so this isn’t fully +defined. Some important items that are expected to be involved:

        +
          +
        • The release process should be done by automated script.
        • +
        • Documentation is currently hosted at http://readthedocs.org/docs/astropy, +and tested at https://jenkins.shiningpanda.com/astropy/job/astropy-doc/, +automatically updated with every commit to github master.
        • +
        • c files generated by Cython should never be stored in source, but instead +generated during the release process. The setup script will always use these +generated c files for release versions (instead of the .pyx Cython file).
        • +
        +

        There is a central setup.py. It defines which Python packages to +install. Each package does not have its own standalone setup.py.

        +

        Each package that needs to build C extensions has a module +setup_package.py that contains a function get_extensions() which +returns a list of distutils.core.Extension objects defining any +extensions to be built.

        +

        There are a set of helper functions for commonly occurring things when +building C extensions (e.g. finding the Numpy headers and library) in +astropy.setup_helpers.

        +
        +
        +

        Future directions

        +

        We plan to switch to a newer packaging scheme when it’s more stable, the +upcoming standard library packaging module, derived from the +distutils2 +project. Until it’s working right, however, we will be using distribute and +distutils.

        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        Testing Guidelines (Draft)

        +

        Next topic

        +

        Writing Command-Line Scripts

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/development/codeguide.html b/development/codeguide.html index d34d2eea..f520a46f 100644 --- a/development/codeguide.html +++ b/development/codeguide.html @@ -3,17 +3,20 @@ + - Coding Guidelines (Draft 3) — Astropy v0.0.0 documentation + Coding Guidelines (Draft) — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • @@ -51,8 +60,8 @@

        Navigation

        -
        -

        Coding Guidelines (Draft 3)

        +
        +

        Coding Guidelines (Draft)

        Warning

        This document is currently in Draft form and is subject to change.

        @@ -75,6 +84,10 @@

        Interface and DependenciesPython Standard Library (v2.6), NumPy, SciPy, and Matplotlib (versions for these packages will be specified in the Astropy setup.py file and on PyPI). +
      • The package should be importable from the source tree at build time. +This means that, for example, if the package relies on C extensions +that have yet to be built, the Python code is still importable, even +if none of its functionality will work.
      • Additional dependencies are allowed for sub-modules or in function calls, but they must be noted in the package documentation and should only affect the relevant component.
      • @@ -90,7 +103,7 @@

        Interface and Dependencies

        @@ -98,16 +111,22 @@

        Documentation and Testing

        Data and Configuration

          -
        • Packages can include data in path TBD as long as it is less than about -100 kb. These data should be accessed via the -astropy.config.[funcname TBD]() mechanism. If the data exceeds this -size, it should be hosted outside the source code repository and downloaded -using the astropy.config.[funcname TBD]() mechanism. Exceptions to -this size limit may be allowed if there are version dependencies between -data and code.
        • -
        • All persistent configuration should be stored using the functions in -astropy.config, which make use of the ConfigObj class and -associated file format (http://www.voidspace.org.uk/python/configobj.html.
        • +
        • Packages can include data in a directory named data inside a subpackage +source directory as long as it is less than about 100 kb. These data should +always be accessed via the astropy.config.get_data_fileobj() or +astropy.config.get_data_filename() functions. If the data exceeds this +size, it should be hosted outside the source code repository, either at a +third-party location on the internet or the astropy data server. In either +case, it should always be downloaded using the +astropy.config.get_data_fileobj() or +astropy.config.get_data_filename() functions. If a specific version of +a data file is needed, the hash mechanism described in Configuration system Documentation should +be used.
        • +
        • All persistent configuration should use the +astropy.config.ConfigurationItem mechanism. Such configuration items +should be placed at the top of the module or package that makes use of them, +and supply a description sufficient for users to understand what the setting +changes.

        @@ -123,46 +142,81 @@

        Coding Style/Conventions

        Note

        -

        A pep8.py checker script is available at -http://pypi.python.org/pypi/pep8.

        +

        There are multiple options for testing PEP8 compliance of code, +see Testing Guidelines (Draft) for more information.

        See Emacs setup for following coding guidelines for some configuration options for Emacs that helps in ensuring conformance to PEP8.

        -
          -
        • The import numpy as np, import matplotlib as mpl, and import +
            +
          • Astropy source code should contain a comment at the beginning of the file (or +imppediately after the #!/usr/bin env python command, if relevant) +pointing to the license for the Astropy source code. This line should say:

            +
            # Licensed under a 3-clause BSD style license - see LICENSE.rst
            +
            +
            +
          • +
          • The import numpy as np, import matplotlib as mpl, and import matplotlib.pyplot as plt naming conventions should be used wherever relevant. from packagename import * should never be used, except as a tool to flatten the namespace of a module. An example of the allowed usage -is given below.

          • -
          • Classes should either use direct variable access, or python’s property +is given in Acceptable use of from module import *.

            +
          • +
          • Classes should either use direct variable access, or python’s property mechanism for setting object instance variables. get_value/set_value style methods should be used only when getting and setting the values -requires a computationally-expensive operation. The example below -illustrates this guideline.

          • -
          • Classes are discouraged from using the builtin python super() -function, unless absolutely needed. If used, it should be used -consistentently by all subclasses, and noted in the class’s docstrings. An -example illustrating why this is important (and alternative solutions) is -included below.
          • -
          • Affiliated packages are required to follow the layout and documentation form -of the template package included in the core package source distribution.
          • +requires a computationally-expensive operation. Properties vs. get_/set_ +below illustrates this guideline.

            + +
          • All new classes should be new-style classes inheriting from object +(in Python 3 this is a non-issue as all classes are new-style by default). +The one exception to this rule is older classes in third-party libraries such +the Python standard library or numpy.

            +
          • +
          • Classes should use the builtin super() function when making calls to +methods in their super-class(es) unless there are specific reasons not to. +super() should be used consistently in all subclasses since it does not +work otherwise. super() vs. Direct Calling illustrates why this is +important.

            +
          • +
          • Multiple inheritance should be avoided in general without good reason. +Mulitple inheritance is complicated to implement well, which is why many +object-oriented languages, like Java, do not allow it at all. Python does +enable multiple inheritance through use of the +C3 Linearization +algorithm, which provides a consistent method resolution ordering. +Non-trivial multiple-inheritance schemes should not be attempted without +good justification, or without understanding how C3 is used to determine +method resolution order. However, trivial multiple inheritance using +orthogonal base classes, known as the ‘mixin’ pattern, may be used.

            +
          • +
          • __init__.py files for modules should not contain any significant +implementation code. __init__.py can contain docstrings and code for +organizing the module layout, however (e.g. from submodule import * +in accord with the guideline above). If a module is small enough that +it fits in one file, it should simple be a single file, rather than a +directory with an __init__.py file.

            +
          • +
          • When try...except blocks are used to catch exceptions, the as syntax +should always be used, because this is available in all supported versions of +python and is less ambiguous syntax (see try...except block “as” syntax).

            +
          • +
          • Affiliated packages are required to follow the layout and documentation form +of the template package included in the core package source distribution.

            +
          • +
          • Command-line scripts should follow the form outlined in the Writing Command-Line Scripts +document.

            +
          -
        -

        Including C code

        +

        Including C Code

        • C extensions are only allowed when they provide a significant performance enhancement over pure python, or a robust C library already exists to provided the needed functionality. When C extensions are used, the Python -interface must meet interface guidelines.
        • +interface must meet the aforementioned python interface guidelines.
        • The use of Cython is strongly recommended for C extensions, as per the -example in the template package. Cython extensions should store .pyx +example in the template package. Cython extensions should store .pyx files in the source code repository, but they should be compiled to .c files that are updated in the repository when important changes are made to the .pyx file.
        • @@ -171,13 +225,16 @@

          Including C codePEP 7 +
        • In cases where C extensions are needed but Cython cannot be used, the PEP 7 Style Guide for C Code is recommended.
        • +
        • C extensions (Cython or otherwise) should provide the necessary information +for building the extension via the mechanisms described in +C or Cython Extensions.
        -

        Requirements specific to Affiliated Packages

        +

        Requirements Specific to Affiliated Packages

        • Affiliated packages must be registered on the Python Package Index, with proper metadata for downloading and installing the source package.
        • @@ -193,7 +250,7 @@

          Examples -

          Properties vs. get_/set_

          +

          Properties vs. get_/set_

          This example shows a sample class illustrating the guideline regarding the use of properties as opposed to getter/setter methods.

          Let’s assuming you’ve defined a Star class and create an instance @@ -221,10 +278,11 @@

          Properties vs. get_/set_

        -

        super() vs. direct calling

        -

        This example shows why the use of super() can be confusing for -subclasses, and gives an alternative syntax:

        -
        #This is dangerous and bug-prone!
        +

        super() vs. Direct Calling

        +

        This example shows why the use of super() leads to a more consistent +method resolution order than manually calling methods of the super classes in a +multiple inheritance case:

        +

        if you then do:

        @@ -255,52 +313,77 @@

        super() vs. direct calling
        Doing A
        -Doing B
        +
        Doing B
        +Doing A

        which is what you expect, and similarly for C. However, if you do:

        >>> d = D()
         >>> d.method()
         
        -

        you might expect to have it call both method in the order A,C,B,D. But it -doesn’t - instead you see:

        -
        Doing A
        +

        you might expect to see the methods called in the order D, B, C, A but instead +you see:

        +
        Doing D
         Doing C
        -Doing D
        +Doing A +Doing B +Doing A
        -

        because the the A.method(self) in C effectively short-circuits the super -mechanism. Thus, it’s crucial that all classes in an inheritance hierarchy -consistently use super and not mix super with the direct syntax. The simplest -approach is to explicitly call each class’ method and avoid super completely:

        -
        #This is safer
        -class A(object):
        -    def __init__(self, a):
        -        self.a = 1
        +

        because both B.method() and C.method() call A.method() unaware of +the fact that they’re being called as part of a chain in a hierarchy. When +C.method() is called it is unaware that it’s being called from a subclass +that inherts from both B and C, and that B.method() should be +called next. By calling super() the entire method resolution order for +D is precomputed, enabling each superclass to cooperatively determine which +class should be handed control in the next super() call:

        +
        # This is safer
         
        +class A(object):
        +    def method(self):
        +        print 'Doing A'
         
         class B(A):
        -    def __init__(self, a, b):
        -        A.__init__(self, a)
        -        self.b = b
        +    def method(self):
        +        print 'Doing B'
        +        super(B, self).method()
         
         
         class C(A):
        -    def __init__(self, a, c):
        -        A.__init__(self, a)
        -        self.c = c
        -
        +    def method(self):
        +        print 'Doing C'
        +        super(C, self).method()
         
         class D(C, B):
        -    def __init__(self, a, b, c, d):
        -        B.__init__(self, a, b)
        -        C.__init__(self, a, c)
        -        self.d = d
        +    def method(self):
        +        print 'Doing D'
        +        super(D, self).method()
         
        +
        >>> d = D()
        +>>> d.method()
        +Doing D
        +Doing C
        +Doing B
        +Doing A
        +
        +
        +

        As you can see, each superclass’s method is entered only once. For this to +work it is very important that each method in a class that calls its +superclass’s version of that method use super() instead of calling the +method directly. In the most common case of single-inheritance, using +super() is functionally equivalent to calling the superclass’s method +directly. But as soon as a class is used in a multiple-inheritance +hierarchy it must use super() in order to cooperate with other classes in +the hierarchy.

        +
        -

        Acceptable use of from module import *

        +

        Acceptable use of from module import *

        from module import * is discouraged in a module that contains implementation code, as it impedes clarity and often imports unused variables. It can, however, be used for a package that is laid out in the following @@ -338,7 +421,28 @@

        Acceptable use of from

        This ensures that from submodule import * only imports foo() and -AClass, but not numpy.array or numpy.linspace().

        +AClass, but not numpy.array or numpy.linspace().

        +
        +
        +

        try...except block “as” syntax

        +

        Catching of exceptions should always use this syntax:

        +
        try:
        +    ... some code that might produce a variety of exceptions ...
        +except ImportError as e:
        +    if 'somemodule' in e.args[0]"
        +        #for whatever reason, failed import of somemodule is ok
        +        pass
        +    else:
        +        raise
        +except ValueError, TypeError as e:
        +    msg = 'Hit an input problem, which is ok,'
        +    msg2 = 'but we're printing it here just so you know:'
        +    print msg, msg2, e
        +
        +

        This avoids the old style syntax of except ImportError, e or +except (ValueError,TypeError), e, which is dangerous because it’s easy to +instead accidentally do something like except ValueError,TypeError, which +won’t catch TypeError.

        \ No newline at end of file diff --git a/development/codeguide_emacs.html b/development/codeguide_emacs.html index 614c09ec..76aa72f8 100644 --- a/development/codeguide_emacs.html +++ b/development/codeguide_emacs.html @@ -3,17 +3,20 @@ + - Emacs setup for following coding guidelines — Astropy v0.0.0 documentation + Emacs setup for following coding guidelines — Astropy 0.0.dev664 documentation + + - - - - + + + + @@ -54,16 +63,16 @@

        Navigation

        Emacs setup for following coding guidelines

        -

        The AstroPy coding guidelines are listed in Coding Guidelines (Draft 3). This +

        The Astropy coding guidelines are listed in Coding Guidelines (Draft). This document will describe some configuration options for Emacs, that will help in ensuring that Python code satisfies the guidelines. Emacs can be configured in several different ways. So instead of providing a drop in configuration file, only the individual configurations are presented below.

        For this setup we will need flymake, pyflakes and the pep8 Python -script, in addition to python-mode.

        +script, in addition to python-mode.

        Flymake comes with Emacs 23. The rest can be obtained from their -websites, or can be installed using easy_install or pip.

        +websites, or can be installed using easy_install or pip.

        Global settings

        @@ -146,8 +155,8 @@

        Flymake red. When cursor is on such a line a message is displayed in the mini-buffer. When mouse pointer is on such a line a “tool tip” message is also shown.

        -

        For flymake to work with pep8 and pyflakes, create an -executable file named pychecker with the following contents. This +

        For flymake to work with pep8 and pyflakes, create an +executable file named pychecker with the following contents. This file must be in the system path.

        Delete trailing white spaces and blank lines

        -

        To manually delete trailing whitespaces, press C-t C-w, which will +

        To manually delete trailing whitespaces, press C-t C-w, which will run the command “delete-whitespaces`. This command is also run when a file is saved, and hence all trailing whitespaces will be deleted on saving a Python file.

        To make sure that all “words” are separated by only one space, type -M-SPC (use the ALT key since M-SPC sometimes brings up a context +M-SPC (use the ALT key since M-SPC sometimes brings up a context menu.).

        To collapse a set of blank lines to one blank line, place the cursor on -one of these and press C-x C-o. This is useful for deleting multiple +one of these and press C-x C-o. This is useful for deleting multiple black lines at the end of a file.

        ;; Remove trailing whitespace manually by typing C-t C-w.
         (add-hook 'python-mode-hook
        @@ -255,10 +264,10 @@ 

        Table Of Contents

        Previous topic

        Coding Guidelines (Draft 3)

        + title="previous chapter">Coding Guidelines (Draft)

        Next topic

        Documentation Guidelines (Draft 2)

        + title="next chapter">Documentation Guidelines (Draft)

        This Page

        \ No newline at end of file diff --git a/development/docguide.html b/development/docguide.html index 193168be..0f7ea266 100644 --- a/development/docguide.html +++ b/development/docguide.html @@ -3,17 +3,20 @@ + - Documentation Guidelines (Draft 2) — Astropy v0.0.0 documentation + Documentation Guidelines (Draft) — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • @@ -51,24 +60,26 @@

        Navigation

        -
        -

        Documentation Guidelines (Draft 2)

        +
        +

        Documentation Guidelines (Draft)

        Warning

        This document is currently in Draft form and is subject to change.

        +

        TODO: Detailed information about building the documentation should be +added here.

        -

        AstroPy Documentation Rules and Recommendations

        +

        Astropy Documentation Rules and Recommendations

        This section describes the standards for documentation format affiliated packages that must follow for consideration of integration into the core -module, as well as the standard AstroPy docstring format.

        +module, as well as the standard Astropy docstring format.

        • Documentation shall use the Sphinx documentation tool.
        • The template package will provide a recommended general structure for documentation.
        • Docstrings must be provided for all public classes, methods, and functions.
        • Docstrings will be incorporated into the documentation using a version of -numpydoc included with AstroPy, and should follow the NumPy/SciPy +numpydoc included with Astropy, and should follow the NumPy/SciPy docstring standards, included below.
        • Examples and/or tutorials are strongly encouraged for typical use-cases of a particular module or class.
        • @@ -83,7 +94,7 @@

          NumPy/SciPy Docstring RulesNumPy project, and the associated numpydoc tools. The most up-to-date version of these standards can be found at numpy’s github site. The -guidelines below have been adapted to the AstroPy pacakge.

          +guidelines below have been adapted to the Astropy pacakge.

          Overview

          In general, we follow the standard Python style conventions as described here:

          @@ -109,7 +120,7 @@

          Overviewpep8.py

        -

        The following import conventions are used throughout the AstroPy source +

        The following import conventions are used throughout the Astropy source and documentation:

        import numpy as np
         import matplotlib as mpl
        @@ -145,7 +156,7 @@ 

        Docstring StandardNumPy and SciPy have defined a common convention for docstrings that provides for consistency, while also allowing our toolchain to produce -well-formatted reference guides. This format should be used for AstroPy +well-formatted reference guides. This format should be used for Astropy docstrings.

        This docstring standard uses re-structured text (reST) syntax and is rendered using Sphinx (a pre-processor that understands the particular @@ -189,7 +200,7 @@

        Sections -
      • In what AstroPy version the object was deprecated, and when it will +
      • In what Astropy version the object was deprecated, and when it will be removed.
      • Reason for deprecation if this is useful information (e.g., object is superseded, duplicates functionality found elsewhere, etc.).
      • @@ -197,8 +208,8 @@

        Sections
        .. note:: Deprecated in AstroPy 1.2
        -          `ndobj_old` will be removed in AstroPy 2.0, it is replaced by
        +
        .. note:: Deprecated in Astropy 1.2
        +          `ndobj_old` will be removed in Astropy 2.0, it is replaced by
                   `ndobj_new` because the latter works also with array subclasses.
        @@ -406,8 +417,8 @@

        Sections

        Documenting classes

        -
        -

        Class docstring

        +
        +

        Class docstrings

        Use the same sections as outlined above (all except Returns are applicable). The constructor (__init__) should also be documented here, the parameters section of the docstring details the constructors @@ -473,7 +484,7 @@

        Method docstrings

        Documenting class instances

        -

        Instances of classes that are part of the AstroPy API may require some care. +

        Instances of classes that are part of the Astropy API may require some care. To give these instances a useful docstring, we do the following:

        • Single instance: If only a single instance of a class is exposed, document @@ -536,9 +547,9 @@

          Other points to keep in mindhttp://docs.scipy.org/numpy/Questions+Answers/.

        • array_like : For functions that take arguments which can have not only -a type ndarray, but also types that can be converted to an ndarray +a type ndarray, but also types that can be converted to an ndarray (i.e. scalar types, sequence types), those arguments can be documented -with type array_like.

          +with type array_like.

        @@ -557,7 +568,7 @@

        Common reST concepts

        Conclusion

        An example of the -format shown here is available. Refer to How to Build API/Reference +format shown here is available. Refer to How to Build API/Reference Documentation on how to use Sphinx to build the manual.

        @@ -575,14 +586,14 @@

        ConclusionTable Of Contents

        \ No newline at end of file diff --git a/development/index.html b/development/index.html index 8ffc3bf0..697a0868 100644 --- a/development/index.html +++ b/development/index.html @@ -3,17 +3,20 @@ + - Documentation for Developers — Astropy v0.0.0 documentation + Documentation for Developers — Astropy 0.0.dev664 documentation + + - - - + + + @@ -50,15 +59,19 @@

        Navigation

        -

        Documentation for Developers

        -

        The information in the following pages are relevant for anyone interesting in contributing to AstroPy:

        +

        Documentation for Developers

        +

        The information in the following pages are relevant for anyone interesting in +contributing to Astropy. In addition, the Overview is a useful guide +to the layout of the astropy package.

        @@ -73,11 +86,11 @@

        Documentation for Developers

        Previous topic

        -

        Welcome to Astropy’s documentation!

        +

        astropy.utils.misc: Miscellaneous/uncategorized Utilities

        Next topic

        Vision for a common Astronomy Python package

        + title="next chapter">Vision for a Common Astronomy Python Package

        This Page

        \ No newline at end of file diff --git a/development/scripts.html b/development/scripts.html new file mode 100644 index 00000000..b24d3dee --- /dev/null +++ b/development/scripts.html @@ -0,0 +1,184 @@ + + + + + + + + + + Writing Command-Line Scripts — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Writing Command-Line Scripts

        +

        Command-line scripts in Astropy should follow a consistent scheme to promote +readability and compatibility.

        +

        The actual script should be in the /scripts directory of the Astropy +source distribution, and should do nothing aside from importing a main +function from astropy and execute it. This is partly necessary because the +“2to3” utility that converts python 2.x code to 3.x does not convert scripts. +These scripts should be executable, include #!/usr/bin/env python at the +top, and should not end in .py.

        +

        The main functions these scripts call should accept an optional single +argument that holds the sys.argv list, except for the script name +(e.g., argv[1:]). This function can live in its own module, or be part of a +larger module that implements a class or function for astropy library use. The +main function should do very little actual work - it should only parse the +arguments and pass those arguments on to some library function so that the +library function can be used programmatically when needed. +Command-line options can be parsed however desired, but the argparse +module is recommended when possible, due to its simpler and more flexible +interface relative to the older optparse. argparse is only +available in python >=2.7 and >=3.2, however, so it should be imported as +from astropy.util.compat import argparse .

        +
        +

        Example

        +

        Contents of /scripts/cmdlinescript

        +
        #!/usr/bin/env python
        +# -*- coding: utf-8 -*-
        +"""An astropy command-line script"""
        +
        +import astropy.somepackage.somemod
        +
        +astropy.somepackage.somemod.main()
        +
        +
        +

        Contents of /astropy/somepackage/somemod.py

        +
        def do_something(args, option=False):
        +    for a in args:
        +        if option:
        +            ...do something...
        +        else:
        +            ...do something else...
        +
        +def main(args=None):
        +    from astropy.utils.compat import argparse
        +
        +    parser = argparse.ArgumentParser(description='Process some integers.')
        +    parser.add_argument('-o', '--option', dest='op',action='store_true',
        +                        help='Some option that turns something on.')
        +    parser.add_argument('stuff', metavar='S', nargs='+',
        +                        help='Some input I should be able to get lots of.')
        +
        +    res = parser.parse_args(args)
        +
        +    do_something(res.stuff,res.op)
        +
        +
        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        Building, Cython/C Extensions, and Distribution

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/development/testguide.html b/development/testguide.html index 14177c71..e29e8536 100644 --- a/development/testguide.html +++ b/development/testguide.html @@ -3,17 +3,20 @@ + - Testing Guidelines (Draft) — Astropy v0.0.0 documentation + Testing Guidelines (Draft) — Astropy 0.0.dev664 documentation + + - + - + + @@ -48,15 +61,404 @@

        Navigation

        -

        Testing Guidelines (Draft)

        +

        Testing Guidelines (Draft)

        Warning

        -

        This document is currently in Draft form and is subject to change.

        +

        This document is currently in Draft form and is subject to change. Not all +described functionality may be implemented.

        +
        +

        This section describes the testing framework and format standards for tests in +Astropy core packages (this also serves as recommendations for affiliated +packages).

        +
        +

        Testing Framework

        +

        The testing framework used by Astropy is the py.test +framework.

        +
        +
        +

        Running Tests

        +

        There are currently three different ways to invoke Astropy tests. Each method +invokes py.test to run the tests but offers different options when calling.

        +

        In addition to running the Astropy tests, these methods can also be called so +that they check Python source code for +PEP8 compliance. All of the PEP8 +testing options require the +pytest-pep8 plugin, which must be +installed separately.

        +
        +

        setup.py test

        +

        The safest way to run the astropy test suite is via the setup command test. +This is invoked by running python setup.py test while in the astropy source +code directory. Run python setup.py test --help to see the options to the +test command.

        +

        Turn on PEP8 checking by passing --pep8 to the test command. This will +turn off regular testing and enable PEP8 testing.

        +
        +

        Note

        +

        This method of running the tests defaults to the version of py.test that +is bundled with Astropy. To use the locally-installed version, you should +either change the use_system_pytest configuration option to “True” +(see Configuration system Documentation) or the py.test method describe below.

        +
        +
        +
        +

        py.test

        +

        An alternative way to run tests from the command line is to switch to the source +code directory of astropy and simply type:

        +
        py.test
        +
        +
        +

        py.test will look for files that look like tests +in the currect directory and all recursive directories then run all the code that +looks like tests +within those files.

        +
        +

        Note

        +

        To test any compiled C/Cython extensions, you must either have run +python setup.py test or python setup.py develop prior to running +the py.test command-line script. Otherwise, any tests that make use of +these extensions will not succeed. Similarly, in python 3, these tests +will not run correctly in the source code, because they need the 2to3 +tool to be run on them.

        +
        +

        You may specify a specific test file or directory at the command line:

        +
        py.test test_file.py
        +
        +

        To run a specific test within a file use the -k option:

        +
        py.test test_file.py -k "test_function"
        +
        +

        You may also use the -k option to not run tests py putting a - in front +of the matching string:

        +
        py.test test_file.py -k "-test_function"
        +
        +

        py.test has a number of command line usage options.

        +

        Turn on PEP8 testing by adding the --pep8 flag to the py.test call. By +default regular tests will also be run but these can be turned off by adding +-k pep8:

        +
        py.test some_dir --pep8 -k pep8
        +
        +
        +

        Note

        +

        This method of running the tests uses the locally-installed version of +py.test rather than the bundled one, and hence will fail if the local +version it is not up-to-date enough (py.test 2.2 as of this writing).

        +
        +
        +
        +

        astropy.test()

        +

        AstroPy includes a standalone version of py.test that allows to tests +to be run even if py.test is not installed. Tests can be run from within +AstroPy with:

        +
        import astropy
        +astropy.test()
        +
        +
        +

        This will run all the default tests for AstroPy.

        +

        Tests for a specific package can be run by specifying the package in the call +to the test() function:

        +
        astropy.test('io.fits')
        +
        +
        +

        This method works only with package names that can be mapped to Astropy +directories. As an alternative you can test a specific directory or file +with the test_path option:

        +
        astropy.test(test_path='wcs/tests/test_wcs.py')
        +
        +
        +

        The test_path must be specified either relative to the working directory +or absolutely.

        +

        By default astropy.test() will skip tests which retrieve data from the +internet. To turn these tests on use the remote_data flag:

        +
        astropy.test('io.fits',remote_data=True)
        +
        +
        +

        In addition, the test function supports any of the options that can be +passed to pytest.main(), +and convenience options verbose= and pastebin=.

        +

        Enable PEP8 compliance testing with pep8=True in the call to +astropy.test. This will enable PEP8 checking and disable regular tests.

        +
        +

        Note

        +

        This method of running the tests defaults to the version of py.test that +is bundled with Astropy. To use the locally-installed version, you should +either change the use_system_pytest configuration option to “True” +(see Configuration system Documentation) or the py.test method describe above.

        +
        -

        This section describes the testing framework and format standards for tests in Astropy core modules (this also serves as recommendations for affiliated packages).

        -
          -
        • Guidelines will be filled in following a discussion on the astropy mailing list.
        • +
        +
        +

        Regression tests

        +

        Any time a bug is fixed, and wherever possible, one or more regression tests +should be added to ensure that the bug is not introduced in future. Regression +tests should include the ticket URL where the bug was reported.

        +
        +
        +

        Where to put tests

        +
        +

        Package-specific tests

        +

        Each package should include a suite of unit tests, covering as many of the +public methods/functions as possible. These tests should be included inside +each sub-package, either in a tests directory, or in a test.py file, e.g:

        +
        astropy/io/fits/tests/
        +
        +

        or:

        +
        astropy/io/fits/test.py
        +
        +
        +

        tests directories should contain an __init__.py file so that the tests +can be imported and so that they can use relative imports.

        +
        +
        +

        Interoperability tests

        +

        Tests involving two or more sub-packages should be included in:

        +
        astropy/tests/
        +
        +

        and using:

        +
        astropy.test()
        +
        +
        +

        then runs both these interoperability tests, and all the unit tests in the +sub-packages. This functionality is especially important for people who install +packages through bundles and package managers, where the original source code +for the tests is not immediately available.

        +
        +
        +
        +

        Writing tests

        +

        py.test has the following test discovery rules:

        +
        +
          +
        • test_*.py or *_test.py files
        • +
        • Test prefixed classes (without an __init__ method)
        • +
        • test_ prefixed functions and methods
        +
        +

        Consult the test discovery rules +for detailed information on how to name files and tests so that they are +automatically discovered by py.test.

        +
        +

        Simple example

        +

        The following example shows a simple function and a test to test this +function:

        +
        def func(x):
        +    return x + 1
        +
        +def test_answer():
        +    assert func(3) == 5
        +
        +
        +

        If we place this in a test.py file and then run:

        +
        py.test test.py
        +
        +

        The result is:

        +
        ============================= test session starts ==============================
        +python: platform darwin -- Python 2.7.2 -- pytest-1.1.1
        +test object 1: /Users/tom/tmp/test.py
        +
        +test.py F
        +
        +=================================== FAILURES ===================================
        +_________________________________ test_answer __________________________________
        +
        +    def test_answer():
        +>       assert func(3) == 5
        +E       assert 4 == 5
        +E        +  where 4 = func(3)
        +
        +test.py:5: AssertionError
        +=========================== 1 failed in 0.07 seconds ===========================
        +
        +
        +
        +

        Working with data files

        +

        Tests that need to make use of a data file should use the +get_data_fileobj or +get_data_filename functions. These functions search +locally first, and then on the astropy data server or an arbitrary URL, and +return a file-like object or a local filename, respectively. They automatically +cache the data locally if remote data is obtained, and from then on the local +copy will be used transparently.

        +

        They also support the use of an MD5 hash to get a specific version of a data +file. This hash can be obtained prior to submitting a file to the astropy +data server by using the compute_hash function on a +local copy of the file.

        +

        Tests that may retrieve remote data should be marked with the @remote_data +decorator. Tests marked with this decorator will be skipped by default by +astropy.test() to prevent test runs from taking too long. These tests can +be run by astropy.test() by adding the remote_data=True flag. +Turn on the remote data tests at the command line with +py.test --remote-data.

        +
        +

        Examples

        +
        from ...config import get_data_filename
        +from ...tests.helper import remote_data
        +
        +def test_1():
        +    #if filename.fits is a local file in the source distribution
        +    datafile = get_data_filename('filename.fits')
        +    # do the test
        +
        +@remote_data
        +def test_2():
        +    #this is the hash for a particular version of a file stored on the
        +    #astropy data server.
        +    datafile = get_data_filename('hash/94935ac31d585f68041c08f87d1a19d4')
        +    # do the test
        +
        +
        +

        The get_remote_test_data will place the files in a temporary directory +indicated by the tempfile module, so that the test files will eventually +get removed by the system. In the long term, once test data files become too +large, we will need to design a mechanism for removing test data immediately.

        +
        +
        +
        +

        Tests that create files

        +

        Tests may often be run from directories where users do not have write permissions +so tests which create files should always do so in temporary directories. This +can be done with the py.test tmpdir function argument +or with Python’s built-in tempfile module.

        +
        +
        +

        Setting up/Tearing down tests

        +

        In some cases, it can be useful to run a series of tests requiring something +to be set up first. There are four ways to do this:

        +
        +

        Module-level setup/teardown

        +

        If the setup_module and teardown_module functions are specified in a +file, they are called before and after all the tests in the file respectively. +These functions take one argument, which is the module itself, which makes it +very easy to set module-wide variables:

        +
        def setup_module(module):
        +    module.NUM = 11
        +
        +def add_num(x):
        +    return x + NUM
        +
        +def test_42():
        +    added = add_num(42)
        +    assert added == 53
        +
        +
        +

        We can use this for example to download a remote test data file and have all +the functions in the file access it:

        +
        import os
        +
        +def setup_module(module):
        +    module.DATAFILE = get_remote_test_data('94935ac31d585f68041c08f87d1a19d4')
        +
        +def test():
        +    f = open(DATAFILE, 'rb')
        +    # do the test
        +
        +def teardown_module(module):
        +    os.remove(DATAFILE)
        +
        +
        +
        +
        +

        Class-level

        +

        Tests can be organized into classes that have their own setup/teardown +functions. In the following

        +
        def add_nums(x, y):
        +    return x + y
        +
        +class TestAdd42(object):
        +
        +    def setup_class(self):
        +        self.NUM = 42
        +
        +    def test_1(self):
        +        added = add_nums(11, self.NUM)
        +        assert added == 53
        +
        +    def test_2(self):
        +        added = add_nums(13, self.NUM)
        +        assert added == 55
        +
        +    def teardown_class(self):
        +        pass
        +
        +
        +

        In the above example, the setup_class method is called first, then all the +tests in the class, and finally the teardown_class is called.

        +
        +
        +

        Method-level

        +

        There are cases where one might want setup and teardown methods to be run +before and after each test. For this, use the setup_method and +teardown_method methods:

        +
        def add_nums(x, y):
        +    return x + y
        +
        +class TestAdd42(object):
        +
        +    def setup_method(self, method):
        +        self.NUM = 42
        +
        +    def test_1(self):
        +        added = add_nums(11, self.NUM)
        +        assert added == 53
        +
        +    def test_2(self):
        +        added = add_nums(13, self.NUM)
        +        assert added == 55
        +
        +    def teardown_method(self, method):
        +        pass
        +
        +
        +
        +
        +

        Function-level

        +

        Finally, one can use setup_function and teardown_function to define a +setup/teardown mechanism to be run before and after each function in a module. +These take one argument, which is the function being tested:

        +
        def setup_function(function):
        +    pass
        +
        +def test_1(self):
        +    # do test
        +
        +def test_2(self):
        +    # do test
        +
        +def teardown_method(function):
        +    pass
        +
        +
        +
        +
        +

        Using py.test helper functions

        +

        If your tests need to use py.test helper functions, such as pytest.raises, +import pytest into your test module like so:

        +
        from ...tests.helper import pytest
        +
        +
        +

        You may need to adjust the relative import to work for the depth of your module. +tests.helper imports pytest either from the user’s system or extern.pytest +if the user does not have py.test installed. This is so that users need not +install py.test to run AstroPy’s tests.

        +
        +
        +
        +

        Using data in tests

        +

        Tests can include very small datafiles, but any files significantly larger +than the source code should be placed on a remote server. The base URL for the +test files will be:

        +
        http://data.astropy.org/
        +
        +

        and files will be accessed by their MD5 hash, for example:

        +
        http://data.astropy.org/94935ac31d585f68041c08f87d1a19d4
        +
        +

        Tests then retrieve data via this URL. This implicitly allows versioning, +since different versions of data files will have different hashes. Old data +files should not be removed, so that tests can be run in any version of +AstroPy.

        +

        The details of the server implementation have yet to be decided, but using +these static hash-based URLs ensures that even if we change the backend, the +URL will remain the same.

        +
        @@ -68,9 +470,50 @@

        Testing Guidelines (Draft)

        +

        Table Of Contents

        + +

        Previous topic

        Documentation Guidelines (Draft 2)

        + title="previous chapter">Documentation Guidelines (Draft)

        +

        Next topic

        +

        Building, Cython/C Extensions, and Distribution

        This Page

        \ No newline at end of file diff --git a/development/vision.html b/development/vision.html index 8f88163b..6ecac35b 100644 --- a/development/vision.html +++ b/development/vision.html @@ -3,17 +3,20 @@ + - Vision for a common Astronomy Python package — Astropy v0.0.0 documentation + Vision for a Common Astronomy Python Package — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • @@ -52,38 +61,97 @@

        Navigation

        -

        Vision for a common Astronomy Python package

        -

        The following document summarizes a vision for a common Astronomy Python package, and how we can best all work together to achieve this. In the following document, this common package will be referred to as the core package. This vision is not set in stone, and we are committed to adapting it to whatever process and guidelines work in practice.

        -

        The ultimate goal that we seek is a package that would contain much of the core functionality and some common tools required across Astronomy, but not everything Astronomers will ever need. The aim is primarily to avoid duplication for common core tasks, and to provide a robust framework upon which to build more complex tools.

        -

        Such a common package should not preclude any other Astronomy package from existing, because there will always be more complex and/or specialized tools required. These tools will be able to rely on a single core library for many tasks, and thus reduce the number of dependencies, reduce duplication of functionality, and increase consistency of their interfaces.

        +

        Vision for a Common Astronomy Python Package

        +

        The following document summarizes a vision for a common Astronomy Python +package, and how we can best all work together to achieve this. In the +following document, this common package will be referred to as the core +package. This vision is not set in stone, and we are committed to adapting it +to whatever process and guidelines work in practice.

        +

        The ultimate goal that we seek is a package that would contain much of the core +functionality and some common tools required across Astronomy, but not +everything Astronomers will ever need. The aim is primarily to avoid +duplication for common core tasks, and to provide a robust framework upon which +to build more complex tools.

        +

        Such a common package should not preclude any other Astronomy package from +existing, because there will always be more complex and/or specialized tools +required. These tools will be able to rely on a single core library for many +tasks, and thus reduce the number of dependencies, reduce duplication of +functionality, and increase consistency of their interfaces.

        Procedure

        -

        With the help of the community, the coordination committee will start by identifying a few of key areas where initial development/consolidation will be needed (such as FITS, WCS, coordinates, tables, photometry, spectra, etc.) and will encourage teams to be formed to build standalone packages implementing this functionality. These packages will be referred to as affiliated packages (meaning that they are intended for future integration in the core package).

        -

        A set of requirements will be set out concerning the interfaces and classes/methods that affiliated packages will need to make available in order to ensure consistency between the different components. As the core package grows, new potential areas/components for the core package will be identified. Competition cannot be avoided, and will not be actively discouraged, but whenever possible, developers should strive to work as a team to provide a single and robust affiliated package, for the benefit of the community.

        -

        The affiliated packages will be developed outside the core package in independent repositories, which will allow the teams the choice of tool and organization. Once an affiliated package has implemented the desired functionality, and satisfies quality criteria for coding style, documentation, and testing, it will be considered for inclusion in the core package, and further development will be done directly in the core package either via direct access to the repository, or via patches/pull requests (exactly how this will be done will be decided later).

        -

        To ensure uniformity across affiliated packages, and to facilitate integration with the core package, developers who wish to submit their affiliated packages for inclusion in the core will need to follow the layout of a ‘template’ package that will be provided before development starts.

        +

        With the help of the community, the coordination committee will start by +identifying a few of key areas where initial development/consolidation will be +needed (such as FITS, WCS, coordinates, tables, photometry, spectra, etc.) and +will encourage teams to be formed to build standalone packages implementing +this functionality. These packages will be referred to as affiliated packages +(meaning that they are intended for future integration in the core package).

        +

        A set of requirements will be set out concerning the interfaces and +classes/methods that affiliated packages will need to make available in order +to ensure consistency between the different components. As the core package +grows, new potential areas/components for the core package will be identified. +Competition cannot be avoided, and will not be actively discouraged, but +whenever possible, developers should strive to work as a team to provide a +single and robust affiliated package, for the benefit of the community.

        +

        The affiliated packages will be developed outside the core package in +independent repositories, which will allow the teams the choice of tool and +organization. Once an affiliated package has implemented the desired +functionality, and satisfies quality criteria for coding style, documentation, +and testing, it will be considered for inclusion in the core package, and +further development will be done directly in the core package either via direct +access to the repository, or via patches/pull requests (exactly how this will +be done will be decided later).

        +

        To ensure uniformity across affiliated packages, and to facilitate integration +with the core package, developers who wish to submit their affiliated packages +for inclusion in the core will need to follow the layout of a ‘template’ +package that will be provided before development starts.

        Dependencies

        -

        Affiliated packages should be able to be imported with only the following dependencies:

        +

        Affiliated packages should be able to be imported with only the following +dependencies:

          -
        • The Python Standard Library
        • -
        • NumPy, SciPy, and Matplotlib
        • -
        • Components already in the core Astronomy package
        • +
        • The Python Standard Library NumPy, SciPy, and Matplotlib Components already +* in the core Astronomy package
        -

        Other packages may be used, but must be imported as needed rather than during the initial import of the package.

        -

        If a dependency is needed, but is an affiliated package, the dependent package will need to wait until the dependency is integrated into the core package before being itself considered for inclusion. In the mean time, it can make use of the other affiliated package in its current form, or other packages, so as not to stall development. Thus, the first packages to be included in the core will be those only requiring the standard library, NumPy, SciPy, and Matplotlib.

        -

        If the required dependency will never be part of a main package, then by default the dependency can be included but should be imported as needed (meaning that it only prevents the importing of that component, not the entire core package), unless a strong case is made and a general consensus is reached by the community that this dependency is important enough to be required at a higher level.

        -

        This system means that packages will be integrated into the core package in an order depending on the dependency tree, and also ensures that the interfaces of packages being integrated into the core package are consistent with those already in the core package.

        -

        Initially, no dependency on GUI toolkits will be allowed in the core package. If the community reaches agrees on a single toolkit that could be used, then this toolkit will be allowed (but will only be imported as needed).

        +

        Other packages may be used, but must be imported as needed rather than during +the initial import of the package.

        +

        If a dependency is needed, but is an affiliated package, the dependent package +will need to wait until the dependency is integrated into the core package +before being itself considered for inclusion. In the mean time, it can make use +of the other affiliated package in its current form, or other packages, so as +not to stall development. Thus, the first packages to be included in the core +will be those only requiring the standard library, NumPy, SciPy, and +Matplotlib.

        +

        If the required dependency will never be part of a main package, then by +default the dependency can be included but should be imported as needed +(meaning that it only prevents the importing of that component, not the entire +core package), unless a strong case is made and a general consensus is reached +by the community that this dependency is important enough to be required at a +higher level.

        +

        This system means that packages will be integrated into the core package in an +order depending on the dependency tree, and also ensures that the interfaces of +packages being integrated into the core package are consistent with those +already in the core package.

        +

        Initially, no dependency on GUI toolkits will be allowed in the core package. +If the community reaches agrees on a single toolkit that could be used, then +this toolkit will be allowed (but will only be imported as needed).

        Keeping track of affiliated packages

        -

        Affiliated packages will be listed in a central location (in addition to PyPI) that will allow an easy installation of all the affiliated packages, for example with a script that will seamlessly download and install all the affiliated packages. The core package will also include mechanisms to facilitate this installation process.

        +

        Affiliated packages will be listed in a central location (in addition to PyPI) +that will allow an easy installation of all the affiliated packages, for +example with a script that will seamlessly download and install all the +affiliated packages. The core package will also include mechanisms to +facilitate this installation process.

        Existing Packages

        -

        Developers who already have existing packages will be encouraged to continue supporting them for the benefit of users until the core library is considered stable, contains this functionality, and is released to the community. Thereafter, developers should encourage users to transition to using the functionality in the core package, and eventually phase out their own packages, unless they provide added value over the core package.

        +

        Developers who already have existing packages will be encouraged to continue +supporting them for the benefit of users until the core library is considered +stable, contains this functionality, and is released to the community. +Thereafter, developers should encourage users to transition to using the +functionality in the core package, and eventually phase out their own packages, +unless they provide added value over the core package.

        @@ -98,7 +166,7 @@

        Existing PackagesTable Of Contents

        \ No newline at end of file diff --git a/development/workflow/development_workflow.html b/development/workflow/development_workflow.html index b7b06456..97d4610f 100644 --- a/development/workflow/development_workflow.html +++ b/development/workflow/development_workflow.html @@ -3,17 +3,20 @@ + - Development workflow — Astropy v0.0.0 documentation + Development workflow — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • Contributing To/Developing Astropy or Affiliated Packages »
      • @@ -99,7 +108,7 @@

        This Page

        \ No newline at end of file diff --git a/development/workflow/development_workflow_advanced.html b/development/workflow/development_workflow_advanced.html index f8f28d2b..55d68db0 100644 --- a/development/workflow/development_workflow_advanced.html +++ b/development/workflow/development_workflow_advanced.html @@ -3,17 +3,20 @@ + - Development Workflow (Advanced) — Astropy v0.0.0 documentation + Development Workflow (Advanced) — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • Contributing To/Developing Astropy or Affiliated Packages »
      • Development workflow »
      • @@ -55,7 +64,7 @@

        Navigation

        Development Workflow (Advanced)

        -

        In the present document, we refer to the AstroPy master branch, as the +

        In the present document, we refer to the Astropy master branch, as the trunk.

        Creating a fork

        @@ -198,7 +207,7 @@

        Deleting your master branchgithub -fork of Astropy. To do this, you git push this new branch up to your +fork of Astropy. To do this, you git push this new branch up to your github repo. Generally (if you followed the instructions in these pages, and by default), git will have a link to your GitHub repo, called origin. You push up to your own repo on GitHub with:

        @@ -225,7 +234,7 @@

        In more detail
      • Make some changes

      • -
      • See which files have changed with git status (see git status). +

      • See which files have changed with git status (see git status). You’ll see a listing like this one:

        # On branch ny-new-feature
         # Changed but not updated:
        @@ -241,22 +250,22 @@ 

        In more detail

      • -
      • Check what the actual changes are with git diff (git diff).

        +
      • Check what the actual changes are with git diff (git diff).

      • Add any new files to version control git add new_file_name (see -git add).

        +git add).

      • To commit all modified files into the local copy of your repo,, do git commit -am 'A commit message'. Note the -am options to commit. The m flag just signals that you’re going to type a message on the command line. The a flag — you can just take on faith — or see why the -a flag? — and the helpful use-case -description in the tangled working copy problem. The git commit +description in the tangled working copy problem. The git commit manual page might also be useful.

      • To push the changes up to your forked repo on github, do a git -push (see git push).

        +push (see git push).

      • @@ -389,9 +398,9 @@

        Explore your repositoryIf it doesn’t look good you may need to have a look at Recovering from mess-ups.

        If you have made changes to files that have also changed in trunk, this may -generate merge conflicts that you need to resolve - see the git rebase man +generate merge conflicts that you need to resolve - see the git rebase man page for some instructions at the end of the “Description” section. There is -some related help on merging in the git user manual - see resolving a +some related help on merging in the git user manual - see resolving a merge.

        @@ -554,7 +563,7 @@

        This Page

        \ No newline at end of file diff --git a/development/workflow/development_workflow_basic.html b/development/workflow/development_workflow_basic.html index 628cf208..776e0dbf 100644 --- a/development/workflow/development_workflow_basic.html +++ b/development/workflow/development_workflow_basic.html @@ -3,17 +3,20 @@ + - Development Workflow (Beginner) — Astropy v0.0.0 documentation + Development Workflow (Beginner) — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • Contributing To/Developing Astropy or Affiliated Packages »
      • Development workflow »
      • @@ -207,7 +216,7 @@

        This Page

        \ No newline at end of file diff --git a/development/workflow/git_configure.html b/development/workflow/git_configure.html index abd5e096..0f006b96 100644 --- a/development/workflow/git_configure.html +++ b/development/workflow/git_configure.html @@ -3,17 +3,20 @@ + - Configuring git — Astropy v0.0.0 documentation + Configuring git — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • Contributing To/Developing Astropy or Affiliated Packages »
      • Development workflow »
      • @@ -234,7 +243,7 @@

        This Page

        \ No newline at end of file diff --git a/development/workflow/git_install.html b/development/workflow/git_install.html index 2d1df5b6..1a29172f 100644 --- a/development/workflow/git_install.html +++ b/development/workflow/git_install.html @@ -3,17 +3,20 @@ + - Installing git — Astropy v0.0.0 documentation + Installing git — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • Contributing To/Developing Astropy or Affiliated Packages »
      • Development workflow »
      • @@ -116,7 +125,7 @@

        This Page

        \ No newline at end of file diff --git a/development/workflow/git_resources.html b/development/workflow/git_resources.html index 42ec2219..6df13578 100644 --- a/development/workflow/git_resources.html +++ b/development/workflow/git_resources.html @@ -3,17 +3,20 @@ + - Git resources — Astropy v0.0.0 documentation + Git resources — Astropy 0.0.dev664 documentation + + - + @@ -35,13 +38,19 @@

        Navigation

      • index
      • +
      • + modules |
      • +
      • + modules |
      • next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • Contributing To/Developing Astropy or Affiliated Packages »
      • @@ -61,8 +70,8 @@

        Tutorials and summarieslearn.github has an excellent series of tutorials
      • The pro git book is a good in-depth book on git.
      • A git cheat sheet is a page giving summaries of common commands.
      • -
      • The git user manual
      • -
      • The git tutorial
      • +
      • The git user manual
      • +
      • The git tutorial
      • The git community book
      • git ready — a nice series of tutorials
      • git casts — video snippets giving git how-tos.
      • @@ -93,18 +102,18 @@

        Manual pages onlinegit push --help, but, for convenience, here are the online manual pages for some common commands:

        @@ -142,7 +151,7 @@

        This Page

        \ No newline at end of file diff --git a/development/workflow/index.html b/development/workflow/index.html index 0eeaf5ab..61104144 100644 --- a/development/workflow/index.html +++ b/development/workflow/index.html @@ -3,17 +3,20 @@ + - Contributing To/Developing Astropy or Affiliated Packages — Astropy v0.0.0 documentation + Contributing To/Developing Astropy or Affiliated Packages — Astropy 0.0.dev664 documentation + + - + - + @@ -55,7 +64,7 @@

        Navigation

        Contributing To/Developing Astropy or Affiliated Packages

        Summary

        -

        As described in Vision for a common Astronomy Python package, development of components intended for +

        As described in Vision for a Common Astronomy Python Package, development of components intended for inclusion in the core astropy package will initially be done by different teams via affiliated packages. These affiliated packages will then be submitted for inclusion in the astropy core package by creating a git fork @@ -142,7 +151,7 @@

        Table Of Contents

        Previous topic

        Vision for a common Astronomy Python package

        + title="previous chapter">Vision for a Common Astronomy Python Package

        Next topic

        Installing git

        @@ -154,7 +163,7 @@

        This Page

        \ No newline at end of file diff --git a/development/workflow/maintainer_workflow.html b/development/workflow/maintainer_workflow.html index 83ff72d4..c2ea3581 100644 --- a/development/workflow/maintainer_workflow.html +++ b/development/workflow/maintainer_workflow.html @@ -3,17 +3,20 @@ + - Maintainer workflow — Astropy v0.0.0 documentation + Maintainer workflow — Astropy 0.0.dev664 documentation + + - + - + @@ -36,12 +39,18 @@

        Navigation

        index
      • - modules |
      • +
      • + modules |
      • +
      • + next |
      • previous |
      • -
      • Astropy v0.0.0 documentation »
      • +
      • Astropy 0.0.dev664 documentation »
      • Documentation for Developers »
      • Contributing To/Developing Astropy or Affiliated Packages »
      • @@ -162,7 +171,7 @@

        Previous topic

        title="previous chapter">Development Workflow (Advanced)

        Next topic

        Coding Guidelines (Draft 3)

        + title="next chapter">Coding Guidelines (Draft)

        This Page

        \ No newline at end of file diff --git a/genindex.html b/genindex.html index 944dfc51..427293ed 100644 --- a/genindex.html +++ b/genindex.html @@ -1,19 +1,24 @@ + + + - Index — Astropy v0.0.0 documentation + Index — Astropy 0.0.dev664 documentation + + - + @@ -42,11 +53,1859 @@

        Navigation

        -

        Index

        +

        Index

        + +
        + _ + | A + | B + | C + | D + | E + | F + | G + | H + | I + | K + | L + | M + | N + | O + | P + | R + | S + | T + | U + | V + | W + | X + | Z + +
        +

        _

        + + + +
        + +
        __dict__ (astropy.utils.collections.HomogeneousList attribute) +
        + + +
        __enter__() (astropy.utils.console.ProgressBar method) +
        + +
        + +
        (astropy.utils.console.ProgressBarOrSpinner method) +
        + + +
        (astropy.utils.console.Spinner method) +
        + +
        + +
        __exit__() (astropy.utils.console.ProgressBar method) +
        + +
        + +
        (astropy.utils.console.ProgressBarOrSpinner method) +
        + + +
        (astropy.utils.console.Spinner method) +
        + +
        + +
        __iadd__() (astropy.utils.collections.HomogeneousList method) +
        + +
        + +
        __init__() (astropy.utils.collections.HomogeneousList method) +
        + +
        + +
        (astropy.utils.console.ProgressBar method) +
        + + +
        (astropy.utils.console.ProgressBarOrSpinner method) +
        + + +
        (astropy.utils.console.Spinner method) +
        + + +
        (astropy.utils.xml.writer.XMLWriter method) +
        + +
        + +
        __module__ (astropy.utils.collections.HomogeneousList attribute) +
        + +
        + +
        (astropy.utils.console.ProgressBar attribute) +
        + + +
        (astropy.utils.console.ProgressBarOrSpinner attribute) +
        + + +
        (astropy.utils.console.Spinner attribute) +
        + + +
        (astropy.utils.xml.writer.XMLWriter attribute) +
        + +
        + +
        __setitem__() (astropy.utils.collections.HomogeneousList method) +
        + + +
        __weakref__ (astropy.utils.collections.HomogeneousList attribute) +
        + +
        + +

        A

        + + + +
        + +
        a (astropy.wcs.Sip attribute) +
        + + +
        a_order (astropy.wcs.Sip attribute) +
        + + +
        all_pix2sky() (astropy.wcs.WCS method) +
        + + +
        alt (astropy.wcs.Wcsprm attribute) +
        + + +
        ap (astropy.wcs.Sip attribute) +
        + + +
        ap_order (astropy.wcs.Sip attribute) +
        + + +
        append() (astropy.utils.collections.HomogeneousList method) +
        + + +
        arraysize (astropy.io.vo.tree.Field attribute) +
        + + +
        astropy.config.configs (module) +
        + + +
        astropy.config.data (module) +
        + + +
        astropy.config.paths (module) +
        + + +
        astropy.io.vo.converters (module) +
        + + +
        astropy.io.vo.exceptions (module) +
        + + +
        astropy.io.vo.table (module) +
        + + +
        astropy.io.vo.tree (module) +
        + + +
        astropy.io.vo.ucd (module) +
        + +
        + +
        astropy.io.vo.unit (module) +
        + + +
        astropy.io.vo.util (module) +
        + + +
        astropy.io.vo.validator (module) +
        + + +
        astropy.io.vo.xmlutil (module) +
        + + +
        astropy.tools.misc (module) +
        + + +
        astropy.utils.collections (module) +
        + + +
        astropy.utils.console (module) +
        + + +
        astropy.utils.misc (module) +
        + + +
        astropy.utils.xml.check (module) +
        + + +
        astropy.utils.xml.iterparser (module) +
        + + +
        astropy.utils.xml.validate (module) +
        + + +
        astropy.utils.xml.writer (module) +
        + + +
        astropy.wcs (module) +
        + + +
        astropy.wcs.wcs (module) +
        + + +
        axis_types (astropy.wcs.Wcsprm attribute) +
        + +
        + +

        B

        + + + +
        + +
        b (astropy.wcs.Sip attribute) +
        + + +
        b_order (astropy.wcs.Sip attribute) +
        + +
        + +
        bp (astropy.wcs.Sip attribute) +
        + + +
        bp_order (astropy.wcs.Sip attribute) +
        + +
        + +

        C

        + + + +
        + +
        calcFootprint() (astropy.wcs.WCS method) +
        + + +
        cd (astropy.wcs.Wcsprm attribute) +
        + + +
        cdelt (astropy.wcs.DistortionLookupTable attribute) +
        + +
        + +
        (astropy.wcs.Wcsprm attribute) +
        + +
        + +
        cdfix() (astropy.wcs.Wcsprm method) +
        + + +
        cel_offset (astropy.wcs.Wcsprm attribute) +
        + + +
        celfix() (astropy.wcs.Wcsprm method) +
        + + +
        check_anyuri() (in module astropy.io.vo.xmlutil) +
        + +
        + +
        (in module astropy.utils.xml.check) +
        + +
        + +
        check_id() (in module astropy.io.vo.xmlutil) +
        + +
        + +
        (in module astropy.utils.xml.check) +
        + +
        + +
        check_mime_content_type() (in module astropy.io.vo.xmlutil) +
        + +
        + +
        (in module astropy.utils.xml.check) +
        + +
        + +
        check_token() (in module astropy.io.vo.xmlutil) +
        + +
        + +
        (in module astropy.utils.xml.check) +
        + +
        + +
        check_ucd() (in module astropy.io.vo.ucd) +
        + + +
        check_unit() (in module astropy.io.vo.unit) +
        + + +
        clear_data_cache() (in module astropy.config.data) +
        + + +
        close() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        cname (astropy.wcs.Wcsprm attribute) +
        + + +
        coerce_range_list_param() (in module astropy.io.vo.util) +
        + + +
        colax (astropy.wcs.Wcsprm attribute) +
        + + +
        colnum (astropy.wcs.Wcsprm attribute) +
        + + +
        color_print() (in module astropy.utils.console) +
        + + +
        comment() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        compute_hash() (in module astropy.config.data) +
        + + +
        ConfigurationItem (class in astropy.config.configs) +
        + +
        + +
        content (astropy.io.vo.tree.Info attribute) +
        + +
        + +
        (astropy.io.vo.tree.SimpleElementWithContent attribute) +
        + +
        + +
        content_role (astropy.io.vo.tree.Link attribute) +
        + + +
        content_type (astropy.io.vo.tree.Link attribute) +
        + + +
        convert() (astropy.wcs.UnitConverter method) +
        + + +
        convert_to_writable_filelike() (in module astropy.io.vo.util) +
        + + +
        coord (astropy.wcs._wcs.Tabprm attribute) +
        + + +
        coordinate_systems (astropy.io.vo.tree.Resource attribute) +
        + +
        + +
        (astropy.io.vo.tree.VOTableFile attribute) +
        + +
        + +
        CooSys (class in astropy.io.vo.tree) +
        + + +
        copy() (astropy.wcs.WCS method) +
        + + +
        cpdis1 (astropy.wcs.WCS attribute) +
        + + +
        cpdis2 (astropy.wcs.WCS attribute) +
        + + +
        crder (astropy.wcs.Wcsprm attribute) +
        + + +
        create_arrays() (astropy.io.vo.tree.Table method) +
        + + +
        crota (astropy.wcs.Wcsprm attribute) +
        + + +
        crpix (astropy.wcs.DistortionLookupTable attribute) +
        + +
        + +
        (astropy.wcs.Sip attribute) +
        + + +
        (astropy.wcs.Wcsprm attribute) +
        + +
        + +
        crval (astropy.wcs._wcs.Tabprm attribute) +
        + +
        + +
        (astropy.wcs.DistortionLookupTable attribute) +
        + + +
        (astropy.wcs.Wcsprm attribute) +
        + +
        + +
        csyer (astropy.wcs.Wcsprm attribute) +
        + + +
        ctype (astropy.wcs.Wcsprm attribute) +
        + + +
        cubeface (astropy.wcs.Wcsprm attribute) +
        + + +
        cunit (astropy.wcs.Wcsprm attribute) +
        + + +
        cylfix() (astropy.wcs.Wcsprm method) +
        + +
        + +

        D

        + + + +
        + +
        data (astropy.wcs.DistortionLookupTable attribute) +
        + + +
        data() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        datatype (astropy.io.vo.tree.Field attribute) +
        + + +
        dateavg (astropy.wcs.Wcsprm attribute) +
        + + +
        dateobs (astropy.wcs.Wcsprm attribute) +
        + + +
        datfix() (astropy.wcs.Wcsprm method) +
        + +
        + +
        deepcopy() (astropy.wcs.WCS method) +
        + + +
        delta (astropy.wcs._wcs.Tabprm attribute) +
        + + +
        det2im() (astropy.wcs.WCS method) +
        + + +
        det2im1 (astropy.wcs.WCS attribute) +
        + + +
        det2im2 (astropy.wcs.WCS attribute) +
        + + +
        DistortionLookupTable (class in astropy.wcs) +
        + +
        + +

        E

        + + + +
        + +
        Element (class in astropy.io.vo.tree) +
        + + +
        element() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        end() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        entries (astropy.io.vo.tree.Group attribute) +
        + + +
        epoch (astropy.io.vo.tree.CooSys attribute) +
        + +
        + +
        equinox (astropy.io.vo.tree.CooSys attribute) +
        + +
        + +
        (astropy.wcs.Wcsprm attribute) +
        + +
        + +
        extend() (astropy.utils.collections.HomogeneousList method) +
        + + +
        extra_attributes (astropy.io.vo.tree.Resource attribute) +
        + + +
        extrema (astropy.wcs._wcs.Tabprm attribute) +
        + +
        + +

        F

        + + + +
        + +
        Field (class in astropy.io.vo.tree) +
        + + +
        FieldRef (class in astropy.io.vo.tree) +
        + + +
        fields (astropy.io.vo.tree.Table attribute) +
        + + +
        find_all_wcs() (in module astropy.wcs) +
        + + +
        find_current_module() (in module astropy.utils.misc) +
        + + +
        fix() (astropy.wcs.Wcsprm method) +
        + + +
        fix_id() (in module astropy.io.vo.xmlutil) +
        + +
        + +
        (in module astropy.utils.xml.check) +
        + +
        +
        + +
        flush() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        fnpickle() (in module astropy.utils.misc) +
        + + +
        fnunpickle() (in module astropy.utils.misc) +
        + + +
        foc2pix() (astropy.wcs.Sip method) +
        + + +
        footprint_to_file() (astropy.wcs.WCS method) +
        + + +
        format (astropy.io.vo.tree.Table attribute) +
        + +
        + +

        G

        + + + +
        + +
        get_axis_types() (astropy.wcs.WCS method) +
        + + +
        get_cache_dir() (in module astropy.config.paths) +
        + + +
        get_cdelt() (astropy.wcs.Wcsprm method) +
        + + +
        get_config() (in module astropy.config.configs) +
        + + +
        get_config_dir() (in module astropy.config.paths) +
        + + +
        get_converter() (in module astropy.io.vo.converters) +
        + + +
        get_coosys_by_id() (astropy.io.vo.tree.VOTableFile method) +
        + + +
        get_data_contents() (in module astropy.config.data) +
        + + +
        get_data_filename() (in module astropy.config.data) +
        + + +
        get_data_filenames() (in module astropy.config.data) +
        + + +
        get_data_fileobj() (in module astropy.config.data) +
        + + +
        get_data_fileobjs() (in module astropy.config.data) +
        + + +
        get_field_by_id() (astropy.io.vo.tree.Table method) +
        + +
        + +
        (astropy.io.vo.tree.VOTableFile method) +
        + +
        + +
        get_field_by_id_or_name() (astropy.io.vo.tree.Table method) +
        + +
        + +
        (astropy.io.vo.tree.VOTableFile method) +
        + +
        + +
        get_first_table() (astropy.io.vo.tree.VOTableFile method) +
        + + +
        get_group_by_id() (astropy.io.vo.tree.Table method) +
        + +
        + +
        (astropy.io.vo.tree.VOTableFile method) +
        + +
        +
        + +
        get_indentation() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        get_indentation_spaces() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        get_naxis() (astropy.wcs.WCS method) +
        + + +
        get_offset() (astropy.wcs.DistortionLookupTable method) +
        + + +
        get_pc() (astropy.wcs.Wcsprm method) +
        + + +
        get_ps() (astropy.wcs.Wcsprm method) +
        + + +
        get_pv() (astropy.wcs.Wcsprm method) +
        + + +
        get_ref() (astropy.io.vo.tree.FieldRef method) +
        + +
        + +
        (astropy.io.vo.tree.ParamRef method) +
        + +
        + +
        get_table_by_id() (astropy.io.vo.tree.VOTableFile method) +
        + + +
        get_table_by_index() (astropy.io.vo.tree.VOTableFile method) +
        + + +
        get_values_by_id() (astropy.io.vo.tree.VOTableFile method) +
        + + +
        get_xml_encoding() (in module astropy.utils.xml.iterparser) +
        + + +
        get_xml_iterator() (in module astropy.utils.xml.iterparser) +
        + + +
        Group (class in astropy.io.vo.tree) +
        + + +
        groups (astropy.io.vo.tree.Table attribute) +
        + +
        + +
        (astropy.io.vo.tree.VOTableFile attribute) +
        + +
        +
        + +

        H

        + + + +
        + +
        has_cd() (astropy.wcs.Wcsprm method) +
        + + +
        has_cdi_ja() (astropy.wcs.Wcsprm method) +
        + + +
        has_crota() (astropy.wcs.Wcsprm method) +
        + + +
        has_crotaia() (astropy.wcs.Wcsprm method) +
        + + +
        has_pc() (astropy.wcs.Wcsprm method) +
        + +
        + +
        has_pci_ja() (astropy.wcs.Wcsprm method) +
        + + +
        have (astropy.wcs.UnitConverter attribute) +
        + + +
        HomogeneousList (class in astropy.utils.collections) +
        + + +
        href (astropy.io.vo.tree.Link attribute) +
        + + +
        human_time() (in module astropy.utils.console) +
        + +
        + +

        I

        + + + +
        + +
        ID (astropy.io.vo.tree.CooSys attribute) +
        + + +
        imgpix_matrix (astropy.wcs.Wcsprm attribute) +
        + + +
        Info (class in astropy.io.vo.tree) +
        + + +
        infos (astropy.io.vo.tree.Resource attribute) +
        + +
        + +
        (astropy.io.vo.tree.Table attribute) +
        + + +
        (astropy.io.vo.tree.VOTableFile attribute) +
        + +
        + +
        insert() (astropy.utils.collections.HomogeneousList method) +
        + + +
        InvalidConfigurationItemWarning +
        + + +
        IOWarning (class in astropy.io.vo.exceptions) +
        + + +
        is_callable() (in module astropy.io.vo.util) +
        + + +
        is_defaults() (astropy.io.vo.tree.Values method) +
        + + +
        is_empty() (astropy.io.vo.tree.Table method) +
        + +
        + +
        is_unit() (in module astropy.io.vo.unit) +
        + + +
        is_unity() (astropy.wcs.Wcsprm method) +
        + + +
        isatty() (in module astropy.utils.console) +
        + + +
        iter_coosys() (astropy.io.vo.tree.Resource method) +
        + +
        + +
        (astropy.io.vo.tree.VOTableFile method) +
        + +
        + +
        iter_fields_and_params() (astropy.io.vo.tree.Group method) +
        + +
        + +
        (astropy.io.vo.tree.Resource method) +
        + + +
        (astropy.io.vo.tree.Table method) +
        + + +
        (astropy.io.vo.tree.VOTableFile method) +
        + +
        + +
        iter_groups() (astropy.io.vo.tree.Group method) +
        + +
        + +
        (astropy.io.vo.tree.Table method) +
        + + +
        (astropy.io.vo.tree.VOTableFile method) +
        + +
        + +
        iter_tables() (astropy.io.vo.tree.Resource method) +
        + +
        + +
        (astropy.io.vo.tree.VOTableFile method) +
        + +
        + +
        iter_values() (astropy.io.vo.tree.VOTableFile method) +
        + + +
        iterate() (astropy.utils.console.ProgressBar class method) +
        + +
        + +

        K

        + + +
        + +
        K (astropy.wcs._wcs.Tabprm attribute) +
        + +
        + +

        L

        + + + +
        + +
        lat (astropy.wcs.Wcsprm attribute) +
        + + +
        latpole (astropy.wcs.Wcsprm attribute) +
        + + +
        lattyp (astropy.wcs.Wcsprm attribute) +
        + + +
        Link (class in astropy.io.vo.tree) +
        + +
        + +
        links (astropy.io.vo.tree.Field attribute) +
        + +
        + +
        (astropy.io.vo.tree.Resource attribute) +
        + + +
        (astropy.io.vo.tree.Table attribute) +
        + +
        + +
        lng (astropy.wcs.Wcsprm attribute) +
        + + +
        lngtyp (astropy.wcs.Wcsprm attribute) +
        + + +
        lonpole (astropy.wcs.Wcsprm attribute) +
        + +
        + +

        M

        + + + +
        + +
        M (astropy.wcs._wcs.Tabprm attribute) +
        + + +
        make_validation_report() (in module astropy.io.vo.validator.main) +
        + + +
        map (astropy.wcs._wcs.Tabprm attribute) +
        + + +
        map() (astropy.utils.console.ProgressBar class method) +
        + + +
        max (astropy.io.vo.tree.Values attribute) +
        + + +
        max_inclusive (astropy.io.vo.tree.Values attribute) +
        + +
        + +
        min (astropy.io.vo.tree.Values attribute) +
        + + +
        min_inclusive (astropy.io.vo.tree.Values attribute) +
        + + +
        mix() (astropy.wcs.Wcsprm method) +
        + + +
        mjdavg (astropy.wcs.Wcsprm attribute) +
        + + +
        mjdobs (astropy.wcs.Wcsprm attribute) +
        + +
        + +

        N

        + + + +
        + +
        name (astropy.io.vo.tree.Info attribute) +
        + +
        + +
        (astropy.wcs.Wcsprm attribute) +
        + +
        + +
        naxis (astropy.wcs.Wcsprm attribute) +
        + + +
        nc (astropy.wcs._wcs.Tabprm attribute) +
        + +
        + +
        nrows (astropy.io.vo.tree.Table attribute) +
        + + +
        null (astropy.io.vo.tree.Values attribute) +
        + +
        + +

        O

        + + + +
        + +
        object_attrs() (astropy.utils.xml.writer.XMLWriter static method) +
        + + +
        obsgeo (astropy.wcs.Wcsprm attribute) +
        + +
        + +
        offset (astropy.wcs.UnitConverter attribute) +
        + + +
        options (astropy.io.vo.tree.Values attribute) +
        + +
        + +

        P

        + + + +
        + +
        p0 (astropy.wcs._wcs.Tabprm attribute) +
        + + +
        p2s() (astropy.wcs.Wcsprm method) +
        + + +
        p4_pix2foc() (astropy.wcs.WCS method) +
        + + +
        Param (class in astropy.io.vo.tree) +
        + + +
        ParamRef (class in astropy.io.vo.tree) +
        + + +
        params (astropy.io.vo.tree.Resource attribute) +
        + +
        + +
        (astropy.io.vo.tree.Table attribute) +
        + + +
        (astropy.io.vo.tree.VOTableFile attribute) +
        + +
        + +
        parse() (astropy.io.vo.tree.Field method) +
        + +
        + +
        (astropy.io.vo.tree.Group method) +
        + + +
        (astropy.io.vo.tree.Resource method) +
        + + +
        (astropy.io.vo.tree.SimpleElement method) +
        + + +
        (astropy.io.vo.tree.Table method) +
        + + +
        (astropy.io.vo.tree.VOTableFile method) +
        + + +
        (astropy.io.vo.tree.Values method) +
        + + +
        (in module astropy.io.vo.table) +
        + +
        + +
        parse_single_table() (in module astropy.io.vo.table) +
        + + +
        parse_ucd() (in module astropy.io.vo.ucd) +
        + + +
        parse_vowarning() (in module astropy.io.vo.exceptions) +
        + + +
        pc (astropy.wcs.Wcsprm attribute) +
        + +
        + +
        phi0 (astropy.wcs.Wcsprm attribute) +
        + + +
        pix2foc() (astropy.wcs.Sip method) +
        + +
        + +
        (astropy.wcs.WCS method) +
        + +
        + +
        piximg_matrix (astropy.wcs.Wcsprm attribute) +
        + + +
        power (astropy.wcs.UnitConverter attribute) +
        + + +
        precision (astropy.io.vo.tree.Field attribute) +
        + + +
        print_code_line() (in module astropy.utils.console) +
        + + +
        print_contents() (astropy.wcs._wcs.Tabprm method) +
        + +
        + +
        (astropy.wcs.Wcsprm method) +
        + +
        + +
        printwcs() (astropy.wcs.WCS method) +
        + + +
        ProgressBar (class in astropy.utils.console) +
        + + +
        ProgressBarOrSpinner (class in astropy.utils.console) +
        + +
        + +

        R

        + + + +
        + +
        radesys (astropy.wcs.Wcsprm attribute) +
        + + +
        ref (astropy.io.vo.tree.Field attribute) +
        + +
        + +
        (astropy.io.vo.tree.FieldRef attribute) +
        + + +
        (astropy.io.vo.tree.Group attribute) +
        + + +
        (astropy.io.vo.tree.Info attribute) +
        + + +
        (astropy.io.vo.tree.ParamRef attribute) +
        + + +
        (astropy.io.vo.tree.Table attribute) +
        + + +
        (astropy.io.vo.tree.Values attribute) +
        + +
        + +
        reload() (astropy.config.configs.ConfigurationItem method) +
        + + +
        reload_config() (in module astropy.config.configs) +
        + + +
        Resource (class in astropy.io.vo.tree) +
        + +
        + +
        resources (astropy.io.vo.tree.Resource attribute) +
        + +
        + +
        (astropy.io.vo.tree.VOTableFile attribute) +
        + +
        + +
        restfrq (astropy.wcs.Wcsprm attribute) +
        + + +
        restwav (astropy.wcs.Wcsprm attribute) +
        + + +
        rotateCD() (astropy.wcs.WCS method) +
        + +
        + +

        S

        + + + +
        + +
        s2p() (astropy.wcs.Wcsprm method) +
        + + +
        save() (astropy.config.configs.ConfigurationItem method) +
        + + +
        save_config() (in module astropy.config.configs) +
        + + +
        scale (astropy.wcs.UnitConverter attribute) +
        + + +
        sense (astropy.wcs._wcs.Tabprm attribute) +
        + + +
        set() (astropy.config.configs.ConfigurationItem method) +
        + +
        + +
        (astropy.wcs.Wcsprm method) +
        + + +
        (astropy.wcs._wcs.Tabprm method) +
        + +
        + +
        set_all_tables_format() (astropy.io.vo.tree.VOTableFile method) +
        + + +
        set_ps() (astropy.wcs.Wcsprm method) +
        + + +
        set_pv() (astropy.wcs.Wcsprm method) +
        + + +
        sigma_clip() (in module astropy.tools.misc) +
        + + +
        SimpleElement (class in astropy.io.vo.tree) +
        + + +
        SimpleElementWithContent (class in astropy.io.vo.tree) +
        + + +
        sip (astropy.wcs.WCS attribute) +
        + +
        + +
        Sip (class in astropy.wcs) +
        + + +
        sip_foc2pix() (astropy.wcs.WCS method) +
        + + +
        sip_pix2foc() (astropy.wcs.WCS method) +
        + + +
        spcfix() (astropy.wcs.Wcsprm method) +
        + + +
        spec (astropy.wcs.Wcsprm attribute) +
        + + +
        specsys (astropy.wcs.Wcsprm attribute) +
        + + +
        Spinner (class in astropy.utils.console) +
        + + +
        sptr() (astropy.wcs.Wcsprm method) +
        + + +
        ssysobs (astropy.wcs.Wcsprm attribute) +
        + + +
        ssyssrc (astropy.wcs.Wcsprm attribute) +
        + + +
        start() (astropy.utils.xml.writer.XMLWriter method) +
        + + +
        sub() (astropy.wcs.WCS method) +
        + +
        + +
        (astropy.wcs.Wcsprm method) +
        + +
        + +
        system (astropy.io.vo.tree.CooSys attribute) +
        + +
        + +

        T

        + + + +
        + +
        tab (astropy.wcs.Wcsprm attribute) +
        + + +
        Table (class in astropy.io.vo.tree) +
        + + +
        tables (astropy.io.vo.tree.Resource attribute) +
        + + +
        Tabprm (class in astropy.wcs._wcs) +
        + + +
        tag() (astropy.utils.xml.writer.XMLWriter method) +
        + +
        + +
        theta0 (astropy.wcs.Wcsprm attribute) +
        + + +
        to_header() (astropy.wcs.WCS method) +
        + +
        + +
        (astropy.wcs.Wcsprm method) +
        + +
        + +
        to_header_string() (astropy.wcs.WCS method) +
        + + +
        to_xml() (astropy.io.vo.tree.Field method) +
        + +
        + +
        (astropy.io.vo.tree.Group method) +
        + + +
        (astropy.io.vo.tree.Param method) +
        + + +
        (astropy.io.vo.tree.Resource method) +
        + + +
        (astropy.io.vo.tree.SimpleElement method) +
        + + +
        (astropy.io.vo.tree.SimpleElementWithContent method) +
        + + +
        (astropy.io.vo.tree.Table method) +
        + + +
        (astropy.io.vo.tree.VOTableFile method) +
        + + +
        (astropy.io.vo.tree.Values method) +
        + +
        + +
        type (astropy.io.vo.tree.Field attribute) +
        + +
        + +
        (astropy.io.vo.tree.Resource attribute) +
        + + +
        (astropy.io.vo.tree.Values attribute) +
        + +
        +
        + +

        U

        + + + +
        + +
        UnimplementedWarning (class in astropy.io.vo.exceptions) +
        + + +
        uniqify_names() (astropy.io.vo.tree.Field class method) +
        + + +
        unit (astropy.io.vo.tree.Field attribute) +
        + +
        + +
        (astropy.io.vo.tree.Info attribute) +
        + +
        +
        + +
        UnitConverter (class in astropy.wcs) +
        + + +
        unitfix() (astropy.wcs.Wcsprm method) +
        + + +
        update() (astropy.utils.console.ProgressBar method) +
        + +
        + +
        (astropy.utils.console.ProgressBarOrSpinner method) +
        + +
        +
        + +

        V

        + + + +
        + +
        validate() (in module astropy.io.vo.table) +
        + + +
        validate_schema() (in module astropy.io.vo.xmlutil) +
        + +
        + +
        (in module astropy.utils.xml.validate) +
        + +
        + +
        value (astropy.io.vo.tree.Info attribute) +
        + +
        + +
        (astropy.io.vo.tree.Param attribute) +
        + +
        + +
        values (astropy.io.vo.tree.Field attribute) +
        + + +
        Values (class in astropy.io.vo.tree) +
        + + +
        velangl (astropy.wcs.Wcsprm attribute) +
        + + +
        velosys (astropy.wcs.Wcsprm attribute) +
        + + +
        version (astropy.io.vo.tree.VOTableFile attribute) +
        + +
        + +
        vo_raise() (in module astropy.io.vo.exceptions) +
        + + +
        vo_reraise() (in module astropy.io.vo.exceptions) +
        + + +
        vo_warn() (in module astropy.io.vo.exceptions) +
        + + +
        VOTableChangeWarning (class in astropy.io.vo.exceptions) +
        + + +
        VOTableFile (class in astropy.io.vo.tree) +
        + + +
        VOTableSpecError (class in astropy.io.vo.exceptions) +
        + + +
        VOTableSpecWarning (class in astropy.io.vo.exceptions) +
        + + +
        VOWarning (class in astropy.io.vo.exceptions) +
        + +
        + +

        W

        + + + +
        + +
        want (astropy.wcs.UnitConverter attribute) +
        + + +
        warn_or_raise() (in module astropy.io.vo.exceptions) +
        + + +
        wcs (astropy.wcs.WCS attribute) +
        + + +
        WCS (class in astropy.wcs) +
        + +
        + +
        wcs_pix2sky() (astropy.wcs.WCS method) +
        + + +
        wcs_sky2pix() (astropy.wcs.WCS method) +
        + + +
        Wcsprm (class in astropy.wcs) +
        + + +
        width (astropy.io.vo.tree.Field attribute) +
        + +
        + +

        X

        + + + +
        + +
        xml_escape() (in module astropy.utils.xml.writer) +
        + + +
        xml_escape_cdata() (in module astropy.utils.xml.writer) +
        + +
        + +
        xml_readlines() (in module astropy.utils.xml.iterparser) +
        + + +
        XMLWriter (class in astropy.utils.xml.writer) +
        + +
        + +

        Z

        + + +
        + +
        zsource (astropy.wcs.Wcsprm attribute) +
        + +
        -
        - -
        @@ -63,7 +1922,7 @@

        Index

        \ No newline at end of file diff --git a/index.html b/index.html index bd641076..d515f474 100644 --- a/index.html +++ b/index.html @@ -3,17 +3,20 @@ + - Welcome to Astropy’s documentation! — Astropy v0.0.0 documentation + Welcome to Astropy’s Documentation! — Astropy 0.0.dev664 documentation + + - - + + @@ -46,25 +55,61 @@

        Navigation

        - \ No newline at end of file + diff --git a/install.html b/install.html new file mode 100644 index 00000000..656e9730 --- /dev/null +++ b/install.html @@ -0,0 +1,245 @@ + + + + + + + + + + Installation — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Installation

        +
        +

        Requirements

        +

        Astropy has the following strict requirements:

        + +

        Astropy also depends on other projects for optional features.

        +
          +
        • xmllint: To validate VOTABLE XML files.
        • +
        +

        TODO: Link to the planned dependency checker/installer tool.

        +
        +
        +

        Installing Astropy

        +
        +

        Using pip

        +

        TODO: Write once we’re up on PyPI.

        +
        +
        +

        Binary installers

        +

        TODO: Write about where to obtain binary packages (.dmg, .msi etc.)

        +
        +
        +
        +

        Building from source

        +
        +

        Prerequisites

        +

        You will need a compiler suite and the development headers for Python +and Numpy in order to build Astropy. Using the package manager for +your platform will usually be the easiest route.

        +

        The instructions for building Numpy from source are also a good +resource for setting up your environment to build Python packages.

        +
        +
        +

        Obtaining the source

        +
        +

        Source packages

        +

        Source tarballs of past releases and the current development branch of +astropy can be downloaded from here:

        +
        +
        +
        +
        +

        Development repository

        +

        The latest development version of Astropy can be cloned from github +using this command:

        +
        git clone git://github.com/astropy/astropy.git
        +
        +
        +

        Note

        +

        If you wish to participate in the development of Astropy, see +Documentation for Developers. This document covers only the basics +necessary to install Astropy.

        +
        +
        +
        +
        +

        Building and Installing

        +

        Astropy uses the Python distutils framework for building and +installing.

        +

        To build Astropy (from the root of the source tree):

        +
        python setup.py build
        +
        +

        To install Astropy (from the root of the source tree):

        +
        python setup.py install
        +
        +
        +
        +

        Building documentation

        +

        Building the documentation requires some additional packages:

        +
        +
        +
        +

        To build the Astropy documentation (from the root of the source tree):

        +
        python setup.py build_sphinx
        +
        +

        The documentation tree will be built in the docs/_build/html +directory.

        +
        +
        +

        Testing Astropy

        +

        The easiest way to test that your Astropy built correctly is to run +(from the root of the source tree):

        +
        python setup.py test
        +
        +

        There are also alternative methods of Running Tests.

        +
        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        Overview

        +

        Next topic

        +

        Configuration system Documentation

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/np-modindex.html b/np-modindex.html new file mode 100644 index 00000000..99902659 --- /dev/null +++ b/np-modindex.html @@ -0,0 +1,231 @@ + + + + + + + + + + Python Module Index — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + + +

        Python Module Index

        + +
        + a +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
         
        + a
        + astropy +
            + astropy.config.configs +
            + astropy.config.data +
            + astropy.config.paths +
            + astropy.io.vo.converters +
            + astropy.io.vo.exceptions +
            + astropy.io.vo.table +
            + astropy.io.vo.tree +
            + astropy.io.vo.ucd +
            + astropy.io.vo.unit +
            + astropy.io.vo.util +
            + astropy.io.vo.validator +
            + astropy.io.vo.xmlutil +
            + astropy.tools.misc +
            + astropy.utils.collections +
            + astropy.utils.console +
            + astropy.utils.misc +
            + astropy.utils.xml.check +
            + astropy.utils.xml.iterparser +
            + astropy.utils.xml.validate +
            + astropy.utils.xml.writer +
            + astropy.wcs +
            + astropy.wcs.wcs +
        + + +
        +
        +
        +
        +
        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/objects.inv b/objects.inv index fdd8d7f7a0518bd6bafcac99ff72d036de2730a3..932c0c34a3bdb7f9578176b6e88415c82c0b9efa 100644 GIT binary patch delta 8485 zcmWlbcRZVK7sgA}CRVAL)+)7k6rn#wl~&E#qc%lQqoiWTDz$eNReR6c#IB+?wIcT3 zV!zM(Up`Ns&wXF#I^XL&XY&5v|Gvr-T3LHaN{YuSJVVx+7`bB`D*dL)%~yX6$mCBl z8J+Do|9qP7FnPvVHdxwIEz=(#@$*rnV}#Yqfw-gXF$#aLum4GTn|jK{P2US>^#Uyl zQbxMVlinDwn3|R>DBtFWH6N?FKvv3c#Etis7%mXnA9C+5s?V9P(PQ#i)=f}KZ2s|o zD@yB_L~kUuW}LHdH^=o}ZGH`) zv^M>*>($bCEZP_+uTKFwL!z$zY*HAA9aVVN}ea zh0tJ&uwQ_Q8D1ut<1+@Amg+<^9Q3!?uuud)V(vlb@2)m43vNBOujjdaGQLRUIp%DT zHWu05GGOtQZ~J-Kg3q~w^S3PPTM_Ub2a{!?mzjRNQS<2;rf6EHc+1y54yA-+H>V&y zeKpxj+>p-$tP3U>Wj9|qs~*p;DcC2qFs*-AR!WISB{-Bi90 zlT^XY_ylJy`YgZgYTE6az1NXdLUOC)VuJJ=B&*!rVcw$95z_K{VZqPyY%Seq`pW3$ z09>EiCTRM{zdoKJ_VK1i(ud)C_Tgc#O&y1IN2LYDqi@_TL zqM`DRg>4OGN*mPV)oJNIs*V#M4}U)ARAtBX3j8-YaQr?XIFJ*B$0z%iE{6R$&LhuB zL6wJ9?tG7u_nPozl%8KNCD1x}ku?EnBiETSd3m?|YWJ~smkGxu~Abh;z%e|=JU?((< zn{hm7!2hU9r*Tas*#N4Yf|2E!2A}^6Jgy@-X77(4D-?RYsC^>$8hMt(64+sZ96#qu zU7RSNFq*%|h3l1h>!X_SA!Z@jvN8bNitDJpyMWCXV#H& zJggiyO8UPV4$#o^Xf{7-5K<%x`K~>p)M6C-=^})w{VJuz^8hF3M=<7NDJMXMQRKB< zkQ{WMYa762b>G%)2HK36A@4xGU>3RBDBaUv!toh{=MsL5;o;^@(Uj9 za9LX=AUmRbP|le|y1a9%S9m&fwIV#1cM4CA2>2#i=?rCQ{{q>QzX2^G-ML0?PRY9U zR?|&~ge+3Xwk-r5Ow4c^xKQ`uCS(NdIIEa>H2$?n;L}l!1khYDGReno-}a%_YTXzx zOm<5tcD=-F5=9agAYo$8Durcnz48i$AXP^T<*V7Fh}dp?oJcd1UEhO|#=4*P>!?;K z<+27UCf#*ETpiwGO)ijpn-cBBlUkvnqmM}2KDQ7(l{e6~Z)jo$a`?*zQQ~%+Z~?(jxn^B0JEzRnTn`^q&&)py?t32c5C0AlWs+EI5h4O_xCu1X zZtgMsF>L(H3l(R*vK0G95R02Oe>RKgy|LIr6Foq~;EmBMq zR~tQkqPfIB)ZL-7{&!iRXoX5vu!@~v&%1xUJ*fLg;;o^i=Y!9~@bpfb+)L>je2S@i zDct=(K<;KVJeG3$3A!{<{N9m+PBc3Q+WoGha!msL-x+K5ka8)M1t!r0m>KSNA1#yb ze_C678!mkAR{!0sYpiMnKsfI1VHS#nc#ewQg4@sUl~M5jSQ8$SD5a7@>Q!ZN}ijAV!gL^-q5bbA$yzi3qq_w65k z_qgX5xlJ6MpEuV;S1IT6JkL8y{D8}n{q)16%KqUg=oBgBz(&Zv-LN6t8llls?lXAin>Gq_dx$3opaU+ zJF9Mse`jowbiGqyoPmL`4+Wh6^||#WvVjrhd06j883%~DH7QErd9$&C26!g@mJ`ot zDHvUl#?@CE`|?wa(>IB=C|?hgi!8VD2~WEI>JeAZv3~r{$;Rs~+bCUs0nINR{2~R4 z5k|H33InrEE%^I&HkF31-(^(W8bfhU&B&C%wE&0vmhQ0ppv%ohSo~eUYe} zodVNeQS>7gmzzu}_msSJ*RRf9O75?{Ry40czT~bOpUXvzP?bfO1xUyWC);6nC1Db#w$VQSZLrsj(Am+H^I9y z>)o$z$7#N{e}t%4+Douc4XK?l_MhOdS3{P*VS{xWiX}&CM}upgkClB5|LExwq)t_& z0S^$kkDO{zU#RJ{i)H4r_Nb;H$a6X7lt$h>X-WjfgO0 z@Y$J(!p>EbY22h~7nP3Qa~bDmuQNC4Hh+P(x`iXh5*i{ZUyD8BR_S6sj?|Z*YtoPk zLq5oIkuTK0$?*+6Qp?)^6s?&g26k3y;mzqJa`>CoHmZ>MI0*zzk@Yw1S`>=}#MOG6 z1bHWpriY)J{SDlcdTe+4rTq8}bb0?^r)z#i?&HeEoglaQ5OY zOR0Lo&D+CKzK4B=-6m~?Vr~XB9s@^6UA2ze+1Ui+Al?pARk7^?7K-T+cGX9uokfnL zurgvKF!OV_-lm3amSuisq z+mImMVD*_ZebjzR%3*+)xcz~HfLs)l`i34CP*_!xoQT2SFPsac z)AB-$f5y>W>%J!JZPc_bZi*OH*JrMm5qGZNu*tFOmsNd)%`{$B6Skcyv~l`zw|)cn zzK_+PV*J~si!JG9<4FMF<;4fFBF+9FY8&0Z7Vu=bpk)t6u|}CY4F}`BZqU=2i>#L8 zt;f@XV~R(X($?2oU1KOG@#F!#&tzf`uKTHCg;RsR^e)!1O{#@vWqIrTA_}!--Zc+J zbp*J`1ygy(>hWy(^v_K5Cw%s^2Jo^G9FftBC!dbyXXtmdnxiSolAybCB(^ zzwVbEvf)g_k5SIAizxvCHPpMz#2d`b}l$w#~jsa@!Ht6H!&n>W~=QKKD; zvX7L8wk}SX6%jYT$Wks-icSpu?o&z|+=LKGCT~Hge*FCJI^r{j-TT-J-;;o~S}~#; z2cey+VF{2`D=xL|=INw6|Kazsxw$$`_J(9P#mD4o)w|b_d0ufz);6TP>JmqyLhnMs zU7*rJMBdqWvgnC}Q1t_;gd({=?d!%lj;#qKb&s_Kw1pcjQ$i@Fdh?=6zM4{9d~&W| zp$K9>C%fY@lh_|DcNS5X0vp1BS;k+KqWsS&t5+PBE|F#>B zE)eH0b)y^@t@79q`c{TplMi*7>kd=uyLsrL9Y!-UsO!_ms^7de>$No0=$)JY6kR?J zFoM~F3(2d}=mb)f1WQM$9zI#`&B#|N!t*qeH>Llsv@sg(-l52al*)^FmRxEEI<~LX zd{}Q%cEDm(>RuK&m659}6OMs&er$acsKmq;rJjyH=a_7^4pQ0m(r$cDCzNK+c;Uuo z<+JcJ4}u-3qm>m(x3Xr#wNkYM{J$Pip75IpF|noo=_~mfb6`aNw6kzUvz%>jSlOjZg3|Tcb9E}6TgN>VqEGF#1l+e+!hKklRdb<< z8W%tEnF5f%x%Pb1OF1mK%}jsbt^M3c5>!vN9I(V$l>WBBjy_is-gvu}ACwqITEx0> z;gEO!(w&y+7>OB@ClX7NU2B&5+VK>}V=e4RoLdB+>~lnJiuUWhn)v!qSA&h*r}Es4 zCCSVlE>1KmWCCML#*lJzwb&Sj<*WxAXofnPt23EO#)pEix;BI1c$-OWA|Wr8QW8iW zg2?%)leV2{%`?sprURZA8c(Wf6^xJ%7V=xTWo!*_M=Hi%{B8tg)hu&_3Wpt(5dQt0 zMAJvr-V=$G3)XLH(XLJ2x2XK3DYD#L67ctPzp~ykmw^rYG1_>9_TgtDX@l}wc_nx( zO7YFikZzct`D^#bI#z?{6H%LL#k*5=?l0UlY_$T(qgsQG>>HmAy=sVm_|1~zn1%WC z074i}DxC1)nZ%Ly6Q>V`!f;Xgr4JP~{-ZTp88t>x$Zj`=(7@zaRu(eT%W5rK;u-rE zDBS$VD|91c73Uj|2cfo2&%b}GyA=&fFqY8&(Ee4*eMt)+Uw)cc9~TvCtu6Cvf=j^c zJ)d{_$lLBVUT!O?q;+PFJSy=3jLe8*3kR4UJqAdzg^LQ3YRLT<|sw2z9CN~Db< zbsfjDg00Gzt-j7_N(y`urqx_77cU>panYuw?2h)3(qOdNT1(v;%=jaNqJAB)~HUg!LkjZ?#p_L%{-LnB-iUR z^k&|ehpLHcTia^HQO|I)o5+7zHCaEWt6<*!8G~mr4-`wu?bJ+%3Ks1)v`&^w`!*f2 zKRmP1C1VaD$;*S*lC+qBZkUsb%pXZUl0LJeMpizkll30r@uU>0%G|fecd2;XDeZm` z$6smjC3#0_mF&)JZCJ&Vw_-Z1v(0?6^M{2x!ArF0G4{z0Hqc*}TYyI(^v@SR! zwMPy1T#IzjWF_9v#dd(ikW_V}>& zjmBT_b?`h+_sktirID)L-740PTKXro-Q=D9D5@z~VnI0W(ZGYe(7LsODvx~!F^&gp z3VU-QZ+JOA<3Y3s5={LH^@2IxkN5SAOr;^YJ9@ewKY8Untf?S`w;eP%d+<{4TYQWZ zt5Wtj-CrF`6KYuoJ(I(-p*bVfm-P_}uM?)dlYBAqpm|>7-<}NO+BjJ7q5Dii#UQx^ z%+NM)@(jFmy3kMNW5;`pDGMykYV@Q_AQ7gN=V4Vkx$>DOmkkxYudqhx6uCCEmbQib zO&`WsUx_9h?D{oh@@P+ceQ7$}uFe|8fw8^hA<|3T3}0xRd6A~4lU_u@-ES9Bz0bHk zkgSO}TUYLGG<-AO?W7(AzaaYK!cug<;aFE!B+a-G%$fvEjodsj7|3CgXj^n>@PL~) zP7rSXIF6ujA~G;}qI4WNQyY!Mglbf30HJ$h1lM-_JN1tjJS=u0H~NxwSWz-Fth^a6;Ym=~`Un z3Pd_nH>0q~HiN$0rpO&B1H$14{U1bdvv&GvxPfC zmZG|PfoTJKVFvRty5}Yi&8WZf z9%q<{XI5WMxZ>0>Ztcum5x9;0aB-_^9+9T$>$eL8*#kE>+rC%2V(XHOloP)+KuXHWXcNj~<+p8D4d3E7@7b#9XPy8NVBs#1?A zekr`@&CXJ5n=v0FD8Jw0#ZU2jmL=)Lj2V#{?Fu0-cfGKMKX zew#{xV453d#j=wnZ%j;yE){a74vEclN-x%I;wVw>_!yy6sI+8~m0?)1m-K#;RYZSk z*W-tG>*qIY1m8Y+*JL72u~7@LIOfX^a?6f%HB;ihz?=6B^hf|BRGEOvwMgnSJi&#rZ{6# zu_*jKQkU`FH12}|tJ-%nDQ<1%DYZ2cZ){#3d8$FQ8P>cqN6|~~;EHS7`itK**(IE7 z5{5r|tRWwJEGdV7!kLETJ)dn%ntM9pDo81_pd#X(6>b?g1+PtSE!(fjk(^?Qf`KLS z^vtw+HYV(cdUS5p@gJ^vC8cf6lO>z3XR3*oWGZu`^#|q59N{SsL zeH`U3lG0nHOXPvPU>H}U+C4h3Zsd0IGc@?N`R1`ri`8Ki;$w$^<;UQZvQ)w}Pp%i1 z5Qg>z!}?OLQ&Fxl-BV}0XA8vziTGIh0YUtbL@~dul0B`Q)YTJ?rdk&#_2Zdy7N(m= z?l%)X8;au;`@cNuu1+WL)t|d8%5JT3-tX)@6)O@FeO315_a%At+7kM&?PzOV_qFVONSSH}8)T>kGl_$TqQY_T6V)k{8%3_z zA!Z}}ohO&q%oGjq_ZBAt3c_Q8WvJ@g@Z_n(vJuzJ08*q(QqazgF#coE-$0;TKW$#v+nLasA?Mm zGDHJ+sr><_#8xT_tP-1ohk!b=PIaL;o+^W2EUu1(hnT^C|8=4G47{Hq8VHrxU@U4e z4-YVXqcDH4lrV$|#-iOJb$}@#U+hAOiR|(s8h%o6FQa1#9LXWh=9`&^m^51C$`ZO# zDP?a)e+f;oX$ym~Jg_u&64Fb!<3Vr6z2eV7uw5v54m4E*QK%fFJ7k_Y)I3 zA-)FavsJ0_A%-|zDiFN>w7%+oVqqXPB${d9>=46!^sp zN=;@+wC30CW%TRy7j*}ipC*+>jHP1#cn>feoL4yb=YH!YbnO3k&mk*7pWGr~^3!Yp zzrtp*XmD@xuRbAfT1PCJLYhqw2k$9}hy<&oe+Q~BPXJ^~=gp!~)s(comku}_obp*M z;O)Ry5=gX3a>*ekB?mbNFuSu3g|WDcGC`b~w0nOuo-$M9cc5}r9@FFCQ4ZORkZAq% zjU}`zUH>1n!iS|`a4(OiAqM>g$3}pFP7OW}2lu`@^E|{r^Ax^-dy7N9V9?Ztlsn6F_5}3@A0>H+oi#fL=CeCdEp{oiqby&%Qbs_x zC)her*t*Z6X^DW+sJsopKPB^@{tb#t2mSFV9~E# zNsTe+L+-Iol>5PJW`K2GfC1NZ=6~i4Z_QBS`DJQPqv2eZYtkCIRSkUcb8p z!b@KW%#`=x&_#=%RLE3lvG0Js`R7J$cmN^%k4UOCu8CklJIb#jPlh!+7S z?>isB$&tMas-HgtK@^ba_@f&wHfnPK>8(z{mdpaCE)*7d)J_FsQ3N)TC@~m|3Ui*I zEtLc;qj<4n?{yV`Lazu22QTX&zF7_cZu%M7-KOVB0C5g{^Tcnp3-~PUXO{zW%0&!t zXQS2u_(%w~0OiDHl>&uo$8m$Yfwa`k8)4DE3PBvOIi1(D*EMbcKWH&Pflul;!P6fy@%L03f%08vmm@ii6MD zG$?H)O=$vyO@QJvq9HWGatSTs+$98jrnv~PB7~AKmYds*=Tz)8u#D|Oum1~J59cn3 h_W-E(0X7DCGCBklg|%h{QudJbt+V>I5Xy9*_S4KLIe2MLK`2RZWl6Fc7`_SB%6S*n_FKa%+n~d#I?E1&);yPg1L~ z9obGx{ypP3PP^YCF)e?T3G_q9Pu3l( z#-3hIDtj!>QM+tQ;5V?Do*+LlA&m4GEgS_cy@vx8T;*W^tz?$4#+DM zp>xO!N7nsZ)EjZ2u7d!BCm1OpQLtJCURqPBI`S&rilAbOf2Y2f(+zyG4#J)$l>wN; z(jL(fF|VA}T%-5AYv+He>3)KT2oEE?XEmB2Fq0n=s_l0sh zDm*b|d=O2;sn1tnlhbS0_$2S0&=aK zvyKPXnZsON_!gmK=5aL=0oV!#4we++wP!Y<{Q1UKSSv$Ee#?J4AIE*&C?2i%+M3{0 z(GA5s*u_W`zm~K(w(WsRTUM276g5-AR+I-(qaW_ep|_nY(O)^U$v@M7ri>>eyNG*j z`<`puB!wP@`(1>RZM>qd$ze-{vWlW&J7(IPH63F}q7{)DO6udBa{NFW89^h*RPk91 zd6E9G{_nW@mN1UIU&Wu17;?gco9Fn=lJi*n|6gZCZP G(@hIlMJNpb diff --git a/overview.html b/overview.html new file mode 100644 index 00000000..3b163191 --- /dev/null +++ b/overview.html @@ -0,0 +1,209 @@ + + + + + + + + + + Overview — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Overview

        +

        Here we describe a broad overview of the astropy project and its associated +modules and packages.

        +
        +

        astropy Package Layout

        +

        Astropy contains the following base-level subpackages:

        +
          +
        • +
          config
          +

          This subpackage contains configuration and setup utilities, including the +affiliated package install tools.

          +
          +
          +
        • +
        • +
          utils
          +

          This subpackage contains utilities of general use for multiple modules or +affiliated packages.

          +
          +
          +
        • +
        • +
          version
          +

          This subpackage contains the version number information for the package. +Note that the version is also available at the base level of the package as +astropy.__version__.

          +
          +
          +
        • +
        • +
          extern
          +

          This subpackage contains small python packages that are not unique to +astropy but are convinient to include as part of the astropy source code.

          +
          +
          +
        • +
        • +
          tests
          +

          This subpackage contains utilities to run the astropy test suite (the +simplest method is to just call astropy.test()), tools for writing +tests, and general tests that are not associated with a particular package.

          +
          +
          +
        • +
        • +
          wcs
          +

          This subpackage contains a python wrapper around the +wcslib library for +managing FITS world coordinate systems (WCS).

          +
          +
          +
        • +
        +
        +
        +

        Affiliated Packages

        +

        Astropy also includes the concept of “affiliated packages.” An affiliated +package is an astronomy-related python package that is not included as part of +the Astropy source code, but has officially requested to be included in the +Astropy community. Such a package may be a candidate for eventual inclusion in +the main astropy package. Astropy comes with a tool to install a affiliated +packages by name, and a single official index with a list and description of +each package. See the config module documentation for details +regarding this install tool.

        +

        Affiliated packages do not use the astropy namespace, but rather either use +their package name directly, or awastropy.packagename (“affiliated with +astropy”). These packages may later be merged into the astropy package, in +which case the original package may still be used, but it is recommended that +users switch to the astropy.packagename version as soon as possible. +Alternatively, some affiliated packages may not wish to ever be merged with the +astropy source code, but rather remain as separate packages that make use of +other astropy modules or affiliated packages.

        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        Welcome to Astropy’s Documentation!

        +

        Next topic

        +

        Installation

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/py-modindex.html b/py-modindex.html new file mode 100644 index 00000000..6a82acec --- /dev/null +++ b/py-modindex.html @@ -0,0 +1,231 @@ + + + + + + + + + + Python Module Index — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + + +

        Python Module Index

        + +
        + a +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
         
        + a
        + astropy +
            + astropy.config.configs +
            + astropy.config.data +
            + astropy.config.paths +
            + astropy.io.vo.converters +
            + astropy.io.vo.exceptions +
            + astropy.io.vo.table +
            + astropy.io.vo.tree +
            + astropy.io.vo.ucd +
            + astropy.io.vo.unit +
            + astropy.io.vo.util +
            + astropy.io.vo.validator +
            + astropy.io.vo.xmlutil +
            + astropy.tools.misc +
            + astropy.utils.collections +
            + astropy.utils.console +
            + astropy.utils.misc +
            + astropy.utils.xml.check +
            + astropy.utils.xml.iterparser +
            + astropy.utils.xml.validate +
            + astropy.utils.xml.writer +
            + astropy.wcs +
            + astropy.wcs.wcs +
        + + +
        +
        +
        +
        +
        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/search.html b/search.html index 1ad12e0f..03a2b02f 100644 --- a/search.html +++ b/search.html @@ -3,17 +3,20 @@ + - Search — Astropy v0.0.0 documentation + Search — Astropy 0.0.dev664 documentation + + - + @@ -38,7 +41,13 @@

        Navigation

      • index
      • -
      • Astropy v0.0.0 documentation »
      • +
      • + modules |
      • +
      • + modules |
      • +
      • Astropy 0.0.dev664 documentation »
      • @@ -89,12 +98,18 @@

        Navigation

      • index
      • -
      • Astropy v0.0.0 documentation »
      • +
      • + modules |
      • +
      • + modules |
      • +
      • Astropy 0.0.dev664 documentation »
      • \ No newline at end of file diff --git a/searchindex.js b/searchindex.js index 0ef27e7e..be885895 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{scm:14,represent:[12,4],all:[2,5,6,9,12,13,11],code:[1,2,5,3,6,9,10,12,13,11],consider:5,osx:14,illustr:[5,2],pep:[5,2],global:[10,6,9,13],yellow:13,signific:[5,2],concept:[0,5],per:2,computation:2,follow:[2,7,4,5,6,3,8,9,10,12,13,11],alt:6,haggi:5,compact:4,cython:2,privat:5,complet:[2,4],depend:[5,2,11,10],system:[5,11,2,6,10],graph:[12,4,13],elsewher:5,readabl:[5,12],pycodecheck:6,fft2:5,articl:5,environment:5,messi:[12,4],init:6,present:[12,2,6],under:5,sens:5,save:[12,6,13],messag:[12,6,9],adapt:[5,11,14],"case":[5,11,2,12,4],file:[2,5,6,9,12,13],sourc:[5,2,10],string:5,ndobj_old:5,fals:12,mpl:[5,2],util:2,print:2,candid:5,mechan:[5,2,11],upstream:[0,12,4,13],veri:[5,12,13],affect:[2,12],relev:[5,2,3],method:[5,2,11],cool:[12,4],magic:0,when:[2,5,6,9,12,13],level:[11,6],did:12,notabl:5,flymak:6,list:[5,7,6,9,12,11],prefix:5,iter:5,"try":12,red:6,team:[10,11],quick:[5,9],set_color:2,refer:[5,11,12],overview:[5,12,9,4,13],pleas:[12,9],prevent:[5,11,13],impli:[5,4],smaller:6,abil:12,natur:5,consistent:2,direct:[5,2,11],meld:12,maintain:[10,12,4],jump:6,second:[5,4],blanklin:5,design:5,pass:2,download:[6,2,11,14],further:[5,2,11],click:12,compat:2,index:[1,2],what:[5,2,12],msysgit:14,sub:[5,2],compar:4,defin:[5,2],infrequ:5,section:[2,4,5,7,6,10,12,13],asid:5,abl:[5,11,4,13],brief:5,uniform:11,access:[11,2,12,9,4],delet:[12,6],abbrevi:5,version:[5,2,12,10],"new":[2,4,5,6,10,9,12,11],setter:2,ever:11,"public":[5,2,12],nep:12,metadata:2,submodule1:2,submodule2:2,dropdown:12,gener:[5,11,2,12,9],never:[2,11],decid:11,matplotlib:[5,2,11],instanc:[5,2,12],satisfi:[11,6],explicitli:[5,2],let:[12,2,6,4],cursor:6,agre:11,trunk:[12,4],path:[5,2,6],safer:2,becom:5,modifi:12,sinc:[12,2,6,9],valu:[5,11,2,6],wait:11,convert:[5,13],produc:5,ahead:12,larger:5,host:[2,8],scari:4,precis:5,doctest:5,pick:12,action:12,awastropi:2,implement:[5,11,2,12],fourier:5,chanc:5,ourselv:5,via:[11,2,12,10,4],repositori:[10,4,11,8,2,9,12,14],packagenam:2,danger:2,dtype:5,modul:[5,1,2,7],prefer:[5,12],submodul:2,backtick:5,vim:13,deprec:5,api:[5,13],send:9,visibl:5,marker:6,instal:[10,6,8,2,11,12,14],should:[2,4,5,12,13,11],unit:[2,13],sky:5,plot:5,from:[0,2,4,5,11,6,9,12,13,14],describ:[2,5,8,7,6,10],would:[5,11,2,12],commun:[0,11],fill:[7,6],doubl:5,regist:2,two:[5,10],subvers:0,websit:6,few:[5,11,2,12,4],call:[2,12,13],typo:12,recommend:[5,2,7,4],black:6,jonathan:13,type:[5,12,6,9],until:11,more:[1,2,5,9,10,12,11],sort:5,desir:11,henc:6,relat:[5,2,12,4],pylint:5,about:[5,2,12,9,10],notic:12,enhanc:2,warn:[5,2,7],trail:6,flag:[12,9],exce:2,templat:[5,2,11],particular:[5,2,12],known:5,set_valu:2,easiest:[14,9],must:[5,11,2,6],fly:12,"_flymak":6,account:12,graphic:12,word:[12,6,13],augment:5,alia:[12,13],setup:[2,6],outlin:[5,2],uniqu:4,histori:[0,12,4],remain:12,paragraph:5,can:[0,2,4,5,6,8,9,10,11,12,13,14],learn:[0,10],imped:2,webster:13,purpos:12,root:2,fetch:[12,4],def:[5,2],appropri:5,control:[10,12],backspac:6,explor:[5,12],"65af65":13,give:[0,5,2,12,13],process:[5,2,11],lock:6,sudo:14,share:12,calcul:2,indic:[5,1],abort:12,tab:[2,6],onlin:0,standard:[5,2,7,11],spc:6,unus:2,delai:6,alwai:[2,11],scalar:5,cours:[0,13],multipl:[5,6],goal:[5,11],quot:5,pycheck:6,anoth:[5,12,13],comfort:10,length:5,invalidwcsexcept:5,aclass:2,snippet:0,how:[0,10,4,5,8,9,12,11],anyon:[3,12],recoveri:12,pure:2,"__all__":[5,2],answer:5,instead:[5,2,6,9,4],config:[0,2,5,9,10,13],get_color:2,updat:[2,12,10,13],mar:2,resourc:[0,2,10],circuit:2,referenc:5,mess:12,keithdeven:2,clone:[0,10,12,9],after:[5,12,10,6],minimum:13,"956fbab":13,befor:[2,4,5,8,12,11],wrong:12,attent:12,commit:[0,4,9,12,13,11],mai:[2,5,14,12,13,11],end:[12,6,4],underscor:5,associ:[5,2],grow:11,harmon:12,mous:6,"short":[5,2,12],practic:[11,13],vicin:5,array_lik:5,read:[0,5,2,12,4],confus:[5,2,12],spectra:11,buxfix:12,corran:13,assign:5,caus:6,enh:12,geoscienc:5,preced:5,combin:[5,12],allow:[5,12,2,11,6],enter:12,lambda:6,order:[5,2,11],mcnoleg:5,excurs:6,hugo:13,help:[0,2,5,6,10,12,11],rhetting:2,over:[5,2,11],move:[2,9],becaus:[5,11,2,12,4],kbd:6,typewrit:5,whilst:5,through:5,same:[0,5,10,12],left:12,hierarchi:2,still:[5,2,12],pointer:6,e701:6,paramet:5,"2_installing_git":14,write:[5,12,6,4,13],style:[5,2,11],outer:13,get_valu:2,fit:11,matthew:13,chosen:10,invalid:5,fix:[5,10,12,9,13],sourcetre:14,better:[12,9],resort:5,window:14,html:[2,14],wordpress:2,persist:2,bin:6,mail:[7,12,9],main:[11,12,9,4],might:[2,12,13],pixel:5,them:[5,11,12,9],scipi:[5,2,11],crash:[0,6],thei:[5,11,2,12,10],python:[1,2,5,3,6,10,11],auto:6,supersed:5,alist:6,initi:[10,11,13],underneath:5,mention:5,facilit:[5,11],now:[12,9,4,13],discuss:[5,7,13],oper:2,introduct:[0,10],choic:[11,13],document:[1,2,3,5,6,7,8,10,12,13,11],somewher:9,name:[2,4,5,6,10,9,12,13],anyth:[2,12,9],edit:[0,5,12,9,13],simpl:9,wdiff:13,refresh:6,linspac:2,separ:[5,12,6],astronom:11,achiev:[11,12],alreadi:[11,2,12,9,4],mode:[6,9],each:[5,2,12],"29001ed":12,found:5,went:12,collaps:[12,6],button:12,mean:[5,11,12],compil:2,inplac:6,"6ad92e5":12,replac:[5,6,13],individu:6,hard:[5,12],continu:11,procedur:11,realli:4,tip:[0,2,6],astropi:[1,2,3,4,5,6,7,8,9,10,12],expect:2,forgot:12,our:[5,12,4],thing:[0,12,9],orient:5,special:[5,11],out:[2,11,9,4],variabl:[5,2,6],shown:[5,6,8],voidspac:2,network:[5,12],space:[5,2,6],goe:2,b605216:13,crucial:2,"4aff2a8":13,identifi:[10,11,13],your:[0,10,4,9,12,13,14],content:[5,1,6,13],rewrit:12,laid:2,reflog:12,rel:[5,12,2,6,13],reader:5,sparingli:5,got:[12,4],current:[1,2,4,5,7,6,12,13,11],ref:12,correct:2,math:5,integr:[5,2,11,10,4],clarifi:5,linear:12,insid:5,workflow:[0,10,4,8,9,12],brett:13,situat:[5,12],given:[5,2,12],free:[10,14],test_bugfix:13,standalon:11,reason:[5,12,6,4],base:12,modnam:2,theori:5,usual:[5,12],put:[5,10],embarrass:12,new_file_nam:12,bash:6,care:5,indent:[5,2,6],unwant:12,could:11,ask:12,mac:14,advanc:[0,12,10,8,9],keep:[5,11,12],recov:12,turn:[12,6],perhap:12,enforc:13,place:[2,6],outsid:[2,11],enough:11,principl:5,onto:12,interact:[12,6],first:[5,11,12,4],origin:[5,12,13],softwar:10,suffix:6,directli:[2,4,10,12,13,11],onc:[11,2,12,10,13],arrai:[5,2,13],independ:11,qualiti:11,number:[5,11,6],yourself:[10,12,13],hook:6,instruct:[12,14,10,8,4],"68f6752":13,done:[10,4,9,12,13,11],fast:[5,4],blank:[5,6],oppos:2,stabl:11,ndobj_new:5,open:12,"long":[2,4],fanci:[12,13],size:2,"7beda5a":13,differ:[5,11,10,6],set_:2,reword:12,convent:[5,2],script:[11,2,6],data:[5,2,13],top:[12,4],sometim:[12,6],least:5,checker:[5,2],underlin:5,draft:[1,2,3,5,7,6],accept:[2,10],similarli:2,termin:5,white:6,man:12,cite:5,store:2,prone:2,adher:2,luckili:12,option:[2,4,5,6,9,12],courier:5,especi:5,namespac:2,fuzzi:5,tool:[0,5,2,11,6],copi:[10,5,6,9,12,13],specifi:[5,2,6],"var":5,yuri:13,getter:2,enclos:5,checkout:[0,12,9,4,13],kept:5,exactli:[5,11],haven:9,progn:6,serv:7,succinctli:12,conveni:0,tangl:12,keyword:5,whenev:[11,4],clariti:2,remov:[5,12,6],branchnam:12,tree:[5,11],see:[1,2,5,9,10,12],structur:5,charact:[5,6],project:[0,1,2,12,5],apt:14,stall:11,str:5,posit:6,video:0,minut:13,other:[0,2,4,5,11,12,14],mathtt:5,beginn:[10,8,9],seri:[0,4],pre:[5,12],mini:6,sai:[12,4],comput:[5,10,12,13],abov:[5,12,4,13],summar:11,"26aa21a":12,viewer:5,thereaft:11,pro:[0,2],mind:5,ani:[4,5,9,12,13,11],packag:[1,2,3,5,7,8,10,12,11],clutter:5,manner:2,have:[0,2,4,5,11,8,9,10,12,14],propos:13,need:[2,4,5,6,10,12,13,11],exclud:4,seek:11,normal:5,issu:12,date:[5,13],squar:5,equival:5,inform:[5,1,10,3,12],self:[5,2],"switch":[12,9],port:14,note:[2,4,5,6,9,12,13],mix:2,builtin:2,discret:5,take:[5,12,9],advis:12,tupl:5,techniqu:5,subject:[5,2,7],brace:5,bundl:2,singl:[5,11,12],expens:2,pyx:2,simplifi:2,begin:5,sure:[6,8,4,13],unless:[2,11,13],distribut:2,preliminari:12,buffer:6,githhub:12,previou:[12,6],reach:[11,4],discov:[5,9],most:[5,10,12],render:5,larg:5,phase:11,alpha:5,subset:5,judici:5,everyth:[11,12],appear:[5,4],latex:5,wish:11,don:[12,6,9],expert:5,consist:[5,2,11],url:12,doc:5,clear:5,later:[10,11],cover:10,doe:5,abbrev:13,part:[5,11],yum:14,clean:0,warmli:9,hardcor:12,latest:10,pyplot:[5,2],tear:12,introspect:5,show:[12,2,6,4],joshu:13,text:[5,12,6,4,13],random:5,radiu:5,syntax:[5,2,6],connect:12,bring:[12,6],fink:14,you:[0,2,4,5,8,9,10,12,13,14],particularli:5,hack:[12,9],inherit:2,font:[5,6],find:[10,12,9],"0f22701":12,absolut:[2,10,13],onli:[2,4,5,6,10,9,12,13,11],maskedconst:12,locat:[5,11],execut:[5,6],pretti:13,plt:[5,2],menu:[12,6],explain:[0,5,12,9],configur:[2,5,8,6,9,10,12,13],solut:2,written:[5,2,12],than:[2,4,5,9,12,11],dict:5,rich:5,local:[12,6],creset:13,meant:5,info:[5,2,10,13],"6d8e1e":13,contribut:[12,1,10,3,8],variou:10,satisfact:12,between:[5,2,11],pypi:[2,11],func_b:5,autoload:6,repo:[12,4],obviou:5,cannot:[2,11],ssh:12,cheat:0,"import":[5,2,11],increas:11,tbd:2,requir:[5,11,2,6],layout:[2,11],think:[12,9],bar:2,enabl:6,organ:[11,12],typeset:5,parabl:0,specif:[5,12,2,6],coord:5,patch:[11,9,4],provid:[5,11,2,6],bad:2,stuff:[12,4],common:[0,1,10,5,3,13,11],contain:[5,2,11,4,13],"376adbd":13,where:[0,2,5,6,9,12,11],seamlessli:11,vision:[1,10,3,11],summari:[0,5,10,12,13],wiki:1,conform:2,reduc:[11,12],set:[2,4,5,6,9,12,13,11],detail:[0,10,5,9,12,13],respect:[5,8],placehold:13,maximum:6,index_bi:13,emac:[2,6],bare:13,result:[5,6],reserv:2,close:[12,4],zaytsev:13,best:[11,9],concern:11,awar:5,statu:[0,12,9,13],detect:4,kei:[12,11,6],correctli:[12,8],databas:12,someth:[12,9,13],thumb:0,"278dd2a":12,hhuuggoo:13,state:[5,12],quickest:9,simplest:[2,9,13],progress:[12,9],awai:12,approach:2,across:11,attribut:[5,2],altern:2,signatur:5,unmodifi:9,terhorst:13,extend:[0,5],exampl:[2,4,5,6,8,9,10,11,12,13,14],fk5_to_gal:5,contort:5,sophist:12,copul:12,extens:[5,2],entir:[5,11],here:[0,2,5,8,9,12,13,14],recent:[10,14],highlight:6,ipython:12,func_d:5,come:[0,12,6],thank:[9,13],func_c_:5,sketchi:13,accident:12,last:12,easi:[0,5,11],impliment:13,admin:12,similar:12,howev:[5,2,12,10],hint:2,equal:[8,13],etc:[5,11,4],tutori:[0,5],equat:5,committe:[2,11,10],logic:5,mani:[0,5,2,11],highland:5,com:[10,4,2,9,12,13,14],con:[2,6],load:6,simpli:[5,2,14],consolid:11,technic:0,point:[5,2,12],color:[2,13],guidelin:[1,2,3,5,7,6,10,11],format:[5,2,7,9,13],ubuntu:14,gitk:12,header:5,"5e9":2,sky2pix:5,framework:[5,7,11],linux:[0,12],diff:[0,12,4,13],comprehend:5,gitx:14,e221:6,simpler:2,duplic:[5,11],sever:[5,6,14,9,12],quit:12,ultim:[10,11],strong:11,why:[2,12,9],platform:5,addition:2,func_a:5,numpi:[5,2,11],three:12,been:[1,2,4,5,10,12],mark:[5,6],compon:[2,11,10],much:[11,12],autofil:6,interpret:6,interest:[5,3],basic:[5,10,6,4],addit:[5,6,2,11,14],"__doc__":5,rather:[5,11,2,12,4],both:[5,2],imag:5,star:2,search:[5,1],argument:5,deliber:12,coordin:[5,2,11,10],understand:5,togeth:11,input:5,summat:5,impati:[10,9],those:[0,5,11,12,4],blue:13,sound:12,multi:5,onelin:[12,4],look:[5,12,4],amend:12,cred:13,also:[10,5,11,7,6,12,13,14],properti:[5,2],easier:12,aim:11,cast:0,"while":[5,12],my_new_fil:12,behavior:13,error:5,pix2ski:5,region:6,rebas:[12,4],stop:[12,6],krige:5,vol:5,made:[10,4,2,9,12,13,11],tabl:[5,1,11],readm:12,site:5,worri:12,numpydoc:5,"2dec1ac":12,pip:6,good:[0,4,5,12,13,14],motiv:5,get_:2,"return":[5,9],revis:12,"__init__":[5,2],around:6,disabl:12,develop:[0,1,2,4,10,3,8,9,12,11],welcom:1,author:5,perform:2,suggest:12,make:[0,2,4,5,6,8,9,12,13,11],belong:5,shorten:13,defun:6,who:[11,9,4,13],funni:9,lengthi:2,complex:[2,11],gui:[11,14],sentenc:5,fedora:14,eventu:11,start:[5,11,12],conflict:12,higher:11,week:13,competit:11,finish:[12,9],archiv:2,context:[5,6],nil:6,pyflak:[5,6],assist:5,upon:11,someon:[12,4],remot:[0,5,12,4,13],rais:5,temporari:5,user:[0,10,5,9,12,13,11],improv:[2,10],extern:[5,2],robust:[2,11],wherev:2,typic:5,expand:0,built:5,safe:9,task:[5,11,12],off:4,lib:12,discourag:[5,2,11],neural:5,incorpor:[5,4],markup:5,happi:12,well:[5,12,8,13],hypothet:5,object:[5,2,12,13],without:[5,12],thought:12,person:13,weblog:2,contact:[10,13],command:[0,12,6,9,13],setq:6,thi:[2,4,5,8,7,6,9,12,13,11],choos:[10,12],gzip:12,strive:11,latter:5,meet:2,explan:[5,12],comment:5,itself:11,protocol:12,paus:12,just:[12,10,6,9,4],less:2,excel:[0,9],obtain:[5,6],rest:[5,12,6,4,13],activ:[0,11],collabor:12,shape:5,pep8:[5,2,6],spread:5,human:5,behind:0,yet:[5,1],sugget:2,web:[5,4],detach:12,expos:5,botch:12,preclud:11,had:12,except:[5,2,13],littl:[0,12],add:[0,4,5,6,9,12,13],macport:14,"2e991e8":13,appli:12,effect:2,els:[12,9],ufunc:13,subsequ:10,transit:11,match:5,build:[5,11],real:5,applic:5,torvald:0,"11ee694744f2552d":12,which:[2,5,6,10,12,13,11],whatev:11,mayb:12,handl:[5,12],foundat:0,regard:[5,2],consensu:11,suppos:12,alias:13,know:12,background:[5,6],press:6,world:5,tick:5,non:[5,14,13],licens:[5,2],review:12,sternli:12,insert:[12,6],fixup:12,like:[5,2,12,4,13],lost:12,whitespac:6,"721fc64":12,d304a73:13,signal:[12,9],arbitrari:12,manual:[0,5,6,4,12],fernando:0,collect:12,benefit:[11,13],necessari:[5,2,9,10,13],eadc391:12,docutil:5,leftrightarrow:5,output:[5,12,13],tower:14,manag:[0,14,4],www:2,drop:6,often:[5,2,12],habitat:5,ascend:5,back:[5,12,9],resolv:12,intern:[10,8],a7ff2e5:13,sampl:2,flatten:2,mask:[12,6],mistak:12,proper:2,home:[12,13],successfulli:12,librari:[11,2,6],tmp:12,thu:[2,11],guid:[0,5,2,12],remind:[12,4],assum:[5,2,4],avoid:[5,11,2,12],shall:5,definit:5,subclass:[5,2],get:[0,2,5,6,9,10,12,13,14],track:[11,4,13],mathemat:5,leav:9,select:12,sequenc:5,toolkit:11,condit:5,foo:[2,12],complic:12,either:[2,11,10,4],machin:0,core:[2,5,11,7,8,10,12,13,14],encourag:[5,2,11,10],sensibl:[12,4],run:[5,6,13],bold:[5,13],whose:5,view:5,usag:[5,2],sacrif:5,funcnam:2,step:[10,12,13],great:[5,10],ndarrai:5,corr:13,offset:6,meantim:12,immut:5,post:[0,13],"super":2,"throw":13,stage:12,fft:5,faith:[12,9],stone:11,photometri:11,central:[5,11],column:[5,6],toolchain:5,structured_array_extens:12,http:[5,12,2,14],label:[9,13],surround:5,page:[0,1,10,4,5,3,8,12],includ:[2,4,5,14,12,11],constructor:5,discard:12,compute_color:2,upward:5,backup:12,processor:5,routin:5,own:[0,5,11,12,4],emphasi:5,"final":[12,9],primarili:[2,11],convolut:5,"float":5,easy_instal:6,automat:[6,4],due:2,down:12,maco:14,randomize_posit:5,replai:12,master:[12,9,4,13],empti:[5,6],ensur:[12,2,11,6],chang:[2,4,5,7,10,9,12,13],test_my_bug:9,sheet:0,merg:[0,10,12,4,13],straightforward:12,inclus:[10,11],git:[0,10,4,8,9,12,13,14],axisindex:13,log:[0,12,4,13],wai:[0,10,4,5,6,9,12,13,14],area:11,support:[2,11],question:5,transform:5,submit:[10,11],custom:13,avail:[5,2,11],stuck:12,reli:11,gitconfig:13,interfac:[2,11,4],editor:[12,13],address:13,pacakg:5,forward:4,yourdomain:[10,9,13],rejoin:4,"function":[5,2,11],svn:0,head:[12,4,13],seek_gzip_factori:12,form:[2,4,5,7,6,11],offer:10,forc:4,poster:12,linu:0,criteria:11,github:[0,1,10,4,5,8,9,12,14],tidi:4,link:[0,10,12],branch:[0,12,9,4,13],line:[10,4,5,6,9,12,13],inlin:5,"true":[5,6,13],bug:[2,5,9,10,12,13],conclus:5,reset:12,pull:[0,10,4,12,13,11],tripl:5,immedi:12,algorithm:5,temp:6,possibl:[0,2,4,5,12,11],"default":[5,12,11,6],bugfix:12,displai:[5,6],strang:12,tell:[12,9,13],work:[0,10,5,6,8,9,12,11],below:[5,2,6,10],limit:[5,1,2],time:[5,11,12],sum:5,otherwis:12,problem:12,even:[12,9],email:[10,9,13],a815645:12,configobj:2,model:5,featur:[12,9,4,13],constant:5,creat:[12,2,6,10,13],"int":5,request:[2,4,10,12,13,11],dure:[11,12,13],mirror:12,filenam:5,doesn:[2,12],repres:[5,12],strongli:[5,2],e202:6,right:[12,4,13],carefulli:5,some:[0,2,4,5,6,9,12,13,11],perez:0,exist:[2,11],face:6,check:[5,12,6,9,4],probabl:9,again:[12,13],readi:[0,12],want:[12,10,14,9,13],titl:12,"2to3":2,depth:0,refactor:12,book:[0,14],bool:5,futur:11,rememb:[12,4],peopl:[12,4],test:[1,2,3,5,7,9,12,13,11],func_:5,intermedi:0,nice:[0,5,9,13],fork:[10,12,4],stat:13,repeat:[12,6],intend:[10,11],colon:12,affili:[1,2,3,5,7,8,10,11],actual:[12,13],ital:5,org:[5,2],astronomi:[1,10,3,11],docstr:[5,2],cgreen:13,squash:12,"class":[5,2,11],releas:[11,14],consid:[11,2,12,9,4],throughout:5,omega:5,debian:14,deserv:5,ago:13,assert:13,axi:13,sphinx:5,longer:4,furthermor:5,untrack:12,directori:[5,12,10,6,13],bottom:10,descript:[5,12],visual:12,rule:[0,5],"13d7934":12,summit:13,ignor:[6,13],obj:12,potenti:11,leak:12,push:[0,12,4]},objtypes:{},titles:["Git resources","Welcome to Astropy’s documentation!","Coding Guidelines (Draft 3)","Documentation for Developers","Maintainer workflow","Documentation Guidelines (Draft 2)","Emacs setup for following coding guidelines","Testing Guidelines (Draft)","Development workflow","Development Workflow (Beginner)","Contributing To/Developing Astropy or Affiliated Packages","Vision for a common Astronomy Python package","Development Workflow (Advanced)","Configuring git","Installing git"],objnames:{},filenames:["development/workflow/git_resources","index","development/codeguide","development/index","development/workflow/maintainer_workflow","development/docguide","development/codeguide_emacs","development/testguide","development/workflow/development_workflow","development/workflow/development_workflow_basic","development/workflow/index","development/vision","development/workflow/development_workflow_advanced","development/workflow/git_configure","development/workflow/git_install"]}) \ No newline at end of file +Search.setIndex({objects:{"astropy.tools.misc":{sigma_clip:[15,10,1,""]},"astropy.config.configs":{ConfigurationItem:[33,14,1,""],save_config:[33,10,1,""],reload_config:[33,10,1,""],get_config:[33,10,1,""],InvalidConfigurationItemWarning:[33,15,1,""]},"astropy.utils.misc":{find_current_module:[22,10,1,""],fnunpickle:[22,10,1,""],fnpickle:[22,10,1,""]},"astropy.config.paths":{get_cache_dir:[33,10,1,""],get_config_dir:[33,10,1,""]},"astropy.io.vo.tree.SimpleElement":{parse:[8,9,1,""],to_xml:[8,9,1,""]},"astropy.io.vo.tree.CooSys":{epoch:[8,12,1,""],equinox:[8,12,1,""],ID:[8,12,1,""],system:[8,12,1,""]},"astropy.utils.xml.validate":{validate_schema:[6,10,1,""]},"astropy.tools":{misc:[15,8,1,""]},"astropy.io.vo.util":{is_callable:[27,10,1,""],coerce_range_list_param:[27,10,1,""],convert_to_writable_filelike:[27,10,1,""]},"astropy.utils.console.Spinner":{"__module__":[13,12,1,""],"__enter__":[13,9,1,""],"__exit__":[13,9,1,""],"__init__":[13,9,1,""]},"astropy.wcs.WCS":{get_naxis:[41,9,1,""],det2im2:[41,12,1,""],pix2foc:[41,9,1,""],wcs_sky2pix:[41,9,1,""],printwcs:[41,9,1,""],deepcopy:[41,9,1,""],sip_foc2pix:[41,9,1,""],det2im1:[41,12,1,""],wcs:[41,12,1,""],sip:[41,12,1,""],sub:[41,9,1,""],footprint_to_file:[41,9,1,""],to_header_string:[41,9,1,""],p4_pix2foc:[41,9,1,""],rotateCD:[41,9,1,""],wcs_pix2sky:[41,9,1,""],get_axis_types:[41,9,1,""],det2im:[41,9,1,""],copy:[41,9,1,""],to_header:[41,9,1,""],cpdis2:[41,12,1,""],calcFootprint:[41,9,1,""],cpdis1:[41,12,1,""],sip_pix2foc:[41,9,1,""],all_pix2sky:[41,9,1,""]},"astropy.io.vo.table":{parse:[32,10,1,""],validate:[32,10,1,""],parse_single_table:[32,10,1,""]},"astropy.wcs.Wcsprm":{theta0:[5,12,1,""],ssysobs:[5,12,1,""],equinox:[5,12,1,""],is_unity:[5,9,1,""],cubeface:[5,12,1,""],lonpole:[5,12,1,""],cd:[5,12,1,""],restfrq:[5,12,1,""],cdfix:[5,9,1,""],tab:[5,12,1,""],spcfix:[5,9,1,""],crder:[5,12,1,""],lng:[5,12,1,""],dateavg:[5,12,1,""],has_pc:[5,9,1,""],colnum:[5,12,1,""],sptr:[5,9,1,""],mjdobs:[5,12,1,""],specsys:[5,12,1,""],fix:[5,9,1,""],mjdavg:[5,12,1,""],phi0:[5,12,1,""],s2p:[5,9,1,""],get_ps:[5,9,1,""],has_crotaia:[5,9,1,""],has_cd:[5,9,1,""],mix:[5,9,1,""],set_ps:[5,9,1,""],cname:[5,12,1,""],set_pv:[5,9,1,""],velosys:[5,12,1,""],set:[5,9,1,""],cylfix:[5,9,1,""],spec:[5,12,1,""],get_pc:[5,9,1,""],restwav:[5,12,1,""],print_contents:[5,9,1,""],velangl:[5,12,1,""],zsource:[5,12,1,""],celfix:[5,9,1,""],unitfix:[5,9,1,""],get_cdelt:[5,9,1,""],csyer:[5,12,1,""],has_pci_ja:[5,9,1,""],dateobs:[5,12,1,""],crota:[5,12,1,""],cdelt:[5,12,1,""],piximg_matrix:[5,12,1,""],crpix:[5,12,1,""],ctype:[5,12,1,""],p2s:[5,9,1,""],lat:[5,12,1,""],cel_offset:[5,12,1,""],radesys:[5,12,1,""],has_cdi_ja:[5,9,1,""],lngtyp:[5,12,1,""],sub:[5,9,1,""],to_header:[5,9,1,""],datfix:[5,9,1,""],has_crota:[5,9,1,""],cunit:[5,12,1,""],name:[5,12,1,""],alt:[5,12,1,""],colax:[5,12,1,""],pc:[5,12,1,""],imgpix_matrix:[5,12,1,""],naxis:[5,12,1,""],axis_types:[5,12,1,""],lattyp:[5,12,1,""],ssyssrc:[5,12,1,""],get_pv:[5,9,1,""],latpole:[5,12,1,""],obsgeo:[5,12,1,""],crval:[5,12,1,""]},"astropy.wcs":{WCS:[41,14,1,""],Sip:[4,14,1,""],DistortionLookupTable:[45,14,1,""],Wcsprm:[5,14,1,""],wcs:[30,8,1,""],find_all_wcs:[41,10,1,""],UnitConverter:[19,14,1,""]},"astropy.utils.xml.check":{check_id:[6,10,1,""],check_anyuri:[6,10,1,""],check_token:[6,10,1,""],fix_id:[6,10,1,""],check_mime_content_type:[6,10,1,""]},"astropy.io.vo.validator.main":{make_validation_report:[34,10,1,""]},"astropy.utils.xml.writer":{XMLWriter:[6,14,1,""],xml_escape_cdata:[6,10,1,""],xml_escape:[6,10,1,""]},"astropy.io.vo.tree.Resource":{tables:[8,12,1,""],extra_attributes:[8,12,1,""],coordinate_systems:[8,12,1,""],links:[8,12,1,""],iter_coosys:[8,9,1,""],parse:[8,9,1,""],to_xml:[8,9,1,""],params:[8,12,1,""],iter_fields_and_params:[8,9,1,""],infos:[8,12,1,""],type:[8,12,1,""],iter_tables:[8,9,1,""],resources:[8,12,1,""]},"astropy.utils.console":{ProgressBarOrSpinner:[13,14,1,""],isatty:[13,10,1,""],print_code_line:[13,10,1,""],color_print:[13,10,1,""],ProgressBar:[13,14,1,""],Spinner:[13,14,1,""],human_time:[13,10,1,""]},"astropy.io.vo.tree.ParamRef":{ref:[8,12,1,""],get_ref:[8,9,1,""]},"astropy.io.vo.tree.Field":{to_xml:[8,9,1,""],links:[8,12,1,""],datatype:[8,12,1,""],ref:[8,12,1,""],precision:[8,12,1,""],parse:[8,9,1,""],width:[8,12,1,""],uniqify_names:[8,13,1,""],values:[8,12,1,""],arraysize:[8,12,1,""],type:[8,12,1,""],unit:[8,12,1,""]},"astropy.io.vo":{xmlutil:[14,8,1,""],tree:[8,8,1,""],util:[27,8,1,""],ucd:[31,8,1,""],exceptions:[7,8,1,""],table:[32,8,1,""],converters:[35,8,1,""],unit:[37,8,1,""],validator:[34,8,1,""]},"astropy.utils.xml.writer.XMLWriter":{comment:[6,9,1,""],"__module__":[6,12,1,""],end:[6,9,1,""],get_indentation_spaces:[6,9,1,""],element:[6,9,1,""],start:[6,9,1,""],tag:[6,9,1,""],object_attrs:[6,11,1,""],flush:[6,9,1,""],close:[6,9,1,""],get_indentation:[6,9,1,""],data:[6,9,1,""],"__init__":[6,9,1,""]},"astropy.io.vo.tree.Values":{ref:[8,12,1,""],min:[8,12,1,""],max:[8,12,1,""],parse:[8,9,1,""],to_xml:[8,9,1,""],is_defaults:[8,9,1,""],max_inclusive:[8,12,1,""],min_inclusive:[8,12,1,""],"null":[8,12,1,""],type:[8,12,1,""],options:[8,12,1,""]},"astropy.config.data":{get_data_filename:[33,10,1,""],get_data_fileobjs:[33,10,1,""],compute_hash:[33,10,1,""],get_data_fileobj:[33,10,1,""],clear_data_cache:[33,10,1,""],get_data_contents:[33,10,1,""],get_data_filenames:[33,10,1,""]},"astropy.wcs.UnitConverter":{convert:[19,9,1,""],scale:[19,12,1,""],have:[19,12,1,""],power:[19,12,1,""],want:[19,12,1,""],offset:[19,12,1,""]},"astropy.io.vo.tree.Table":{nrows:[8,12,1,""],links:[8,12,1,""],format:[8,12,1,""],fields:[8,12,1,""],iter_groups:[8,9,1,""],parse:[8,9,1,""],is_empty:[8,9,1,""],to_xml:[8,9,1,""],create_arrays:[8,9,1,""],groups:[8,12,1,""],iter_fields_and_params:[8,9,1,""],get_field_by_id_or_name:[8,9,1,""],params:[8,12,1,""],infos:[8,12,1,""],get_group_by_id:[8,9,1,""],ref:[8,12,1,""],get_field_by_id:[8,9,1,""]},"astropy.config.configs.ConfigurationItem":{reload:[33,9,1,""],set:[33,9,1,""],save:[33,9,1,""]},"astropy.utils.console.ProgressBar":{map:[13,13,1,""],"__module__":[13,12,1,""],"__exit__":[13,9,1,""],"__enter__":[13,9,1,""],update:[13,9,1,""],iterate:[13,13,1,""],"__init__":[13,9,1,""]},"astropy.io.vo.tree.Group":{iter_fields_and_params:[8,9,1,""],parse:[8,9,1,""],iter_groups:[8,9,1,""],to_xml:[8,9,1,""],entries:[8,12,1,""],ref:[8,12,1,""]},"astropy.io.vo.tree.VOTableFile":{get_first_table:[8,9,1,""],coordinate_systems:[8,12,1,""],parse:[8,9,1,""],iter_values:[8,9,1,""],set_all_tables_format:[8,9,1,""],iter_coosys:[8,9,1,""],iter_groups:[8,9,1,""],get_field_by_id:[8,9,1,""],version:[8,12,1,""],params:[8,12,1,""],get_table_by_index:[8,9,1,""],get_group_by_id:[8,9,1,""],resources:[8,12,1,""],get_table_by_id:[8,9,1,""],to_xml:[8,9,1,""],groups:[8,12,1,""],iter_fields_and_params:[8,9,1,""],get_field_by_id_or_name:[8,9,1,""],get_values_by_id:[8,9,1,""],infos:[8,12,1,""],iter_tables:[8,9,1,""],get_coosys_by_id:[8,9,1,""]},"astropy.io.vo.xmlutil":{validate_schema:[14,10,1,""],check_id:[14,10,1,""],check_token:[14,10,1,""],fix_id:[14,10,1,""],check_mime_content_type:[14,10,1,""],check_anyuri:[14,10,1,""]},"astropy.io.vo.converters":{get_converter:[35,10,1,""]},"astropy.io.vo.unit":{is_unit:[37,10,1,""],check_unit:[37,10,1,""]},astropy:{wcs:[46,8,1,""]},"astropy.utils":{console:[13,8,1,""],misc:[22,8,1,""],collections:[40,8,1,""]},"astropy.utils.xml":{iterparser:[6,8,1,""],validate:[6,8,1,""],writer:[6,8,1,""],check:[6,8,1,""]},"astropy.wcs._wcs.Tabprm":{print_contents:[5,9,1,""],map:[5,12,1,""],p0:[5,12,1,""],set:[5,9,1,""],K:[5,12,1,""],nc:[5,12,1,""],M:[5,12,1,""],coord:[5,12,1,""],delta:[5,12,1,""],crval:[5,12,1,""],sense:[5,12,1,""],extrema:[5,12,1,""]},"astropy.utils.xml.iterparser":{get_xml_encoding:[6,10,1,""],xml_readlines:[6,10,1,""],get_xml_iterator:[6,10,1,""]},"astropy.io.vo.exceptions":{VOTableSpecWarning:[7,14,1,""],VOWarning:[7,14,1,""],parse_vowarning:[7,10,1,""],IOWarning:[7,14,1,""],vo_raise:[7,10,1,""],UnimplementedWarning:[7,14,1,""],warn_or_raise:[7,10,1,""],VOTableSpecError:[7,14,1,""],vo_warn:[7,10,1,""],VOTableChangeWarning:[7,14,1,""],vo_reraise:[7,10,1,""]},"astropy.utils.collections.HomogeneousList":{insert:[40,9,1,""],"__module__":[40,12,1,""],extend:[40,9,1,""],"__iadd__":[40,9,1,""],"__setitem__":[40,9,1,""],append:[40,9,1,""],"__dict__":[40,12,1,""],"__weakref__":[40,12,1,""],"__init__":[40,9,1,""]},"astropy.io.vo.tree.Info":{content:[8,12,1,""],unit:[8,12,1,""],ref:[8,12,1,""],name:[8,12,1,""],value:[8,12,1,""]},"astropy.io.vo.tree":{Info:[8,14,1,""],FieldRef:[8,14,1,""],Resource:[8,14,1,""],Group:[8,14,1,""],CooSys:[8,14,1,""],SimpleElement:[8,14,1,""],Param:[8,14,1,""],Element:[8,14,1,""],Field:[8,14,1,""],Link:[8,14,1,""],Table:[8,14,1,""],Values:[8,14,1,""],ParamRef:[8,14,1,""],SimpleElementWithContent:[8,14,1,""],VOTableFile:[8,14,1,""]},"astropy.io.vo.tree.Param":{to_xml:[8,9,1,""],value:[8,12,1,""]},"astropy.utils.collections":{HomogeneousList:[40,14,1,""]},"astropy.io.vo.tree.SimpleElementWithContent":{content:[8,12,1,""],to_xml:[8,9,1,""]},"astropy.wcs.DistortionLookupTable":{get_offset:[45,9,1,""],crpix:[45,12,1,""],data:[45,12,1,""],crval:[45,12,1,""],cdelt:[45,12,1,""]},"astropy.utils.console.ProgressBarOrSpinner":{"__module__":[13,12,1,""],"__enter__":[13,9,1,""],"__exit__":[13,9,1,""],update:[13,9,1,""],"__init__":[13,9,1,""]},"astropy.wcs.Sip":{a:[4,12,1,""],b:[4,12,1,""],b_order:[4,12,1,""],foc2pix:[4,9,1,""],bp_order:[4,12,1,""],ap:[4,12,1,""],a_order:[4,12,1,""],bp:[4,12,1,""],ap_order:[4,12,1,""],pix2foc:[4,9,1,""],crpix:[4,12,1,""]},"astropy.io.vo.ucd":{parse_ucd:[31,10,1,""],check_ucd:[31,10,1,""]},"astropy.wcs._wcs":{Tabprm:[5,14,1,""]},"astropy.io.vo.tree.Link":{href:[8,12,1,""],content_type:[8,12,1,""],content_role:[8,12,1,""]},"astropy.config":{paths:[33,8,1,""],configs:[33,8,1,""],data:[33,8,1,""]},"astropy.io.vo.tree.FieldRef":{ref:[8,12,1,""],get_ref:[8,9,1,""]}},terms:{haggi:20,orthogon:11,resist:19,yellow:[13,44],four:[3,5,29],warn_or_rais:7,prefix:[20,30,3,33,19],vspan:5,tcnana:29,cython_skip:1,whose:[20,5,29],moshir:4,typeerror:[40,11,33],get_cache_dir:33,messi:[42,38],deviat:15,under:[1,20,11,30,19],spec:[8,36,7,5,32],suitabl:[27,5],digit:[7,5],everi:[1,7,13,28],risk:19,msg2:11,distort:[30,4,41,28,45,46],lumin:19,quantiz:[41,5],delv:33,affect:[11,42],beam:19,heasarc:34,flymak:39,factori:35,vector:[5,24],phase:23,matric:28,verif:[47,37],readthedoc:1,direct:[11,1,5,4,20,30,23],consequ:29,second:[13,38,20,3,5,24,19],aggreg:30,ill:[41,5],illumin:19,even:[11,36,3,18,29,41,7,5,42,19],asin:19,msysgit:9,insid:[11,1,3,20,7,8],check_id:[14,6],neg:19,get_extens:1,introspect:20,mixpix:5,lightr:13,sigma_clip:15,conduct:19,"new":[11,36,38,20,23,39,18,4,6,7,24,28,42,33,8,26],net:7,ever:[2,23,5,6],nep:42,urlerror:33,manipul:[5,36],hdr:[1,33],submodule1:11,submodule2:11,footprint_to_fil:41,never:[11,1,5,29,41,23],droettboom:46,here:[0,11,20,2,9,17,18,5,6,41,7,43,44,42,8,19],foccrd:4,base64:[7,36],lgpl:46,pos_eq_dec_main:36,path:[20,36,1,39,6,27,14,32,33,34,8],interpret:[39,5,28,33,15,19],"94935ac31d585f68041c08f87d1a19d4":3,iter_group:8,xmllint:[14,6,7,43,32],zsourcea:[5,29],vowarn:7,progressbar:13,precis:[20,8,41,7,5],get_first_t:[8,36],fourier:20,glu:7,yuri:44,set_reference_fram:27,"_test":3,tcdena:29,icsyena:29,unix:33,crder:5,total:[13,19,5],unit:[28,11,36,37,3,5,30,7,47,44,8,19,41],highli:33,plot:[20,41],describ:[11,20,2,3,17,26,29,39,46,33,8,19],would:[11,20,5,29,41,42,28,33,23],ddthh:5,cmdlinescript:25,recommenc:5,readi:[0,42],datadir:33,call:[25,11,13,1,2,46,3,5,22,6,41,7,44,42,33,34,28,36],card:[41,24,19],typo:42,recommend:[25,11,38,1,2,3,5,29,20,7,33,15,19],type:[20,13,40,14,3,39,18,5,6,41,7,28,42,33,8,19,36],until:[1,23,5,22,7,15],relax:[30,5,41,29],relat:[11,38,14,2,5,6,41,42,21,20,15,47],notic:42,warn:[11,36,20,3,5,41,7,45,32,33,47],exce:[11,41,5,29],isatti:13,loss:7,plt:[20,11],hold:[15,8,25],complexarrayvararrai:35,must:[11,13,27,1,15,3,39,5,4,6,20,23,7,24,14,33,8,19,41,36],word:[42,31,39,44],restor:7,setup:[11,1,2,3,39,43,33],work:[0,25,11,13,1,23,3,17,18,26,5,20,42,39,8],coerce_range_list_param:27,xmlutil:[14,47],new_vot:36,reword:42,root:[11,7,33,43,19],obliqu:5,give:[0,1,28,22,20,42,44,33],indic:[10,13,27,20,3,5,6,7],unavail:28,want:[26,1,3,18,5,42,44,33,9,19],lonpol:5,end:[25,13,38,1,39,5,22,6,41,42],turn:[25,13,3,39,42,36],str3:19,str2:19,str1:19,setq:39,ictypn:29,w26:7,how:[0,11,38,20,23,3,17,18,26,5,7,42,33,22,8],w24:7,"0x11f00f0":[],w22:7,w23:7,env:[25,11],w21:7,answer:20,verifi:[27,28,47,37,31],config:[0,11,37,1,2,3,18,26,14,44,7,20,33,8,35],w28:7,updat:[11,13,1,28,26,7,44,42,33],ipvn_ma:29,recogn:[41,5,19,29],hhuuggoo:44,rebas:[42,38],mess:42,after:[11,13,20,3,39,5,26,41,7,42,33],substanc:19,befor:[11,38,20,23,3,17,5,29,7,42,32,8],wrong:42,human_tim:13,currect:3,lat:[41,5],parallel:[34,36],attempt:[11,7],third:[1,11,5],coordinate_system:8,classmethod:[8,13],opaqu:6,bootstrap:1,tcn_ka:29,lost:[42,41,8,5],exclud:38,alias:[30,7,19,44],maintain:[26,42,5,38],environ:[33,43],incorpor:[20,38],enter:[11,42],wcshdo_:29,first:[36,38,20,23,3,42,5,29,22,41,7,32,33,34,8],order:[11,20,23,5,4,29,41,7,43,8,19],mcnoleg:20,origin:[28,20,2,3,5,4,41,7,24,44,42],deci:19,rhetting:11,k93model:33,upstream:[0,42,38,44],becaus:[25,11,38,20,8,3,5,29,42,33,23],wcshdo_al:29,typewrit:20,pascal:19,get_field_by_id_or_nam:8,flexibl:[25,41,36],vari:5,digest:33,ucd1:[7,31],shorter:29,fit:[11,1,2,30,3,5,4,23,7,24,28,46,33,8,19,41],unforeseen:7,fix:[28,26,36,20,3,18,5,41,7,44,42,8,46],tcdltn:29,comprehend:20,better:[42,18,28],persist:11,nelem:[5,4],cred:44,easier:[42,36],them:[11,20,23,3,18,5,42,29,8,19],thei:[11,36,1,23,3,5,26,29,20,41,7,28,42,33,8,19],proce:7,"_xtypeproperti":8,safe:[18,29],colsel:41,axis_typ:[41,5],choic:[23,8,44],tendenc:29,regula:5,unpickl:22,accommod:29,good:[0,11,36,38,20,7,43,44,42,9],tabprm:[30,5],each:[1,2,3,4,7,15,11,13,8,5,20,27,29,41,31,33,34,19,36,42,28,45,46],"29001ed":42,went:42,ictyna:29,side:[1,5],mean:[11,20,15,5,23,7,42,33,8,19,41],voxel:19,ncoord:[5,4],"6ad92e5":42,arrayvararrai:35,is_empti:8,forgot:42,extract:[41,7,5,36],ndobj_new:20,unbound:7,network:[20,42,7],goe:11,content:[25,20,12,14,31,39,5,22,6,7,24,44,46,33,8,47],rewrit:42,laid:[11,5],adapt:[20,23,9],reader:20,got:[42,7,38],unrecogn:[41,5],smallish:22,linear:[11,5,41,42,28,45],p4_pix2foc:[46,41],written:[11,20,5,29,41,7,42,8],get_cdelt:[5,28],situat:[20,42],free:[26,9,33],standard:[1,3,4,6,7,15,11,12,13,8,5,20,23,29,41,31,32,33,19,36,37,46,47],"__setitem__":40,freq:5,validate_schema:[14,6],md5:[33,3],"_idproperti":8,tctypna:29,workaround:7,ds9:41,pkname:33,traceback:[7,13],iso:5,isn:[1,5,22],regress:3,onto:42,rang:[27,13,5],render:20,rydberg:19,independ:[46,23],get_p:5,restrict:[7,5],hook:[1,39],unlik:[33,5,29],alreadi:[11,38,18,5,7,42,33,23],wcshdr_none:29,voidspac:33,primari:[29,5,24],hood:30,"7beda5a":44,xml_readlin:6,airi:24,top:[25,11,36,38,42,33,8],sometim:[42,39],astropi:[1,2,3,4,5,6,7,15,10,11,12,13,14,8,16,17,18,19,20,21,22,24,25,26,27,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,28,45,46,47],underlin:20,master:[1,42,18,38,44],too:[3,7],xiv:4,tom:3,ioerror:33,outag:7,consol:[13,21],namespac:[1,2,11,7,31],tool:[0,10,11,37,20,2,3,39,23,7,43,33,15],coordinate_typ:41,task:[20,42,23,13],tcrdna:29,gitconfig:44,"_nameproperti":8,cdata:6,conserv:19,technic:0,printwc:41,keyword:[36,20,5,29,6,41,27,24,32,8,19],x_fit:28,provid:[11,36,27,1,15,39,5,29,20,23,7,28,32,33,34,8,41,46],offici:2,tree:[11,36,20,23,6,43,32,34,8,35,47],wcshdr_:29,project:[0,10,11,1,2,5,20,7,24,43,42],pressur:19,da34a7b07ef153eede67387bf950bb32:33,minut:[19,44],mathtt:20,beginn:[26,17,18],latitud:[41,5,29],mini:39,rad:19,fashion:33,behavior:[29,44],mind:20,spectrum:27,raw:[5,28],aforement:11,votabl:[36,37,14,7,43,31,32,34,8,35,47],manner:11,increment:[45,13,5],seen:7,seek:23,latter:[20,33,29],matthew:44,get_group_by_id:8,wcshdr_dobsn:29,branchnam:42,simplifi:11,wcsbth:28,glon:5,though:[33,8,28],glob:33,object:[1,3,4,6,7,8,11,13,5,20,24,27,28,29,30,32,33,22,19,36,40,41,42,44,46],terrestri:5,did:[14,42],regular:[3,7],distutils2:1,letter:[7,5],bsd:[46,11],paramref:8,shiningpanda:1,yourdomain:[26,18,44],w42:7,don:[39,18,22,42,5,29,8],nosolutionerror:5,doc:[1,8,20,7,43],doe:[25,11,13,1,3,5,29,20,41,7,33,34,8,19],abbrev:44,declar:[7,24],wildcard:[1,5],tctyna:29,sum:20,dot:[33,7],asid:[20,25],reload_config:33,tcunin:29,random:[20,15,5],radiu:[20,19],syntax:[11,37,20,39,7,8,19],radio:28,pkg:22,identifi:[26,5,6,41,7,44,32,23],autoload:39,involv:[1,3],absolut:[33,11,3,26,44],"0x1525330":15,just:[11,36,38,14,2,39,18,26,5,6,42,46,33],menu:[42,39],explain:[0,20,42,18],configur:[10,11,20,2,3,17,18,26,42,39,44,32,33,35],tcrvlna:29,get_xml_encod:6,rich:20,vo_warn:7,likewis:[41,7,5,29],stop:[42,39],corr:44,viter:5,report:[36,3,7,32,34,47],iter_valu:8,bar:[6,11,13],excel:[0,18],lonpna:29,"public":[11,12,20,3,42,33,15,47],reload:33,bad:11,jcrpna:29,metadata:11,wcsnna:[41,29],epocha:29,commandlin:24,tcrpxna:29,datatyp:[8,7,35,47,36],num:3,mandatori:19,result:[28,20,3,39,5,29,27,41,7,31,34,8],fail:[11,3,5,4,41,7],icrden:29,zaytsev:44,best:[23,18],subject:[20,11,3,29],awar:20,peta:19,fnpickl:22,hopefulli:33,databas:[42,7],discoveri:3,test_fil:3,fcontent:33,figur:7,setup_method:3,simplest:[2,36,18,44],awai:[27,42],approach:5,attribut:[11,36,37,14,5,22,6,41,7,20,8],get_length:13,accord:[11,36,37,5,7,28],extend:[0,20,36,40],write_null_valu:8,crotan:[41,5,29],weak:40,fk5_to_gal:20,contort:20,clear_data_cach:33,extens:[10,11,16,1,3,5,29,20,41,7,8,19],autofil:39,deby:[5,19],func_d:20,func_a:20,func_b:20,icnana:29,accident:[11,42],easi:[0,11,1,3,20,23],impliment:44,howev:[25,11,36,1,5,26,29,20,41,7,42,8,19],crvalia:[45,5,29],against:[14,6,7,31],get_coosys_by_id:8,logic:[20,7],fnunpickl:22,com:[11,38,1,18,26,42,43,44,9],col:[6,13],con:[11,39],kwd:[27,6],calabretta:46,velosysa:[5,29],diff:[0,42,38,44],summat:20,assum:[11,13,38,20,5,22,7],summar:23,ipsn_ma:29,duplic:[20,23,7],wcsnamea:[5,29],foc2pix:4,numpi:[11,36,1,15,5,4,20,23,7,24,43,28,47,8,35,41],three:[3,5,41,42,46,33],been:[10,11,38,1,5,26,22,20,41,7,28,42,33],viewer:20,much:[42,6,28,23,10],interest:[20,16,24],thereaft:23,restfreq:29,"__doc__":20,projpn:29,life:28,search:[10,1,3,5,22,20,33],argument:[25,13,27,20,3,5,29,6,41,7,24,28,32,8,36],multithread:28,child:[8,7],"catch":11,ident:41,tanh:19,servic:[27,7],properti:[20,11,28,5,24],aip:[28,5,29],radecsi:29,air:24,aim:23,calcul:[1,11,41,28],publicli:8,build_sphinx:43,krige:20,toolkit:23,"_flymak":39,kwarg:[27,32,41,8,13],somemodul:11,ictypna:29,perform:[11,12,36,4,22,30,7,46,34,15,19,41],suggest:[42,19],make:[0,28,11,38,44,1,2,3,17,18,5,6,23,7,39,20,42,33,8],oseerror:33,complex:[15,11,23,7,35],split:29,complet:[33,7,13,38,5],reticul:13,galact:[8,7],nil:39,tcdltna:29,pyflak:[20,39],blue:[13,44],hand:11,get_package_data:1,rais:[11,37,40,14,3,5,4,22,20,41,7,31,45,32,33,8,19],configurationitem:[11,33],latpolea:[41,5,29],squar:[20,19],kept:[20,8],thu:[11,5,29,41,23,19],my_new_fil:42,hypothet:20,inherit:[11,29],pvi_2a:5,contact:[26,44],thi:[1,2,3,5,6,7,15,11,13,14,8,17,18,19,20,24,22,23,25,29,41,31,32,33,34,35,36,38,39,42,43,44],gzip:42,everyth:[42,23,33,15,22],left:[1,41,42,5,29],wcssub_stok:[41,5],protocol:[27,8,7,42,22],vararrai:35,modnam:11,tsn_ma:29,newton:19,ordin:8,human:[20,13],"__dict__":40,yet:[10,11,1,3,20,41,33],languag:11,previous:[8,33,7,28],expos:20,wcslib:[2,30,5,29,41,28,46,19],keysel:41,had:[42,7,36,28],builtin:11,fortran:[28,41,5,4,24],spread:20,primit:7,els:[25,11,13,18,22,42,8],save:[36,39,42,24,44,33],radesysa:[5,29],restwav:5,applic:[36,20,5,7,8,19],milli:19,wcshdo_crpxna:29,mayb:42,zsouna:29,textwrap:13,is_default:8,icrvna:29,background:[20,39],aclass:11,specif:[11,36,20,15,3,39,5,29,30,7,31,42,8,19,41],arbitrari:[14,6,3,8,42],transvers:5,manual:[0,11,38,20,39,42,24],colnum:5,remind:[42,38],confid:24,leftrightarrow:20,unnecessari:5,csiro:46,underli:[30,41,28],www:[33,7],right:[1,29,42,38,44],old:[1,11,3,5],cnameia:[5,29],negat:[41,5],interv:5,begin:[20,11,7,33,29],percentag:13,e03:7,j2000:8,intern:[26,17,5,41,7,19],flatten:11,there_is_a_syntax_error_her:13,successfulli:42,insensit:[7,5,19],cooper:11,bottom:26,subclass:[20,40,11,8],"_utypeproperti":8,track:[36,23,13,38,44],scalarvararrai:35,condit:[20,41,5],foo:[6,11,42,33],icunina:29,core:[11,13,1,23,3,17,26,20,30,42,44,46,34,9,41],plu:[5,29],tcunna:29,bold:[20,44],promot:25,repositori:[26,38,9,17,11,18,42,43,23],post:[0,8,44],idref:7,"super":11,unsaf:[5,19,29],obj:[6,42,22],structured_array_extens:42,surround:[20,19],fiduci:5,commit:[0,38,1,18,42,44,23],attrib:6,produc:[11,20,5,6,7,33,15],capacit:19,naxi:[5,4,41,24,28,45],specsysa:[5,29],"float":[36,20,15,5,41,7,24,28,45,8,35],encod:[6,7,36],down:[3,42],barycentr:[8,7],wrap:[1,6],ivn_ma:29,precomput:11,accordingli:[13,5],git:[0,26,38,17,18,42,43,44,9],axisindex:44,some_opt:33,setup_modul:3,transform:[20,5,4,30,24,28,45,46,41],happi:42,avail:[25,11,1,2,3,5,22,20,41,7,28,33,23],stuck:42,reli:[11,23],wordpress:11,editor:[33,42,44],unimplementedwarn:7,gil:28,fork:[26,42,38],head:[42,38,44],creation:1,"_ucdproperti":8,form:[28,11,38,20,3,39,5,29,6,41,7,31,23,19],offer:[26,3],forc:[5,38,19],wcshdr_all:29,solar:19,synonym:5,"true":[13,37,27,20,15,31,3,39,5,29,6,22,41,7,44,32,33,34,8],reset:[42,13,5],electr:19,attr:6,arrays:[8,7,36],bugfix:42,pvi_3a:5,maximum:[39,8,5,19],tell:[42,18,44],absenc:5,atto:19,wcshdr_radecsi:29,emit:[7,36],khz:19,featur:[38,18,42,43,44,7,46],alongsid:13,shim:1,tesla:19,"abstract":27,diagnost:8,exist:[11,13,1,15,5,29,23,7,33,34,8,41],perez:0,quantiti:[41,7,5,19],mole:19,jcrpxn:29,tip:[0,11,39],refactor:42,role:[8,7],test:[10,11,16,28,1,2,3,18,20,23,27,24,43,44,42,33,8],legitim:29,intend:[15,26,23,7],asterisk:[7,19],urllib2:33,get_remote_test_data:3,felo:5,intens:[1,5,19],intent:29,lightmagenta:13,consid:[11,38,18,29,41,7,5,42,23,19],easili:33,get_values_by_id:8,keycom:[41,5],omega:20,makovoz:4,receiv:7,longer:[33,38],furthermor:20,anywher:36,pseudo:5,fileornam:22,"13d7934":42,ignor:[39,5,29,7,44,45,8,19],time:[11,13,20,15,3,5,29,6,23,7,42,8,19],push:[0,42,38],backward:[1,5],"__________________________________":3,osx:9,concept:[0,2,20],chain:11,skip:[3,8],global:[36,26,39,18,44],wcshdo_saf:29,signific:[20,11,41,7,5],invalidcoordinateerror:5,computation:[1,11],"3a1":[46,28],sip_pix2foc:[46,41,4],row:[8,36,7,5,32],arcsec:19,decid:[3,23],depend:[11,13,20,23,5,26,6,41,7,43,8,36],uniqify_nam:8,graph:[42,38,44],decim:[41,7,5],readabl:[25,20,6,42,32,33],fft2:20,inconsistentaxistypeserror:[41,5],environment:20,cheat:0,quasi:29,singularmatrixerror:[41,5],bitpix:[41,5],wcshdr_cnamn:29,"_debug_python_based_pars":[32,8],giga:19,wcshdr_auximg:29,pywc:[46,28,29],brown:13,sourc:[1,2,3,6,7,15,10,11,13,14,8,5,20,25,26,27,22,31,32,33,34,35,37,40,43],"__exit__":13,string:[28,20,13,37,27,14,15,3,5,6,41,7,31,32,33,34,8,19,36],ndobj_old:20,w35:7,pixcrd:[5,4,24],icr:[8,7,5,36],cyan:13,cool:[42,38],level:[36,27,2,3,39,5,6,8,32,33,23,47],tear:[3,42],gui:[23,9],henri:[5,19],ssysobsa:[5,29],iter:[13,20,15,5,6,33,8],magnet:19,item:[11,13,40,1,27,33],unsupport:7,sine:19,team:[26,23],quick:[20,18],tcsyen:29,round:[8,19],prevent:[36,20,8,3,44,23,19],telescop:46,vsouna:29,cosh:19,whiich:33,sensibl:[42,5,38],port:9,spectral:[27,41,5,28],appear:[38,20,5,29,6,41,7,8],lightblu:13,pyplot:[20,11],favour:29,uniform:23,current:[10,11,36,38,1,23,3,39,6,44,7,43,20,42,33,34,8,19],exception_class:7,erg:19,ground:19,meld:42,tangenc:5,defici:8,deriv:[1,7,5,19],dropdown:42,urlopen:33,gener:[11,13,1,2,18,5,20,22,23,7,47,15,42,33,34,8,19,41,36],coeffici:46,satisfi:[39,23],tangent:19,address:[36,44],along:[1,8],do_someth:25,wait:23,primaryhdu:24,icdena:29,trial:5,atom:19,commonli:[1,46,5,19],ourselv:20,regardless:[41,7,5],fileobj:33,extra:[6,8],dtype:[20,36],modul:[10,11,13,25,1,2,3,29,6,41,7,20,32,33,22,15,35,36],prefer:[20,42,19],backtick:20,leav:18,xdg_config_hom:33,marker:39,configspec:33,set_all_tables_format:[8,36],red:[39,13],memori:[6,41,5,4,32],distortionlookupt:[45,30,41],subvers:0,live:[25,22],theta_0:5,criteria:23,msg:[11,13],black:[39,13],checkout:[0,42,18,38,44],capit:7,nadia:46,peopl:[3,42,38],claus:11,pylint:20,finit:5,ctype:[41,5,24],enhanc:11,visual:42,accept:[25,26,36,27,11,5,40,41,7,33,29,19],examin:36,easiest:[9,18,43],content_typ:[14,6,8],tcrvln:29,fly:42,icnamna:29,graphic:42,local:[3,39,42,7,33,34],uniqu:[2,33,7,38,8],descriptor:[7,36,47,31],vega:33,whatev:[11,23],imped:11,webster:44,purpos:[5,22,42,28,7,8],overwritten:22,point_3d:7,stream:[27,6],add_argu:25,janski:19,abort:42,spc:39,occur:[1,5,22,41,7,33,19],alwai:[11,13,1,23,3,29,6,41,7,28,33,8,19,36],"956fbab":44,multipl:[11,20,2,39,7,15,19],satisfact:42,write:[20,2,3,6,7,8,10,11,13,16,5,24,25,27,29,30,33,34,36,38,39,41,42,43,44],anyon:[16,42],pure:[11,8],vo_rerais:7,parameter:[5,29],get_color:11,map:[13,1,3,5,6,7,33,36],product:5,mar:11,atan:19,max:[8,7,24],clone:[0,26,42,18,43],crotaia:[5,29],mac:9,mag:19,mai:[20,2,3,4,7,8,11,13,9,5,24,23,27,29,41,31,32,33,19,36,42,44,45,46],underscor:[14,6,20,7],data:[11,36,1,15,3,6,44,7,20,45,33,8,41],grow:23,harmon:42,subsequ:[26,41,5,19,29],stress:19,tpsn_ma:29,practic:[36,5,41,7,44,33,23],array_lik:20,quot:20,favorit:33,ghz:19,enh:42,"switch":[1,2,3,42,18],preced:[20,7,19],combin:[36,20,5,41,42,8],maskedarr:15,callabl:[27,15],adass:4,yocto:19,tty:13,comfort:26,creset:44,graphviz:43,cmod:22,lsr:5,still:[11,36,1,2,20,7,42],pointer:[39,8],dynam:5,divis:[5,19,24],conjunct:[5,29],group:[8,41,7,5,29],thank:[18,44],w27:7,platform:[20,3,43],window:[9,28],w25:7,mail:[42,18],main:[25,38,2,3,18,42,33,34,23],recoveri:42,non:[11,36,14,44,5,29,6,41,7,20,46,9,19],w20:7,halv:5,supersed:20,alist:39,initi:[26,5,40,41,44,33,23,19],nation:46,underneath:20,"try":[11,42],half:5,now:[36,38,28,18,7,24,44,42],discuss:[20,44],nor:[19,29],introduct:[0,10,26,12,36],term:[3,5,41],name:[1,2,3,5,6,7,8,11,13,14,18,20,24,25,26,27,22,41,32,33,19,36,38,39,42,44],drop:[39,29],another_opt:33,vegaurl:33,tera:19,linspac:11,separ:[1,2,3,39,5,29,20,30,7,42,19,41],x10:19,dictproxi:40,collaps:[42,39],ters:29,compil:[11,3,43,34],domain:[8,7],replai:42,inhert:11,replac:[20,14,39,29,6,7,44],individu:[39,8,47,22],continu:[15,23,7],significantli:3,year:[8,7,5,19],icrvln:29,happen:7,shown:[20,39,33,17,29],dencheva:46,space:[11,13,20,39,5,6,7,46,19],storag:[8,36],wcshdo_tpcn_ka:29,cobe:5,internet:[11,3],usecpickl:22,correct:[11,13,5,4,30,7,31,46,33,15,41],earlier:[28,7,31],variant:29,runtimeerror:33,setup_funct:3,argv:[25,24],mime:[14,6,7,8],theori:20,exc_typ:13,org:[1,20,33,3],"byte":[33,7,19,36],"0x240078":[32,13],sollum:19,care:[20,5],suffici:[11,29],frequenc:[5,19],recov:[42,7],thing:[0,36,1,18,27,42],place:[11,3,39,5,4,22,7,28,33,15],principl:[20,7],think:[42,18],lambda:39,oper:[11,13,5,30,8,19,41],filtereddata:15,directli:[11,38,26,2,5,22,41,7,15,44,42,33,23],onc:[11,26,3,5,22,7,43,44,42,33,34,23],arrai:[11,36,20,15,28,5,4,29,41,7,24,19,44,45,32,8,35],"65af65":44,yourself:[26,42,44],stsci:33,submit:[26,3,23,33],oppos:11,sip_foc2pix:[46,41,4],open:[13,27,3,22,6,42,24,32,33],size:[11,13,5,4,41,7,28,45,8,36],given:[11,13,40,1,28,42,5,22,6,20,41,7,19,14,32,33,34,8,35,36],sheet:0,silent:13,convent:[11,20,5,4,29,30,7,28,46,41],width:[8,41,7,13,15],teardown:3,analog:[19,29],fobj:[33,41],checker:[20,43],necessarili:[1,15],draft:[10,11,16,36,20,3,39,29],iau:19,white:[39,13],conveni:[0,36,3,5,6,41],cite:20,"26aa21a":42,courier:20,especi:[20,3,29],copi:[26,20,3,39,18,5,41,7,44,42,33,15],compute_hash:[33,3],"short":[36,20,7,42,8,35],enclos:[20,8,19],complexvararrai:35,than:[11,13,38,1,15,3,18,5,6,23,7,24,20,42,22,29,8,19,41],progn:39,serv:3,wide:[3,29],vicin:20,obsgzn:29,were:[5,29,41,7,24,28,32,33],posit:[13,39,35,41,7,8,19],seri:[0,3,19,38],pre:[20,4,6,7,15,13,14,8,5,35,21,27,22,41,31,32,34,19,36,37,40,42,45],parse_vowarn:7,sai:[42,11,7,38],ap_i_j:4,tcsyena:29,pro:[0,11],save_config:33,ani:[11,13,38,44,1,15,46,3,18,5,6,23,7,20,42,33,29,8,19,41,36],dash:[7,5],measur:5,repeatedli:36,wcshdr_longkei:29,techniqu:[20,15],institut:46,note:[1,2,3,4,5,7,15,11,36,8,18,20,29,41,33,34,19,38,39,42,43,44],unitconvers:28,unitconvert:[30,19],take:[20,3,18,41,7,42,33,15],advis:42,phi0:5,green:[41,13],noth:[25,15],channel:19,pc1_1:5,pc1_2:5,sure:[17,8,39,38,44],normal:[20,5],multipli:19,compress:5,tcsyna:29,exclus:29,pair:[13,30,5,41,45,8,19],latex:20,annum:19,wcsaxesa:[5,29],renam:7,later:[26,2,7,43,23,8],typeset:20,parse_single_t:[32,36],axi:[5,4,29,41,44,45],sigma:15,bp_i_j:4,show:[42,11,3,39,38],joshu:44,luminos:19,wcshdr_allimg:29,subprocess:6,permiss:[3,7,5,41,19],hack:[42,7,18],corner:41,label:[44,18,5],has_pci_ja:5,"0f22701":42,xml:[36,14,6,7,21,43,32,8,35,47],onli:[20,3,4,5,7,15,11,34,13,14,8,18,23,25,26,28,29,41,32,33,22,19,36,38,39,40,42,43,44],explicitli:[20,8,7,31],favor:7,activ:[0,23],behind:0,k_1:5,dict:[20,6,41,5,35],test_2:3,test_1:3,restfrq:5,over:[11,13,20,8,29,6,23,7,15,36],backspac:39,variou:[26,14,6,27,33,35],get:[0,25,11,36,28,20,8,3,39,18,26,5,6,41,42,44,33,9,35],repr:5,icunin:29,secondari:28,repo:[42,38],progressbarorspinn:13,cannot:[11,23,33,19,22],ssh:42,theta:[41,5],requir:[10,11,20,23,3,39,5,41,7,43,31,32,33,8,19],icdltna:29,randvar:15,median:15,b1950:8,icrdna:29,restfrqa:[5,29],"376adbd":44,where:[0,11,13,20,15,3,39,18,4,5,23,7,43,42,32,33,29,8,19],vision:[10,26,16,23],summari:[0,26,20,7,44,42,33],wiki:10,wcssub_latitud:[41,5],"__module__":[6,13,40],mixcel:5,xtype:8,bitarrai:35,icrvlna:29,index_bi:44,davgn:29,reserv:[11,8],lng:[41,5],maskedarrai:15,concern:23,detect:[33,38],"__all__":[20,11,15,22],specna:29,review:42,enumer:13,pc2_2:5,pc2_1:5,"278dd2a":42,enough:[23,11,3,15],between:[20,5,29,7,19,23,35,47],"import":[25,11,36,1,23,3,22,20,41,24,46,33,15],bytes_read:13,warning_class:7,across:[23,15,5],pixcrd2:24,parent:[8,7],ctypeia:[41,5,29],pypi:[11,23,43],rare:[7,5,19],teardown_funct:3,add_legacy_alia:1,come:[0,2,39,13,42],"0x14432b0":[],copul:42,sketchi:44,pkgname:33,region:[41,39],tutori:[0,20],ssyssrc:5,improv:[11,26],scope:29,configobj:33,wcssub_celesti:[41,5],color:[11,41,13,44],overview:[10,38,20,2,16,18,42,44],ap_ord:4,latpol:5,pole:5,colon:[42,31,7,29],xml_escape_cdata:6,typic:[1,20,33],sourcetre:9,caret:13,obsgyn:29,implictli:7,invers:5,mark:[20,46,3,39],velangla:29,valueerror:[11,37,14,5,4,41,7,31,19],qsc:5,wcse:41,rotatecd:41,resolut:11,photon:19,squash:42,check_controlled_vocabulari:31,votablechangewarn:7,impati:[26,18],former:33,varfunc:15,icsyen:29,sound:42,hdu:24,interoper:3,tcnamna:29,pedant:[32,7,36],float64:7,cast:0,invok:[3,5],syntaxwarn:7,invoc:5,argpars:25,zenith:[5,24],ctrl:19,metric:19,tcunina:29,henc:[39,3,15],worri:42,scipi:[20,11,23],clutter:20,"__init__":[11,13,40,20,3,6,33],get_config_dir:33,develop:[0,10,11,16,38,26,23,3,17,18,42,43,33,15],cpickl:22,author:[20,7,36],same:[0,26,20,8,3,5,29,6,41,7,24,42,33,15,19],trip:8,binari:[36,5,22,43,41,7,19,28,29,8,35],epoch:[8,5,29],inconsist:[41,5],eventu:[2,3,23],week:44,exhaust:29,finish:[42,18],kelvin:19,nest:[32,8,36],assist:20,driver:33,someon:[42,38],mani:[0,11,36,20,23,3,5,22,7,8],extern:[11,1,2,3,20,8],tcrvna:29,appropri:[14,6,20,35,33],moder:36,vstep:5,choos:[26,42],markup:20,get_ref:8,pep8:[20,11,3,39],without:[11,20,3,5,4,29,7,28,42,33,19],test_answ:3,model:[20,7],dimension:[45,41,7,5,29],noao:7,execut:[20,25,39],when:[25,11,36,28,1,3,39,18,5,6,44,7,20,42,32,33,29,8,19,41],rest:[38,20,39,5,42,44,8],kilo:19,speed:[1,5],get_data_filenam:[1,11,3,33],is_cal:27,miscellan:[21,22],hint:[8,11,7],except:[25,11,36,14,5,29,20,7,44,32,33,8,47],littl:[0,25,42],pvi_ma:[5,29],ssysob:5,versa:5,ufunc:44,translate_unit:[5,19],real:[20,8],around:[2,8,39],"\u03c9":19,rejoin:38,check_token:[14,6],temperatur:19,grid:[45,33],mol:19,world:[20,2,5,29,41,24],mod:22,sternli:42,"0x14ec4f0":15,whitespac:[39,7,5,19],d304a73:44,integ:[25,27,5,41,7,33,35],server:[11,3,8,33],benefit:[23,44],wcshdo_pvn_ma:29,either:[11,13,38,26,2,3,5,29,27,23,7,15,33,8,19,41,36],a_i_j:4,output:[13,27,20,8,42,5,6,41,7,21,44,32,15,36],tower:9,manag:[0,38,2,3,43,9],supplementari:[41,19],iterpars:[6,21],test_wc:3,ascend:20,twcsna:[41,29],crpixja:[45,5,4,29],assertionerror:3,mixin:11,invalidtabularparamet:5,add_num:3,definit:[20,8,7,36],extnum:7,legal:[8,7],cylindr:5,parse_ucd:31,notabl:20,refer:[10,40,20,15,42,5,4,27,23,7,28,45,32,33,8],power:19,table_numb:[32,8],refere:7,convert_to_writable_filelik:27,debug:5,datanam:33,fulli:1,immut:[20,8],"throw":[32,44],stone:23,central:[1,20,23,15],floatingpoint:35,aco:19,greater:[41,5,19,29],degre:[41,5,19],"2x2":[36,28],backup:42,processor:[20,13],routin:[20,5,31],w09:7,effici:[6,5],wcshdr_vsourc:29,redshift:5,stoke:[41,5],your:[0,26,38,1,3,18,42,43,44,33,9],certainli:[41,5],complianc:[6,11,3,12,36],area:[23,19],set_p:5,wcshdo_dobsn:29,k_2:5,hex:33,overwrit:33,start:[20,3,5,6,42,24,33,23,19],interfac:[25,11,23,33,38],low:[27,47],lot:[25,28],hel:5,strictli:[7,29],stage:42,wcaxna:29,svn:0,seek_gzip_factori:42,programmat:[25,24,46],verbatim:27,tupl:[13,20,5,6,41,27,31,45,8,35],bundl:[11,3],regard:[20,2,11],packageormod:33,denomin:19,conclus:20,faster:[32,36,22],pull:[0,26,38,6,42,44,23],tripl:20,coulomb:19,possibl:[0,25,11,36,38,1,2,3,5,20,7,42,23],"default":[28,11,13,20,15,3,39,5,29,27,22,23,7,31,42,32,33,34,8,41],k_m:5,embed:7,connect:42,ohm:19,creat:[11,36,1,3,39,26,4,29,6,44,7,24,14,42,33,34,8,19],deep:[41,5],strongli:[20,11],crderia:[5,29],decreas:5,file:[1,3,6,7,8,11,13,14,18,20,24,27,22,41,31,32,33,34,35,36,39,42,43,44,46,47],fill:[28,39,5,36],incorrect:7,again:[42,8,44],vsysna:29,upcom:1,event:[6,19],field:[36,5,29,41,7,19,32,8,35],wai:[0,26,38,27,1,9,3,39,18,5,20,28,7,43,44,42,33,29,8],check_ucd:31,writabl:[27,6,8,13,32],you:[0,11,36,38,1,9,3,17,18,26,5,20,7,43,44,42,33,8,46],latpna:29,ftp:[33,8],sequenc:[13,40,20,5,6,41,27,32,7],symbol:19,docstr:[20,11,33],multidimension:[8,41,7,5],ansi:13,arcmin:19,radomain:7,extra_attribut:8,vocabulari:[7,31],reduc:[42,23],deliber:42,unbalanc:19,cunit:[5,28],obsgxn:29,directori:[25,11,1,3,39,26,20,42,43,44,33,34],descript:[25,11,36,20,2,42,5,41,7,32,33,8],kilogram:19,construtor:29,mass:19,potenti:[23,5,19,29],escap:[6,13],scm:9,represent:[13,38,5,29,42,28],all:[1,3,5,6,7,15,29,11,13,8,18,20,24,23,22,30,32,33,34,19,36,39,41,42,44,46],consider:[20,12,36],illustr:[20,11],alg:15,forbidden:19,scalar:[20,36],"2_installing_git":9,abil:42,follow:[1,2,3,5,7,8,11,36,16,17,18,20,23,25,26,28,22,41,32,33,29,19,38,39,42,43,44,46],alt:[39,5],csyeria:[5,29],get_xml_iter:6,pycodecheck:39,articl:20,init:39,radena:29,deka:19,scratch:36,testadd42:3,tpvn_ma:29,"case":[11,36,38,20,2,3,5,29,27,7,24,42,33,23,19],liter:[40,13,37,27,14,15,5,4,22,6,41,7,21,19,31,45,32,34,8,35,36],straightforward:42,fals:[25,13,27,8,42,5,29,6,41,7,31,32,33,22,15,36],mpl:[20,11],util:[10,11,40,13,25,14,2,22,6,27,7,21,15,47],print:[11,13,5,22,24,32,33],candid:[20,2],mechan:[11,1,3,29,20,32,23],ssyssrca:[5,29],veri:[25,11,1,3,5,29,20,42,44],unoffici:19,ticket:3,strang:42,induct:19,votablespecerror:[14,7],list:[20,2,5,6,7,8,29,36,18,1,24,23,25,27,22,41,31,32,33,34,19,39,40,42,28],object_attr:6,amend:42,adjust:3,cosin:19,stderr:[14,6],small:[2,11,3],dimens:[41,7,5,28],test_path:3,setup_help:1,maout:15,past:43,zero:[41,8,5],b605216:44,design:[13,1,3,20,7,33,47],pass:[25,11,13,27,3,5,29,6,7,22,36],further:[20,23,11,7],what:[11,1,5,29,20,7,42,33,19],sub:[11,1,8,3,5,20,41,33,15,19],nano:19,sun:19,section:[11,38,20,3,39,26,27,42,44,33,19],abl:[25,38,20,7,44,23],brief:20,delet:[45,42,33,39,5],abbrevi:20,version:[11,36,37,1,2,31,3,5,26,29,14,28,7,43,20,42,33,8,46],intersect:5,consecut:19,eq_fk5:[8,7],method:[11,36,20,2,3,5,6,23,27,43,28,46,33,8,19,41],restwava:[5,29],full:[33,5,29],hash:[11,3,33],variat:[15,5],unmodifi:18,iraf:5,icrotn:29,trunk:[42,38],strong:23,modifi:[5,42,28,33,8,47],valu:[20,4,6,7,15,11,13,8,5,24,23,27,29,41,32,33,19,36,39,40,28,45],tpcn_ka:29,narron:4,ahead:42,hecto:19,prior:[3,7],amount:19,pico:19,keyvalu:[5,29],doctest:20,pick:42,action:[42,25,8],awastropi:[2,11],narrow:46,magnitud:19,via:[11,38,1,3,5,26,41,42,33,23],packagenam:[2,11],declin:36,intermedi:[0,5],transit:23,cfgtype:33,vim:44,filenam:[20,36,14,3,22,6,41,7,32,33],href:[8,7],decrement:5,dangl:19,select:[41,42,5,28],convini:2,regist:11,two:[26,36,20,3,5,29,41,7,28,22,19],book:[0,9],"0x8afe3b0":40,taken:33,wcshdr_crotaia:29,more:[1,3,5,6,7,15,10,11,13,8,18,20,23,25,26,41,32,33,19,36,42,28],flat:[8,36],wrapper:[2,30,46],desir:[25,33,23],equina:[41,29],canon:[5,28],wcsprm:[28,30,5,41,29],is_un:5,ital:20,glat:5,cdelt:[45,5,24],flag:[3,42,18,41,29],particular:[11,13,20,2,3,5,29,41,42,33,8,19],known:[20,11,13],set_valu:11,check_anyuri:[14,6],cach:[33,3,7,34],none:[25,11,13,37,27,14,15,5,29,6,22,41,7,32,33,34,8,35],hour:[5,19],attr_nam:[14,37],oversight:29,outlin:[20,11],histori:[0,10,38,42,28,46],angl:[5,19],remain:[2,33,3,42,5],paragraph:20,del:[45,5],learn:[0,26],dec:[36,41,5,24],def:[25,11,13,1,3,22,20,33],deg:[36,5,19],w50:7,find_current_modul:22,share:42,templat:[1,20,11,23],tabular:[41,5],iter_t:[8,36],minimum:[8,5,44],explor:[20,42],magenta:13,coosi:[8,7],cours:[0,29,44],goal:[20,23],rather:[11,38,1,2,3,6,20,7,24,14,42,23],anoth:[1,5,20,7,44,42,8,19],hugo:44,csc:5,snippet:[0,7],reject:[15,29],mjdobn:29,scienc:46,simpl:[11,27,15,3,18,5,6,41,7,8],unabl:7,resourc:[0,11,36,26,7,43,32,33,8],referenc:[20,8,7],brett:44,reflect:33,catalog:7,plane:[30,5,4,41,46,19],buffer:39,remote_data:3,varianc:15,associ:[20,2,5,29,41,33,8],circumst:[1,5],github:[0,10,26,38,1,17,18,20,42,43,9],e20:7,e21:7,read:[0,11,13,38,20,42,5,4,29,6,30,7,28,32,33,8,41,36],confus:[20,42,19,29],spectra:23,ambigu:[11,19],caus:[39,7,36,29],mjdob:5,csyer:5,votablefil:[32,8,36],simpleelementwithcont:8,help:[0,25,11,1,3,39,26,20,42,23],fft:20,equatori:[8,5],soon:[2,11,33],cross:[8,5],paper:[30,5,29,41,45,46,19],through:[11,1,3,5,20,8],hierarchi:11,"__weakref__":40,e701:39,paramet:[20,13,40,1,15,31,5,4,22,6,41,27,19,14,45,32,33,34,8,35],style:[11,13,20,41,33,23],get_valu:11,dobsn:29,geoscienc:20,resort:20,wrt:19,html:[6,43,33,34,9,47],onelin:[42,38],might:[11,36,3,42,44,33],color_print:13,clariti:11,"return":[20,3,4,5,6,15,13,14,8,18,35,1,27,22,41,31,32,33,29,19,36,37,28,45],sentenc:20,tcrotna:29,framework:[20,3,23,43],compound:19,detach:42,parenthesi:19,document:[1,2,3,7,15,10,11,12,36,8,16,17,20,21,23,26,30,33,39,42,43,44,46,47],cpdis2:41,cpdis1:41,solver:5,instruct:[26,38,17,42,43,9],refresh:[34,39],micro:19,token:[14,6,7],radian:19,radial:5,found:[20,5,29,6,32,33,22],unicod:[6,7,13,8,36],errata:29,truncat:[7,13],memoryerror:[41,5,4],inplac:[39,15],icunna:29,monoton:5,procedur:23,realli:38,expect:[11,36,1,5,27,7,33],energi:19,beyond:13,todo:[20,27,43],orient:[20,11,15],phi_0:5,agre:23,shortcom:36,publish:[41,5],get_convert:35,set_pv:[5,24],sparingli:20,difficulti:29,qualifi:5,advanc:[0,42,26,17,18],tcrpna:29,votlint:34,reason:[11,38,20,39,29,42],base:[11,36,40,2,3,5,6,41,7,24,28,42,33,34,8,19],put:[20,26,3,33],bash:39,basi:36,veloc:[5,28],upsilon_m:5,perhap:[42,5],amper:19,lightgrei:13,assign:[20,7],excurs:39,velo:[5,28],obviou:[20,7,29],upper:[41,5],feel:33,misc:[15,21,19,22],number:[40,13,27,20,2,3,39,5,29,6,23,7,24,15,28,32,22,8,19,41,36],velangl:5,placehold:44,footprint:41,smaller:39,done:[26,38,1,3,18,5,41,42,44,23],construct:[8,5],stdlib:41,blank:[20,39,5,29],stabl:[1,23],miss:[8,7,36],fanci:[42,44],differ:[26,13,20,3,39,5,22,27,30,7,33,23,41],exponenti:19,lightcyan:13,farad:19,interact:[42,39],radesi:5,least:[20,14,29,6,7,19],statement:[6,33,13],natur:[20,19,29],illeg:7,steradian:19,scheme:[1,25,11,33],store:[11,36,1,3,5,29,41,7,33,8],schema:[14,6,7,32],adher:11,luckili:42,stdout:[14,6,32,13,5],option:[1,3,5,7,8,11,13,18,35,20,25,27,22,41,31,32,33,34,19,38,39,40,42,43,46],ncp:5,similarli:[11,3],tabwidth:13,pars:[25,36,5,7,24,31,32,8,47],consult:3,setup_packag:1,simplist:[14,6],whenev:[23,7,38],remot:[0,38,20,3,42,44,33],remov:[20,3,39,5,42,34],dtd:[14,6,32],gref:7,stall:23,str:[20,13,27,14,5,22,6,7,31,32,33,8,36],cunitia:[41,5,29],pvi_4a:5,comput:[26,20,5,29,42,44,33,15,19],cubefac:[41,5],packag:[10,11,16,36,1,2,3,17,26,22,20,43,23,42,15,28,33,8],doublecomplex:[8,7,35,36],"null":[8,7],lie:5,built:[11,13,1,3,20,43,33,34],equival:[11,36,20,5,29,7,19],check:[20,38,14,3,39,18,5,6,7,21,42],self:[20,11,3,5,41],violat:[32,7],get_naxi:41,also:[26,36,20,2,3,39,5,29,43,23,7,8,44,42,32,33,9,19,41],build:[10,11,36,1,23,16,6,28,24,43,20,46,8],joul:19,brace:20,imgpix_matrix:5,zepto:19,w40:7,w41:7,pipelin:[46,30],w43:7,w44:7,distribut:[10,11,16,13,25,1,3,33,15],w46:7,w47:7,w48:7,w49:7,previou:[42,39],reach:[23,38],most:[11,13,1,26,29,6,7,20,42,33,22],get_table_by_id:8,exc_valu:13,plan:[1,43],conic:5,maco:9,alpha:20,hashorurl:33,numericarrai:35,charg:19,exc:7,exa:19,clear:[20,33,8,22],cover:[26,3,43],part:[25,11,27,14,2,30,31,6,23,7,20,33,8,19,47],clean:0,warmli:18,icrdena:29,microsoft:28,somewhat:7,cdb:33,carefulli:20,tcdn_ka:29,fink:9,session:[33,3],particularli:20,font:[20,39,13],utyp:[8,7],find:[26,1,18,22,41,42,33],e19:7,cell:[7,36],coerc:27,randn:15,pretti:44,e11:7,e10:7,e13:7,ultim:[26,23],solut:5,e14:7,e17:7,e16:7,factor:19,darwin:3,"6d8e1e":44,hit:11,unus:11,express:[7,19],nativ:5,celementtre:6,fastest:[7,5],stc:7,coord:[20,45,41,5],rfc:[14,6,7],common:[0,10,11,20,23,16,26,41,44,33,15,19],new_file_nam:42,nowher:[8,5],seamlessli:23,votable1:7,set:[1,3,5,7,8,11,36,18,20,24,23,27,28,29,41,32,33,34,38,39,40,42,43,44],equinox:[8,5],decompos:5,mutabl:[8,28],emac:[11,39],arc:19,bare:44,arg:[25,11,13,27,6,41,7],close:[38,6,42,7,33,19],configdir:33,barn:19,expert:20,jenkin:1,someth:[25,11,36,3,18,6,42,44,33],particip:43,struct:[28,29],has_crotaia:5,lonpolea:[41,5,29],won:11,teardown_modul:3,find2:22,find1:22,altern:[2,3,5,29,6,7,43],signatur:20,catalogu:[7,37],syntact:[14,6,41,5],web:[20,34,38],numer:[27,8,7,35,19],complement:5,cproject:7,disallow:[7,19],func_c_:20,lowercas:7,cachedir:33,len:13,ipython:42,"_generate_all_config_item":33,popul:[33,36],both:[11,36,1,3,5,4,29,20,41],last:[27,5,29,41,7,42,15],mega:19,numpydoc:20,package_data:1,f2w:5,context:[13,20,39,5,7,19],whole:[1,33,36,29],iowarn:7,load:[36,1,39,41,24,46,32,33,47],simpli:[11,36,20,8,3,5,29,33,9,19],celesti:[41,5],point:[11,20,8,5,6,41,7,24,45,42,15],format:[28,36,20,3,18,5,27,41,7,44,33,8,35],returncod:[14,6],header:[20,1,5,4,29,6,30,7,24,43,28,46,41],"5e9":11,param:[8,7],linux:[0,42],mistak:[42,29],throughout:[20,15,7],e221:39,backend:3,sever:[20,39,18,42,28,9],extrema:5,java:[11,34],tctypn:29,devic:19,due:[25,11,7],empti:[20,8,39,7,13],get_legacy_alia:1,check_unit:37,imag:[36,20,5,4,29,30,7,28,45,46,19,41],great:[20,26],append:[8,40,7,36,22],wcshdr_cd00i00j:29,coordin:[11,20,2,5,4,29,23,7,24,28,45,46,33,8,26,41],understand:[20,11],func:3,det2im:[46,41],repetit:7,iter_coosi:8,look:[13,38,1,3,20,7,42,33,8,36],solid:19,erron:[5,29],histor:[5,29],"while":[13,1,3,5,29,20,7,42,33],unifi:[7,19,47,31],abov:[11,13,38,1,3,5,29,20,7,44,42,33],error:[13,14,5,19,20,41,7,24,28,32,35,36],pix2ski:20,anonym:8,loop:36,earli:29,vol:20,transfor:5,readm:42,wcs_sky2pix:[46,41,24],"2dec1ac":42,centi:19,itself:[36,1,23,3,29,7,33,8,19],limit:[10,20,15,5,29,7,8],decor:3,irrelev:5,fedora:9,minim:19,zopt:5,belong:20,shorten:44,instal:[10,11,1,2,3,17,26,23,42,39,43,32,9],cd00i00j:29,funni:18,lengthi:11,pytest:3,simpleel:8,conflict:[42,7],higher:[32,23],"_descriptionproperti":8,archiv:[11,7],optic:28,tvn_ma:29,optim:5,wherea:[7,5,19],moment:[14,6,36],temporari:[20,3,41],user:[0,10,11,13,1,2,3,18,26,29,20,23,42,44,33,15,19,41],robust:[11,23],wherev:[11,3,8],stack:22,focal:[46,41,4],recent:[6,26,9,22],subpackag:[1,2,11,33],lower:5,has_crota:5,machineri:[1,8],discourag:[20,11,23],older:[25,11,7,5],entri:[8,5,28],pickl:22,person:44,expens:11,runtimewarn:7,propos:[7,44],explan:[20,42,7],unicodechar:[8,7,35,36],det2im1:41,det2im2:41,collabor:42,shape:[20,15,19],cel_offset:5,sugget:11,unicodestr:7,somepackag:25,botch:42,wcshdo_wcsnna:29,appli:[5,22,41,42,33,29,8,19],input:[25,11,36,20,5,41,7,15,35],"395dd6493cc584df1e78b474fb150840":33,float32:7,obsgeo:[5,29],bin:[25,11,39,19],sobsna:29,australia:46,eoferror:22,transpar:3,invalidwcsexcept:20,bit:[36,35,5,29,41,7,8,19],analogu:29,"2e991e8":44,formal:[5,19,29],fixup:42,jcrpxna:29,e08:7,e09:7,e06:7,docutil:[20,4,6,7,15,13,14,8,5,35,21,27,22,41,31,32,34,19,36,37,40,45],signal:[42,18],e05:7,e02:7,resolv:42,e01:7,"3d_cd":[1,33],collect:[6,34,42,21,40],mjdan:29,eadc391:42,encount:[32,7],to_header_str:[41,29],often:[11,20,3,42,8,19],visibl:[20,5],some:[0,1,2,3,5,6,7,11,13,18,20,24,23,25,28,33,36,38,39,42,43,44],back:[36,20,18,22,7,24,42,8],iter_fields_and_param:8,understood:5,unspecifi:5,sampl:[11,15],mirror:42,w45:7,affili:[10,11,16,1,2,3,17,26,20,33,23],scale:[41,5,19],support:[11,36,1,23,3,5,30,7,28,46,33,8,19,41],ijcdna:29,shall:20,pep:[20,11],per:[11,13,36],substitut:5,mathemat:[20,19],larg:[20,3,34],slash:19,mhz:19,machin:[0,34],print_cont:[5,24],run:[20,2,3,39,28,43,44,33,34],solrad:19,sacrif:20,step:[26,36,5,42,44,45,13],prerequisit:43,meantim:42,faith:[42,18],idx:8,constraint:29,preclud:23,wcshdr_projpn:29,optpars:25,buxfix:42,block:[11,7,33],repair:7,"__future__":24,emphasi:20,primarili:[23,11,15],within:[1,15,3,5,7,33,8,19],pvi_1a:5,pastebin:3,watt:19,randomize_posit:20,ensur:[11,13,3,39,41,7,42,23],dateavg:5,test_my_bug:18,inclus:[2,26,23,19],span:[40,13,37,27,14,15,5,4,22,6,41,7,21,19,31,45,32,34,8,35,36],make_validation_report:34,question:20,fast:[20,6,38],custom:[1,44],"__enter__":13,wcsunit:5,includ:[25,11,13,38,1,2,3,5,6,23,42,15,8,20,32,33,9,19,41,36],suit:[2,3,43],forward:38,parse_arg:25,xdg_cache_hom:33,properli:28,msi:43,poster:42,linu:0,gauss:19,link:[0,26,1,7,43,42,8],translat:[28,41,5,19],newer:[1,7],delta:5,line:[10,11,16,13,38,25,20,3,39,18,26,6,41,7,44,42],info:[11,20,26,7,44,8],utf:[25,36],tcrpxn:29,consist:[20,25,11,23,5],yotta:19,those:[0,25,13,38,1,23,3,5,29,20,7,24,28,42,33,15,36],highlight:[39,13],yyyi:5,similar:[42,33,41,15],curv:5,constant:[20,5,29,30,8,41],zetta:19,lyr:19,parser:[25,29,6,7,19,34,8,35],chan:19,doesn:[1,5,6,41,7,42,33,8,19],repres:[13,20,5,4,7,45,42,8,19,36],"char":[8,36,7,13,35],parsec:19,darkgrei:13,fieldref:8,specsi:5,titl:[42,8],nan:[45,7,5],invalid:[20,5,4,41,7,31,32,19],bracket:19,angstrom:19,new_wc:[41,5],nice:[0,6,20,18,44],test_funct:3,floatcomplex:[8,7,35,36],introduc:[3,29],meaning:[41,5],crota:[5,28],lightgreen:13,longitud:[41,5],deserv:20,ago:44,infrequ:20,algorithm:[20,11,41,15,5],vice:5,max_inclus:8,depth:[0,3,22],summit:44,broad:2,far:22,unboundedstr:7,velref:[28,29],code:[10,11,16,13,25,1,2,3,39,18,26,5,20,41,7,44,42,33,23],partial:[41,5],queri:[8,33,7],cenfunc:15,edu:[33,7],rfrqna:[41,29],compact:[36,38],cython:[1,10,11,3,16],privat:[20,12,47],sensit:[33,19],elsewher:[20,8],func_:20,friendli:[41,13,19],send:[32,18],macport:9,somemod:25,aris:[7,5],fatal:7,logarithm:[41,5,19],datafil:3,print_code_lin:13,distribute_setup:1,minerr:41,mous:39,electron:19,implicitli:[6,3],relev:[11,1,16,5,20,7,33],tri:[41,5],magic:0,unsignedbyt:[8,7,35,36],meant:[20,8,7],complic:[11,42,5],button:42,michael:46,fewer:[7,22],undistort:41,update_package_fil:1,w29:7,set_color:11,blocksiz:13,pleas:[42,18],impli:[20,7,38],cdfix:5,cfg:33,zsourc:5,submultipl:19,jump:39,blanklin:20,video:0,download:[11,9,3,39,43,33,34,23],click:42,quadcub:[41,5],compat:[1,25,11,5],index:[10,11,2,5,4,22,19],compar:38,fine:29,access:[11,38,1,15,3,18,5,27,23,7,28,42,33,34,8,47],geo_app:[8,7],can:[0,1,3,5,6,7,9,11,13,14,8,17,18,20,24,23,25,26,28,41,33,19,36,38,39,42,43,44,46],equinoxa:[5,29],consolid:23,usag:[10,11,36,20,3,5,29,41,24,46,33,15],matplotlib:[20,11,23],bodi:6,piximg_matrix:5,let:[42,11,39,38],sinh:19,ubuntu:9,layout:[2,11,16,23,10],safer:11,becom:[20,3],sinc:[11,14,3,39,18,5,6,7,28,42,8,19],convert:[25,13,20,28,5,4,19,6,41,7,24,44,32,8,35,47,46],to_head:[29,5,41,24],convers:[28,35,47,19],larger:[20,25,3],fix_id:[14,6],converg:15,chang:[28,11,38,20,3,18,4,5,41,7,44,42,33,29,26],chanc:20,writer:[6,21],danger:11,e15:7,foundat:0,submodul:11,apt:9,volt:19,api:[10,12,20,30,21,44,46,33,15,47],"__name__":22,underflow:19,subimag:[41,5],from:[0,1,3,5,6,7,8,9,10,11,36,14,15,18,19,20,24,23,25,28,22,41,33,34,35,38,39,42,43,44,45,46],commun:[0,2,23],isn_ma:29,doubl:[36,20,5,4,19,7,45,33,8,35],upgrad:7,next:[33,11,13],websit:39,eleven:19,usr:[25,11],crab:19,deepcopi:41,jonathan:44,sort:20,datfix:5,trail:[39,5],get_offset:45,toolchain:20,getter:11,iii:[5,29],w33:7,account:[41,42],alik:29,retriev:[6,33,3,7,36],augment:[20,28],dest:25,alia:[41,42,5,44],meet:11,fetch:[42,38],control:[11,1,42,5,26,29,7,31,32,33,19],malform:[7,5],vsourcea:29,process:[25,11,13,1,5,20,28,23],lock:39,sudo:9,high:[32,24],tag:[6,7],some_func:33,tab:[11,39,13,5],tarbal:43,onlin:0,serial:8,has_colon:31,imgcrd:5,sip:[41,46,30,4,28],pycheck:39,six:5,pci_ja:[41,5,29],tabledata:[8,7,35,36],has_cd:5,sig:15,teardown_method:3,instead:[11,38,1,15,39,18,5,20,22,7,33,29,8],narg:25,sin:[5,19],delai:39,int16:7,recomput:28,singular:[41,5],keithdeven:11,pyfit:[1,46,41,24,28],differenti:5,attent:42,ijpcna:29,mjd:[5,29],alloc:[41,8,5,4],store_tru:25,light:19,correspond:[8,33,41,7,5],element:[13,40,27,5,6,41,7,32,33,8,19,36],issu:[42,32,11,7,33],prettifi:13,allow:[11,1,23,3,39,5,29,20,7,42,8,19],cdi_ja:[45,5,29],get_field_or_param_by_id:36,fallback:7,move:[11,18],kbd:39,whilst:[20,19],comma:7,bunch:6,finddiff:22,mod2:22,outer:44,e04:7,consensu:23,chosen:26,tsc:5,therefor:[32,41,7],pixel:[20,5,4,29,41,24,28,45,46,19],weber:19,pci_j:[41,5],crash:[0,39],fourth:5,python:[1,2,3,6,7,10,11,13,16,5,20,24,23,25,26,27,22,41,32,33,36,39,43,28,46],auto:39,dai:[5,19],xml_escap:6,dat:33,mention:20,facilit:[20,23],front:[3,13],strive:23,multiprocess:[34,13],somewher:18,recarrai:8,anyth:[11,42,18],edit:[0,20,18,42,44,33],wdiff:44,astronom:[8,23,7,19,37],create_arrai:[8,36],scrollbar:13,mode:[36,39,18,22,7,32,13],mnemon:29,astroyear:7,tmpdir:3,upward:20,few:[20,42,11,23,38],w19:7,w18:7,w17:7,subset:[20,5],w15:7,strip:5,w13:7,w12:7,localfn:33,w10:7,consum:32,meta:[8,7],"static":[6,3],wcshdr_pc00i00j:29,hyperbol:19,patch:[23,18,38,28],metavar:25,special:[40,1,8,5,20,23,21,28,15,41],out:[11,13,38,23,18,5,6,41,7,24,32,8,36],variabl:[11,36,20,3,39,7,33,8],overridden:29,contigu:5,defaultvalu:33,mjdavg:5,"4aff2a8":44,spline:13,reflog:42,rel:[25,11,1,3,39,5,20,41,7,44,42,33,15],calcfootprint:41,ref:[42,8,7,5],reg:41,math:20,clarifi:20,nonseparablesubimagecoordinatesystem:[41,5],workflow:[0,26,38,17,18,42,46],md5hash:33,standalon:[1,3,23],crval:[45,5,24],dictionari:[1,5,6,41,8,35],latest:[26,7,43],releas:[1,23,9,43,28],embarrass:42,log:[0,42,19,38,44],find_diff:22,indent:[20,6,11,39],unwant:42,could:[6,28,23,5,29],ask:42,supergalact:[8,7],keep:[20,42,23,36],scari:38,length:[13,20,5,41,7,8,19,36],cname:5,outsid:[11,23],all_pix2ski:[46,41],ivoa:[7,31],softwar:[26,7],suffix:39,parabl:0,qualiti:23,date:[20,3,5,29,7,44],"68f6752":44,some_dir:3,hertz:19,lib:42,facil:46,"long":[11,13,38,3,29,7,28,8,35,36],strict:43,unknown:[7,5],licens:[20,46,11],system:[10,11,20,2,3,39,5,26,23,7,33,34,8,19,41],messag:[13,14,39,18,7,28,42,32,35],eighth:5,is_valid:32,get_field_by_id:8,lumen:19,termin:[20,13],man:42,"final":[36,3,42,18,5],prone:11,shell:34,icrotna:29,wavelength:5,fuzzi:20,shallow:41,has_length:13,rst:11,exactli:[20,23,7,13,22],haven:18,succinctli:42,tangl:42,colax:5,see:[10,11,1,2,3,42,18,26,5,20,22,41,7,43,32,33,29,8,19],structur:[36,20,5,24,46,8],charact:[20,13,14,39,5,29,6,7,19],siemen:[5,19],sens:[20,41,7,5],sec:19,exp:19,cylfix:5,e18:7,clip:15,terribl:7,falsi:5,julian:[7,5,19],icdltn:29,corran:44,teardown_class:3,have:[0,1,3,5,7,9,11,13,14,8,17,18,20,24,23,26,22,41,33,29,19,36,38,42],tabl:[10,12,36,20,23,5,29,30,7,47,28,45,32,8,19,41,46],need:[25,11,38,1,23,3,39,5,26,29,20,7,43,44,42,8,19,46],tidi:38,cfg_option:33,ecl_fk5:[8,7],ecl_fk4:[8,7],min:[8,7,19],rout:43,mid:5,accuraci:8,mix:5,unawar:11,discret:20,"_wc":5,which:[1,2,3,6,7,8,11,13,14,5,20,23,26,27,28,29,32,33,22,19,36,39,42,44],discrep:15,int64:7,detector:[46,30,19,41],singl:[25,11,36,1,2,5,22,20,23,42,45,33,8,19,41],uppercas:7,pyx:[1,11],a7ff2e5:44,unless:[11,29,23,19,44],preliminari:42,githhub:42,who:[3,23,18,38,44],discov:[20,3,18],sfl:5,eight:29,dateob:5,has_pc:5,judici:20,why:[11,42,18],"_build":43,crpix:[45,5,4,24],shupe:4,url:[32,33,3,42,34],test_42:3,request:[11,38,2,26,42,44,33,23],uri:[14,6,7,8],face:[39,5],yum:9,determin:[11,13,5,22,6,41,33,8],flux:19,occasion:19,hardcor:42,fact:[11,29],text:[38,20,39,6,42,44,33,19],syntaxerror:19,verbos:3,invalidsubimagespecificationerror:[41,5],bring:[42,39,36],stilt:34,cfgoption:33,tcrdena:29,trivial:[11,29],wcspih:[41,28],setter:11,homogeneouslist:40,maskedconst:42,locat:[11,1,23,5,20,7,33,8],xmlwriter:6,jar:34,should:[25,11,36,38,1,23,3,5,29,20,41,7,24,44,42,33,22,15,19],schema_fil:6,suppos:[1,33,42,36],wcsax:[41,5],discontinu:5,"721fc64":42,wcssub_longitud:[41,5],cube:5,contribut:[42,10,26,16,17],celfix:5,disagre:5,velrefa:29,autom:[1,33],get_table_by_index:8,meter:[5,19],increas:[23,5],cdeltia:[45,5,29],lngtyp:[41,5],a725fa6ba642587436612c2df0451956:33,wcshdr_epocha:29,enabl:[11,3,39,29],organ:[42,11,3,23],stuff:[25,42,38],shd:[5,19],integr:[11,38,20,23,26,7,8],contain:[11,40,36,38,44,1,2,31,3,5,22,6,23,7,15,20,32,33,8,19,41],view:[20,33,5],conform:[11,36,29,7,8,19],legaci:1,modulo:24,frame:[27,5],min_inclus:8,statu:[0,44,42,18,5],correctli:[42,6,3,17,43],record:[8,7,5,36],lux:19,pattern:[11,7,33],thumb:[0,7],e12:7,state:[20,42,7,13],quickest:18,progress:[42,18,13],neither:[33,8],email:[26,18,44],w08:7,terhorst:44,kei:[8,39,5,41,42,33,23],mod1:22,w04:7,w05:7,w06:7,w07:7,w01:7,w02:7,w03:7,tempfil:3,job:1,entir:[11,20,8,6,32,23,47],crotai:29,w38:7,eclipt:[8,5],addit:[11,16,20,23,3,39,5,41,7,43,34,9,19],plugin:3,admin:42,equal:[17,5,44],configpars:33,etc:[38,20,8,5,29,41,43,23],admit:[41,5],instanc:[11,36,20,42,7,32,8,35],grain:29,equat:20,committe:[11,23,26],highland:20,comment:[11,20,5,6,41,33],theta0:5,ra_dec_ord:41,icsyna:29,guidelin:[10,11,16,20,3,39,26,23,19],argumentpars:25,gitk:42,solv:5,ucd:[8,7,36,47,31],sky2pix:20,respect:[20,3,17,5,41,7],gitx:9,quit:42,get_indentation_spac:6,addition:[11,30,8],writeto:24,get_pv:5,compon:[26,11,5,7,31,23,19],treat:[28,7,29],"0x8758990":[],immedi:[33,3,42,5,19],get_pc:[5,28],e202:39,get_data_cont:33,presenc:5,assert:[3,24,44],untrack:42,x_2:7,togeth:[46,30,23,29],solmass:19,velosi:5,b_i_j:4,present:[11,1,39,5,29,41,7,28,45,42,33,15],rightward:29,simpletyp:7,multi:[20,7],besselian:7,wcshdo_non:29,to_xml:[8,36],get_indent:6,"__iadd__":40,cursor:39,defin:[1,3,6,7,8,11,13,14,5,20,24,27,29,30,31,33,36,37,40,41,45,47],wild:[8,7,36],pc00i00j:29,observ:5,tpn_ka:29,get_axis_typ:41,helper:[1,33,3],almost:[41,5],setup_class:3,pix2foc:[41,4],unitfix:5,site:20,mulitpl:11,inform:[10,11,16,36,1,2,3,42,5,26,29,20,41,7,24,46,32,33,8,19],motiv:20,get_:11,revis:42,avg:[5,29],uncategor:[21,22],uniti:[41,5,19],wcshdr_velrefa:29,mutat:36,welcom:10,parti:[1,11],began:28,defun:39,sqrt:19,member:[36,5,41,28,8,13],handl:[20,5,29,30,7,28,42,35],s2p:5,float_:24,psi_ma:[5,29],failur:3,"__version__":2,infer:33,competit:23,phi:5,http:[11,1,9,3,20,7,43,42,33,34,8],booleanarrai:35,a_ord:4,upon:[23,7],effect:[36,19,22],hdulist:[46,24],get_config:33,icnamn:29,femto:19,set_:11,distutil:[1,43],expand:0,chunk_siz:32,off:[36,38,3,5,41,7],center:[15,36],neural:20,well:[11,20,17,5,29,6,42,44],thought:[33,42],weblog:11,exampl:[1,3,5,7,8,9,10,11,36,15,17,18,20,24,23,25,26,27,22,41,33,29,19,38,39,42,44,46],command:[0,10,11,16,25,3,39,18,42,43,44],achiev:[42,23,15],interpol:5,undefin:[45,8,5],usual:[20,42,5,43],test1:36,spcaip:28,test2:36,paus:42,less:[11,41,13,19,5],"boolean":[36,15,5,7,8,35],check_mime_content_typ:[14,6],wcshdo_cnamna:29,obtain:[20,3,39,43],settabl:8,spcfix:5,sptr:5,systemat:5,"_________________________________":3,expon:19,adu:19,omit:[6,7,5,36],wcssub_spectr:[41,5],onward:28,sky:[20,46,41,5,24],vangna:29,spinner:13,script:[10,11,16,25,1,3,39,33,23],add:[0,38,20,28,39,18,6,42,44],valid:[37,27,14,28,5,6,7,21,43,31,32,33,34,8,47],densiti:19,lookup:[5,30,28,45,46,8,41],warrant:15,c16:36,match:[13,20,3,5,6,7,33,15,19],int32:7,eq_fk4:[8,7],torvald:0,"11ee694744f2552d":42,branch:[0,38,18,42,43,44],tcnamn:29,b_order:4,hard:[20,41,42,5],punctuat:7,know:[42,11,8],press:39,tick:20,recurs:[3,8],is_unit:37,insert:[42,40,39,13],like:[11,13,38,20,15,3,42,29,6,27,24,44,32,33,22,8,19,36],success:5,safest:3,fernando:0,test_:3,use_system_pytest:3,necessari:[25,11,20,18,26,5,43,44,33,8],resiz:[36,4],page:[0,10,26,38,20,16,17,42],cfgobj:33,photometri:23,specifi:[28,11,36,20,15,3,39,5,4,29,40,41,7,31,33,22,8,19],habitat:20,revert:5,suppli:[11,5,24],destdir:34,sophist:42,get_data_fileobj:[1,11,3,33],superclass:11,flush:6,proper:[11,7],home:[33,42,44],wcssub_cubefac:[41,5],librari:[25,11,13,6,1,2,39,14,27,32,33,23,47],tmp:[3,42],guid:[0,11,20,16,42,33],lead:11,leak:42,avoid:[11,20,7,42,23,19],rwavna:29,disk:36,estim:15,filesystem:33,speak:[7,29],encourag:[20,11,23,26],bintabl:29,importerror:11,deprec:[20,46,41,7,5],symlink:33,stellar:19,host:[1,11,17],cgreen:44,although:[41,5,19],offset:[45,6,39,5,19],has_cdi_ja:5,simpler:[25,11],about:[11,36,20,15,18,26,41,7,43,42,33,8],actual:[25,5,29,7,44,42,33,8],interven:19,polynomi:[41,46,30,4],column:[13,20,39,5,29,7,46,32,8,36],cleans:7,justif:11,candela:19,invalidtransformerror:[41,5],constructor:[20,46,13,29],discard:42,compute_color:11,disabl:[1,3,42],metr:19,own:[0,25,38,1,23,3,20,7,42,15],convolut:20,inlin:[20,7,19],easy_instal:39,automat:[38,1,3,39,7,33],diagon:[41,5],ssrcna:29,merg:[0,26,38,2,42,44],dec_targ:36,val:33,bp_order:4,rotat:5,pacakg:20,"var":[20,15],anno_opt:33,"function":[1,3,6,15,11,13,5,35,20,23,25,22,30,31,32,33,19,36,41,28,46,47],basic:[26,38,20,39,5,41,43,46,33,19],gaussian:15,astro:7,w11:7,wcs_pix2ski:[46,41,24],overflow:19,highest:5,bug:[11,36,20,3,18,26,28,7,44,42],test_bugfix:44,count:[27,19],succe:3,made:[26,36,38,11,18,7,5,44,42,33,23,19],temp:39,dmg:43,whether:[28,41,13,5],wish:[2,33,23,43],"_astropy_vers":8,writeabl:13,displai:[20,39,13],w31:7,w30:7,below:[11,1,8,3,39,5,26,29,20,41,33,22,15,19],w32:7,lattyp:[41,5],w34:7,w37:7,w36:7,w39:7,otherwis:[11,8,3,42,5,22,6,41,7,31,32,33,15],problem:[42,11,7,33],subordin:29,a815645:42,"int":[20,13,14,15,5,4,29,6,41,7,28,32,22,8,35,36],mask:[36,15,39,7,42,32,8],dure:[1,42,23,36,44],pix:19,implement:[25,11,36,20,23,3,7,42,33,8,19],our:[20,42,38],pip:[39,43],probabl:[1,18,5],"2to3":[25,11,3],detail:[0,28,26,36,1,2,3,18,5,20,41,42,44,33,22,8],other:[0,1,2,7,8,11,36,15,5,20,23,29,41,32,33,22,38,9,40,42,43,28],bool:[13,20,8,5,22,27,41,31,32,33,34,15],futur:[36,1,8,3,5,29,6,23],rememb:[42,19,38],varieti:11,stat:[5,44],repeat:[42,39],star:11,"class":[20,3,4,6,7,15,11,13,14,8,5,19,21,23,25,27,22,30,31,32,33,34,35,36,37,40,41,28,45,46,47],astronomi:[10,26,2,16,15,23],invalidconfigurationitemwarn:33,imppedi:11,ndarrai:[20,15],tcrden:29,content_rol:8,vo_rais:7,debian:9,tan:19,matrix:[36,5,4,41,28,45],sphinx:[20,43],find_all_wc:[41,29],nrow:[8,7,36],complexarrai:35,rule:[0,20,11,3,19],votablespecwarn:[7,36],auxiliari:[5,29],partli:25,enforc:44,cookbook:27},objtypes:{"0":"py:module","1":"py:method","2":"py:function","3":"py:staticmethod","4":"py:attribute","5":"py:classmethod","6":"py:class","7":"py:exception","8":"np:module","9":"np:method","10":"np:function","11":"np:staticmethod","12":"np:attribute","13":"np:classmethod","14":"np:class","15":"np:exception"},titles:["Git resources","Building, Cython/C Extensions, and Distribution","Overview","Testing Guidelines (Draft)","Sip","Wcsprm","astropy.utils.xml: Utilities related to XML","astropy.io.vo.exceptions","astropy.io.vo.tree: Accessing and modifying the individual parts of VOTable files","Installing git","Welcome to Astropy’s Documentation!","Coding Guidelines (Draft)","astropy.io.vo Documentation","astropy.utils.console: Utilities for console output","astropy.io.vo.xmlutil: XML-related utilities used by the library","astropy.tools documentation","Documentation for Developers","Development workflow","Development Workflow (Beginner)","UnitConverter","Documentation Guidelines (Draft)","astropy.utils documentation","astropy.utils.misc: Miscellaneous/uncategorized Utilities","Vision for a Common Astronomy Python Package","Example Usage","Writing Command-Line Scripts","Contributing To/Developing Astropy or Affiliated Packages","astropy.io.vo.util: Low-level utilities used by the library","astropy.wcs History","Relax constants","API Documentation","astropy.io.vo.ucd: Functions to parse and verify unified content descriptors","astropy.io.vo.table: Loading entire VOTable files","Configuration system Documentation","astropy.io.vo.validator: Generates HTML validation reports","astropy.io.vo.converters: Conversions between XML and Numpy datatypes","Introduction to astropy.io.vo.table","astropy.io.vo.unit: Verification of units as defined in the VOTable standard","Maintainer workflow","Emacs setup for following coding guidelines","astropy.utils.collections: Specialized collection classes","WCS","Development Workflow (Advanced)","Installation","Configuring git","DistortionLookupTable","astropy.wcs Documentation","API documentation"],objnames:{"0":["py","module","Python module"],"1":["py","method","Python method"],"2":["py","function","Python function"],"3":["py","staticmethod","Python static method"],"4":["py","attribute","Python attribute"],"5":["py","classmethod","Python class method"],"6":["py","class","Python class"],"7":["py","exception","Python exception"],"8":["np","module","Python module"],"9":["np","method","Python method"],"10":["np","function","Python function"],"11":["np","staticmethod","Python static method"],"12":["np","attribute","Python attribute"],"13":["np","classmethod","Python class method"],"14":["np","class","Python class"],"15":["np","exception","Python exception"]},filenames:["development/workflow/git_resources","development/building_packaging","overview","development/testguide","wcs/api_sip","wcs/api_wcsprm","utils/api_xml","vo/api_exceptions","vo/api_tree","development/workflow/git_install","index","development/codeguide","vo/index","utils/api_console","vo/api_xmlutil","tools","development/index","development/workflow/development_workflow","development/workflow/development_workflow_basic","wcs/api_units","development/docguide","utils/index","utils/api_misc","development/vision","wcs/examples","development/scripts","development/workflow/index","vo/api_util","wcs/history","wcs/relax","wcs/api","vo/api_ucd","vo/api_table","configs","vo/api_validator","vo/api_converters","vo/intro_table","vo/api_unit","development/workflow/maintainer_workflow","development/codeguide_emacs","utils/api_collections","wcs/api_wcs","development/workflow/development_workflow_advanced","install","development/workflow/git_configure","wcs/api_distortion","wcs/index","vo/api"]}) \ No newline at end of file diff --git a/tools.html b/tools.html new file mode 100644 index 00000000..c413496c --- /dev/null +++ b/tools.html @@ -0,0 +1,250 @@ + + + + + + + + + + astropy.tools documentation — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.tools documentation

        +

        The tools package holds general astronomy functions or algorithms +that are likely of use to users, but either not related to functionality in +an existing package or of general use across multiple packages.

        +
        +

        Note

        +

        For functions and classes that are more developer-oriented, the correct +package is astropy.utils. astropy.tools is intended primarily for +functionality that is astronomy-specific and/or of use to users.

        +
        +
        +

        Reference/API

        +

        Below are the reference documentation for the tools sub-packages. All public +functions and classes in these packages will be imported into the +astropy.tools package, so the recommended usage is e.g. +from astropy.tools import sigma_clip or import astropy.tools instead of +from astropy.tools.misc import sigma_clip or similar.

        +
        +

        astropy.tools.misc

        +

        This module contains simple algorithmic functionality common in astronomy or +used in multiple places throughout Astropy, but are not complex enough to +necessarily warrant their own module.

        +

        This package should generally not be used directly. Everything in __all__ is +imported into astropy.tools, and hence that package should be used for +access.

        +
        +
        +astropy.tools.misc.sigma_clip(data, sig=3, iters=1, cenfunc=<function median at 0x14ec4f0>, varfunc=<function var at 0x1525330>, maout=False)[source]
        +

        Perform sigma-clipping on the provided data.

        +

        This performs the sigma clipping algorithm - i.e. the data will be iterated +over, each time rejecting points that are more than a specified number of +standard deviations discrepant.

        + +++ + + + + + +
        Parameters :

        data : array-like

        +
        +

        The data to be sigma-clipped (any shape).

        +
        +

        sig : float

        +
        +

        The number of standard deviations (not variances) to use as the +clipping limit.

        +
        +

        iters : int or None

        +
        +

        The number of iterations to perform clipping for, or None to clip until +convergence is achieved (i.e. continue until the last iteration clips +nothing).

        +
        +

        cenfunc : callable

        +
        +

        The technique to compute the center for the clipping. Must be a +callable that takes in a 1D data array and outputs the central value. +Defaults to the median.

        +
        +

        varfunc : callable

        +
        +

        The technique to compute the variance about the center. Must be a +callable that takes in a 1D data array and outputs the width estimator +that will be interpreted as a variance. Defaults to the variance.

        +
        +

        maout : bool or ‘copy’

        +
        +

        If True, a masked array will be returned. If the special string +‘inplace’, the masked array will contain the same array as data, +otherwise the array data will be copied.

        +
        +
        Returns :

        filtereddata : numpy.ndarray or numpy.masked.MaskedArray

        +
        +

        If maout is True, this is a masked array with a shape matching the +input that is masked where the algorithm has rejected those values. +Otherwise, a 1D array of values including only those that are not +clipped.

        +
        +

        mask : boolean array

        +
        +

        Only present if maout is False. A boolean array with a shape matching +the input data that is False for rejected values and True for all +others.

        +
        +
        +

        Examples

        +

        This will generate random variates from a Gaussian distribution and return +only the points that are within 2 sample standard deviation from the +median:

        +
        >>> from astropy.tools.alg import sigma_clip
        +>>> from numpy.random import randn
        +>>> randvar = randn(10000)
        +>>> data,mask = sigma_clip(randvar,2,1)
        +
        +
        +

        This will clipping on a similar distribution, but for 3 sigma relative to +the sample mean, will clip until converged, and produces a +numpy.masked.MaskedArray:

        +
        >>> from astropy.tools.alg import sigma_clip
        +>>> from numpy.random import randn
        +>>> from numpy import mean
        +>>> randvar = randn(10000)
        +>>> maskedarr = sigma_clip(randvar,3,None,mean,maout=True)
        +
        +
        +
        + +
        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        +

        Next topic

        +

        astropy.utils documentation

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/utils/api_collections.html b/utils/api_collections.html new file mode 100644 index 00000000..eff0b3f4 --- /dev/null +++ b/utils/api_collections.html @@ -0,0 +1,203 @@ + + + + + + + + + + astropy.utils.collections: Specialized collection classes — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.utils.collections: Specialized collection classes

        +

        A number of specialized collection classes.

        +
        +
        +class astropy.utils.collections.HomogeneousList(types, values=[])[source]
        +

        Bases: list

        +

        A subclass of list that contains only elements of a given type or +types. If an item that is not of the specified type is added to +the list, a TypeError is raised.

        +
        +
        +__dict__ = <dictproxy object at 0x8afe3b0>
        +
        + +
        +
        +__iadd__(other)[source]
        +
        + +
        +
        +__init__(types, values=[])[source]
        +
        +++ + + + +
        Parameters :

        types : sequence of types

        +
        +

        The types to accept.

        +
        +

        values : sequence, optional

        +
        +

        An initial set of values.

        +
        +
        +
        + +
        +
        +__module__ = 'astropy.utils.collections'
        +
        + +
        +
        +__setitem__(x)[source]
        +
        + +
        +
        +__weakref__
        +

        list of weak references to the object (if defined)

        +
        + +
        +
        +append(x)[source]
        +
        + +
        +
        +extend(x)[source]
        +
        + +
        +
        +insert(i, x)[source]
        +
        + +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.utils documentation

        +

        Next topic

        +

        astropy.utils.console: Utilities for console output

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/utils/api_console.html b/utils/api_console.html new file mode 100644 index 00000000..8c48ac93 --- /dev/null +++ b/utils/api_console.html @@ -0,0 +1,545 @@ + + + + + + + + + + astropy.utils.console: Utilities for console output — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.utils.console: Utilities for console output

        +

        Utilities for prettifying output to the console.

        +
        +
        +astropy.utils.console.isatty(file)[source]
        +

        Returns True if file is a tty.

        +

        Most built-in Python file-like objects have an isatty member, +but some user-defined types may not, so this assumes those are not +ttys.

        +
        + +
        +
        +astropy.utils.console.color_print(*args, **kwargs)[source]
        +

        Prints colors and styles to the terminal uses ANSI escape +sequences:

        +
        color_print('This is the color ', 'default', 'GREEN', 'green')
        +
        +
        + +++ + + + +
        Parameters :

        positional args : strings

        +
        +

        The positional arguments come in pairs (msg, color), where +msg is the string to display and color is the color to +display it in.

        +

        color is an ANSI terminal color name. Must be one of: +black, red, green, brown, blue, magenta, cyan, lightgrey, +default, darkgrey, lightred, lightgreen, yellow, lightblue, +lightmagenta, lightcyan, white, or ‘’ (the empty string).

        +
        +

        file : writeable file-like object, optional

        +
        +

        Where to write to. Defaults to sys.stdout. If file is not +a tty (as determined by calling its isatty member, if one +exists), no coloring will be included.

        +
        +

        end : str, optional

        +
        +

        The ending of the message. Defaults to \n. The end will +be printed after resetting any color or font state.

        +
        +
        +
        + +
        +
        +astropy.utils.console.human_time(seconds)[source]
        +

        Returns a human-friendly time string that is always exactly 6 +characters long.

        +

        Depending on the number of seconds given, can be one of:

        +
        1w 3d
        +2d 4h
        +1h 5m
        +1m 4s
        +  15s
        +
        +

        Will be in color if console coloring is turned on.

        + +++ + + + + + +
        Parameters :

        seconds : int

        +
        +

        The number of seconds to represent

        +
        +
        Returns :

        time : str

        +
        +

        A human-friendly representation of the given number of seconds +that is always exactly 6 characters.

        +
        +
        +
        + +
        +
        +class astropy.utils.console.ProgressBar(total, file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        +

        A class to display a progress bar in the terminal.

        +

        It is designed to be used with the with statement:

        +
        with ProgressBar(len(items)) as bar:
        +    for item in enumerate(items):
        +        bar.update()
        +
        +
        +
        +
        +__enter__()[source]
        +
        + +
        +
        +__exit__(exc_type, exc_value, traceback)[source]
        +
        + +
        +
        +__init__(total, file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        +
        +++ + + + +
        Parameters :

        total : int

        +
        +

        The number of increments in the process being tracked.

        +
        +

        file : writable file-like object, optional

        +
        +

        The file to write the progress bar to. Defaults to +sys.stdout. If file is not a tty (as determined by +calling its isatty member, if any), the scrollbar will +be completely silent.

        +
        +
        +
        + +
        +
        +__module__ = 'astropy.utils.console'
        +
        + +
        +
        +classmethod iterate(items, file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        +

        Iterate over a sequence while indicating progress with a progress +bar in the terminal:

        +
        for item in ProgressBar.iterate(items):
        +    pass
        +
        +
        + +++ + + + + + +
        Parameters :

        items : sequence

        +
        +

        A sequence of items to iterate over

        +
        +

        file : writeable file-like object, optional

        +
        +

        The file to write the progress bar to. Defaults to +sys.stdout. If file is not a tty (as determined by +calling its isatty member, if any), the scrollbar will +be completely silent.

        +
        +
        Returns :

        generator : :

        +
        +

        A generator over items

        +
        +
        +
        + +
        +
        +classmethod map(function, items, multiprocess=False, file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        +

        Does a map operation while displaying a progress bar with +percentage complete:

        +
        def work(i):
        +    print(i)
        +
        +ProgressBar.map(work, range(50))
        +
        +
        + +++ + + + +
        Parameters :

        function : function

        +
        +

        Function to call for each step

        +
        +

        items : sequence

        +
        +

        Sequence where each element is a tuple of arguments to pass to +function.

        +
        +

        multiprocess : bool, optional

        +
        +

        If True, use the multiprocessing module to distribute each +task to a different processor core.

        +
        +

        file : writeable file-like object, optional

        +
        +

        The file to write the progress bar to. Defaults to +sys.stdout. If file is not a tty (as determined by +calling its isatty member, if any), the scrollbar will +be completely silent.

        +
        +
        +
        + +
        +
        +update(value=None)[source]
        +

        Update the progress bar to the given value (out of the total +given to the constructor.

        +
        + +
        + +
        +
        +class astropy.utils.console.Spinner(msg, color='default', file=<open file '<stdout>', mode 'w' at 0x240078>, step=1, chars=None)[source]
        +

        A class to display a spinner in the terminal.

        +

        It is designed to be used with the with statement:

        +
        with Spinner("Reticulating splines", "green") as s:
        +    for item in enumerate(items):
        +        s.next()
        +
        +
        +
        +
        +__enter__()[source]
        +
        + +
        +
        +__exit__(exc_type, exc_value, traceback)[source]
        +
        + +
        +
        +__init__(msg, color='default', file=<open file '<stdout>', mode 'w' at 0x240078>, step=1, chars=None)[source]
        +
        +++ + + + +
        Parameters :

        msg : str

        +
        +

        The message to print

        +
        +

        color : str, optional

        +
        +

        An ANSI terminal color name. Must be one of: black, red, +green, brown, blue, magenta, cyan, lightgrey, default, +darkgrey, lightred, lightgreen, yellow, lightblue, +lightmagenta, lightcyan, white.

        +
        +

        file : writeable file-like object, optional

        +
        +

        The file to write the spinner to. Defaults to +sys.stdout. If file is not a tty (as determined by +calling its isatty member, if any), the scrollbar will +be completely silent.

        +
        +

        step : int, optional

        +
        +

        Only update the spinner every step steps

        +
        +

        chars : str, optional

        +
        +

        The character sequence to use for the spinner

        +
        +
        +
        + +
        +
        +__module__ = 'astropy.utils.console'
        +
        + +
        + +
        +
        +astropy.utils.console.print_code_line(line, col=None, file=<open file '<stdout>', mode 'w' at 0x240078>, tabwidth=8, width=70)[source]
        +

        Prints a line of source code, highlighting a particular character +position in the line. Useful for displaying the context of error +messages.

        +

        If the line is more than width characters, the line is truncated +accordingly and ‘…’ characters are inserted at the front and/or +end.

        +

        It looks like this:

        +
        there_is_a_syntax_error_here :
        +                             ^
        +
        + +++ + + + +
        Parameters :

        line : unicode

        +
        +

        The line of code to display

        +
        +

        col : int, optional

        +
        +

        The character in the line to highlight. col must be less +than len(line).

        +
        +

        file : writeable file-like object, optional

        +
        +

        Where to write to. Defaults to sys.stdout.

        +
        +

        tabwidth : int, optional

        +
        +

        The number of spaces per tab ('       ') character. Default is +8. All tabs will be converted to spaces to ensure that the +caret lines up with the correct column.

        +
        +

        width : int, optional

        +
        +

        The width of the display, beyond which the line will be +truncated. Defaults to 70 (this matches the default in the +standard library’s textwrap module).

        +
        +
        +
        + +
        +
        +class astropy.utils.console.ProgressBarOrSpinner(total, msg, color='default', file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        +

        A class that displays either a ProgressBar or Spinner +depending on whether the total size of the operation is +known or not.

        +

        It is designed to be used with the with statement:

        +
        if file.has_length():
        +    length = file.get_length()
        +else:
        +    length = None
        +bytes_read = 0
        +with ProgressBarOrSpinner(length) as bar:
        +    while file.read(blocksize):
        +        bytes_read += blocksize
        +        bar.update(bytes_read)
        +
        +
        +
        +
        +__enter__()[source]
        +
        + +
        +
        +__exit__(exc_type, exc_value, traceback)[source]
        +
        + +
        +
        +__init__(total, msg, color='default', file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        +
        +++ + + + +
        Parameters :

        total : int or None

        +
        +

        If an int, the number of increments in the process being +tracked and a ProgressBar is displayed. If None, a +Spinner is displayed.

        +
        +

        msg : str

        +
        +

        The message to display above the ProgressBar or +alongside the Spinner.

        +
        +

        color : str, optional

        +
        +

        The color of msg, if any. Must be an ANSI terminal +color name. Must be one of: black, red, green, brown, +blue, magenta, cyan, lightgrey, default, darkgrey, +lightred, lightgreen, yellow, lightblue, lightmagenta, +lightcyan, white.

        +
        +

        file : writable file-like object, optional

        +
        +

        The file to write the to. Defaults to sys.stdout. If +file is not a tty (as determined by calling its isatty +member, if any), only msg will be displayed: the +ProgressBar or Spinner will be silent.

        +
        +
        +
        + +
        +
        +__module__ = 'astropy.utils.console'
        +
        + +
        +
        +update(value)[source]
        +

        Update the progress bar to the given value (out of the total +given to the constructor.

        +
        + +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.utils.collections: Specialized collection classes

        +

        Next topic

        +

        astropy.utils.xml: Utilities related to XML

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/utils/api_misc.html b/utils/api_misc.html new file mode 100644 index 00000000..96b33ca8 --- /dev/null +++ b/utils/api_misc.html @@ -0,0 +1,292 @@ + + + + + + + + + + astropy.utils.misc: Miscellaneous/uncategorized Utilities — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.utils.misc: Miscellaneous/uncategorized Utilities

        +

        This package contains smallish general-purpose utilities that don’t have a +clear other module to live in.

        +

        This module should not be used directly, as everything in __all__` is +imported into astropy.utils

        +
        +
        +astropy.utils.misc.find_current_module(depth=1, finddiff=False)[source]
        +

        Determines the module/package this function is called from.

        + +++ + + + + + +
        Parameters :

        depth : int

        +
        +

        Specifies how far back to go in the call stack (0-indexed, so that +passing in 0 gives back astropy.utils.misc).

        +
        +

        finddiff : bool

        +
        +

        If True, once the module at depth is determined, a search will be +performed up the call stack until a different module is found +from the one at depth.

        +
        +
        Returns :

        mod : module or None

        +
        +

        The module object or None if the package cannot be found. The name of +the module is available as the __name__ attribute of the returned +object (if it isn’t None).

        +
        +
        +

        Examples

        +

        The examples below assume that there are two modules in a package named +pkg. mod1.py:

        +
        def find1():
        +    from astropy.utils import find_current_module
        +    print find_current_module(1).__name__
        +def find2():
        +    from astropy.utils import find_current_module
        +    cmod = find_current_module(2)
        +    if cmod is None:
        +        print 'None'
        +    else:
        +        print cmod.__name__
        +def find_diff():
        +    from astropy.utils import find_current_module
        +    print find_current_module(0,True).__name__
        +
        +
        +

        mod2.py:

        +
        def find():
        +    from .mod1 import find2
        +    find2()
        +
        +
        +

        With these modules in place, the following occurs:

        +
        >>> from pkg import mod1, mod2
        +>>> from astropy.utils import find_current_module
        +>>> mod1.find1()
        +pkg.mod1
        +>>> mod1.find2()
        +None
        +>>> mod2.find()
        +pkg.mod2
        +>>> find_current_module(0)
        +<module 'astropy.utils.misc' from 'astropy/utils/misc.py'>
        +>>> mod1.find_diff()
        +pkg.mod1
        +
        +
        +
        + +
        +
        +astropy.utils.misc.fnpickle(object, fileorname, usecPickle=True, protocol=None, append=False)[source]
        +

        Pickle an object to a specified file.

        + +++ + + + +
        Parameters :

        object :

        +
        +

        The python object to pickle.

        +
        +

        fileorname : str or file-like

        +
        +

        The filename or file into which the object should be pickled. If a +file object, it should have been opened in binary mode.

        +
        +

        usecPickle : bool

        +
        +

        If True (default), the cPickle module is to be used in place of +pickle (cPickle is faster). This only applies for python 2.x.

        +
        +

        protocol : int or None

        +
        +

        Pickle protocol to use - see the pickle module for details on +these options. If None, the most recent protocol will be used.

        +
        +

        append : bool

        +
        +

        If True, the object is appended to the end of the file, otherwise the +file will be overwritten (if a file object is given instead of a +file name, this has no effect).

        +
        +
        +
        + +
        +
        +astropy.utils.misc.fnunpickle(fileorname, number=0, usecPickle=True)[source]
        +

        Unpickle pickled objects from a specified file and return the contents.

        + +++ + + + + + + + +
        Parameters :

        fileorname : str or file-like

        +
        +

        The file name or file from which to unpickle objects. If a file object, +it should have been opened in binary mode.

        +
        +

        number : int

        +
        +

        If 0, a single object will be returned (the first in the file). If >0, +this specifies the number of objects to be unpickled, and a list will be +returned with exactly that many objects. If <0, all objects in the file +will be unpickled and returned as a list.

        +
        +

        usecPickle : bool

        +
        +

        If True, the cPickle module is to be used in place of +pickle (cPickle is faster). This only applies for python 2.x.

        +
        +
        Returns :

        contents : obj or list

        +
        +

        If number is 0, this is a individual object - the first one unpickled +from the file. Otherwise, it is a list of objects unpickled from the +file.

        +
        +
        Raises :

        EOFError :

        +
        +

        If number is >0 and there are fewer than number objects in the +pickled file.

        +
        +
        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.utils.xml: Utilities related to XML

        +

        Next topic

        +

        Documentation for Developers

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/utils/api_xml.html b/utils/api_xml.html new file mode 100644 index 00000000..c090a93d --- /dev/null +++ b/utils/api_xml.html @@ -0,0 +1,532 @@ + + + + + + + + + + astropy.utils.xml: Utilities related to XML — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + + + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        astropy.utils.console: Utilities for console output

        +

        Next topic

        +

        astropy.utils.misc: Miscellaneous/uncategorized Utilities

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/utils/index.html b/utils/index.html new file mode 100644 index 00000000..bb99423f --- /dev/null +++ b/utils/index.html @@ -0,0 +1,155 @@ + + + + + + + + + + astropy.utils documentation — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vo/api.html b/vo/api.html new file mode 100644 index 00000000..5e2935b0 --- /dev/null +++ b/vo/api.html @@ -0,0 +1,174 @@ + + + + + + + + + + API documentation — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vo/api_converters.html b/vo/api_converters.html new file mode 100644 index 00000000..3a2c7b44 --- /dev/null +++ b/vo/api_converters.html @@ -0,0 +1,165 @@ + + + + + + + + + + astropy.io.vo.converters: Conversions between XML and Numpy datatypes — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        +

        +Inheritance diagram of astropy.io.vo.converters +

        +

        This module handles the conversion of various VOTABLE datatypes +to/from TABLEDATA and BINARY formats.

        +
        +
        +astropy.io.vo.converters.get_converter(field, config={}, pos=None)[source]
        +

        Factory function to get an appropriate converter instance for a +given field.

        + +++ + + + + + +
        Parameters :

        field : astropy.io.vo.tree.Field

        +

        config : dict, optional

        +
        +

        Parser configuration dictionary

        +
        +

        pos : tuple

        +
        +

        Position in the input XML file. Used for error messages.

        +
        +
        Returns :

        converter : astropy.io.vo.converters.Converter

        +
        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.io.vo.xmlutil: XML-related utilities used by the library

        +

        Next topic

        +

        astropy.tools documentation

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/api_exceptions.html b/vo/api_exceptions.html new file mode 100644 index 00000000..0a4775c7 --- /dev/null +++ b/vo/api_exceptions.html @@ -0,0 +1,1034 @@ + + + + + + + + + + astropy.io.vo.exceptions — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.exceptions

        +
        +

        Contents

        + +
        +
        +

        Warnings

        +
        +

        Note

        +

        Most of the following warnings indicate violations of the VOTable +specification. They should be reported to the authors of the +tools that produced the VOTable file.

        +

        To control the warnings emitted, use the standard Python +warnings module. Most of these are of the type +VOTableSpecWarning.

        +
        +
        +

        W01: Array uses commas rather than whitespace

        +

        The VOTable spec states:

        +
        +
        If a cell contains an array or complex number, it should be +encoded as multiple numbers separated by whitespace.
        +

        Many VOTable files in the wild use commas as a separator instead, +and vo.table supports this convention when not in +Pedantic mode.

        +

        vo.table always outputs files using only spaces, regardless of +how they were input.

        +

        References: 1.1, +1.2

        +
        +
        +

        W02: x attribute ‘y’ is invalid. Must be a standard XML id

        +

        XML ids must match the following regular expression:

        +
        ^[A-Za-z_][A-Za-z0-9_\.\-]*$
        +
        +

        The VOTable 1.1 says the following:

        +
        +
        According to the XML standard, the attribute ID is a +string beginning with a letter or underscore (_), followed +by a sequence of letters, digits, or any of the punctuation +characters . (dot), - (dash), _ (underscore), or +: (colon).
        +

        However, this is in conflict with the XML standard, which says +colons may not be used. VOTable 1.1’s own schema does not allow a +colon here. Therefore, vo.table disallows the colon.

        +

        VOTable 1.2 corrects this error in the specification.

        +

        References: 1.1, +XML Names

        +
        +
        +

        W03: Implictly generating an ID from a name ‘x’ -> ‘y’

        +

        The VOTable 1.1 spec says the following about name vs. ID +on FIELD and VALUE elements:

        +
        +
        ID and name attributes have a different role in +VOTable: the ID is meant as a unique identifier of an +element seen as a VOTable component, while the name is +meant for presentation purposes, and need not to be unique +throughout the VOTable document. The ID attribute is +therefore required in the elements which have to be +referenced, but in principle any element may have an ID +attribute. ... In summary, the ID is different from the +name attribute in that (a) the ID attribute is made +from a restricted character set, and must be unique throughout +a VOTable document whereas names are standard XML attributes +and need not be unique; and (b) there should be support in the +parsing software to look up references and extract the +relevant element with matching ID.
        +

        It is further recommended in the VOTable 1.2 spec:

        +
        +
        While the ID attribute has to be unique in a VOTable +document, the name attribute need not. It is however +recommended, as a good practice, to assign unique names within +a TABLE element. This recommendation means that, between a +TABLE and its corresponding closing TABLE tag, +name attributes of FIELD, PARAM and optional +GROUP elements should be all different.
        +

        Since vo.table requires a unique identifier for each of its +columns, ID is used for the column name when present. +However, when ID is not present, (since it is not required by +the specification) name is used instead. However, name +must be cleansed by replacing invalid characters (such as +whitespace) with underscores.

        +
        +

        Note

        +

        This warning does not indicate that the input file is invalid +with respect to the VOTable specification, only that the +column names in the record array may not match exactly the +name attributes specified in the file.

        +
        +

        References: 1.1, +1.2

        +
        +
        +

        W04: content-type ‘x’ must be a valid MIME content type

        +

        The content-type attribute must use MIME content-type syntax as +defined in RFC 2046.

        +

        The current check for validity is somewhat over-permissive.

        +

        References: 1.1, +1.2

        +
        +
        +

        W05: ‘x’ is not a valid URI

        +

        The attribute must be a valid URI as defined in RFC 2396.

        +
        +
        +

        W06: Invalid UCD ‘x’: explanation

        +

        This warning is emitted when a ucd attribute does not match +the syntax of a unified content descriptor.

        +

        If the VOTable version is 1.2 or later, the UCD will also be +checked to ensure it conforms to the controlled vocabulary defined +by UCD1+.

        +

        References: 1.1, +1.2

        +
        +
        +

        W07: Invalid astroYear in x: ‘y’

        +

        As astro year field is a Besselian or Julian year matching the +regular expression:

        +
        ^[JB]?[0-9]+([.][0-9]*)?$
        +
        +

        Defined in this XML Schema snippet:

        +
        <xs:simpleType  name="astroYear">
        +  <xs:restriction base="xs:token">
        +    <xs:pattern  value="[JB]?[0-9]+([.][0-9]*)?"/>
        +  </xs:restriction>
        +</xs:simpleType>
        +
        +
        +
        +

        W08: ‘x’ must be a str or unicode object

        +

        To avoid local-dependent number parsing differences, vo.table +may require a string or unicode string where a numeric type may +make more sense.

        +
        +
        +

        W09: ID attribute not capitalized

        +

        The VOTable specification uses the attribute name ID (with +uppercase letters) to specify unique identifiers. Some +VOTable-producing tools use the more standard lowercase id +instead. vo.table accepts id and emits this warning when +not in pedantic mode.

        +

        References: 1.1, +1.2

        +
        +
        +

        W10: Unknown tag ‘x’. Ignoring

        +

        The parser has encountered an element that does not exist in the +specification, or appears in an invalid context. Check the file +against the VOTable schema (with a tool such as xmllint. If the file validates +against the schema, and you still receive this warning, this may +indicate a bug in vo.table.

        +

        References: 1.1, +1.2

        +
        + +
        +

        W12: ‘x’ element must have at least one of ‘ID’ or ‘name’ attributes

        +

        In order to name the columns of the Numpy record array, each +FIELD element must have either an ID or name attribute +to derive a name from. Strictly speaking, according to the +VOTable schema, the name attribute is required. However, if +name is not present by ID is, and pedantic mode is off, +vo.table will continue without a name defined.

        +

        References: 1.1, +1.2

        +
        +
        +

        W13: ‘x’ is not a valid VOTable datatype, should be ‘y’

        +

        Some VOTable files in the wild use non-standard datatype names. These +are mapped to standard ones using the following mapping:

        +
        string        -> char
        +unicodeString -> unicodeChar
        +int16         -> short
        +int32         -> int
        +int64         -> long
        +float32       -> float
        +float64       -> double
        +
        +

        References: 1.1, +1.2

        +
        +
        +

        W15: x element missing required ‘name’ attribute

        +

        The name attribute is required on every FIELD element. +However, many VOTable files in the wild omit it and provide only +an ID instead. In this case, when pedantic mode is off, +vo.table will copy the name attribute to a new ID +attribute.

        +

        References: 1.1, +1.2

        +
        +
        +

        W17: x element contains more than one DESCRIPTION element

        +

        A DESCRIPTION element can only appear once within its parent +element.

        +

        According to the schema, it may only occur once (1.1, +1.2)

        +

        However, it is a proposed extension +to VOTable 1.2.

        +
        +
        +

        W18: TABLE specified nrows=x, but table contains y rows

        +

        The number of rows explicitly specified in the nrows attribute +does not match the actual number of rows (TR elements) present +in the TABLE. This may indicate truncation of the file, or an +internal error in the tool that produced it. If pedantic mode +is off, parsing will proceed, with the loss of some performance.

        +

        References: 1.1, +1.2

        +
        +
        +

        W19: The fields defined in the VOTable do not match those in the embedded FITS file

        +

        The column fields as defined using FIELD elements do not match +those in the headers of the embedded FITS file. If pedantic +mode is off, the embedded FITS file will take precedence.

        +
        +
        +

        W20: No version number specified in file. Assuming 1.1

        +

        If no version number is explicitly given in the VOTable file, the +parser assumes it is written to the VOTable 1.1 specification.

        +
        +
        +

        W21: vo.table is designed for VOTable version 1.1 and 1.2, but this file is x

        +

        Unknown issues may arise using vo.table with VOTable files +from a version other than 1.1 or 1.2.

        +
        +
        +

        W22: The DEFINITIONS element is deprecated in VOTable 1.1. Ignoring

        +

        Version 1.0 of the VOTable specification used the DEFINITIONS +element to define coordinate systems. Version 1.1 now uses +COOSYS elements throughout the document.

        +

        References: 1.1, +1.2

        +
        +
        +

        W23: Unable to update service information for ‘x’

        +

        Raised when the VO service database can not be updated (possibly +due to a network outage). This is only a warning, since an older +and possible out-of-date VO service database was available +locally.

        +
        +
        +

        W24: The VO catalog database is for a later version of vo.table

        +

        The VO catalog database retrieved from the www is designed for a +newer version of vo.table. This may cause problems or limited +features performing service queries. Consider upgrading vo.table +to the latest version.

        +
        +
        +

        W25: ‘service’ failed with: ...

        +

        A VO service query failed due to a network error or malformed +arguments. Another alternative service may be attempted. If all +services fail, an exception will be raised.

        +
        +
        +

        W26: ‘child’ inside ‘parent’ added in VOTable X.X

        +

        The given element was not supported inside of the given element +until the specified VOTable version, however the version declared +in the file is for an earlier version. These attributes may not +be written out to the file.

        +
        +
        +

        W27: COOSYS deprecated in VOTable 1.2

        +

        The COOSYS element was deprecated in VOTABLE version 1.2 in +favor of a reference to the Space-Time Coordinate (STC) data +model (see utype +and the IVOA note referencing STC in VOTable.

        +
        +
        +

        W28: ‘attribute’ on ‘element’ added in VOTable X.X

        +

        The given attribute was not supported on the given element until the +specified VOTable version, however the version declared in the file is +for an earlier version. These attributes may not be written out to +the file.

        +
        +
        +

        W29: Version specified in non-standard form ‘v1.0’

        +

        Some VOTable files specify their version number in the form “v1.0”, +when the only supported forms in the spec are “1.0”.

        +

        References: 1.1, +1.2

        +
        +
        +

        W30: Invalid literal for float ‘x’. Treating as empty.

        +

        Some VOTable files write missing floating-point values in non-standard +ways, such as “null” and “-”. In non-pedantic mode, any non-standard +floating-point literals are treated as missing values.

        +

        References: 1.1, +1.2

        +
        +
        +

        W31: NaN given in an integral field without a specified null value

        +

        Since NaN’s can not be represented in integer fields directly, a null +value must be specified in the FIELD descriptor to support reading +NaN’s from the tabledata.

        +

        References: 1.1, +1.2

        +
        +
        +

        W32: Duplicate ID ‘x’ renamed to ‘x_2’ to ensure uniqueness

        +

        Each field in a table must have a unique ID. If two or more fields +have the same ID, some will be renamed to ensure that all IDs are +unique.

        +

        From the VOTable 1.2 spec:

        +
        +
        The ID and ref attributes are defined as XML types +ID and IDREF respectively. This means that the +contents of ID is an identifier which must be unique +throughout a VOTable document, and that the contents of the +ref attribute represents a reference to an identifier +which must exist in the VOTable document.
        +

        References: 1.1, +1.2

        +
        +
        +

        W33: Column name ‘x’ renamed to ‘x_2’ to ensure uniqueness

        +

        Each field in a table must have a unique name. If two or more +fields have the same name, some will be renamed to ensure that all +names are unique.

        +

        References: 1.1, +1.2

        +
        +
        +

        W34: ‘x’ is an invalid token for attribute ‘y’

        +

        The attribute requires the value to be a valid XML token, as +defined by XML 1.0.

        +
        +
        +

        W35: ‘x’ attribute required for INFO elements

        +

        The name and value attributes are required on all INFO +elements.

        +

        References: 1.1, +1.2

        +
        +
        +

        W36: null value ‘x’ does not match field datatype, setting to 0

        +

        If the field specifies a null value, that value must conform +to the given datatype.

        +

        References: 1.1, +1.2

        +
        +
        +

        W37: Unsupported data format ‘x’

        +

        The 3 datatypes defined in the VOTable specification and supported by +vo.table are TABLEDATA, BINARY and FITS.

        +

        References: 1.1, +1.2

        +
        +
        +

        W38: Inline binary data must be base64 encoded, got ‘x’

        +

        The only encoding for local binary data supported by the VOTable +specification is base64.

        +
        +
        +

        W39: Bit values can not be masked

        +

        Bit values do not support masking. This warning is raised upon +setting masked data in a bit column.

        +

        References: 1.1, +1.2

        +
        +
        +

        W40: ‘cprojection’ datatype repaired

        +

        This is a terrible hack to support Simple Image Access Protocol +results from archive.noao.edu. It creates a field for the +coordinate projection type of type “double”, which +actually contains character data. We have to hack the field +to store character data, or we can’t read it in. A warning +will be raised when this happens.

        +
        +
        +

        W41: An XML namespace is specified, but is incorrect. Expected ‘x’, got ‘y’

        +

        An XML namespace was specified on the VOTABLE element, but the +namespace does not match what is expected for a VOTABLE file.

        +

        The VOTABLE namespace is:

        +
        http://www.ivoa.net/xml/VOTable/vX.X
        +
        +

        where “X.X” is the version number.

        +

        Some files in the wild set the namespace to the location of the +VOTable schema, which is not correct and will not pass some +validating parsers.

        +
        +
        +

        W42: No XML namespace specified

        +

        The root element should specify a namespace.

        +

        The VOTABLE namespace is:

        +
        http://www.ivoa.net/xml/VOTable/vX.X
        +
        +

        where “X.X” is the version number.

        +
        +
        +

        W43: element ref=’x’ which has not already been defined

        +

        Referenced elements should be defined before referees. From the +VOTable 1.2 spec:

        +
        +
        In VOTable1.2, it is further recommended to place the ID +attribute prior to referencing it whenever possible.
        +
        +
        +

        W44: VALUES element with ref attribute has content (‘element’)

        +

        VALUES elements that reference another element should not have +their own content.

        +

        From the VOTable 1.2 spec:

        +
        +
        The ref attribute of a VALUES element can be used to +avoid a repetition of the domain definition, by referring to a +previously defined VALUES element having the referenced +ID attribute. When specified, the ref attribute +defines completely the domain without any other element or +attribute, as e.g. <VALUES ref="RAdomain"/>
        +
        +
        +

        W45: content-role attribute ‘x’ invalid

        +

        The content-role attribute on the LINK element must be one of +the following:

        +
        query, hints, doc, location
        +
        +
        +

        References: 1.1, +1.2

        +
        +
        +

        W46: char or unicode value is too long for specified length of x

        +

        The given char or unicode string is too long for the specified +field length.

        +
        +
        +

        W47: Missing arraysize indicates length 1

        +

        If no arraysize is specified on a char field, the default of ‘1’ +is implied, but this is rarely what is intended.

        +
        +
        +

        W48: Unknown attribute ‘attribute’ on element

        +

        The attribute is not defined in the specification.

        +
        +
        +

        W49: Empty cell illegal for integer fields.

        +

        Empty cell illegal for integer fields.

        +

        If a “null” value was specified for the cell, it will be used +for the value, otherwise, 0 will be used.

        +
        + +
        +
        +

        Exceptions

        +
        +

        Note

        +

        This is a list of many of the fatal exceptions emitted by vo.table +when the file does not conform to spec. Other exceptions may be +raised due to unforeseen cases or bugs in vo.table itself.

        +
        +
        +

        E01: Invalid size specifier ‘x’ for a char/unicode field (in field ‘y’)

        +

        The size specifier for a char or unicode field must be +only a number followed, optionally, by an asterisk. +Multi-dimensional size specifiers are not supported for these +datatypes.

        +

        Strings, which are defined as a set of characters, can be +represented in VOTable as a fixed- or variable-length array of +characters:

        +
        <FIELD name="unboundedString" datatype="char" arraysize="*"/>
        +
        +

        A 1D array of strings can be represented as a 2D array of +characters, but given the logic above, it is possible to define a +variable-length array of fixed-length strings, but not a +fixed-length array of variable-length strings.

        +
        +
        +

        E02: Incorrect number of elements in array. Expected multiple of x, got y

        +

        The number of array elements in the data does not match that specified +in the FIELD specifier.

        +
        +
        +

        E03: ‘x’ does not parse as a complex number

        +

        Complex numbers should be two values separated by whitespace.

        +

        References: 1.1, +1.2

        +
        +
        +

        E04: Invalid bit value ‘x’

        +

        A bit array should be a string of ‘0’s and ‘1’s.

        +

        References: 1.1, +1.2

        +
        +
        +

        E05: Invalid boolean value ‘x’

        +

        A boolean value should be one of the following strings (case +insensitive) in the TABLEDATA format:

        +
        'TRUE', 'FALSE', '1', '0', 'T', 'F', '\0', ' ', '?'
        +
        +
        +

        and in BINARY format:

        +
        'T', 'F', '1', '0', '\0', ' ', '?'
        +
        +
        +

        References: 1.1, +1.2

        +
        +
        +

        E06: Unknown datatype ‘x’ on field ‘y’

        +

        The supported datatypes are:

        +
        double, float, bit, boolean, unsignedByte, short, int, long,
        +floatComplex, doubleComplex, char, unicodeChar
        +
        +
        +

        The following non-standard aliases are also supported, but in +these case W13 will be raised:

        +
        string        -> char
        +unicodeString -> unicodeChar
        +int16         -> short
        +int32         -> int
        +int64         -> long
        +float32       -> float
        +float64       -> double
        +
        +

        References: 1.1, +1.2

        +
        + +
        +

        E09: ‘x’ must have a value attribute

        +

        The MIN, MAX and OPTION elements must always have a +value attribute.

        +

        References: 1.1, +1.2

        +
        +
        +

        E10: ‘datatype’ attribute required on all ‘FIELD’ elements

        +

        From VOTable 1.1 and later, FIELD and PARAM elements must have +a datatype field.

        +

        References: 1.1, +1.2

        +
        +
        +

        E11: precision ‘x’ is invalid

        +

        The precision attribute is meant to express the number of significant +digits, either as a number of decimal places (e.g. precision="F2" or +equivalently precision="2" to express 2 significant figures +after the decimal point), or as a number of significant figures +(e.g. precision="E5" indicates a relative precision of 10-5).

        +

        It is validated using the following regular expression:

        +
        [EF]?[1-9][0-9]*
        +
        +

        References: 1.1, +1.2

        +
        +
        +

        E12: width must be a positive integer, got ‘x’

        +

        The width attribute is meant to indicate to the application the +number of characters to be used for input or output of the +quantity.

        +

        References: 1.1, +1.2

        +
        +
        +

        E13: Invalid arraysize attribute ‘x’

        +

        From the VOTable 1.2 spec:

        +
        +

        A table cell can contain an array of a given primitive type, +with a fixed or variable number of elements; the array may +even be multidimensional. For instance, the position of a +point in a 3D space can be defined by the following:

        +
        <FIELD ID="point_3D" datatype="double" arraysize="3"/>
        +
        +

        and each cell corresponding to that definition must contain +exactly 3 numbers. An asterisk (*) may be appended to +indicate a variable number of elements in the array, as in:

        +
        <FIELD ID="values" datatype="int" arraysize="100*"/>
        +
        +

        where it is specified that each cell corresponding to that +definition contains 0 to 100 integer numbers. The number may +be omitted to specify an unbounded array (in practice up to +=~2×10⁹ elements).

        +

        A table cell can also contain a multidimensional array of a +given primitive type. This is specified by a sequence of +dimensions separated by the x character, with the first +dimension changing fastest; as in the case of a simple array, +the last dimension may be variable in length. As an example, +the following definition declares a table cell which may +contain a set of up to 10 images, each of 64×64 bytes:

        +
        <FIELD ID="thumbs" datatype="unsignedByte" arraysize="64×64×10*"/>
        +
        +
        +

        References: 1.1, +1.2

        +
        +
        +

        E14: value attribute is required for all PARAM elements

        +

        All PARAM elements must have a value attribute.

        +

        References: 1.1, +1.2

        +
        +
        +

        E15: ID attribute is required for all COOSYS elements

        +

        All COOSYS elements must have an ID attribute.

        +

        Note that the VOTable 1.1 specification says this attribute is +optional, but its corresponding schema indicates it is required.

        +

        In VOTable 1.2, the COOSYS element is deprecated.

        +
        +
        +

        E16: Invalid system attribute ‘x’

        +

        The system attribute on the COOSYS element must be one of the +following:

        +
        'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic',
        +'supergalactic', 'xy', 'barycentric', 'geo_app'
        +
        +
        +

        References: 1.1

        +
        +
        +

        E17: extnum must be a positive integer

        +

        extnum attribute must be a positive integer.

        +

        References: 1.1, +1.2

        +
        +
        +

        E18: type must be ‘results’ or ‘meta’, not ‘x’

        +

        The type attribute of the RESOURCE element must be one of +“results” or “meta”.

        +

        References: 1.1, +1.2

        +
        +
        +

        E19: File does not appear to be a VOTABLE

        +

        Raised either when the file doesn’t appear to be XML, or the root +element is not VOTABLE.

        +
        +
        +

        E20: Data has more columns than are defined in the header (x)

        +

        The table had only x fields defined, but the data itself has more +columns than that.

        +
        +
        +

        E21: Data has fewer columns (x) than are defined in the header (y)

        +

        The table had x fields defined, but the data itself has only y +columns.

        +
        +
        +
        +

        Exception utilities

        +
        +
        +astropy.io.vo.exceptions.warn_or_raise(warning_class, exception_class=None, args=(), config={}, pos=None)[source]
        +

        Warn or raise an exception, depending on the pedantic setting.

        +
        + +
        +
        +astropy.io.vo.exceptions.vo_raise(exception_class, args=(), config={}, pos=None)[source]
        +

        Raise an exception, with proper position information if available.

        +
        + +
        +
        +astropy.io.vo.exceptions.vo_reraise(exc, config={}, pos=None, additional='')[source]
        +

        Raise an exception, with proper position information if available.

        +

        Restores the original traceback of the exception, and should only +be called within an “except:” block of code.

        +
        + +
        +
        +astropy.io.vo.exceptions.vo_warn(warning_class, args=(), config={}, pos=None)[source]
        +

        Warn, with proper position information if available.

        +
        + +
        +
        +astropy.io.vo.exceptions.parse_vowarning(line)[source]
        +

        Parses the vo warning string back into its parts.

        +
        + +
        +
        +class astropy.io.vo.exceptions.VOWarning(args, config={}, pos=None)[source]
        +

        Bases: exceptions.Warning

        +

        The base class of all VO warnings and exceptions. Handles the +formatting of the message with a warning or exception code, +filename, line and column number.

        +
        + +
        +
        +class astropy.io.vo.exceptions.VOTableChangeWarning(args, config={}, pos=None)[source]
        +

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.SyntaxWarning

        +

        Warning emitted when a change has been made to the input XML file.

        +
        + +
        +
        +class astropy.io.vo.exceptions.VOTableSpecWarning(args, config={}, pos=None)[source]
        +

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.SyntaxWarning

        +

        Warning emitted when the input XML file violates the spec, but +there is an obvious workaround.

        +
        + +
        +
        +class astropy.io.vo.exceptions.UnimplementedWarning(args, config={}, pos=None)[source]
        +

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.SyntaxWarning

        +

        Warning emitted when the a feature of VOTABLE is not implemented.

        +
        + +
        +
        +class astropy.io.vo.exceptions.IOWarning(args, config={}, pos=None)[source]
        +

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.RuntimeWarning

        +

        Warning emitted when a network or IO error occurred, but the +system is able to recover using a cached copy of the data or some +other fallback.

        +
        + +
        +
        +class astropy.io.vo.exceptions.VOTableSpecError(args, config={}, pos=None)[source]
        +

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.ValueError

        +

        Error raised when the input XML file violates the spec and there +is no good workaround.

        +
        + +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        +

        Next topic

        +

        astropy.io.vo.ucd: Functions to parse and verify unified content descriptors

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/api_table.html b/vo/api_table.html new file mode 100644 index 00000000..aa2350d4 --- /dev/null +++ b/vo/api_table.html @@ -0,0 +1,265 @@ + + + + + + + + + + astropy.io.vo.table: Loading entire VOTable files — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.table: Loading entire VOTable files

        +

        This file contains a contains the high-level functions to read a +VOTable file.

        +
        +
        +astropy.io.vo.table.parse(source, columns=None, invalid='exception', pedantic=None, chunk_size=256, table_number=None, filename=None, _debug_python_based_parser=False)[source]
        +

        Parses a VOTABLE xml file (or file-like object), and returns a +VOTable object, with nested +Resource instances and +Table instances.

        + +++ + + + + + +
        Parameters :

        source : str or readable file-like object

        +
        +

        Path or file object containing a VOTABLE xml file.

        +
        +

        columns : sequence of str, optional

        +
        +

        List of field names to include in the output. The default is +to include all fields.

        +
        +

        invalid : str, optional

        +
        +

        One of the following values:

        +
        +
          +
        • ‘exception’: throw an exception when an invalid value is +encountered (default)
        • +
        • ‘mask’: mask out invalid values
        • +
        +
        +
        +

        pedantic : bool, optional

        +
        +

        When True, raise an error when the file violates the spec, +otherwise issue a warning. Warnings may be controlled using +the standard Python mechanisms. See the warnings +module in the Python standard library for more information. +When not provided, uses the configuration setting +astropy.io.vo.pedantic, which defaults to True.

        +
        +

        chunk_size : int, optional

        +
        +

        The number of rows to read before converting to an array. +Higher numbers are likely to be faster, but will consume more +memory.

        +
        +

        table_number : int, optional

        +
        +

        The number of table in the file to read in. If None, all +tables will be read. If a number, 0 refers to the first table +in the file, and only that numbered table will be parsed and +read in.

        +
        +

        filename : str, optional

        +
        +

        A filename, URL or other identifier to use in error messages. +If filename is None and source is a string (i.e. a path), +then source will be used as a filename for error messages. +Therefore, filename is only required when source is a +file-like object.

        +
        +
        Returns :

        votable : astropy.io.vo.tree.VOTableFile object

        +
        +
        +

        See also

        +
        +
        astropy.io.vo.exceptions
        +
        The exceptions this function may raise.
        +
        +
        +
        + +
        +
        +astropy.io.vo.table.parse_single_table(source, **kwargs)[source]
        +

        Parses a VOTABLE xml file (or file-like object), reads only the +first TABLE element, and returns a Table +instance.

        +

        See parse for a description of the keyword arguments.

        + +++ + + + +
        Returns :votable : astropy.io.vo.tree.Table object
        +
        + +
        +
        +astropy.io.vo.table.validate(filename, output=<open file '<stdout>', mode 'w' at 0x240078>, xmllint=False)[source]
        +

        Prints a validation report for the given file.

        + +++ + + + + + +
        Parameters :

        filename : str path

        +
        +

        Path to a VOTABLE xml file.

        +
        +

        output : writable file-like object, optional

        +
        +

        Where to output the report. Defaults to sys.stdout. +If None, the output will be returned as a string.

        +
        +

        xmllint : bool, optional

        +
        +

        When True, also send the file to xmllint for schema and +DTD validation. Requires that xmllint is installed. The +default is False.

        +
        +
        Returns :

        is_valid : bool or str

        +
        +

        Returns True if no warnings were found. If output is +None, the return value will be a string.

        +
        +
        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        API documentation

        +

        Next topic

        +

        astropy.io.vo.tree: Accessing and modifying the individual parts of VOTable files

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/api_tree.html b/vo/api_tree.html new file mode 100644 index 00000000..c69da93b --- /dev/null +++ b/vo/api_tree.html @@ -0,0 +1,1064 @@ + + + + + + + + + + astropy.io.vo.tree: Accessing and modifying the individual parts of VOTable files — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.tree: Accessing and modifying the individual parts of VOTable files

        +

        +Inheritance diagram of astropy.io.vo.tree + + + + + + + + + + + + + + + + + +

        +
        +
        +class astropy.io.vo.tree.Element[source]
        +

        Bases: object

        +

        A base class for all classes that represent XML elements in the +VOTABLE file.

        +
        + +
        +
        +class astropy.io.vo.tree.SimpleElement[source]
        +

        Bases: astropy.io.vo.tree.Element

        +

        A base class for simple elements, such as FIELD, PARAM and INFO +that don’t require any special parsing or outputting machinery.

        +
        +
        +parse(iterator, config)[source]
        +
        + +
        +
        +to_xml(w, **kwargs)[source]
        +
        + +
        + +
        +
        +class astropy.io.vo.tree.SimpleElementWithContent[source]
        +

        Bases: astropy.io.vo.tree.SimpleElement

        +

        A base class for simple elements, such as FIELD, PARAM and INFO +that don’t require any special parsing or outputting machinery.

        +
        +
        +content[source]
        +

        The content of the element.

        +
        + +
        +
        +to_xml(w, **kwargs)[source]
        +
        + +
        + +
        +
        +class astropy.io.vo.tree.VOTableFile(ID=None, id=None, config={}, pos=None, version='1.2')[source]
        +

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._DescriptionProperty

        +

        A class to represent the top-level VOTABLE element.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +

        version is settable at construction time only, since conformance +tests for building the rest of the structure depend on it.

        +
        +
        +coordinate_systems[source]
        +

        A list of coordinate system descriptions for the file. Must +contain only CooSys objects.

        +
        + +
        +
        +get_coosys_by_id(ref, before=None)
        +

        Looks up a COOSYS element by the given ID.

        +
        + +
        +
        +get_field_by_id(ref, before=None)
        +

        Looks up a FIELD element by the given ID. Used by the field’s +“ref” attribute.

        +
        + +
        +
        +get_field_by_id_or_name(ref, before=None)
        +

        Looks up a FIELD element by the given ID or name.

        +
        + +
        +
        +get_first_table()[source]
        +

        Often, you know there is only one table in the file, and +that’s all you need. This method returns that first table.

        +
        + +
        +
        +get_group_by_id(ref, before=None)
        +

        Looks up a GROUP element by the given ID. Used by the group’s +“ref” attribute

        +
        + +
        +
        +get_table_by_id(ref, before=None)
        +

        Looks up a TABLE element by the given ID. Used by the table +“ref” attribute.

        +
        + +
        +
        +get_table_by_index(idx)[source]
        +

        Get a table by its ordinal position in the file.

        +
        + +
        +
        +get_values_by_id(ref, before=None)
        +

        Looks up a VALUES element by the given ID. Used by the values +“ref” attribute.

        +
        + +
        +
        +groups[source]
        +

        A list of groups, in the order they appear in the file. Only +supported as a child of the VOTABLE element in VOTable 1.2 or +later.

        +
        + +
        +
        +infos[source]
        +

        A list of informational parameters (key-value pairs) for the +entire file. Must only contain Info objects.

        +
        + +
        +
        +iter_coosys()[source]
        +

        Recursively iterate over all COOSYS elements in the VOTABLE +file.

        +
        + +
        +
        +iter_fields_and_params()[source]
        +

        Recursively iterate over all FIELD and PARAM elements in the +VOTABLE file.

        +
        + +
        +
        +iter_groups()[source]
        +

        Recursively iterate over all GROUP elements in the VOTABLE +file.

        +
        + +
        +
        +iter_tables()[source]
        +

        Iterates over all tables in the VOTable file in a “flat” way, +ignoring the nesting of resources etc.

        +
        + +
        +
        +iter_values()[source]
        +

        Recursively iterate over all VALUES elements in the VOTABLE +file.

        +
        + +
        +
        +params[source]
        +

        A list of parameters (constant-valued columns) that apply to +the entire file. Must contain only Param objects.

        +
        + +
        +
        +parse(iterator, config)[source]
        +
        + +
        +
        +resources[source]
        +

        A list of resources, in the order they appear in the file. +Must only contain Resource objects.

        +
        + +
        +
        +set_all_tables_format(format)[source]
        +

        Set the output storage format of all tables in the file.

        +
        + +
        +
        +to_xml(fd, write_null_values=False, _debug_python_based_parser=False, _astropy_version=None)[source]
        +

        Write to an XML file.

        + +++ + + + +
        Parameters :

        fd : str path or writable file-like object

        +
        +

        Where to write the file.

        +
        +

        write_null_values : bool

        +
        +

        When True, write the ‘null’ value (specified in the null +attribute of the VALUES element for each FIELD) for empty +values. When False (default), simply write no value.

        +
        +
        +
        + +
        +
        +version[source]
        +

        The version of the VOTable specification that the file uses.

        +
        + +
        + +
        +
        +class astropy.io.vo.tree.Resource(name=None, ID=None, utype=None, type='results', id=None, config={}, pos=None, **kwargs)[source]
        +

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._NameProperty, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._DescriptionProperty

        +

        A class to store the information in a RESOURCE element. Each +resource may contain zero-or-more TABLE elements and zero-or-more +nested RESOURCE elements.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +
        +
        +coordinate_systems[source]
        +

        A list of coordinate system definitions (COOSYS elements) for +the RESOURCE. Must contain only CooSys objects.

        +
        + +
        +
        +extra_attributes[source]
        +

        A dictionary of string keys to string values containing any +extra attributes of the RESOURCE element that are not defined +in the specification. (The specification explicitly allows +for extra attributes here, but nowhere else.)

        +
        + +
        +
        +infos[source]
        +

        A list of informational parameters (key-value pairs) for the +resource. Must only contain Info objects.

        +
        + +
        +
        +iter_coosys()[source]
        +

        Recursively iterates over all the COOSYS elements in the +resource and nested resources.

        +
        + +
        +
        +iter_fields_and_params()[source]
        +

        Recursively iterates over all FIELD and PARAM elements in +the resource, its tables and nested resources.

        +
        + +
        +
        +iter_tables()[source]
        +

        Recursively iterates over all tables in the resource and +nested resources.

        +
        + +
        + +

        A list of links (pointers to other documents or servers +through a URI) for the resource. Must contain only Link +objects.

        +
        + +
        +
        +params[source]
        +

        A list of parameters (constant-valued columns) for the +resource. Must contain only Param objects.

        +
        + +
        +
        +parse(votable, iterator, config)[source]
        +
        + +
        +
        +resources[source]
        +

        A list of nested resources inside this resource. Must contain +only Resource objects.

        +
        + +
        +
        +tables[source]
        +

        A list of tables in the resource. Must contain only +Table objects.

        +
        + +
        +
        +to_xml(w, **kwargs)[source]
        +
        + +
        +
        +type[source]
        +

        [required] The type of the resource. Must be either:

        +
        +
          +
        • ‘results’: This resource contains actual result values +(default)
        • +
        • ‘meta’: This resource contains only datatype descriptions +(FIELD elements), but no actual data.
        • +
        +
        +
        + +
        + +
        +
        +class astropy.io.vo.tree.Table(votable, ID=None, name=None, ref=None, ucd=None, utype=None, nrows=None, id=None, config={}, pos=None, **extra)[source]
        +

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._NameProperty, astropy.io.vo.tree._UcdProperty, astropy.io.vo.tree._DescriptionProperty

        +

        A class to store a TABLE element, which optionally contains data.

        +

        It contains the following publicly-accessible members, all of +which are mutable:

        +
        +

        array: A Numpy recarray of the data itself, where each row +is a row of votable data, and columns are named and typed +based on the <FIELD> elements of the table.

        +

        mask: A Numpy recarray of only boolean values, set to True +wherever a value is undefined.

        +
        +

        If the Table contains no data, (for example, its enclosing +Resource has type == ‘meta’) array +and mask will be zero-length arrays.

        +
        +

        Note

        +

        In a future version of the vo package, the array and mask +elements will likely be combined into a single Numpy masked +record array. However, there are a number of deficiencies the +current implementation of Numpy that prevent this.

        +
        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +
        +
        +create_arrays(nrows=0, config={})[source]
        +

        Create new arrays to hold the data based on the current set of +fields, and store them in the array and mask member +variables. Any data in existing arrays will be lost.

        +

        nrows, if provided, is the number of rows to allocate.

        +
        + +
        +
        +fields[source]
        +

        A list of Field objects describing the types of each +of the data columns.

        +
        + +
        +
        +format[source]
        +

        [required] The serialization format of the table. Must be +one of:

        +
        +
        ‘tabledata’ (TABLEDATA), ‘binary’ (BINARY), ‘fits’ (FITS).
        +

        Note that the ‘fits’ format, since it requires an external +file, can not be written out. Any file read in with ‘fits’ +format will be read out, by default, in ‘tabledata’ format.

        +
        + +
        +
        +get_field_by_id(ref, before=None)
        +

        Looks up a FIELD or PARAM element by the given ID.

        +
        + +
        +
        +get_field_by_id_or_name(ref, before=None)
        +

        Looks up a FIELD or PARAM element by the given ID or name.

        +
        + +
        +
        +get_group_by_id(ref, before=None)
        +

        Looks up a GROUP element by the given ID. Used by the group’s +“ref” attribute

        +
        + +
        +
        +groups[source]
        +

        A list of Group objects describing how the columns +and parameters are grouped. Currently this information is +only kept around for round-tripping and informational +purposes.

        +
        + +
        +
        +infos[source]
        +

        A list of Info objects for the table. Allows for +post-operational diagnostics.

        +
        + +
        +
        +is_empty()[source]
        +

        Returns True if this table doesn’t contain any real data +because it was skipped over by the parser (through use of the +table_number kwarg).

        +
        + +
        +
        +iter_fields_and_params()[source]
        +

        Recursively iterate over all FIELD and PARAM elements in the +TABLE.

        +
        + +
        +
        +iter_groups()[source]
        +

        Recursively iterate over all GROUP elements in the TABLE.

        +
        + +
        + +

        A list of Link objects (pointers to other documents +or servers through a URI) for the table.

        +
        + +
        +
        +nrows[source]
        +

        [immutable] The number of rows in the table, as specified in +the XML file.

        +
        + +
        +
        +params[source]
        +

        A list of parameters (constant-valued columns) for the +table. Must contain only Param objects.

        +
        + +
        +
        +parse(iterator, config)[source]
        +
        + +
        +
        +ref[source]
        +
        + +
        +
        +to_xml(w, **kwargs)[source]
        +
        + +
        + +
        +
        +class astropy.io.vo.tree.Group(table, ID=None, name=None, ref=None, ucd=None, utype=None, id=None, config={}, pos=None, **extra)[source]
        +

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._NameProperty, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._UcdProperty, astropy.io.vo.tree._DescriptionProperty

        +

        Stores information about the grouping of FIELD and PARAM +elements.

        +

        This information is currently ignored by the vo package—that is +the columns in the recarray are always flat—but the grouping +information is stored so that it can be written out again to the +XML file.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +
        +
        +entries[source]
        +

        [read-only] A list of members of the GROUP. This list may +only contain objects of type Param, Group, +ParamRef and FieldRef.

        +
        + +
        +
        +iter_fields_and_params()[source]
        +

        Recursively iterate over all Param elements in this +Group.

        +
        + +
        +
        +iter_groups()[source]
        +

        Recursively iterate over all sub-Group instances in +this Group.

        +
        + +
        +
        +parse(iterator, config)[source]
        +
        + +
        +
        +ref[source]
        +

        Currently ignored, as it’s not clear from the spec how this is +meant to work.

        +
        + +
        +
        +to_xml(w, **kwargs)[source]
        +
        + +
        + +
        +
        +class astropy.io.vo.tree.Info(ID=None, name=None, value=None, id=None, xtype=None, ref=None, unit=None, ucd=None, utype=None, config={}, pos=None, **extra)[source]
        +

        Bases: astropy.io.vo.tree.SimpleElementWithContent, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._XtypeProperty, astropy.io.vo.tree._UtypeProperty

        +

        A class for storing INFO elements, which contain arbitrary +key-value pairs for extensions to the standard.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +
        +
        +content[source]
        +

        The content inside the INFO element.

        +
        + +
        +
        +name[source]
        +

        [required] The key of the key-value pair.

        +
        + +
        +
        +ref[source]
        +

        Refer to another INFO element by ID, defined previously in +the document.

        +
        + +
        +
        +unit[source]
        +

        A string specifying the units for the INFO.

        +
        + +
        +
        +value[source]
        +

        [required] The value of the key-value pair. (Always stored +as a string or unicode string).

        +
        + +
        + +
        +
        +class astropy.io.vo.tree.Field(votable, ID=None, name=None, datatype=None, arraysize=None, ucd=None, unit=None, width=None, precision=None, utype=None, ref=None, type=None, id=None, xtype=None, config={}, pos=None, **extra)[source]
        +

        Bases: astropy.io.vo.tree.SimpleElement, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._NameProperty, astropy.io.vo.tree._XtypeProperty, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._UcdProperty

        +

        A class that represents the FIELD element, which describes the +datatype of a particular column of data.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +

        If ID is provided, it is used for the column name in the +resulting recarray of the table. If no ID is provided, name +is used instead. If neither is provided, an exception will be +raised.

        +
        +
        +arraysize[source]
        +

        Specifies the size of the multidimensional array if this +FIELD contains more than a single value.

        +

        See multidimensional arrays.

        +
        + +
        +
        +datatype[source]
        +

        [required] The datatype of the column. Valid values (as +defined by the spec) are:

        +
        +
        ‘boolean’, ‘bit’, ‘unsignedByte’, ‘short’, ‘int’, ‘long’, +‘char’, ‘unicodeChar’, ‘float’, ‘double’, ‘floatComplex’, or +‘doubleComplex’
        +

        Many VOTABLE files in the wild use ‘string’ instead of ‘char’, +so that is also a valid option, though ‘string’ will always be +converted to ‘char’ when writing the file back out.

        +
        + +
        + +

        A list of Link instances used to reference more +details about the meaning of the FIELD. This is purely +informational and is not used by the astropy.io.vo package.

        +
        + +
        +
        +parse(iterator, config)[source]
        +
        + +
        +
        +precision[source]
        +

        Along with width, defines the numerical accuracy +associated with the data. These values are used to limit the +precision when writing floating point values back to the XML +file. Otherwise, it is purely informational – the Numpy +recarray containing the data itself does not use this +information.

        +
        + +
        +
        +ref[source]
        +

        On FIELD elements, ref is used only for informational +purposes, for example to refer to a COOSYS element.

        +
        + +
        +
        +to_xml(w, **kwargs)[source]
        +
        + +
        +
        +type[source]
        +

        The type attribute on FIELD elements is reserved for future +extensions.

        +
        + +
        +
        +classmethod uniqify_names(fields)[source]
        +

        Make sure that all names and titles in a list of fields are +unique, by appending numbers if necessary.

        +
        + +
        +
        +unit[source]
        +

        A string specifying the units for the FIELD.

        +
        + +
        +
        +values[source]
        +

        A Values instance (or None) defining the domain +of the column.

        +
        + +
        +
        +width[source]
        +

        Along with precision, defines the numerical +accuracy associated with the data. These values are used to +limit the precision when writing floating point values back to +the XML file. Otherwise, it is purely informational – the +Numpy recarray containing the data itself does not use this +information.

        +
        + +
        + +
        +
        +class astropy.io.vo.tree.Param(votable, ID=None, name=None, value=None, datatype=None, arraysize=None, ucd=None, unit=None, width=None, precision=None, utype=None, type=None, id=None, config={}, pos=None, **extra)[source]
        +

        Bases: astropy.io.vo.tree.Field

        +

        A class to represent the PARAM element, which are constant-valued +columns in the data.

        +

        Param objects are a subclass of Field, and have +all of its methods and members. Additionally, it defines value.

        +
        +
        +to_xml(w, **kwargs)[source]
        +
        + +
        +
        +value[source]
        +

        [required] The constant value of the parameter. Its type is +determined by the datatype member.

        +
        + +
        + +
        + +

        Bases: astropy.io.vo.tree.SimpleElement, astropy.io.vo.tree._IDProperty

        +

        A class for storing LINK elements, which are used to reference +external documents and servers through a URI.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +
        +
        +content_role[source]
        +

        Defines the MIME role of the referenced object. Must be one of:

        +
        +
        None, ‘query’, ‘hints’, ‘doc’ or ‘location’
        +
        + +
        +
        +content_type[source]
        +

        Defines the MIME content type of the referenced object.

        +
        + +
        +
        +href[source]
        +

        A URI to an arbitrary protocol. The vo package only supports +http and anonymous ftp.

        +
        + +
        + +
        +
        +class astropy.io.vo.tree.CooSys(ID=None, equinox=None, epoch=None, system=None, id=None, config={}, pos=None, **extra)[source]
        +

        Bases: astropy.io.vo.tree.SimpleElement

        +

        A class representing the COOSYS element, which defines a +coordinate system.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +
        +
        +ID[source]
        +

        [required] The XML ID of the COOSYS element, used for +cross-referencing. May be None or a string conforming to +XML ID syntax.

        +
        + +
        +
        +epoch[source]
        +

        Specifies the epoch of the positions. It must be a string +specifying an astronomical year.

        +
        + +
        +
        +equinox[source]
        +

        A parameter required to fix the equatorial or ecliptic systems +(as e.g. “J2000” as the default “eq_FK5” or “B1950” as the +default “eq_FK4”).

        +
        + +
        +
        +system[source]
        +

        Specifies the type of coordinate system. Valid choices are:

        +
        +
        ‘eq_FK4’, ‘eq_FK5’, ‘ICRS’, ‘ecl_FK4’, ‘ecl_FK5’, ‘galactic’, +‘supergalactic’, ‘xy’, ‘barycentric’, or ‘geo_app’
        +
        + +
        + +
        +
        +class astropy.io.vo.tree.FieldRef(table, ref, ucd=None, utype=None, config={}, pos=None, **extra)[source]
        +

        Bases: astropy.io.vo.tree.SimpleElement, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._UcdProperty

        +

        A class representing the FIELDref element, which is used inside +of GROUP elements to refer to FIELD elements defined elsewhere.

        +
        +
        +get_ref()[source]
        +

        Lookup the Field instance that this FieldRef +references.

        +
        + +
        +
        +ref[source]
        +

        The ID of the FIELD that this FIELDref references.

        +
        + +
        + +
        +
        +class astropy.io.vo.tree.ParamRef(table, ref, ucd=None, utype=None, config={}, pos=None)[source]
        +

        Bases: astropy.io.vo.tree.SimpleElement, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._UcdProperty

        +

        A class representing the PARAMref element, which is used inside +of GROUP elements to refer to PARAM elements defined elsewhere.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +

        It contains the following publicly-accessible members:

        +
        +
        ref: An XML ID refering to a <PARAM> element.
        +
        +
        +get_ref()[source]
        +

        Lookup the Param instance that this PARAMref +references.

        +
        + +
        +
        +ref[source]
        +

        The ID of the PARAM that this PARAMref references.

        +
        + +
        + +
        +
        +class astropy.io.vo.tree.Values(votable, field, ID=None, null=None, ref=None, type='legal', id=None, config={}, pos=None, **extras)[source]
        +

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty

        +

        A class to represent the VALUES element, used within FIELD and +PARAM elements to define the domain of values.

        +

        The keyword arguments correspond to setting members of the same +name, documented below.

        +
        +
        +is_defaults()[source]
        +
        + +
        +
        +max[source]
        +

        The maximum value of the domain. See max_inclusive.

        +
        + +
        +
        +max_inclusive[source]
        +

        When True, the domain includes the maximum value.

        +
        + +
        +
        +min[source]
        +

        The minimum value of the domain. See min_inclusive.

        +
        + +
        +
        +min_inclusive[source]
        +

        When True, the domain includes the minimum value.

        +
        + +
        +
        +null[source]
        +

        For integral datatypes, null is used to define the value +used for missing values.

        +
        + +
        +
        +options[source]
        +

        A list of string key-value tuples defining other OPTION +elements for the domain. All options are ignored – they are +stored for round-tripping purposes only.

        +
        + +
        +
        +parse(iterator, config)[source]
        +
        + +
        +
        +ref[source]
        +

        Refer to another VALUES element by ID, defined previously in +the document, for MIN/MAX/OPTION information.

        +
        + +
        +
        +to_xml(w, **kwargs)[source]
        +
        + +
        +
        +type[source]
        +

        [required] Defines the applicability of the domain defined +by this VALUES element. Must be one of the following +strings:

        +
        +
          +
        • ‘legal’: The domain of this column applies in general to +this datatype. (default)
        • +
        • ‘actual’: The domain of this column applies only to the +data enclosed in the parent table.
        • +
        +
        +
        + +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.io.vo.table: Loading entire VOTable files

        +

        Next topic

        +

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/api_ucd.html b/vo/api_ucd.html new file mode 100644 index 00000000..e2dc9495 --- /dev/null +++ b/vo/api_ucd.html @@ -0,0 +1,205 @@ + + + + + + + + + + astropy.io.vo.ucd: Functions to parse and verify unified content descriptors — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.ucd: Functions to parse and verify unified content descriptors

        +

        This file contains routines to verify the correctness of UCD strings.

        +
        +
        +astropy.io.vo.ucd.parse_ucd(ucd, check_controlled_vocabulary=False, has_colon=False)[source]
        +

        Parse the UCD into its component parts.

        + +++ + + + + + + + +
        Parameters :

        ucd : str

        +
        +

        The UCD string

        +
        +

        check_controlled_vocabulary : bool, optional

        +
        +

        If True, then each word in the UCD will be verified against +the UCD1+ controlled vocabulary, (as required by the VOTable +specification version 1.2), otherwise not.

        +
        +

        has_colon : bool, optional

        +
        +

        If True, the UCD may contain a colon (as defined in earlier +versions of the standard).

        +
        +
        Returns :

        parts : list

        +
        +

        The result is a list of tuples of the form:

        +
        +

        (namespace, word)

        +
        +

        If no namespace was explicitly specified, namespace will be +returned as 'ivoa' (i.e., the default namespace).

        +
        +
        Raises :

        ValueError : ucd is invalid

        +
        +
        + +
        +
        +astropy.io.vo.ucd.check_ucd(ucd, check_controlled_vocabulary=False, has_colon=False)[source]
        +

        Returns False if ucd is not a valid unified content +descriptor.

        + +++ + + + + + +
        Parameters :

        ucd : str

        +
        +

        The UCD string

        +
        +

        check_controlled_vocabulary : bool, optional

        +
        +

        If True, then each word in the UCD will be verified against +the UCD1+ controlled vocabulary, (as required by the VOTable +specification version 1.2), otherwise not.

        +
        +
        Returns :

        valid : bool

        +
        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.io.vo.exceptions

        +

        Next topic

        +

        astropy.io.vo.unit: Verification of units as defined in the VOTable standard

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/api_unit.html b/vo/api_unit.html new file mode 100644 index 00000000..761d4aa2 --- /dev/null +++ b/vo/api_unit.html @@ -0,0 +1,149 @@ + + + + + + + + + + astropy.io.vo.unit: Verification of units as defined in the VOTable standard — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.unit: Verification of units as defined in the VOTable standard

        +

        Tools to verify the syntax of unit attributes according to the +Standards for Astronomical Catalogues, Version 2.0

        +
        +
        +astropy.io.vo.unit.is_unit(s)[source]
        +

        Returns True if s is a valid unit string as defined by +Standards for Astronomical Catalogues, Version 2.0

        +
        + +
        +
        +astropy.io.vo.unit.check_unit(unit, attr_name, config={}, pos=None)[source]
        +

        Raises a ValueError if unit is not a valid unit as defined by +Standards for Astronomical Catalogues, Version 2.0

        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.io.vo.ucd: Functions to parse and verify unified content descriptors

        +

        Next topic

        +

        astropy.io.vo.util: Low-level utilities used by the library

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/api_util.html b/vo/api_util.html new file mode 100644 index 00000000..32ae6351 --- /dev/null +++ b/vo/api_util.html @@ -0,0 +1,226 @@ + + + + + + + + + + astropy.io.vo.util: Low-level utilities used by the library — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.util: Low-level utilities used by the library

        +

        Various utilities and cookbook-like things.

        +
        +
        +astropy.io.vo.util.convert_to_writable_filelike(*args, **kwds)[source]
        +

        Returns a writable file-like object suitable for streaming output.

        + +++ + + + + + +
        Parameters :

        fd : file path string or writable file-like object

        +
        +

        May be:

        +
        +
          +
        • a file path, in which case it is opened, and the file +object is returned.
        • +
        • an object with a write() method, in which case that +object.
        • +
        +
        +
        +
        Returns :

        fd : writable file-like object

        +
        +
        + +
        +
        +astropy.io.vo.util.coerce_range_list_param(p, frames=None, numeric=True)[source]
        +

        Coerces and/or verifies the object p into a valid +range-list-format parameter as defined in Section 8.7.2 of Simple +Spectral Access Protocol.

        + +++ + + + + + +
        Parameters :

        p : str or sequence

        +
        +

        May be a string as passed verbatim to the service expecting a +range-list, or a sequence. If a sequence, each item must be +either:

        +
        +
          +
        • a numeric value
        • +
        • a named value, such as, for example, ‘J’ for named +spectrum (if the numeric kwarg is False)
        • +
        • a 2-tuple indicating a range
        • +
        • the last item my be a string indicating the frame of +reference
        • +
        +
        +
        +

        frames : sequence of str, optional

        +
        +

        A sequence of acceptable frame of reference keywords. If not +provided, the default set in set_reference_frames will be +used.

        +
        +

        numeric : bool, optional

        +
        +

        TODO

        +
        +
        Returns :

        parts : tuple

        +
        +
        +
        The result is a tuple:
        +
          +
        • a string suitable for passing to a service as a range-list +argument
        • +
        • an integer counting the number of elements
        • +
        +
        +
        +
        +
        +
        + +
        +
        +astropy.io.vo.util.is_callable(o)[source]
        +

        Abstracts away the different ways to test for a callable object in +Python 2.x and 3.x.

        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.io.vo.unit: Verification of units as defined in the VOTable standard

        +

        Next topic

        +

        astropy.io.vo.validator: Generates HTML validation reports

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/api_validator.html b/vo/api_validator.html new file mode 100644 index 00000000..050a7f1d --- /dev/null +++ b/vo/api_validator.html @@ -0,0 +1,180 @@ + + + + + + + + + + astropy.io.vo.validator: Generates HTML validation reports — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.validator: Generates HTML validation reports

        +

        Validates a large collection of web-accessible VOTable files, +and generates a report as a directory tree of HTML files.

        +
        +
        +astropy.io.vo.validator.main.make_validation_report(urls=None, destdir='astropy.io.vo.validator.results', multiprocess=True, stilts=None)[source]
        +

        Validates a large collection of web-accessible VOTable files, +and generates a report as a directory tree of HTML files.

        + +++ + + + +
        Parameters :

        urls : list of strings, optional

        +
        +

        If provided, is a list of HTTP urls to download VOTable files +from. If not provided, a built-in set of ~22,000 urls +compiled by HEASARC will be used.

        +
        +

        destdir : path, optional

        +
        +

        The directory to write the report to. By default, this is a +directory called astropy.io.vo.validator.results in the +current directory. If the directory does not exist, it will +be created.

        +
        +

        multiprocess : bool, optional

        +
        +

        If True (default), perform validations in parallel using all +of the cores on this machine.

        +
        +

        stilts : path, optional

        +
        +

        To perform validation with votlint from the the Java-based +STILTS VOTable +parser, in addition to astropy.io.vo, set this to the path +of the stilts.jar file. java on the system shell path +will be used to run it.

        +
        +
        +

        Notes

        +

        Downloads of each given URL will be performed only once and cached +locally in destdir. To refresh the cache, remove destdir +first.

        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.io.vo.util: Low-level utilities used by the library

        +

        Next topic

        +

        astropy.io.vo.xmlutil: XML-related utilities used by the library

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/api_xmlutil.html b/vo/api_xmlutil.html new file mode 100644 index 00000000..2decdb80 --- /dev/null +++ b/vo/api_xmlutil.html @@ -0,0 +1,204 @@ + + + + + + + + + + astropy.io.vo.xmlutil: XML-related utilities used by the library — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.io.vo.xmlutil: XML-related utilities used by the library

        +

        Various XML-related utilities

        +
        +
        +astropy.io.vo.xmlutil.check_id(ID, name='ID', config={}, pos=None)[source]
        +

        Raises a astropy.io.vo.exceptions.VOTableSpecError if ID is not a +valid XML ID. name is the name of the attribute being checked +(used only for error messages).

        +
        + +
        +
        +astropy.io.vo.xmlutil.fix_id(ID, config={}, pos=None)[source]
        +

        Given an arbitrary string, create one that can be used as an xml +id. This is rather simplistic at the moment, since it just +replaces non-valid characters with underscores.

        +
        + +
        +
        +astropy.io.vo.xmlutil.check_token(token, attr_name, config={}, pos=None)[source]
        +

        Raises a ValueError if token is not a valid XML token, as +defined by XML Schema Part 2.

        +
        + +
        +
        +astropy.io.vo.xmlutil.check_mime_content_type(content_type, config={}, pos=None)[source]
        +

        Raises a astropy.io.vo.exceptions.VOTableSpecError if +content_type is not a valid MIME content type (syntactically at +least), as defined by RFC 2045.

        +
        + +
        +
        +astropy.io.vo.xmlutil.check_anyuri(uri, config={}, pos=None)[source]
        +

        Raises a astropy.io.vo.exceptions.VOTableSpecError if uri is +not a valid URI as defined in RFC 2396.

        +
        + +
        +
        +astropy.io.vo.xmlutil.validate_schema(filename, version='1.2')[source]
        +

        Validates the given file against the appropriate VOTable schema.

        + +++ + + + + + +
        Parameters :

        filename : str

        +
        +

        The path to the XML file to validate

        +
        +

        version : str

        +
        +

        The VOTABLE version to check, which must be a string “1.0”, +“1.1”, or “1.2”.

        +

        For version “1.0”, it is checked against a DTD, since that +version did not have an XML Schema.

        +
        +
        Returns :

        returncode, stdout, stderr : int, str, str

        +
        +

        Returns the returncode from xmllint and the stdout and stderr +as strings

        +
        +
        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        astropy.io.vo.validator: Generates HTML validation reports

        +

        Next topic

        +

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/index.html b/vo/index.html new file mode 100644 index 00000000..bc1c8bc2 --- /dev/null +++ b/vo/index.html @@ -0,0 +1,144 @@ + + + + + + + + + + astropy.io.vo Documentation — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + +
        + +
        +
        + +

        Previous topic

        +

        astropy.wcs History

        +

        Next topic

        +

        Introduction to astropy.io.vo.table

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/vo/intro_table.html b/vo/intro_table.html new file mode 100644 index 00000000..4bd67fd2 --- /dev/null +++ b/vo/intro_table.html @@ -0,0 +1,439 @@ + + + + + + + + + + Introduction to astropy.io.vo.table — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Introduction to astropy.io.vo.table

        +

        astropy.io.vo.table is a Python package to read and write VOTable +files into Numpy record arrays.

        +
        +

        Standard compliance

        +

        astropy.io.vo.table supports the VOTable Format Definition Version +1.1 +and Version 1.2. +Some flexibility is provided to support the 1.0 draft version and +other non-standard usage in the wild. To support these cases, set the +keyword argument pedantic to False when parsing.

        +
        +

        Note

        +

        Each warning and VOTABLE-specific exception emitted has a number and +is documented in more detail in Warnings and +Exceptions.

        +
        +

        Output always conforms to the 1.1 or 1.2 spec, depending on the input.

        +
        +
        +

        Using astropy.io.vo.table

        +
        +

        Reading a VOTable file

        +

        To read in a VOTable file, pass a file path to +astropy.io.vo.table.parse:

        +
        from astropy.io.vo.table import parse
        +votable = parse("votable.xml")
        +
        +
        +

        votable is a VOTableFile object, which can +be used to retrieve and manipulate the data and save it back out to +disk.

        +

        VOTable files are made up of nested RESOURCE elements, each of +which may contain one or more TABLE elements. The TABLE +elements contain the arrays of data.

        +

        To get at the TABLE elements, one can write a loop over the +resources in the VOTABLE file:

        +
        for resource in votable.resources:
        +  for table in resource.tables:
        +    # ... do something with the table ...
        +    pass
        +
        +
        +

        However, if the nested structure of the resources is not important, +one can use iter_tables to return a flat +list of all tables:

        +
        for table in votable.iter_tables():
        +  # ... do something with the table ...
        +  pass
        +
        +
        +

        Finally, if there is expected to be only one table in the file, it +might be simplest to just use +get_first_table:

        +
        table = votable.get_first_table()
        +
        +
        +

        Even easier, there is a convenience method to parse a VOTable file and +return the first table all in one step:

        +
        from astropy.io.vo.table import parse_single_table
        +table = parse_single_table("votable.xml")
        +
        +
        +

        From a Table object, one can get the data itself +in the array member variable:

        +
        data = table.array
        +
        +
        +

        This data is a Numpy record array. The columns get their names from +both the ID and name attributes of the FIELD elements in +the VOTABLE file. For example, suppose we had a FIELD +specified as follows:

        +
        <FIELD ID="Dec" name="dec_targ" datatype="char" ucd="POS_EQ_DEC_MAIN"
        +       unit="deg">
        + <DESCRIPTION>
        +  representing the ICRS declination of the center of the image.
        + </DESCRIPTION>
        +</FIELD>
        +
        +
        +

        This column of data can be extracted from the record array using:

        +
        >>> table.array['dec_targ']
        +array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826,
        +       17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136,
        +       17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055,
        +       17.1553884541, 17.15539736932, 17.15539752176,
        +       17.25736014763,
        +       # ...
        +       17.2765703], dtype=object)
        +
        +
        +

        or equivalently:

        +
        >>> table.array['Dec']
        +array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826,
        +       17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136,
        +       17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055,
        +       17.1553884541, 17.15539736932, 17.15539752176,
        +       17.25736014763,
        +       # ...
        +       17.2765703], dtype=object)
        +
        +
        +
        +

        Pedantic mode

        +

        Many VOTABLE files in the wild do not conform to the VOTABLE +specification. If reading one of these files causes exceptions, you +may turn off pedantic mode in astropy.io.vo by passing +pedantic=False to the parse or +parse_single_table functions:

        +
        from astropy.io.vo.table import parse
        +votable = parse("votable.xml", pedantic=False)
        +
        +
        +

        Note, however, that it is good practice to report these errors to the +author of the application that generated the VOTABLE file to bring the +file into compliance with the specification.

        +

        Even with pedantic turned off, many warnings may still be omitted. +These warnings are all of the type +VOTableSpecWarning and can be turned off +using the standard Python warnings module.

        +
        +
        +
        +

        Building a new table from scratch

        +

        It is also possible to build a new table, define some field datatypes +and populate it with data:

        +
        from astropy.io.vo.tree import VOTableFile, Resource, Table, Field
        +
        +# Create a new VOTable file...
        +votable = VOTableFile()
        +
        +# ...with one resource...
        +resource = Resource()
        +votable.resources.append(resource)
        +
        +# ... with one table
        +table = Table(votable)
        +resource.tables.append(table)
        +
        +# Define some fields
        +table.fields.extend([
        +        Field(votable, ID="filename", datatype="char"),
        +        Field(votable, ID="matrix", datatype="double", arraysize="2x2")])
        +
        +# Now, use those field definitions to create the numpy record arrays, with
        +# the given number of rows
        +table.create_arrays(2)
        +
        +# Now table.array can be filled with data
        +table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
        +table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
        +
        +# Now write the whole thing to a file.
        +# Note, we have to use the top-level votable file object
        +votable.to_xml("new_votable.xml")
        +
        +
        +
        +
        +

        Missing values

        +

        Any value in the table may be “missing”. astropy.io.vo.table stores +a parallel array in each Table instance called +mask to keep track of missing values. +This array is False anywhere the value is missing.

        +
        +

        Note

        +

        In the future, the array and mask members will likely be +combined into a single masked record array. There are +implementation bugs in current versions of Numpy that prevent this +at the moment.

        +
        +
        +
        +

        Datatype mappings

        +

        The datatype specified by a FIELD element is mapped to a Numpy +type according to the following table:

        +
        +
        ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        VOTABLE typeNumpy type
        booleanb1
        bitb1
        unsignedByteu1
        char (variable length)O - In Python 2.x, a str object; in 3.x, a bytes object.
        char (fixed length)S
        unicodeChar (variable length)O - In Python 2.x, a unicode object, in utf-16; in 3.x a str object
        unicodeChar (fixed length)U
        shorti2
        inti4
        longi8
        floatf4
        doublef8
        floatComplexc8
        doubleComplexc16
        +
        +

        If the field is a fixed size array, the data is stored as a Numpy +fixed-size array.

        +

        If the field is a variable size array (that is arraysize contains +a ‘*’), the cell will contain a Python list of Numpy values. Each +value may be either an array or scalar depending on the arraysize +specifier.

        +
        +
        +

        Examining field types

        +

        To look up more information about a field in a table, one can use the +get_field_or_param_by_id method, which +returns the Field object with the given ID. For +example:

        +
        >>> field = table.get_field_or_param_by_id('Dec')
        +>>> field.datatype
        +'char'
        +>>> field.unit
        +'deg'
        +
        +
        +
        +

        Note

        +

        Field descriptors should not be mutated – they will have no effect +on the record arrays storing the data. This shortcoming will be +addressed in a future version of astropy.io.vo.

        +
        +
        +
        +

        Outputting a VOTable file

        +

        To save a VOTable file, simply call the +to_xml method. It accepts either a +string or unicode path, or a Python file-like object:

        +
        votable.to_xml('output.xml')
        +
        +
        +

        There are currently two data storage formats supported by +astropy.io.vo. The TABLEDATA format is XML-based and stores +values as strings representing numbers. The BINARY format is more +compact, and stores numbers in base64-encoded binary. The storage +format can be set on a per-table basis using the +format attribute, or globally using the +set_all_tables_format method:

        +
        votable.get_first_table().format = 'binary'
        +votable.set_all_tables_format('binary')
        +votable.to_xml('binary.xml')
        +
        +
        +
        +
        +
        +

        Performance considerations

        +

        File reads will be moderately faster if the TABLE element includes +an nrows attribute. If the number of rows is not specified, the +record array must be resized repeatedly during load.

        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        astropy.io.vo Documentation

        +

        Next topic

        +

        API documentation

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/api.html b/wcs/api.html new file mode 100644 index 00000000..6c4a9b82 --- /dev/null +++ b/wcs/api.html @@ -0,0 +1,196 @@ + + + + + + + + + + API Documentation — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        API Documentation

        +
        +

        astropy.wcs

        +

        Under the hood, there are 3 separate classes that perform different +parts of the transformation:

        +
        +
        +
        +

        Additionally, the class WCS aggregates all of these transformations +together in a pipeline:

        +
        +
        +
        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        Example Usage

        +

        Next topic

        +

        WCS

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/api_distortion.html b/wcs/api_distortion.html new file mode 100644 index 00000000..ef701f6d --- /dev/null +++ b/wcs/api_distortion.html @@ -0,0 +1,217 @@ + + + + + + + + + + DistortionLookupTable — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        DistortionLookupTable

        +
        +
        +class astropy.wcs.DistortionLookupTable
        +

        Represents a single lookup table for a Paper IV distortion +transformation.

        + +++ + + + +
        Parameters :

        table : 2-dimensional array

        +
        +

        The distortion lookup table.

        +
        +

        crpix : 2-tuple

        +
        +

        The distortion array reference pixel

        +
        +

        crval : 2-tuple

        +
        +

        The image array pixel coordinate

        +
        +

        cdelt : 2-tuple

        +
        +

        The grid step size

        +
        +
        +
        +
        +cdelt
        +

        double array[naxis]

        +

        Coordinate increments (CDELTia) for each coord axis.

        +

        If a CDi_ja linear transformation matrix is present, a warning is +raised and cdelt is ignored. The CDi_ja +matrix may be deleted by:

        +
        del wcs.wcs.cd
        +
        +
        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +crpix
        +

        double array[naxis]

        +

        Coordinate reference pixels (CRPIXja) for each pixel axis.

        +
        + +
        +
        +crval
        +

        double array[naxis]

        +

        Coordinate reference values (CRVALia) for each coordinate axis.

        +
        + +
        +
        +data
        +

        float array

        +

        The array data for the DistortionLookupTable.

        +
        + +
        +
        +get_offset(*x, y*) -> (*x, y*)
        +

        Returns the offset as defined in the distortion lookup table.

        + +++ + + + +
        Returns :

        coordinate : coordinate pair

        +
        +

        The offset from the distortion table for pixel point (x, y).

        +
        +
        +
        + +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        Wcsprm

        +

        Next topic

        +

        Sip

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/api_sip.html b/wcs/api_sip.html new file mode 100644 index 00000000..6ca40be4 --- /dev/null +++ b/wcs/api_sip.html @@ -0,0 +1,335 @@ + + + + + + + + + + Sip — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Sip

        +
        +
        +class astropy.wcs.Sip
        +

        The Sip class performs polynomial distortion correction +using the SIP convention in both directions.

        + +++ + + + +
        Parameters :

        a : double array[m+1][m+1]

        +
        +

        The A_i_j polynomial for pixel to focal plane transformation. +Its size must be (m + 1, m + 1) where m = A_ORDER.

        +
        +

        b : double array[m+1][m+1]

        +
        +

        The B_i_j polynomial for pixel to focal plane transformation. +Its size must be (m + 1, m + 1) where m = B_ORDER.

        +
        +

        ap : double array[m+1][m+1]

        +
        +

        The AP_i_j polynomial for pixel to focal plane transformation. +Its size must be (m + 1, m + 1) where m = AP_ORDER.

        +
        +

        bp : double array[m+1][m+1]

        +
        +

        The BP_i_j polynomial for pixel to focal plane transformation. +Its size must be (m + 1, m + 1) where m = BP_ORDER.

        +
        +

        crpix : double array[2]

        +
        +

        The reference pixel.

        +
        +
        +

        Notes

        +

        Shupe, D. L., M. Moshir, J. Li, D. Makovoz and R. Narron. 2005. +“The SIP Convention for Representing Distortion in FITS Image +Headers.” ADASS XIV.

        +
        +
        +a
        +

        double array[a_order+1][a_order+1]

        +

        The SIP A_i_j matrix used for pixel to focal plane +transformation.

        +

        Its values may be changed in place, but it may not be resized, without +creating a new Sip object.

        +
        + +
        +
        +a_order
        +

        int (read-only)

        +

        The order of the polynomial in the SIP A_i_j array (A_ORDER).

        +
        + +
        +
        +ap
        +

        double array[ap_order+1][ap_order+1]

        +

        The SIP AP_i_j matrix used for focal plane to pixel +transformation. Its values may be changed in place, but it may not be +resized, without creating a new Sip object.

        +
        + +
        +
        +ap_order
        +

        int (read-only)

        +

        The order of the polynomial in the SIP AP_i_j array +(AP_ORDER).

        +
        + +
        +
        +b
        +

        double array[b_order+1][b_order+1]

        +

        The SIP B_i_j matrix used for pixel to focal plane +transformation. Its values may be changed in place, but it may not be +resized, without creating a new Sip object.

        +
        + +
        +
        +b_order
        +

        int (read-only)

        +

        The order of the polynomial in the SIP B_i_j array +(B_ORDER).

        +
        + +
        +
        +bp
        +

        double array[bp_order+1][bp_order+1]

        +

        The SIP BP_i_j matrix used for focal plane to pixel +transformation. Its values may be changed in place, but it may not be +resized, without creating a new Sip object.

        +
        + +
        +
        +bp_order
        +

        int (read-only)

        +

        The order of the polynomial in the SIP BP_i_j array +(BP_ORDER).

        +
        + +
        +
        +crpix
        +

        double array[naxis]

        +

        Coordinate reference pixels (CRPIXja) for each pixel axis.

        +
        + +
        +
        +foc2pix()
        +

        sip_foc2pix(foccrd, origin) -> double array[ncoord][nelem]

        +

        Convert focal plane coordinates to pixel coordinates using the SIP +polynomial distortion convention.

        + +++ + + + + + + + +
        Parameters :

        foccrd : double array[ncoord][nelem]

        +
        +

        Array of focal plane coordinates.

        +
        +

        origin : int

        +
        +

        Specifies the origin of pixel values. The Fortran and FITS +standards use an origin of 1. Numpy and C use array indexing with +origin at 0.

        +
        +
        Returns :

        pixcrd : double array[ncoord][nelem]

        +
        +

        Returns an array of pixel coordinates.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +
        +
        + +
        +
        +pix2foc()
        +

        sip_pix2foc(pixcrd, origin) -> double array[ncoord][nelem]

        +

        Convert pixel coordinates to focal plane coordinates using the SIP +polynomial distortion convention.

        + +++ + + + + + + + +
        Parameters :

        pixcrd : double array[ncoord][nelem]

        +
        +

        Array of pixel coordinates.

        +
        +

        origin : int

        +
        +

        Specifies the origin of pixel values. The Fortran and FITS +standards use an origin of 1. Numpy and C use array indexing with +origin at 0.

        +
        +
        Returns :

        foccrd : double array[ncoord][nelem]

        +
        +

        Returns an array of focal plane coordinates.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +
        +
        + +
        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        DistortionLookupTable

        +

        Next topic

        +

        UnitConverter

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/api_units.html b/wcs/api_units.html new file mode 100644 index 00000000..8c73323f --- /dev/null +++ b/wcs/api_units.html @@ -0,0 +1,991 @@ + + + + + + + + + + UnitConverter — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        UnitConverter

        +
        +
        +class astropy.wcs.UnitConverter
        +

        Creates an object for performing conversion from one system of units +to another.

        +

        Use the returned object’s convert method +to convert values from have to want.

        +

        This function is permissive in accepting whitespace in all contexts in +a units specification where it does not create ambiguity (e.g. not +between a metric prefix and a basic unit string), including in strings +like "log (m ** 2)" which is formally disallowed.

        + +++ + + + + + +
        Parameters :

        have : string

        +
        +

        FITS unit specification to convert from, with or without surrounding +square brackets (for inline specifications); text following the +closing bracket is ignored.

        +
        +

        want : string

        +
        +

        FITS unit specification to convert to, with or without surrounding square +brackets (for inline specifications); text following the closing +bracket is ignored.

        +
        +

        ctrl : string, optional

        +
        +

        Do potentially unsafe translations of non-standard unit strings.

        +

        Although "S" is commonly used to represent seconds, its +recognizes "S" formally as Siemens, however rarely that may +be translation to "s" is potentially unsafe since the +standard used. The same applies to "H" for hours (Henry), +and "D" for days (Debye).

        +

        This string controls what to do in such cases, and is +case-insensitive.

        +
          +
        • If the string contains "s", translate "S" to "s".
        • +
        • If the string contains "h", translate "H" to "h".
        • +
        • If the string contains "d", translate "D" to "d".
        • +
        +

        Thus '' doesn’t do any unsafe translations, whereas 'shd' +does all of them.

        +

        See FITS unit specification for more information.

        +
        +
        Raises :

        ValueError :

        +
        +

        Invalid numeric multiplier.

        +
        +

        SyntaxError :

        +
        +

        Dangling binary operator.

        +
        +

        SyntaxError :

        +
        +

        Invalid symbol in INITIAL context.

        +
        +

        SyntaxError :

        +
        +

        Function in invalid context.

        +
        +

        SyntaxError :

        +
        +

        Invalid symbol in EXPON context.

        +
        +

        SyntaxError :

        +
        +

        Unbalanced bracket.

        +
        +

        SyntaxError :

        +
        +

        Unbalanced parenthesis.

        +
        +

        SyntaxError :

        +
        +

        Consecutive binary operators.

        +
        +

        SyntaxError :

        +
        +

        Internal parser error.

        +
        +

        SyntaxError :

        +
        +

        Non-conformant unit specifications.

        +
        +

        SyntaxError :

        +
        +

        Non-conformant functions.

        +
        +

        ValueError :

        +
        +

        Potentially unsafe translation.

        +
        +
        +
        +
        +convert(array)
        +

        Perform the unit conversion on the elements of the given array, +returning an array of the same shape.

        +
        + +
        +
        +have
        +

        The name of the unit being converted from.

        +

        This value always uses standard unit names, even if the +UnitConverter was initialized with a non-standard unit name.

        +
        + +
        +
        +offset
        +

        double

        +

        The offset of the unit conversion.

        +
        + +
        +
        +power
        +

        double

        +

        The exponent of the unit conversion.

        +
        + +
        +
        +scale
        +

        double

        +

        The scaling factor for the unit conversion.

        +
        + +
        +
        +want
        +

        The name of the unit being converted to.

        +

        This value always uses standard unit names, even if the +UnitConverter was initialized with a non-standard unit name.

        +
        + +
        + +
        +
        +

        FITS unit specification

        +
        +

        Supported units

        +

        The following units are supported by the FITS standard:

        +

        SI base & supplementary units

        + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        QuantityUnit StringMeaning
        lengthmmetre
        masskgkilogram
        timessecond of time
        plane angleradradian
        solid anglesrsteradian
        temperatureKkelvin
        electric currentAampere
        amount of substancemolmole
        luminous intensitycdcandela
        +

        IAU-recognized derived units

        + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        QuantityUnit StringMeaningEquivalence
        frequencyHzhertzs-1
        energyJjouleN m
        powerWwattJ s-1
        electric potentialVvoltsJ C-1
        forceNnewtonkg m s-2
        pressure, stressPapascalN m-2
        electric chargeCcoulombA s
        electric resistanceohmohm (Ω)V A-1
        electric conductanceSsiemensA V-1
        electric capacitanceFfaradC V-1
        magnetic fluxWbweberV s
        magnetic flux densityTteslaWb m-2
        inductanceHhenryWb A-1
        luminous fluxlmlumencd sr
        illuminancelxluxlm m-2
        +

        Additional units

        + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        QuantityUnit StringMeaningEquivalence
        massuunified atomic mass unit1.6605387 x 10-27 kg
        masssolMasssolar mass1.9891 x 1030 kg
        plane angledegdegree of arc1.745533 x 10-2 rad
        plane anglearcsecsecond of arc4.848137 x 10-6 rad
        plane anglearcminminute of arc2.90888 x 10-4 rad
        timeminminute 
        timehhour 
        timedday8.64 x 104 s
        timeyryear (Julian)3.15576 x10-7 s (365.25 d)
        energyeVelectron volt1.602177 x 10-19 J
        energyergerg10-7 J
        energyRyRydberg13.605692 eV
        lengthangstromangstrom10-10 m
        lengthAUastronomical unit1.49598 x 1011 m
        lengthlyrlight year9.460530 x 10-15 m
        lengthpcparsec3.0857 x 10-16 m
        lengthsolRadsolar radius6.9599 x 108 m
        eventscountcounts 
        eventsphotonphotons 
        flux densityJyjansky10-16 W m-2 Hz-1
        flux densitymag(stellar) magnitude 
        flux densityCrab‘crab’ 
        flux densitybeambeamJy/beam
        flux densitysolLumsolar luminosity 
        magnetic fieldGgauss10-4 T
        areapixel(image/detector) pixel 
        areavoxel3-d analog of pixel 
        areabarnbarn10-28 m2
        devicechan(detector) channel 
        devicebyte(computer) byte 
        devicebit(computer) bits 
        deviceaduA/D converter units 
        miscbinnumerous applications 
        miscSunwrt. sun 
        +

        Potentially unsafe translations of "D", "H", and "S", are +optional, using the translate_units parameter.

        +
        +
        +

        Unit aliases

        +

        When converting non-standard units to standard ones, a case-sensitive +match is required for the aliases listed below, in particular the only +recognized aliases with metric prefixes are "KM", "KHZ", +"MHZ", and "GHZ".

        + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        UnitRecognized aliases
        Angstromangstrom
        arcminarcmins, ARCMIN, ARCMINS
        arcsecarcsecs, ARCSEC, ARCSECS
        beamBEAM
        byteByte
        countct
        dday, days, (D), DAY, DAYS
        degdegree, degrees, DEG, DEGREE, DEGREES
        GHzGHZ
        hhr, (H), HR
        Hzhz, HZ
        kHzKHZ
        JyJY
        Kkelvin, kelvins, Kelvin, Kelvins, KELVIN, KELVINS
        kmKM
        mmetre, meter, metres, meters, M, METRE, METER, METRES, METERS
        minMIN
        MHzMHZ
        Ohmohm
        Papascal, pascals, Pascal, Pascals, PASCAL, PASCALS
        photonph
        pixelpixels, PIXEL, PIXELS, pix
        radradian, radians, RAD, RADIAN, RADIANS
        ssec, second, seconds, (S), SEC, SECOND, SECONDS
        Vvolt, volts, Volt, Volts, VOLT, VOLTS
        yryear, years, YR, YEAR, YEARS
        +

        The aliases "angstrom", "ohm", and "Byte" for (Angstrom, +Ohm, and byte) are recognized by astropy.wcs/wcslib itself as an +unofficial extension of the standard, but they are converted to the +standard form here.

        +
        +
        +

        Prefixes

        +

        The following metric prefixes are supported:

        + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        PrefixStringMagnitude
        yoctoy10-24
        zeptoz10-21
        attoa10-18
        femtof10-15
        picop10-12
        nanon10-9
        microu10-6
        millim10-3
        centic10-2
        decid10-1
        dekada101
        hectoh102
        kilok103
        MegaM106
        GigaG109
        TeraT1012
        PetaP1015
        ExaE1018
        ZettaZ1021
        YottaY1024
        +

        Table 6 of WCS Paper I lists eleven units for which metric prefixes +are allowed. However, in this implementation only prefixes greater +than unity are allowed for "a" (annum), "yr" (year), "pc" +(parsec), "bit", and "byte", and only prefixes less than unity +are allowed for "mag" (stellar magnitude).

        +

        Metric prefix "P" (peta) is specifically forbidden for "a" +(annum) to avoid confusion with "Pa" (Pascal, not peta-annum). +Note that metric prefixes are specifically disallowed for "h" +(hour) and "d" (day) so that "ph" (photons) cannot be +interpreted as pico-hours, nor "cd" (candela) as centi-days.

        +
        +
        +

        Operators

        +

        A compound unit is considered to be formed by a series of sub-strings +of component units & mathematical operations. Each of these +sub-strings must be separated by at least one space or a mathematical +operator (* or /).

        +
        +

        Multiplication

        +

        Multiplicative units can be specified either:

        +
          +
        • by simply using one or more preceding spaces, e.g. str1 str2 +(The recommended method).
        • +
        • by the use of a single asterisk (*) with optional whitespace, +e.g. str1 * str2.
        • +
        +
        +
        +

        Division

        +

        Units which form the denominator of a compound expression can be +specified either:

        +
          +
        • by using a slash (/) with optional whitespace, e.g. str1 / +str2. If such a syntax is used, it is recommended that no space +is included between the slash and the unit string.
        • +
        • by raising a multiplicative unit to a negative power (see below).
        • +
        +

        It should be stressed that the slash character only effects the +sub-string it immediately precedes. Thus, unless brackets are used, +subsequent sub-strings which also form part of the denominator of the +compound expression must also be preceded by a slash. For example, +str1 /str2 str3 is equivalent to str1 str3 /str2 whilst str1 +/str2 /str3 is equivalent to str1 /(str2 * str3).

        +
        +
        +

        Raising to Powers

        +

        A unit string raised to the power y is specified:

        +
          +
        • by using two asterisks (**) followed by the index enclosed +within round brackets and with no preceding or intervening spaces, +e.g. str1**(y) or str1**(-y).
        • +
        +

        However, if y is positive, then the brackets need not be included, +but a following space is recommended if additional sub-strings follow.

        +
        +
        +

        Use of brackets

        +

        Any number of pairs of round brackets (()) may be used within the +string for a compound unit in order to prevent ambiguities. As +described within this section, a number of rules always/often require +their use. However, it is suggested that conservative use is made of +such pairs of brackets in order to minimize the total length of +compound strings. (It should be remembered that a maximum of 68 +characters are allowed in the card image of keywords.)

        +
        +
        +

        Avoidance of underflows & overflows

        +

        The inclusion of numerical factors within the unit string should +generally be avoided (by the use of multiples and/or submultiples of +component basic units).

        +

        However, occasionally it may be preferable to include such factors on +the grounds of user-friendliness and/or to minimize the risk of +computer under- or overflows. In such cases, the numerical factor can +simply be considered a basic unit string.

        +

        The following additional guidelines are suggested:

        +
          +
        • the numerical factor should precede any unit strings
        • +
        • only powers of 10 are used as numerical factors
        • +
        +
        +
        +

        Mathematical Operations & Functions

        +

        A number of mathematical operations are supported. It should be noted +that the (round) brackets are mandatory in all cases in which they are +included in the table.

        + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        StringMeaning
        str1*str2Multiplication
        str1 /str2Division
        str1**(y)Raised to the power y
        log(str1)Common Logarithm (to base 10)
        ln(str1)Natural Logarithm
        exp(str1)Exponential (expstr1)
        sqrt(str1)Square root
        sin(str1)Sine
        cos(str1)Cosine
        tan(str1)Tangent
        asin(str1)Arc Sine
        acos(str1)Arc Cosine
        atan(str1)Arc Tangent
        sinh(str1)Hyperbolic Sine
        cosh(str1)Hyperbolic Cosine
        tanh(str1)Hyperbolic Tangent
        +

        Function types log(), ln() and exp() may only occur at the +start of the units specification.

        +
        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        Sip

        +

        Next topic

        +

        Relax constants

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/api_wcs.html b/wcs/api_wcs.html new file mode 100644 index 00000000..48c8f69f --- /dev/null +++ b/wcs/api_wcs.html @@ -0,0 +1,1065 @@ + + + + + + + + + + WCS — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        WCS

        +
        +
        +class astropy.wcs.WCS(header=None, fobj=None, key=' ', minerr=0.0, relax=False, naxis=None, keysel=None, colsel=None, fix=True)
        +

        WCS objects perform standard WCS transformations, and correct for +SIP and Paper IV table-lookup distortions, based on the WCS +keywords and supplementary data read from a FITS file.

        +
        +
        +all_pix2sky(*args, **kwargs)
        +

        Transforms pixel coordinates to sky coordinates.

        +

        Performs all of the following in order:

        +
        +
          +
        • Detector to image plane correction (optionally)
        • +
        • SIP distortion correction (optionally)
        • +
        • Paper IV table-lookup distortion correction (optionally)
        • +
        • wcslib WCS transformation
        • +
        +
        + +++ + + + + + + + +
        Parameters :

        args : flexible

        +
        +

        Either two or three arguments may be provided.

        +
        +
          +
        • 2 arguments: An N x naxis array of x- and +y-coordinates, and an origin.
        • +
        • 3 arguments: 2 one-dimensional arrays of x and y +coordinates, and an origin.
        • +
        +
        +

        Here, origin is the coordinate in the upper left corner of the +image. In FITS and Fortran standards, this is 1. In Numpy and C +standards this is 0.

        +

        For a transformation that is not two-dimensional, the +two-argument form must be used.

        +
        +

        ra_dec_order : bool, optional

        +
        +

        When True will ensure that sky coordinates are always given and +returned in as (ra, dec) pairs, regardless of the order of the +axes specified by the in the CTYPE keywords.

        +
        +
        Returns :

        result : array

        +
        +

        Returns the sky coordinates, in degrees. If the input was a single array and +origin, a single array is returned, otherwise a tuple of arrays is +returned.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        SingularMatrixError :

        +
        +

        Linear transformation matrix is singular.

        +
        +

        InconsistentAxisTypesError :

        +
        +

        Inconsistent or unrecognized coordinate axis types.

        +
        +

        ValueError :

        +
        +

        Invalid parameter value.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        ValueError :

        +
        +

        x- and y-coordinate arrays are not the same size.

        +
        +

        InvalidTransformError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        InvalidTransformError :

        +
        +

        Ill-conditioned coordinate transformation parameters.

        +
        +
        +

        Notes

        +

        The order of the axes for the result is determined by the +CTYPEia keywords in the FITS header, therefore it may not +always be of the form (ra, dec). The +lat, lng, +lattyp and lngtyp +members can be used to determine the order of the axes.

        +
        + +
        +
        +calcFootprint(header=None, undistort=True)
        +

        Calculates the footprint of the image on the sky.

        +

        A footprint is defined as the positions of the corners of the +image on the sky after all available distortions have been +applied.

        + +++ + + + + + +
        Parameters :

        header : pyfits header object, optional

        +

        undistort : bool, optional

        +
        +

        If True, take SIP and distortion lookup table into account

        +
        +
        Returns :

        coord : (4, 2) array of (x, y) coordinates.

        +
        +
        + +
        +
        +copy()
        +

        Return a shallow copy of the object.

        +

        Convenience method so user doesn’t have to import the copy +stdlib module.

        +
        + +
        +
        +cpdis1
        +

        DistortionLookupTable

        +

        The pre-linear transformation distortion lookup table, CPDIS1.

        +
        + +
        +
        +cpdis2
        +

        DistortionLookupTable

        +

        The pre-linear transformation distortion lookup table, CPDIS2.

        +
        + +
        +
        +deepcopy()
        +

        Return a deep copy of the object.

        +

        Convenience method so user doesn’t have to import the copy +stdlib module.

        +
        + +
        +
        +det2im(*args, **kwargs)
        +

        Convert detector coordinates to image plane coordinates using +Paper IV table-lookup distortion correction.

        + +++ + + + + + + + +
        Parameters :

        args : flexible

        +
        +

        Either two or three arguments may be provided.

        +
        +
          +
        • 2 arguments: An N x 2 array of x- and +y-coordinates, and an origin.
        • +
        • 3 arguments: 2 one-dimensional arrays of x and y +coordinates, and an origin.
        • +
        +
        +

        Here, origin is the coordinate in the upper left corner of the +image. In FITS and Fortran standards, this is 1. In Numpy and C +standards this is 0.

        +
        +
        Returns :

        result : array

        +
        +

        Returns the pixel coordinates. If the input was a single array and +origin, a single array is returned, otherwise a tuple of arrays is +returned.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +
        +
        + +
        +
        +det2im1
        +

        A DistortionLookupTable object for detector to image plane +correction in the x-axis.

        +
        + +
        +
        +det2im2
        +

        A DistortionLookupTable object for detector to image plane +correction in the y-axis.

        +
        + +
        +
        +footprint_to_file(filename=None, color='green', width=2)
        +

        Writes out a ds9 style regions file. It can be loaded +directly by ds9.

        + +++ + + + +
        Parameters :

        filename : string, optional

        +
        +

        Output file name - default is 'footprint.reg'

        +
        +

        color : string, optional

        +
        +

        Color to use when plotting the line.

        +
        +

        width : int, optional

        +
        +

        Width of the region line.

        +
        +
        +
        + +
        +
        +get_axis_types()
        +

        Similar to self.wcsprm.axis_types +but provides the information in a more Python-friendly format.

        + +++ + + + +
        Returns :

        result : list of dicts

        +
        +

        Returns a list of dictionaries, one for each axis, each +containing attributes about the type of that axis.

        +

        Each dictionary has the following keys:

        +
          +
        • ‘coordinate_type’:
            +
          • None: Non-specific coordinate type.
          • +
          • ‘stokes’: Stokes coordinate.
          • +
          • ‘celestial’: Celestial coordinate (including CUBEFACE).
          • +
          • ‘spectral’: Spectral coordinate.
          • +
          +
        • +
        • ‘scale’:
            +
          • ‘linear’: Linear axis.
          • +
          • ‘quantized’: Quantized axis (STOKES, CUBEFACE).
          • +
          • ‘non-linear celestial’: Non-linear celestial axis.
          • +
          • ‘non-linear spectral’: Non-linear spectral axis.
          • +
          • ‘logarithmic’: Logarithmic axis.
          • +
          • ‘tabular’: Tabular axis.
          • +
          +
        • +
        • ‘group’
            +
          • Group number, e.g. lookup table number
          • +
          +
        • +
        • ‘number’
            +
          • For celestial axes:
              +
            • 0: Longitude coordinate.
            • +
            • 1: Latitude coordinate.
            • +
            • 2: CUBEFACE number.
            • +
            +
          • +
          • For lookup tables:
              +
            • the axis number in a multidimensional table.
            • +
            +
          • +
          +
        • +
        +

        CTYPEia in "4-3" form with unrecognized algorithm code will +generate an error.

        +
        +
        +
        + +
        +
        +get_naxis(header=None)
        +
        + +
        +
        +p4_pix2foc(*args, **kwargs)
        +

        Convert pixel coordinates to focal plane coordinates using +Paper IV table-lookup distortion correction.

        + +++ + + + + + + + +
        Parameters :

        args : flexible

        +
        +

        Either two or three arguments may be provided.

        +
        +
          +
        • 2 arguments: An N x 2 array of x- and +y-coordinates, and an origin.
        • +
        • 3 arguments: 2 one-dimensional arrays of x and y +coordinates, and an origin.
        • +
        +
        +

        Here, origin is the coordinate in the upper left corner of the +image. In FITS and Fortran standards, this is 1. In Numpy and C +standards this is 0.

        +
        +
        Returns :

        result : array

        +
        +

        Returns the focal coordinates. If the input was a single array and +origin, a single array is returned, otherwise a tuple of arrays is +returned.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +
        +
        + +
        +
        +pix2foc(*args, **kwargs)
        +

        Convert pixel coordinates to focal plane coordinates using the +SIP polynomial distortion convention and Paper IV +table-lookup distortion correction.

        + +++ + + + + + + + +
        Parameters :

        args : flexible

        +
        +

        Either two or three arguments may be provided.

        +
        +
          +
        • 2 arguments: An N x 2 array of x- and +y-coordinates, and an origin.
        • +
        • 3 arguments: 2 one-dimensional arrays of x and y +coordinates, and an origin.
        • +
        +
        +

        Here, origin is the coordinate in the upper left corner of the +image. In FITS and Fortran standards, this is 1. In Numpy and C +standards this is 0.

        +
        +
        Returns :

        result : array

        +
        +

        Returns the focal coordinates. If the input was a single array and +origin, a single array is returned, otherwise a tuple of arrays is +returned.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +
        +
        + +
        +
        +printwcs()
        +

        Temporary function for internal use.

        +
        + +
        +
        +rotateCD(theta)
        +
        + +
        +
        +sip
        +

        Get/set the Sip object for performing SIP distortion +correction.

        +
        + +
        +
        +sip_foc2pix(*args, **kwargs)
        +

        Convert focal plane coordinates to pixel coordinates using the +SIP polynomial distortion convention.

        +

        Paper IV table lookup distortion correction is not applied, +even if that information existed in the FITS file that +initialized this WCS object.

        + +++ + + + + + + + +
        Parameters :

        args : flexible

        +
        +

        Either two or three arguments may be provided.

        +
        +
          +
        • 2 arguments: An N x 2 array of x- and +y-coordinates, and an origin.
        • +
        • 3 arguments: 2 one-dimensional arrays of x and y +coordinates, and an origin.
        • +
        +
        +

        Here, origin is the coordinate in the upper left corner of the +image. In FITS and Fortran standards, this is 1. In Numpy and C +standards this is 0.

        +
        +
        Returns :

        result : array

        +
        +

        Returns the pixel coordinates. If the input was a single array and +origin, a single array is returned, otherwise a tuple of arrays is +returned.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +
        +
        + +
        +
        +sip_pix2foc(*args, **kwargs)
        +

        Convert pixel coordinates to focal plane coordinates using the +SIP polynomial distortion convention.

        +

        Paper IV table lookup distortion correction is not applied, +even if that information existed in the FITS file that +initialized this WCS object. To correct +for that, use pix2foc or +p4_pix2foc.

        + +++ + + + + + + + +
        Parameters :

        args : flexible

        +
        +

        Either two or three arguments may be provided.

        +
        +
          +
        • 2 arguments: An N x 2 array of x- and +y-coordinates, and an origin.
        • +
        • 3 arguments: 2 one-dimensional arrays of x and y +coordinates, and an origin.
        • +
        +
        +

        Here, origin is the coordinate in the upper left corner of the +image. In FITS and Fortran standards, this is 1. In Numpy and C +standards this is 0.

        +
        +
        Returns :

        result : array

        +
        +

        Returns the focal coordinates. If the input was a single array and +origin, a single array is returned, otherwise a tuple of arrays is +returned.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +
        +
        + +
        +
        +sub(axes)
        +

        Extracts the coordinate description for a subimage from a +WCS object.

        +

        The world coordinate system of the subimage must be separable in the +sense that the world coordinates at any point in the subimage must +depend only on the pixel coordinates of the axes extracted. In +practice, this means that the PCi_ja matrix of the original image +must not contain non-zero off-diagonal terms that associate any of the +subimage axes with any of the non-subimage axes.

        + +++ + + + + + + + +
        Parameters :

        axes : int or a sequence.

        +
        +
          +
        • If an int, include the first N axes in their original order.
        • +
        • If a sequence, may contain a combination of image axis numbers +(1-relative) or special axis identifiers (see below). Order is +significant; axes[0] is the axis number of the input image +that corresponds to the first axis in the subimage, etc.
        • +
        • If 0, [] or None, do a deep copy.
        • +
        +

        Coordinate axes types may be specified using either strings or +special integer constants. The available types are:

        +
          +
        • 'longitude' / WCSSUB_LONGITUDE: Celestial longitude
        • +
        • 'latitude' / WCSSUB_LATITUDE: Celestial latitude
        • +
        • 'cubeface' / WCSSUB_CUBEFACE: Quadcube CUBEFACE axis
        • +
        • 'spectral' / WCSSUB_SPECTRAL: Spectral axis
        • +
        • 'stokes' / WCSSUB_STOKES: Stokes axis
        • +
        • 'celestial' / WCSSUB_CELESTIAL: An alias for the +combination of 'longitude', 'latitude' and 'cubeface'.
        • +
        +
        +
        Returns :

        new_wcs : WCS object

        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        InvalidSubimageSpecificationError :

        +
        +

        Invalid subimage specification (no spectral axis).

        +
        +

        NonseparableSubimageCoordinateSystem :

        +
        +

        Non-separable subimage coordinate system.

        +
        +
        +

        Notes

        +

        Combinations of subimage axes of particular types may be extracted in +the same order as they occur in the input image by combining the +integer constants with the ‘binary or’ (|) operator. For +example:

        +
        wcs.sub([WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_SPECTRAL])
        +
        +
        +

        would extract the longitude, latitude, and spectral axes in the same +order as the input image. If one of each were present, the resulting +object would have three dimensions.

        +

        For convenience, WCSSUB_CELESTIAL is defined as the combination +WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_CUBEFACE.

        +

        The codes may also be negated to extract all but the types specified, +for example:

        +
        wcs.sub([
        +  WCSSUB_LONGITUDE,
        +  WCSSUB_LATITUDE,
        +  WCSSUB_CUBEFACE,
        +  -(WCSSUB_SPECTRAL | WCSSUB_STOKES)])
        +
        +
        +

        The last of these specifies all axis types other than spectral or +Stokes. Extraction is done in the order specified by axes, i.e. a +longitude axis (if present) would be extracted first (via axes[0]) +and not subsequently (via axes[3]). Likewise for the latitude and +cubeface axes in this example.

        +

        The number of dimensions in the returned object may be less than or +greater than the length of axes. However, it will never exceed the +number of axes in the input image.

        +
        + +
        +
        +to_header(relax=False)
        +

        Generate a pyfits header object with the WCS information +stored in this object.

        +
        +

        Warning

        +

        This function does not write out SIP or Paper IV distortion +keywords, yet, only the core WCS support by wcslib.

        +
        +

        The output header will almost certainly differ from the input in a +number of respects:

        +
        +
          +
        1. The output header only contains WCS-related keywords. In +particular, it does not contain syntactically-required +keywords such as SIMPLE, NAXIS, BITPIX, or +END.
        2. +
        3. Deprecated (e.g. CROTAn) or non-standard usage will +be translated to standard (this is partially dependent on +whether fix was applied).
        4. +
        5. Quantities will be converted to the units used internally, +basically SI with the addition of degrees.
        6. +
        7. Floating-point quantities may be given to a different decimal +precision.
        8. +
        9. Elements of the PCi_j matrix will be written if and +only if they differ from the unit matrix. Thus, if the +matrix is unity then no elements will be written.
        10. +
        11. Additional keywords such as WCSAXES, CUNITia, +LONPOLEa and LATPOLEa may appear.
        12. +
        13. The original keycomments will be lost, although +to_header tries hard to write meaningful comments.
        14. +
        15. Keyword order may be changed.
        16. +
        +
        + +++ + + + + + +
        Parameters :

        relax : bool or int

        +
        +

        Degree of permissiveness:

        +
          +
        • False: Recognize only FITS keywords defined by the +published WCS standard.
        • +
        • True: Admit all recognized informal extensions of the +WCS standard.
        • +
        • int: a bit field selecting specific extensions to +write. See Header-writing relaxation constants for details.
        • +
        +
        +
        Returns :

        header : pyfits Header object

        +
        +
        + +
        +
        +to_header_string(relax=False)
        +

        Identical to to_header, but returns a string containing the +header cards.

        +
        + +
        +
        +wcs
        +

        A Wcsprm object to perform the basic wcslib WCS +transformation.

        +
        + +
        +
        +wcs_pix2sky(*args, **kwargs)
        +

        Transforms pixel coordinates to sky coordinates by doing only +the basic wcslib transformation.

        +

        No SIP or Paper IV table lookup distortion correction is +applied. To perform distortion correction, see +all_pix2sky, +sip_pix2foc, p4_pix2foc, +or pix2foc.

        + +++ + + + + + + + +
        Parameters :

        args : flexible

        +
        +

        Either two or three arguments may be provided.

        +
        +
          +
        • 2 arguments: An N x naxis array of x- and +y-coordinates, and an origin.
        • +
        • 3 arguments: 2 one-dimensional arrays of x and y +coordinates, and an origin.
        • +
        +
        +

        Here, origin is the coordinate in the upper left corner of the +image. In FITS and Fortran standards, this is 1. In Numpy and C +standards this is 0.

        +

        For a transformation that is not two-dimensional, the +two-argument form must be used.

        +
        +

        ra_dec_order : bool, optional

        +
        +

        When True will ensure that sky coordinates are always given and +returned in as (ra, dec) pairs, regardless of the order of the +axes specified by the in the CTYPE keywords.

        +
        +
        Returns :

        result : array

        +
        +

        Returns the sky coordinates, in degrees. If the input was a single array and +origin, a single array is returned, otherwise a tuple of arrays is +returned.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        SingularMatrixError :

        +
        +

        Linear transformation matrix is singular.

        +
        +

        InconsistentAxisTypesError :

        +
        +

        Inconsistent or unrecognized coordinate axis types.

        +
        +

        ValueError :

        +
        +

        Invalid parameter value.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        ValueError :

        +
        +

        x- and y-coordinate arrays are not the same size.

        +
        +

        InvalidTransformError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        InvalidTransformError :

        +
        +

        Ill-conditioned coordinate transformation parameters.

        +
        +
        +

        Notes

        +

        The order of the axes for the result is determined by the +CTYPEia keywords in the FITS header, therefore it may not +always be of the form (ra, dec). The +lat, lng, +lattyp and lngtyp +members can be used to determine the order of the axes.

        +
        + +
        +
        +wcs_sky2pix(*args, **kwargs)
        +

        Transforms sky coordinates to pixel coordinates, using only +the basic wcslib WCS transformation. No SIP or Paper +IV table lookup distortion is applied.

        + +++ + + + + + + + +
        Parameters :

        args : flexible

        +
        +

        Either two or three arguments may be provided.

        +
        +
          +
        • 2 arguments: An N x naxis array of x- and +y-coordinates, and an origin.
        • +
        • 3 arguments: 2 one-dimensional arrays of x and y +coordinates, and an origin.
        • +
        +
        +

        Here, origin is the coordinate in the upper left corner of the +image. In FITS and Fortran standards, this is 1. In Numpy and C +standards this is 0.

        +

        For a transformation that is not two-dimensional, the +two-argument form must be used.

        +
        +

        ra_dec_order : bool, optional

        +
        +

        When True will ensure that sky coordinates are always given and +returned in as (ra, dec) pairs, regardless of the order of the +axes specified by the in the CTYPE keywords.

        +
        +
        Returns :

        result : array

        +
        +

        Returns the pixel coordinates. If the input was a single array and +origin, a single array is returned, otherwise a tuple of arrays is +returned.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        SingularMatrixError :

        +
        +

        Linear transformation matrix is singular.

        +
        +

        InconsistentAxisTypesError :

        +
        +

        Inconsistent or unrecognized coordinate axis types.

        +
        +

        ValueError :

        +
        +

        Invalid parameter value.

        +
        +

        ValueError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        ValueError :

        +
        +

        x- and y-coordinate arrays are not the same size.

        +
        +

        InvalidTransformError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        InvalidTransformError :

        +
        +

        Ill-conditioned coordinate transformation parameters.

        +
        +
        +

        Notes

        +

        The order of the axes for the input sky array is determined by +the CTYPEia keywords in the FITS header, therefore it may +not always be of the form (ra, dec). The +lat, lng, +lattyp and lngtyp +members can be used to determine the order of the axes.

        +
        + +
        + +
        +
        +

        functions

        +
        +
        +astropy.wcs.find_all_wcs(header, relax=False, keysel=None)
        +

        Find all the WCS transformations in the given header.

        + +++ + + + + + +
        Parameters :

        header : string or PyFITS header object.

        +

        relax : bool or int, optional

        +
        +

        Degree of permissiveness:

        +
          +
        • False: Recognize only FITS keywords defined by the +published WCS standard.
        • +
        • True: Admit all recognized informal extensions of the +WCS standard.
        • +
        • int: a bit field selecting specific extensions to accept. +See Header-reading relaxation constants for details.
        • +
        +
        +

        keysel : sequence of flags, optional

        +
        +

        A list of flags used to select the keyword types considered by +wcslib. When None, only the standard image header +keywords are considered (and the underlying wcspih() C +function is called). To use binary table image array or pixel +list keywords, keysel must be set.

        +

        Each element in the list should be one of the following strings:

        +
        +
          +
        • ‘image’: Image header keywords
        • +
        • ‘binary’: Binary table image array keywords
        • +
        • ‘pixel’: Pixel list keywords
        • +
        +
        +

        Keywords such as EQUIna or RFRQna that are common to +binary table image arrays and pixel lists (including +WCSNna and TWCSna) are selected by both ‘binary’ and +‘pixel’.

        +
        +
        Returns :

        wcses : list of WCS objects

        +
        +
        + +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        API Documentation

        +

        Next topic

        +

        Wcsprm

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/api_wcsprm.html b/wcs/api_wcsprm.html new file mode 100644 index 00000000..84dffc5f --- /dev/null +++ b/wcs/api_wcsprm.html @@ -0,0 +1,1943 @@ + + + + + + + + + + Wcsprm — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Wcsprm

        +
        +
        +class astropy.wcs.Wcsprm[source]
        +
        +
        +alt
        +

        str

        +

        Character code for alternate coordinate descriptions. For example, +the "a" in keyword names such as CTYPEia. This is a space +character for the primary coordinate description, or one of the 26 +upper-case letters, A-Z.

        +
        + +
        +
        +axis_types
        +

        int array[naxis]

        +

        An array of four-digit type codes for each axis.

        +
          +
        • First digit (i.e. 1000s):
            +
          • 0: Non-specific coordinate type.
          • +
          • 1: Stokes coordinate.
          • +
          • 2: Celestial coordinate (including CUBEFACE).
          • +
          • 3: Spectral coordinate.
          • +
          +
        • +
        • Second digit (i.e. 100s):
            +
          • 0: Linear axis.
          • +
          • 1: Quantized axis (STOKES, CUBEFACE).
          • +
          • 2: Non-linear celestial axis.
          • +
          • 3: Non-linear spectral axis.
          • +
          • 4: Logarithmic axis.
          • +
          • 5: Tabular axis.
          • +
          +
        • +
        • Third digit (i.e. 10s):
            +
          • 0: Group number, e.g. lookup table number
          • +
          +
        • +
        • The fourth digit is used as a qualifier depending on the axis type.
            +
          • For celestial axes:
              +
            • 0: Longitude coordinate.
            • +
            • 1: Latitude coordinate.
            • +
            • 2: CUBEFACE number.
            • +
            +
          • +
          • For lookup tables: the axis number in a multidimensional table.
          • +
          +
        • +
        +

        CTYPEia in "4-3" form with unrecognized algorithm code will +have its type set to -1 and generate an error.

        +
        + +
        +
        +cd
        +

        double array[naxis][naxis]

        +

        The CDi_ja linear transformation matrix.

        +

        For historical compatibility, three alternate specifications of the +linear transforations are available in wcslib. The canonical +PCi_ja with CDELTia, and the deprecated CDi_ja and +CROTAia keywords. Although the deprecated versions may not +formally co-exist with PCi_ja, the approach here is simply to +ignore them if given in conjunction with PCi_ja.

        +

        has_pc, has_cd and +has_crota can be used to determine which of +these alternatives are present in the header.

        +

        These alternate specifications of the linear transformation matrix are +translated immediately to PCi_ja by set and +are nowhere visible to the lower-level routines. In particular, +set resets cdelt to unity +if CDi_ja is present (and no PCi_ja). If no CROTAia is +associated with the latitude axis, set reverts +to a unity PCi_ja matrix.

        +
        + +
        +
        +cdelt
        +

        double array[naxis]

        +

        Coordinate increments (CDELTia) for each coord axis.

        +

        If a CDi_ja linear transformation matrix is present, a warning is +raised and cdelt is ignored. The CDi_ja +matrix may be deleted by:

        +
        del wcs.wcs.cd
        +
        +
        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +cdfix()
        +

        Fix erroneously omitted CDi_ja keywords.

        +

        Sets the diagonal element of the CDi_ja matrix to unity if all +CDi_ja keywords associated with a given axis were omitted. +According to Paper I, if any CDi_ja keywords at all are given in a +FITS header then those not given default to zero. This results in a +singular matrix with an intersecting row and column of zeros.

        + +++ + + + +
        Returns :

        success : int

        +
        +

        Returns 0 for success; -1 if no change required.

        +
        +
        +
        + +
        +
        +cel_offset
        +

        boolean

        +

        If True, an offset will be applied to (x, y) to force (x,y) = +(0,0) at the fiducial point, (phi_0, theta_0). Default is +False.

        +
        + +
        +
        +celfix()
        +

        Translates AIPS-convention celestial projection types, -NCP and +-GLS.

        + +++ + + + +
        Returns :

        success : int

        +
        +

        Returns 0 for success; -1 if no change required.

        +
        +
        +
        + +
        +
        +cname
        +

        list of strings

        +

        A list of the coordinate axis names, from CNAMEia.

        +
        + +
        +
        +colax
        +

        int array[naxis]

        +

        An array recording the column numbers for each axis in a pixel list.

        +
        + +
        +
        +colnum
        +

        int

        +

        Where the coordinate representation is associated with an image-array +column in a FITS binary table, this property may be used to record the +relevant column number.

        +

        It should be set to zero for an image header or pixel list.

        +
        + +
        +
        +crder
        +

        double array[naxis]

        +

        The random error in each coordinate axis, CRDERia.

        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +crota
        +

        double array[naxis]

        +

        CROTAia keyvalues for each coordinate axis.

        +

        For historical compatibility, three alternate specifications of the +linear transforations are available in wcslib. The canonical +PCi_ja with CDELTia, and the deprecated CDi_ja and +CROTAia keywords. Although the deprecated versions may not +formally co-exist with PCi_ja, the approach here is simply to +ignore them if given in conjunction with PCi_ja.

        +

        has_pc, has_cd and +has_crota can be used to determine which of +these alternatives are present in the header.

        +

        These alternate specifications of the linear transformation matrix are +translated immediately to PCi_ja by set and +are nowhere visible to the lower-level routines. In particular, +set resets cdelt to unity +if CDi_ja is present (and no PCi_ja). If no CROTAia is +associated with the latitude axis, set reverts +to a unity PCi_ja matrix.

        +
        + +
        +
        +crpix
        +

        double array[naxis]

        +

        Coordinate reference pixels (CRPIXja) for each pixel axis.

        +
        + +
        +
        +crval
        +

        double array[naxis]

        +

        Coordinate reference values (CRVALia) for each coordinate axis.

        +
        + +
        +
        +csyer
        +

        double array[naxis]

        +

        The systematic error in the coordinate value axes, CSYERia.

        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +ctype
        +

        list of strings[naxis]

        +

        List of CTYPEia keyvalues.

        +

        The ctype keyword values must be in upper case +and there must be zero or one pair of matched celestial axis types, +and zero or one spectral axis.

        +
        + +
        +
        +cubeface
        +

        int

        +

        Index into the pixcrd (pixel coordinate) array for the +CUBEFACE axis. This is used for quadcube projections where the +cube faces are stored on a separate axis.

        +

        The quadcube projections (TSC, CSC, QSC) may be +represented in FITS in either of two ways:

        +
        +
          +
        • The six faces may be laid out in one plane and numbered as +follows:

          +
                   0
          +
          +4  3  2  1  4  3  2
          +
          +         5
          +
          +

          Faces 2, 3 and 4 may appear on one side or the other (or both). +The sky-to-pixel routines map faces 2, 3 and 4 to the left but +the pixel-to-sky routines accept them on either side.

          +
        • +
        • The COBE convention in which the six faces are stored in a +three-dimensional structure using a CUBEFACE axis indexed +from 0 to 5 as above.

          +
        • +
        +
        +

        These routines support both methods; set +determines which is being used by the presence or absence of a +CUBEFACE axis in ctype. +p2s and s2p translate the +CUBEFACE axis representation to the single plane representation +understood by the lower-level projection routines.

        +
        + +
        +
        +cunit
        +

        list of strings[naxis]

        +

        List of CUNITia keyvalues which define the units of measurement of +the CRVALia, CDELTia and CDi_ja keywords.

        +

        As CUNITia is an optional header keyword, +cunit may be left blank but otherwise is +expected to contain a standard units specification as defined by WCS +Paper I. unitfix is available to translate +commonly used non-standard units specifications but this must be done +as a separate step before invoking set.

        +

        For celestial axes, if cunit is not blank, +set uses wcsunits to parse it and scale +cdelt, crval, and +cd to decimal degrees. It then resets +cunit to "deg".

        +

        For spectral axes, if cunit is not blank, +set uses wcsunits to parse it and scale +cdelt, crval, and +cd to SI units. It then resets +cunit accordingly.

        +

        set ignores cunit for +other coordinate types; cunit may be used to +label coordinate values.

        +
        + +
        +
        +cylfix()
        +

        Fixes WCS keyvalues for malformed cylindrical projections.

        + +++ + + + +
        Returns :

        success : int

        +
        +

        Returns 0 for success; -1 if no change required.

        +
        +
        +
        + +
        +
        +dateavg
        +

        string

        +

        Representative mid-point of the date of observation in ISO format, +yyyy-mm-ddThh:mm:ss.

        + +
        + +
        +
        +dateobs
        +

        string

        +

        Start of the date of observation in ISO format, +yyyy-mm-ddThh:mm:ss.

        + +
        + +
        +
        +datfix()
        +

        Translates the old DATE-OBS date format to year-2000 standard form +(yyyy-mm-ddThh:mm:ss) and derives MJD-OBS from it if not +already set.

        +

        Alternatively, if mjdobs is set and +dateobs isn’t, then datfix +derives dateobs from it. If both are set but +disagree by more than half a day then ValueError is raised.

        + +++ + + + +
        Returns :

        success : int

        +
        +

        Returns 0 for success; -1 if no change required.

        +
        +
        +
        + +
        +
        +equinox
        +

        double

        +

        The equinox associated with dynamical equatorial or ecliptic +coordinate systems, EQUINOXa (or EPOCH in older headers). Not +applicable to ICRS equatorial or ecliptic coordinates.

        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +fix(translate_units='', naxis=0)
        +

        Applies all of the corrections handled separately by +datfix, unitfix, +celfix, spcfix, +cylfix and cdfix.

        + +++ + + + + + +
        Parameters :

        translate_units : str

        +
        +

        Do potentially unsafe translations of non-standard unit strings.

        +

        Although "S" is commonly used to represent seconds, its +translation to "s" is potentially unsafe since the standard +recognizes "S" formally as Siemens, however rarely that may be +used. The same applies to "H" for hours (Henry), and "D" +for days (Debye).

        +

        This string controls what to do in such cases, and is +case-insensitive.

        +
          +
        • If the string contains "s", translate "S" to "s".
        • +
        • If the string contains "h", translate "H" to "h".
        • +
        • If the string contains "d", translate "D" to "d".
        • +
        +

        Thus '' doesn’t do any unsafe translations, whereas 'shd' +does all of them.

        +
        +

        naxis : int array[naxis]

        +
        +

        Image axis lengths. If this array is set to zero or None, +then cylfix will not be invoked.

        +
        +
        Returns :

        status : dict

        +
        +

        Returns a dictionary containing the following keys, each referring +to a status string for each of the sub-fix functions that were +called:

        + +
        +
        +
        + +
        +
        +get_cdelt() → double array[naxis]
        +

        Coordinate increments (CDELTia) for each coord axis.

        +

        Returns the CDELT offsets in read-only form. Unlike the +cdelt property, this works even when the header +specifies the linear transformation matrix in one of the deprecated +CDi_ja or CROTAia forms. This is useful when you want access +to the linear transformation matrix, but don’t care how it was +specified in the header.

        +
        + +
        +
        +get_pc() → double array[naxis][naxis]
        +

        Returns the PC matrix in read-only form. Unlike the +pc property, this works even when the header +specifies the linear transformation matrix in one of the deprecated +CDi_ja or CROTAia forms. This is useful when you want access +to the linear transformation matrix, but don’t care how it was +specified in the header.

        +
        + +
        +
        +get_ps() → list of tuples
        +

        Returns PSi_ma keywords for each i and m.

        + +++ + + + +
        Returns :

        ps : list of tuples

        +
        +

        Returned as a list of tuples of the form (i, m, value):

        +
          +
        • i: int. Axis number, as in PSi_ma, (i.e. 1-relative)
        • +
        • m: int. Parameter number, as in PSi_ma, (i.e. 0-relative)
        • +
        • value: string. Parameter value.
        • +
        +
        +
        +
        +

        See also

        +
        +
        astropy.wcs.Wcsprm.set_ps
        +
        Set PSi_ma values
        +
        +
        +
        + +
        +
        +get_pv() → list of tuples
        +

        Returns PVi_ma keywords for each i and m.

        + +++ + + + +
        Returns :

        Returned as a list of tuples of the form (*i*, *m*, *value*): :

        +
        +
          +
        • i: int. Axis number, as in PVi_ma, (i.e. 1-relative)
        • +
        • m: int. Parameter number, as in PVi_ma, (i.e. 0-relative)
        • +
        • value: string. Parameter value.
        • +
        +
        +
        +
        +

        See also

        +
        +
        astropy.wcs.Wcsprm.set_pv
        +
        Set PVi_ma values
        +
        +
        +

        Notes

        +

        Note that, if they were not given, set resets +the entries for PVi_1a, PVi_2a, PVi_3a, and PVi_4a for +longitude axis i to match (phi_0, theta_0), the native +longitude and latitude of the reference point given by LONPOLEa +and LATPOLEa.

        +
        + +
        +
        +has_cd() → bool
        +

        Returns True if CDi_ja is present.

        +

        CDi_ja is an alternate specification of the linear transformation +matrix, maintained for historical compatibility.

        +

        Matrix elements in the IRAF convention are equivalent to the product +CDi_ja = CDELTia * PCi_ja, but the defaults differ from that of +the PCi_ja matrix. If one or more CDi_ja keywords are present +then all unspecified CDi_ja default to zero. If no CDi_ja (or +CROTAia) keywords are present, then the header is assumed to be in +PCi_ja form whether or not any PCi_ja keywords are present +since this results in an interpretation of CDELTia consistent with +the original FITS specification.

        +

        While CDi_ja may not formally co-exist with PCi_ja, it may +co-exist with CDELTia and CROTAia which are to be ignored.

        +
        +

        See also

        +
        +
        astropy.wcs.Wcsprm.cd
        +
        Get the raw CDi_ja values.
        +
        +
        +
        + +
        +
        +has_cdi_ja() → bool
        +

        Alias for has_cd. Maintained for backward +compatibility.

        +
        + +
        +
        +has_crota() → bool
        +

        Returns True if CROTAia is present.

        +

        CROTAia is an alternate specification of the linear transformation +matrix, maintained for historical compatibility.

        +

        In the AIPS convention, CROTAia may only be associated with the +latitude axis of a celestial axis pair. It specifies a rotation in +the image plane that is applied after the CDELTia; any other +CROTAia keywords are ignored.

        +

        CROTAia may not formally co-exist with PCi_ja. CROTAia and +CDELTia may formally co-exist with CDi_ja but if so are to be +ignored.

        +
        +

        See also

        +
        +
        astropy.wcs.Wcsprm.crota
        +
        Get the raw CROTAia values
        +
        +
        +
        + +
        +
        +has_crotaia() → bool
        +

        Alias for has_crota. Maintained for backward +compatibility.

        +
        + +
        +
        +has_pc() → bool
        +

        Returns True if PCi_ja is present. PCi_ja is the +recommended way to specify the linear transformation matrix.

        +
        +

        See also

        +
        +
        astropy.wcs.Wcsprm.pc
        +
        Get the raw PCi_ja values
        +
        +
        +
        + +
        +
        +has_pci_ja() → bool
        +

        Alias for has_pc. Maintained for backward +compatibility.

        +
        + +
        +
        +imgpix_matrix
        +

        double array[2][2] (read-only)

        +

        Inverse of the matrix containing the product of the CDELTia +diagonal matrix and the PCi_ja matrix.

        +
        + +
        +
        +is_unity() → bool
        +

        Returns True if the linear transformation matrix +(cd) is unity.

        +
        + +
        +
        +lat
        +

        int (read-only)

        +

        The index into the sky coordinate array containing latitude values.

        +
        + +
        +
        +latpole
        +

        double

        +

        The native latitude of the celestial pole, LATPOLEa (deg).

        +
        + +
        +
        +lattyp
        +

        string (read-only)

        +

        Celestial axis type for latitude, e.g. “RA”, “DEC”, “GLON”, “GLAT”, +etc. extracted from ‘RA–’, ‘DEC-‘, ‘GLON’, ‘GLAT’, etc. in the first +four characters of CTYPEia but with trailing dashes removed.

        +
        + +
        +
        +lng
        +

        int (read-only)

        +

        The index into the sky coordinate array containing longitude values.

        +
        + +
        +
        +lngtyp
        +

        string (read-only)

        +

        Celestial axis type for longitude, e.g. “RA”, “DEC”, “GLON”, “GLAT”, +etc. extracted from ‘RA–’, ‘DEC-‘, ‘GLON’, ‘GLAT’, etc. in the first +four characters of CTYPEia but with trailing dashes removed.

        +
        + +
        +
        +lonpole
        +

        double

        +

        The native longitude of the celestial pole, LONPOLEa (deg).

        +
        + +
        +
        +mix(mixpix, mixcel, vspan, vstep, viter, world, pixcrd, origin)
        +

        Given either the celestial longitude or latitude plus an element of +the pixel coordinate, solves for the remaining elements by iterating +on the unknown celestial coordinate element using +s2p.

        + +++ + + + + + + + +
        Parameters :

        mixpix : int

        +
        +

        Which element on the pixel coordinate is given.

        +
        +

        mixcel : int

        +
        +

        Which element of the celestial coordinate is given. If mixcel = +1, celestial longitude is given in world[self.lng], +latitude returned in world[self.lat]. If mixcel = 2, +celestial latitude is given in world[self.lat], longitude +returned in world[self.lng].

        +
        +

        vspan : pair of floats

        +
        +

        Solution interval for the celestial coordinate, in degrees. The +ordering of the two limits is irrelevant. Longitude ranges may be +specified with any convenient normalization, for example +(-120,+120) is the same as (240,480), except that the +solution will be returned with the same normalization, i.e. lie +within the interval specified.

        +
        +

        vstep : float

        +
        +

        Step size for solution search, in degrees. If 0, a sensible, +although perhaps non-optimal default will be used.

        +
        +

        viter : int

        +
        +

        If a solution is not found then the step size will be halved and +the search recommenced. viter controls how many times the step +size is halved. The allowed range is 5 - 10.

        +
        +

        world : double array[naxis]

        +
        +

        World coordinate elements. world[self.lng] and +world[self.lat] are the celestial longitude and latitude, in +degrees. Which is given and which returned depends on the value +of mixcel. All other elements are given. The results will be +written to this array in-place.

        +
        +

        pixcrd : double array[naxis].

        +
        +

        Pixel coordinates. The element indicated by mixpix is given and +the remaining elements will be written in-place.

        +
        +

        origin : int

        +
        +

        Specifies the origin of pixel values. The Fortran and FITS +standards use an origin of 1. Numpy and C use array indexing with +origin at 0.

        +
        +
        Returns :

        result : dict

        +
        +

        Returns a dictionary with the following keys:

        +
          +
        • phi (double array[naxis])

          +
        • +
        • theta (double array[naxis])

          +
          +
            +
          • Longitude and latitude in the native coordinate system of +the projection, in degrees.
          • +
          +
          +
        • +
        • imgcrd (double array[naxis])

          +
          +
            +
          • Image coordinate elements. imgcrd[self.lng] and +imgcrd[self.lat] are the projected x- and +y-coordinates, in decimal degrees.
          • +
          +
          +
        • +
        • world (double array[naxis])

          +
          +
            +
          • Another reference to the world argument passed in.
          • +
          +
          +
        • +
        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        SingularMatrixError :

        +
        +

        Linear transformation matrix is singular.

        +
        +

        InconsistentAxisTypesError :

        +
        +

        Inconsistent or unrecognized coordinate axis types.

        +
        +

        ValueError :

        +
        +

        Invalid parameter value.

        +
        +

        InvalidTransformError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        InvalidTransformError :

        +
        +

        Ill-conditioned coordinate transformation parameters.

        +
        +

        InvalidCoordinateError :

        +
        +

        Invalid world coordinate.

        +
        +

        NoSolutionError :

        +
        +

        No solution found in the specified interval.

        +
        +
        + +

        Notes

        +

        Initially, the specified solution interval is checked to see if it’s a +“crossing” interval. If it isn’t, a search is made for a crossing +solution by iterating on the unknown celestial coordinate starting at +the upper limit of the solution interval and decrementing by the +specified step size. A crossing is indicated if the trial value of +the pixel coordinate steps through the value specified. If a crossing +interval is found then the solution is determined by a modified form +of “regula falsi” division of the crossing interval. If no crossing +interval was found within the specified solution interval then a +search is made for a “non-crossing” solution as may arise from a +point of tangency. The process is complicated by having to make +allowance for the discontinuities that occur in all map projections.

        +

        Once one solution has been determined others may be found by +subsequent invocations of mix with suitably +restricted solution intervals.

        +

        Note the circumstance that arises when the solution point lies at a +native pole of a projection in which the pole is represented as a +finite curve, for example the zenithals and conics. In such cases two +or more valid solutions may exist but mix only +ever returns one.

        +

        Because of its generality, mix is very +compute-intensive. For compute-limited applications, more efficient +special-case solvers could be written for simple projections, for +example non-oblique cylindrical projections.

        +
        + +
        +
        +mjdavg
        +

        double

        +

        Modified Julian Date (MJD = JD - 2400000.5), MJD-AVG, +corresponding to DATE-AVG.

        +

        An undefined value is represented by NaN.

        + +
        + +
        +
        +mjdobs
        +

        double

        +

        Modified Julian Date (MJD = JD - 2400000.5), MJD-OBS, +corresponding to DATE-OBS.

        +

        An undefined value is represented by NaN.

        + +
        + +
        +
        +name
        +

        string

        +

        The name given to the coordinate representation WCSNAMEa.

        +
        + +
        +
        +naxis
        +

        int (read-only)

        +

        The number of axes (pixel and coordinate), given by the NAXIS or +WCSAXESa keyvalues.

        +

        The number of coordinate axes is determined at parsing time, and can +not be subsequently changed.

        +

        It is determined from the highest of the following:

        +
        +
          +
        1. NAXIS
        2. +
        3. WCSAXESa
        4. +
        5. The highest axis number in any parameterized WCS keyword. The +keyvalue, as well as the keyword, must be syntactically valid +otherwise it will not be considered.
        6. +
        +
        +

        If none of these keyword types is present, i.e. if the header only +contains auxiliary WCS keywords for a particular coordinate +representation, then no coordinate description is constructed for it.

        +

        This value may differ for different coordinate representations of the +same image.

        +
        + +
        +
        +obsgeo
        +

        double array[3]

        +

        Location of the observer in a standard terrestrial reference frame, +OBSGEO-X, OBSGEO-Y, OBSGEO-Z (in meters).

        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +p2s(pixcrd, origin)
        +

        Converts pixel to sky coordinates.

        + +++ + + + + + + + +
        Parameters :

        pixcrd : double array[ncoord][nelem]

        +
        +

        Array of pixel coordinates.

        +
        +

        origin : int

        +
        +

        Specifies the origin of pixel values. The Fortran and FITS +standards use an origin of 1. Numpy and C use array indexing with +origin at 0.

        +
        +
        Returns :

        result : dict

        +
        +

        Returns a dictionary with the following keys:

        +
          +
        • imgcrd: double array[ncoord][nelem]
            +
          • Array of intermediate sky coordinates. For celestial axes, +imgcrd[][self.lng] and imgcrd[][self.lat] are the +projected x-, and y-coordinates, in pseudo degrees. For +spectral axes, imgcrd[][self.spec] is the intermediate +spectral coordinate, in SI units.
          • +
          +
        • +
        • phi: double array[ncoord]
        • +
        • theta: double array[ncoord]
            +
          • Longitude and latitude in the native coordinate system of the +projection, in degrees.
          • +
          +
        • +
        • world: double array[ncoord][nelem]
            +
          • Array of sky coordinates. For celestial axes, +world[][self.lng] and world[][self.lat] are the +celestial longitude and latitude, in degrees. For spectral +axes, world[][self.spec] is the intermediate spectral +coordinate, in SI units.
          • +
          +
        • +
        • stat: int array[ncoord]
            +
          • Status return value for each coordinate. 0 for success, +1+ for invalid pixel coordinate.
          • +
          +
        • +
        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        SingularMatrixError :

        +
        +

        Linear transformation matrix is singular.

        +
        +

        InconsistentAxisTypesError :

        +
        +

        Inconsistent or unrecognized coordinate axis types.

        +
        +

        ValueError :

        +
        +

        Invalid parameter value.

        +
        +

        ValueError :

        +
        +

        x- and y-coordinate arrays are not the same size.

        +
        +

        InvalidTransformError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        InvalidTransformError :

        +
        +

        Ill-conditioned coordinate transformation parameters.

        +
        +
        + +
        + +
        +
        +pc
        +

        double array[naxis][naxis]

        +

        The PCi_ja (pixel coordinate) transformation matrix. The order is:

        +
        [[PC1_1, PC1_2],
        + [PC2_1, PC2_2]]
        +
        +
        +

        For historical compatibility, three alternate specifications of the +linear transforations are available in wcslib. The canonical +PCi_ja with CDELTia, and the deprecated CDi_ja and +CROTAia keywords. Although the deprecated versions may not +formally co-exist with PCi_ja, the approach here is simply to +ignore them if given in conjunction with PCi_ja.

        +

        has_pc, has_cd and +has_crota can be used to determine which of +these alternatives are present in the header.

        +

        These alternate specifications of the linear transformation matrix are +translated immediately to PCi_ja by set and +are nowhere visible to the lower-level routines. In particular, +set resets cdelt to unity +if CDi_ja is present (and no PCi_ja). If no CROTAia is +associated with the latitude axis, set reverts +to a unity PCi_ja matrix.

        +
        + +
        +
        +phi0
        +

        double

        +

        The native latitude of the fiducial point, i.e. the point whose +celestial coordinates are given in ref[1:2]. If undefined (NaN) +the initialization routine, set, will set this +to a projection-specific default.

        + +
        + +
        +
        +piximg_matrix
        +

        double array[2][2] (read-only)

        +

        Matrix containing the product of the CDELTia diagonal matrix and +the PCi_ja matrix.

        +
        + +
        +
        +print_contents()
        +

        Print the contents of the Wcsprm object to stdout. +Probably only useful for debugging purposes, and may be removed in the +future.

        +

        To get a string of the contents, use repr.

        +
        + +
        +
        +radesys
        +

        string

        +

        The equatorial or ecliptic coordinate system type, RADESYSa.

        +
        + +
        +
        +restfrq
        +

        double

        +

        Rest frequency (Hz) from RESTFRQa.

        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +restwav
        +

        double

        +

        Rest wavelength (m) from RESTWAVa.

        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +s2p(sky, origin)
        +

        Transforms sky coordinates to pixel coordinates.

        + +++ + + + + + + + +
        Parameters :

        sky : double array[ncoord][nelem]

        +
        +

        Array of sky coordinates, in decimal degrees.

        +
        +

        origin : int

        +
        +

        Specifies the origin of pixel values. The Fortran and FITS +standards use an origin of 1. Numpy and C use array indexing with +origin at 0.

        +
        +
        Returns :

        result : dict

        +
        +

        Returns a dictionary with the following keys:

        +
          +
        • phi: double array[ncoord]

          +
        • +
        • theta: double array[ncoord]

          +
          +
            +
          • Longitude and latitude in the native coordinate system of +the projection, in degrees.
          • +
          +
          +
        • +
        • imgcrd: double array[ncoord][nelem]

          +
          +
            +
          • Array of intermediate sky coordinates. For celestial axes, +imgcrd[][self.lng] and imgcrd[][self.lat] are the +projected x-, and y-coordinates, in pseudo “degrees”. +For quadcube projections with a CUBEFACE axis, the face +number is also returned in imgcrd[][self.cubeface]. For +spectral axes, imgcrd[][self.spec] is the intermediate +spectral coordinate, in SI units.
          • +
          +
          +
        • +
        • pixcrd: double array[ncoord][nelem]

          +
          +
            +
          • Array of pixel coordinates. Pixel coordinates are +zero-based.
          • +
          +
          +
        • +
        • stat: int array[ncoord]

          +
          +
            +
          • Status return value for each coordinate. 0 for success, +1+ for invalid pixel coordinate.
          • +
          +
          +
        • +
        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        SingularMatrixError :

        +
        +

        Linear transformation matrix is singular.

        +
        +

        InconsistentAxisTypesError :

        +
        +

        Inconsistent or unrecognized coordinate axis types.

        +
        +

        ValueError :

        +
        +

        Invalid parameter value.

        +
        +

        InvalidTransformError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        InvalidTransformError :

        +
        +

        Ill-conditioned coordinate transformation parameters.

        +
        +
        + +
        + +
        +
        +set()
        +

        Sets up a WCS object for use according to information supplied within +it.

        +

        Note that this routine need not be called directly; it will be invoked +by p2s and s2p if +necessary.

        +

        Some attributes that are based on other attributes (such as +lattyp on ctype) may not +be correct until after set is called.

        +

        set strips off trailing blanks in all string +members.

        +

        set recognizes the NCP projection and +converts it to the equivalent SIN projection and it also +recognizes GLS as a synonym for SFL. It does alias +translation for the AIPS spectral types (FREQ-LSR, FELO-HEL, +etc.) but without changing the input header keywords.

        + +++ + + + +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        SingularMatrixError :

        +
        +

        Linear transformation matrix is singular.

        +
        +

        InconsistentAxisTypesError :

        +
        +

        Inconsistent or unrecognized coordinate axis types.

        +
        +

        ValueError :

        +
        +

        Invalid parameter value.

        +
        +

        InvalidTransformError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        InvalidTransformError :

        +
        +

        Ill-conditioned coordinate transformation parameters.

        +
        +
        +
        + +
        +
        +set_ps(list)
        +

        Sets PSi_ma keywords for each i and m.

        + +++ + + + +
        Parameters :

        ps : sequence of tuples

        +
        +

        The input must be a sequence of tuples of the form (i, m, +value):

        +
          +
        • i: int. Axis number, as in PSi_ma, (i.e. 1-relative)
        • +
        • m: int. Parameter number, as in PSi_ma, (i.e. 0-relative)
        • +
        • value: string. Parameter value.
        • +
        +
        +
        + +
        + +
        +
        +set_pv(list)
        +

        Sets PVi_ma keywords for each i and m.

        + +++ + + + +
        Parameters :

        pv : list of tuples

        +
        +

        The input must be a sequence of tuples of the form (i, m, +value):

        +
          +
        • i: int. Axis number, as in PVi_ma, (i.e. 1-relative)
        • +
        • m: int. Parameter number, as in PVi_ma, (i.e. 0-relative)
        • +
        • value: float. Parameter value.
        • +
        +
        +
        + +
        + +
        +
        +spcfix() → int
        +

        Translates AIPS-convention spectral coordinate types. {FREQ, +VELO, FELO}-{OBS, HEL, LSR} (e.g. FREQ-LSR, +VELO-OBS, FELO-HEL)

        + +++ + + + +
        Returns :

        success : int

        +
        +

        Returns 0 for success; -1 if no change required.

        +
        +
        +
        + +
        +
        +spec
        +

        int (read-only)

        +

        The index containing the spectral axis values.

        +
        + +
        +
        +specsys
        +

        string

        +

        Spectral reference frame (standard of rest), SPECSYSa.

        + +
        + +
        +
        +sptr(ctype, i=-1)
        +

        Translates the spectral axis in a WCS object.

        +

        For example, a FREQ axis may be translated into ZOPT-F2W and +vice versa.

        + +++ + + + + + +
        Parameters :

        ctype : string

        +
        +

        Required spectral CTYPEia, maximum of 8 characters. The first +four characters are required to be given and are never modified. +The remaining four, the algorithm code, are completely determined +by, and must be consistent with, the first four characters. +Wildcarding may be used, i.e. if the final three characters are +specified as "???", or if just the eighth character is +specified as "?", the correct algorithm code will be +substituted and returned.

        +
        +

        i : int

        +
        +

        Index of the spectral axis (0-relative). If i < 0 (or not +provided), it will be set to the first spectral axis identified +from the CTYPE keyvalues in the FITS header.

        +
        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        SingularMatrixError :

        +
        +

        Linear transformation matrix is singular.

        +
        +

        InconsistentAxisTypesError :

        +
        +

        Inconsistent or unrecognized coordinate axis types.

        +
        +

        ValueError :

        +
        +

        Invalid parameter value.

        +
        +

        InvalidTransformError :

        +
        +

        Invalid coordinate transformation parameters.

        +
        +

        InvalidTransformError :

        +
        +

        Ill-conditioned coordinate transformation parameters.

        +
        +

        InvalidSubimageSpecificationError :

        +
        +

        Invalid subimage specification (no spectral axis).

        +
        +
        +
        + +
        +
        +ssysobs
        +

        string

        +

        The actual spectral reference frame in which there is no differential +variation in the spectral coordinate across the field-of-view, +SSYSOBSa.

        + +
        + +
        +
        +ssyssrc
        +

        string

        +

        The spectral reference frame (standard of rest) in which the redshift +was measured, SSYSSRCa.

        +
        + +
        +
        +sub(axes)
        +

        Extracts the coordinate description for a subimage from a +WCS object.

        +

        The world coordinate system of the subimage must be separable in the +sense that the world coordinates at any point in the subimage must +depend only on the pixel coordinates of the axes extracted. In +practice, this means that the PCi_ja matrix of the original image +must not contain non-zero off-diagonal terms that associate any of the +subimage axes with any of the non-subimage axes.

        + +++ + + + + + + + +
        Parameters :

        axes : int or a sequence.

        +
        +
          +
        • If an int, include the first N axes in their original order.
        • +
        • If a sequence, may contain a combination of image axis numbers +(1-relative) or special axis identifiers (see below). Order is +significant; axes[0] is the axis number of the input image +that corresponds to the first axis in the subimage, etc.
        • +
        • If 0, [] or None, do a deep copy.
        • +
        +

        Coordinate axes types may be specified using either strings or +special integer constants. The available types are:

        +
          +
        • 'longitude' / WCSSUB_LONGITUDE: Celestial longitude
        • +
        • 'latitude' / WCSSUB_LATITUDE: Celestial latitude
        • +
        • 'cubeface' / WCSSUB_CUBEFACE: Quadcube CUBEFACE axis
        • +
        • 'spectral' / WCSSUB_SPECTRAL: Spectral axis
        • +
        • 'stokes' / WCSSUB_STOKES: Stokes axis
        • +
        • 'celestial' / WCSSUB_CELESTIAL: An alias for the +combination of 'longitude', 'latitude' and 'cubeface'.
        • +
        +
        +
        Returns :

        new_wcs : WCS object

        +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        InvalidSubimageSpecificationError :

        +
        +

        Invalid subimage specification (no spectral axis).

        +
        +

        NonseparableSubimageCoordinateSystem :

        +
        +

        Non-separable subimage coordinate system.

        +
        +
        +

        Notes

        +

        Combinations of subimage axes of particular types may be extracted in +the same order as they occur in the input image by combining the +integer constants with the ‘binary or’ (|) operator. For +example:

        +
        wcs.sub([WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_SPECTRAL])
        +
        +
        +

        would extract the longitude, latitude, and spectral axes in the same +order as the input image. If one of each were present, the resulting +object would have three dimensions.

        +

        For convenience, WCSSUB_CELESTIAL is defined as the combination +WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_CUBEFACE.

        +

        The codes may also be negated to extract all but the types specified, +for example:

        +
        wcs.sub([
        +  WCSSUB_LONGITUDE,
        +  WCSSUB_LATITUDE,
        +  WCSSUB_CUBEFACE,
        +  -(WCSSUB_SPECTRAL | WCSSUB_STOKES)])
        +
        +
        +

        The last of these specifies all axis types other than spectral or +Stokes. Extraction is done in the order specified by axes, i.e. a +longitude axis (if present) would be extracted first (via axes[0]) +and not subsequently (via axes[3]). Likewise for the latitude and +cubeface axes in this example.

        +

        The number of dimensions in the returned object may be less than or +greater than the length of axes. However, it will never exceed the +number of axes in the input image.

        +
        + +
        +
        +tab
        +

        list of Tabprm

        +

        A list of tabular coordinate objects associated with this WCS.

        +
        + +
        +
        +theta0
        +

        double

        +

        The native longitude of the fiducial point, i.e. the point whose +celestial coordinates are given in ref[1:2]. If undefined (NaN) +the initialization routine, set, will set this +to a projection-specific default.

        + +
        + +
        +
        +to_header(relax=False)
        +

        to_header translates a WCS object into a FITS header.

        +

        The details of the header depends on context:

        +
        +
          +
        • If the colnum member is non-zero then a +binary table image array header will be produced.
        • +
        • Otherwise, if the colax member is set +non-zero then a pixel list header will be produced.
        • +
        • Otherwise, a primary image or image extension header will be +produced.
        • +
        +
        +

        The output header will almost certainly differ from the input in a +number of respects:

        +
        +
          +
        1. The output header only contains WCS-related keywords. In +particular, it does not contain syntactically-required keywords +such as SIMPLE, NAXIS, BITPIX, or END.
        2. +
        3. Deprecated (e.g. CROTAn) or non-standard usage will be +translated to standard (this is partially dependent on whether +fix was applied).
        4. +
        5. Quantities will be converted to the units used internally, +basically SI with the addition of degrees.
        6. +
        7. Floating-point quantities may be given to a different decimal +precision.
        8. +
        9. Elements of the PCi_j matrix will be written if and only if +they differ from the unit matrix. Thus, if the matrix is unity +then no elements will be written.
        10. +
        11. Additional keywords such as WCSAXES, CUNITia, +LONPOLEa and LATPOLEa may appear.
        12. +
        13. The original keycomments will be lost, although +to_header tries hard to write meaningful +comments.
        14. +
        15. Keyword order may be changed.
        16. +
        +
        +

        Keywords can be translated between the image array, binary table, and +pixel lists forms by manipulating the colnum or +colax members of the WCS +object.

        + +++ + + + + + +
        Parameters :

        relax : bool or int

        +
        +

        Degree of permissiveness:

        +
          +
        • False: Recognize only FITS keywords defined by the published +WCS standard.
        • +
        • True: Admit all recognized informal extensions of the WCS +standard.
        • +
        • int: a bit field selecting specific extensions to write. +See Header-writing relaxation constants for details.
        • +
        +
        +
        Returns :

        header : str

        +
        +

        Raw FITS header as a string.

        +
        +
        +
        + +
        +
        +unitfix(translate_units='')
        +

        Translates non-standard CUNITia keyvalues.

        +

        For example, DEG -> deg, also stripping off unnecessary +whitespace.

        + +++ + + + + + +
        Parameters :

        translate_units : string, optional

        +
        +

        Do potentially unsafe translations of non-standard unit strings.

        +

        Although "S" is commonly used to represent seconds, its +recognizes "S" formally as Siemens, however rarely that may +be translation to "s" is potentially unsafe since the +standard used. The same applies to "H" for hours (Henry), +and "D" for days (Debye).

        +

        This string controls what to do in such cases, and is +case-insensitive.

        +
          +
        • If the string contains "s", translate "S" to "s".
        • +
        • If the string contains "h", translate "H" to "h".
        • +
        • If the string contains "d", translate "D" to "d".
        • +
        +

        Thus '' doesn’t do any unsafe translations, whereas 'shd' +does all of them.

        +

        See FITS unit specification for more information.

        +
        +
        Returns :

        success : int

        +
        +

        Returns 0 for success; -1 if no change required.

        +
        +
        +
        + +
        +
        +velangl
        +

        double

        +

        The angle in degrees that should be used to decompose an observed +velocity into radial and transverse components.

        +

        An undefined value is represented by NaN.

        +
        + +
        +
        +velosys
        +

        double

        +

        The relative radial velocity (m/s) between the observer and the +selected standard of rest in the direction of the celestial reference +coordinate, VELOSYSa.

        +

        An undefined value is represented by NaN.

        + +
        + +
        +
        +zsource
        +

        double

        +

        The redshift, ZSOURCEa, of the source.

        +

        An undefined value is represented by NaN.

        +
        + +
        + +
        +
        +

        Tabprm

        +
        +
        +class astropy.wcs._wcs.Tabprm
        +

        A class to store the information related to tabular coordinates, +i.e. coordinates that are defined via a lookup table.

        +

        This class can not be constructed directly from Python, but instead is +returned from tab.

        +
        +
        +K
        +

        int array[M] (read-only)

        +

        An array of length M whose elements record the lengths of the axes of +the coordinate array and of each indexing vector.

        +
        + +
        +
        +M
        +

        int (read-only)

        +

        Number of tabular coordinate axes.

        +
        + +
        +
        +coord
        +

        double array[K_M]...[K_2][K_1][M]

        +

        The tabular coordinate array, with the dimensions:

        +
        (K_M, ... K_2, K_1, M)
        +
        +

        (see K) i.e. with the M dimension +varying fastest so that the M elements of a coordinate vector are +stored contiguously in memory.

        +
        + +
        +
        +crval
        +

        double array[M]

        +

        Array whose elements contain the index value for the reference pixel +for each of the tabular coordinate axes.

        +
        + +
        +
        +delta
        +

        double array[M] (read-only)

        +

        Array of interpolated indices into the coordinate array such that +Upsilon_m, as defined in Paper III, is equal to +(p0 [m] + 1) + delta[m].

        +
        + +
        +
        +extrema
        +

        double array[K_M]...[K_2][2][M] (read-only)

        +

        An array recording the minimum and maximum value of each element of +the coordinate vector in each row of the coordinate array, with the +dimensions:

        +
        (K_M, ... K_2, 2, M)
        +
        +

        (see K). The minimum is recorded +in the first element of the compressed K_1 dimension, then the +maximum. This array is used by the inverse table lookup function to +speed up table searches.

        +
        + +
        +
        +map
        +

        int array[M]

        +

        A vector of length M that defines +the association between axis m in the M-dimensional coordinate +array (1 <= m <= M) and the indices of the intermediate world +coordinate and world coordinate arrays.

        +

        When the intermediate and world coordinate arrays contain the full +complement of coordinate elements in image-order, as will usually be +the case, then map[m-1] == i-1 for axis i in the N-dimensional +image (1 <= i <= N). In terms of the FITS keywords:

        +
        map[PVi_3a - 1] == i - 1.
        +
        +
        +

        However, a different association may result if the intermediate +coordinates, for example, only contains a (relevant) subset of +intermediate world coordinate elements. For example, if M == 1 for +an image with N > 1, it is possible to fill the intermediate +coordinates with the relevant coordinate element with nelem set to +1. In this case map[0] = 0 regardless of the value of i.

        +
        + +
        +
        +nc
        +

        int (read-only)

        +

        Total number of coordinate vectors in the coordinate array being the +product K_1 * K_2 * ... * K_M.

        +
        + +
        +
        +p0
        +

        int array[M]

        +

        Vector of length M of interpolated +indices into the coordinate array such that Upsilon_m, as defined in +Paper III, is equal to (p0[m] + 1) + delta[m].

        +
        + +
        +
        +print_contents()
        +

        Print the contents of the Tabprm object to +stdout. Probably only useful for debugging purposes, and may be +removed in the future.

        +

        To get a string of the contents, use repr.

        +
        + +
        +
        +sense
        +

        int array[M]

        +

        A vector of length M whose elements +indicate whether the corresponding indexing vector is monotonically +increasing (+1), or decreasing (-1).

        +
        + +
        +
        +set()
        +

        Allocates memory for work arrays in the Tabprm class and sets up +the class according to information supplied within it.

        +

        Note that this routine need not be called directly; it will be invoked by +functions that need it.

        + +++ + + + +
        Raises :

        MemoryError :

        +
        +

        Memory allocation failed.

        +
        +

        InvalidTabularParameters :

        +
        +

        Invalid tabular parameters.

        +
        +
        +
        + +
        + +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        WCS

        +

        Next topic

        +

        DistortionLookupTable

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/examples.html b/wcs/examples.html new file mode 100644 index 00000000..7b732af5 --- /dev/null +++ b/wcs/examples.html @@ -0,0 +1,240 @@ + + + + + + + + + + Example Usage — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Example Usage

        +
        +

        Loading WCS information from a FITS file

        +

        This example loads a FITS file (supplied on the commandline) and uses +the WCS cards in its primary header to transform.

        +
        # Load the WCS information from a fits header, and use it
        +# to convert pixel coordinates to world coordinates.
        +
        +from __future__ import division # confidence high
        +
        +import numpy
        +from astropy import wcs
        +import pyfits
        +import sys
        +
        +# Load the FITS hdulist using pyfits
        +hdulist = pyfits.open(sys.argv[-1])
        +
        +# Parse the WCS keywords in the primary HDU
        +w = wcs.WCS(hdulist[0].header)
        +
        +# Print out the "name" of the WCS, as defined in the FITS header
        +print w.wcs.name
        +
        +# Print out all of the settings that were parsed from the header
        +w.wcs.print_contents()
        +
        +# Some pixel coordinates of interest.
        +pixcrd = numpy.array([[0,0],[24,38],[45,98]], numpy.float_)
        +
        +# Convert pixel coordinates to world coordinates
        +# The second argument is "origin" -- in this case we're declaring we
        +# have 1-based (Fortran-like) coordinates.
        +sky = w.wcs_pix2sky(pixcrd, 1)
        +print sky
        +
        +# Convert the same coordinates back to pixel coordinates.
        +pixcrd2 = w.wcs_sky2pix(sky, 1)
        +print pixcrd2
        +
        +# These should be the same as the original pixel coordinates, modulo
        +# some floating-point error.
        +assert numpy.max(numpy.abs(pixcrd - pixcrd2)) < 1e-6
        +
        +
        +
        +
        +

        Building a WCS structure programmatically

        +

        This example, rather than starting from a FITS header, sets WCS values +programmatically, uses those settings to transform some points, and then +saves those settings to a new FITS header.

        +
        # Set the WCS information manually by setting properties of the WCS
        +# object.
        +
        +from __future__ import division # confidence high
        +
        +import numpy
        +from astropy import wcs
        +import pyfits
        +import sys
        +
        +# Create a new WCS object.  The number of axes must be set
        +# from the start
        +w = wcs.WCS(naxis=2)
        +
        +# Set up an "Airy's zenithal" projection
        +# Vector properties may be set with Python lists, or Numpy arrays
        +w.wcs.crpix = [-234.75, 8.3393]
        +w.wcs.cdelt = numpy.array([-0.066667, 0.066667])
        +w.wcs.crval = [0, -90]
        +w.wcs.ctype = ["RA---AIR", "DEC--AIR"]
        +w.wcs.set_pv([(2, 1, 45.0)])
        +
        +# Print out all of the contents of the WCS object
        +w.wcs.print_contents()
        +
        +# Some pixel coordinates of interest.
        +pixcrd = numpy.array([[0,0],[24,38],[45,98]], numpy.float_)
        +
        +# Convert pixel coordinates to world coordinates
        +world = w.wcs_pix2sky(pixcrd, 1)
        +print world
        +
        +# Convert the same coordinates back to pixel coordinates.
        +pixcrd2 = w.wcs_sky2pix(world, 1)
        +print pixcrd2
        +
        +# These should be the same as the original pixel coordinates, modulo
        +# some floating-point error.
        +assert numpy.max(numpy.abs(pixcrd - pixcrd2)) < 1e-6
        +
        +# Now, write out the WCS object as a FITS header
        +header = w.to_header()
        +
        +# header is a PyFITS Header object.  We can use it to create a new
        +# PrimaryHDU and write it to a file.
        +hdu = pyfits.PrimaryHDU(header=header)
        +hdu.writeto('test.fits')
        +
        +
        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        astropy.wcs Documentation

        +

        Next topic

        +

        API Documentation

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/history.html b/wcs/history.html new file mode 100644 index 00000000..1982400f --- /dev/null +++ b/wcs/history.html @@ -0,0 +1,227 @@ + + + + + + + + + + astropy.wcs History — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.wcs History

        +

        astropy.wcs began life as pywcs. Earlier version numbers refer to +that package.

        +
        +

        pywcs Version 1.11

        +
          +
        • Updated to wcslib version 4.8, which gives much more detailed error +messages.
        • +
        • Added functions get_pc() and get_cdelt(). These provide a way to +always get the canonical representation of the linear transformation +matrix, whether the header specified it in PC, CD or CROTA form.
        • +
        • Long-running process will now release the Python GIL to better +support Python multithreading.
        • +
        • The dimensions of the cd and +pc matrices were always returned as 2x2. They +now are sized according to naxis.
        • +
        • Supports Python 3.x
        • +
        • Builds on Microsoft Windows without severely patching wcslib.
        • +
        • Lots of new unit tests
        • +
        • pywcs will now run without pyfits, though the SIP and distortion +lookup table functionality is unavailable.
        • +
        • Setting cunit will now verify that the values +are valid unit strings.
        • +
        +
        +
        +

        pywcs Version 1.10

        +
          +
        • Adds a UnitConversion class, which gives access to wcslib’s unit +conversion functionality. Given two convertible unit strings, pywcs +can convert arrays of values from one to the other.
        • +
        • Now uses wcslib 4.7
        • +
        • Changes to some wcs values would not always calculate secondary values.
        • +
        +
        +
        +

        pywcs Version 1.9

        +
          +
        • Support binary image arrays and pixel list format WCS by presenting +a way to call wcslib’s wcsbth()

          +
        • +
        • Updated underlying wcslib to version 4.5, which fixes the following:

          +
          +
            +
          • Fixed the interpretation of VELREF when translating +AIPS-convention spectral types. Such translation is now handled +by a new special- purpose function, spcaips(). The wcsprm +struct has been augmented with an entry for velref which is +filled by wcspih() and wcsbth(). Previously, selection by +VELREF of the radio or optical velocity convention for type VELO +was not properly handled.
          • +
          +
          +
        • +
        +
        +

        Bugs

        +
          +
        • The pc member is now available with a default +raw Wcsprm object.
        • +
        • Make properties that return arrays read-only, since modifying a +(mutable) array could result in secondary values not being +recomputed based on those changes.
        • +
        • float properties can now be set using int values
        • +
        +
        +
        +
        +

        pywcs Version 1.3a1

        +

        Earlier versions of pywcs had two versions of every conversion method:

        +
        X(...)      -- treats the origin of pixel coordinates at (0, 0)
        +X_fits(...) -- treats the origin of pixel coordinates at (1, 1)
        +
        +

        From version 1.3 onwards, there is only one method for each +conversion, with an ‘origin’ argument:

        +
        +
          +
        • 0: places the origin at (0, 0), which is the C/Numpy convention.
        • +
        • 1: places the origin at (1, 1), which is the Fortran/FITS +convention.
        • +
        +
        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        Relax constants

        +

        Next topic

        +

        astropy.io.vo Documentation

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/index.html b/wcs/index.html new file mode 100644 index 00000000..e0e0b8ff --- /dev/null +++ b/wcs/index.html @@ -0,0 +1,193 @@ + + + + + + + + + + astropy.wcs Documentation — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        astropy.wcs Documentation

        +

        Python wrappers, SIP, Paper IV support (BSD License):

        +
        +

        Michael Droettboom, Nadia Dencheva

        +

        Space Telescope Science Institute

        +
        +

        wcslib (LGPL License):

        +
        +

        Mark Calabretta

        +

        Australia Telescope National Facility, CSIRO (wcslib)

        +
        +

        astropy.wcs provides transformations following the SIP conventions, +Paper IV table lookup distortion, and the core WCS functionality +provided by wcslib. Each of these transformations can be used +independently or together in a standard pipeline.

        +

        The basic workflow is as follows:

        +
        +
          +
        1. from astropy import wcs
        2. +
        3. Call the wcs.WCS constructor with a pyfits header +and/or hdulist object.
        4. +
        5. Optionally, if the FITS file uses any deprecated or +non-standard features, you may need to call one of the +fix methods on the object.
        6. +
        7. Use one of the following transformation methods:
            +
          • all_pix2sky: Perform all three transformations from +pixel to sky coordinates.
          • +
          • wcs_pix2sky: Perform just the core WCS transformation +from pixel to sky coordinates.
          • +
          • wcs_sky2pix: Perform just the core WCS transformation +from sky to pixel coordinates.
          • +
          • sip_pix2foc: Convert from pixel to focal plane +coordinates using the SIP polynomial coefficients.
          • +
          • sip_foc2pix: Convert from focal plane to pixel +coordinates using the SIP polynomial coefficients.
          • +
          • p4_pix2foc: Convert from pixel to focal plane +coordinates using the table lookup distortion method +described in Paper IV.
          • +
          • det2im: Convert from detector coordinates to image +coordinates. Commonly used for narrow column correction.
          • +
          +
        8. +
        +
        +

        Contents:

        + +
        + + +
        +
        +
        +
        +
        + +

        Previous topic

        +

        Configuration system Documentation

        +

        Next topic

        +

        Example Usage

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file diff --git a/wcs/relax.html b/wcs/relax.html new file mode 100644 index 00000000..c53e74c6 --- /dev/null +++ b/wcs/relax.html @@ -0,0 +1,493 @@ + + + + + + + + + + Relax constants — Astropy 0.0.dev664 documentation + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + +
        +

        Relax constants

        +
        +

        Header-reading relaxation constants

        +

        WCS, Wcsprm and +find_all_wcs have a relax argument, which may be +either True, False or an int.

        +
          +
        • If True, all non-standard WCS extensions recognized by the parser +will be handled.

          +
        • +
        • If False (default), none of the extensions (even those in the +errata) will be handled. Non-conformant keywords will be handled in +the same way as non-WCS keywords in the header, i.e. by simply +ignoring them.

          +
        • +
        • If an int, is is a bit field to provide fine-grained control over +what non-standard WCS keywords to accept. The flag bits are subject +to change in future and should be set by using the constants +beginning with WCSHDR_ in the astropy.wcs module.

          +

          For example, to accept CD00i00j and PC00i00j use:

          +
          relax = astropy.wcs.WCSHDR_CD00i00j | astropy.wcs.WCSHDR_PC00i00j
          +
          +
          +

          The parser always treats EPOCH as subordinate to EQUINOXa if +both are present, and VSOURCEa is always subordinate to +ZSOURCEa.

          +

          Likewise, VELREF is subordinate to the formalism of WCS Paper +III.

          +
        • +
        +

        The flag bits are:

        +
          +
        • WCSHDR_none: Don’t accept any extensions (not even those in the +errata). Treat non-conformant keywords in the same way as non-WCS +keywords in the header, i.e. simply ignore them. (This is +equivalent to the default behavior or passing False)

          +
        • +
        • WCSHDR_all: Accept all extensions recognized by the parser. (This +is equivalent to passing True).

          +
        • +
        • WCSHDR_CROTAia: Accept CROTAia, iCROTna, TCROTna

          +
        • +
        • WCSHDR_EPOCHa: Accept EPOCHa.

          +
        • +
        • WCSHDR_VELREFa: Accept VELREFa.

          +
          +

          The constructor always recognizes the AIPS-convention +keywords, CROTAn, EPOCH, and VELREF for the +primary representation (a = ' ') but alternates are +non-standard.

          +

          The constructor accepts EPOCHa and VELREFa only if +WCSHDR_AUXIMG is also enabled.

          +
          +
        • +
        • WCSHDR_CD00i00j: Accept CD00i00j.

          +
        • +
        • WCSHDR_PC00i00j: Accept PC00i00j.

          +
        • +
        • WCSHDR_PROJPn: Accept PROJPn

          +
          +

          These appeared in early drafts of WCS Paper I+II (before they +were split) and are equivalent to CDi_ja, PCi_ja, and +PVi_ma for the primary representation (a = ' '). +PROJPn is equivalent to PVi_ma with m = n <= +9, and is associated exclusively with the latitude axis.

          +
          +
        • +
        • +
          WCSHDR_RADECSYS: Accept RADECSYS. This appeared in early
          +

          drafts of WCS Paper I+II and was subsequently replaced by +RADESYSa. The construtor accepts RADECSYS only if +WCSHDR_AUXIMG is also enabled.

          +
          +
          +
        • +
        • WCSHDR_VSOURCE: Accept VSOURCEa or VSOUna. This appeared +in early drafts of WCS Paper III and was subsequently dropped in +favour of ZSOURCEa and ZSOUna. The constructor accepts +VSOURCEa only if WCSHDR_AUXIMG is also enabled.

          +
        • +
        • WCSHDR_DOBSn: Allow DOBSn, the column-specific analogue of +DATE-OBS. By an oversight this was never formally defined in +the standard.

          +
        • +
        • WCSHDR_LONGKEY: Accept long forms of the alternate binary table +and pixel list WCS keywords, i.e. with “a” non- blank. +Specifically:

          +
          jCRPXna  TCRPXna  :  jCRPXn  jCRPna  TCRPXn  TCRPna  CRPIXja
          +   -     TPCn_ka  :    -     ijPCna    -     TPn_ka  PCi_ja
          +   -     TCDn_ka  :    -     ijCDna    -     TCn_ka  CDi_ja
          +iCDLTna  TCDLTna  :  iCDLTn  iCDEna  TCDLTn  TCDEna  CDELTia
          +iCUNIna  TCUNIna  :  iCUNIn  iCUNna  TCUNIn  TCUNna  CUNITia
          +iCTYPna  TCTYPna  :  iCTYPn  iCTYna  TCTYPn  TCTYna  CTYPEia
          +iCRVLna  TCRVLna  :  iCRVLn  iCRVna  TCRVLn  TCRVna  CRVALia
          +iPVn_ma  TPVn_ma  :    -     iVn_ma    -     TVn_ma  PVi_ma
          +iPSn_ma  TPSn_ma  :    -     iSn_ma    -     TSn_ma  PSi_ma
          +
          +

          where the primary and standard alternate forms together with the +image-header equivalent are shown rightwards of the colon.

          +

          The long form of these keywords could be described as quasi- +standard. TPCn_ka, iPVn_ma, and TPVn_ma appeared by +mistake in the examples in WCS Paper II and subsequently these and +also TCDn_ka, iPSn_ma and TPSn_ma were legitimized by +the errata to the WCS papers.

          +

          Strictly speaking, the other long forms are non-standard and in fact +have never appeared in any draft of the WCS papers nor in the +errata. However, as natural extensions of the primary form they are +unlikely to be written with any other intention. Thus it should be +safe to accept them provided, of course, that the resulting keyword +does not exceed the 8-character limit.

          +

          If WCSHDR_CNAMn is enabled then also accept:

          +
          iCNAMna  TCNAMna  :   ---   iCNAna    ---   TCNAna  CNAMEia
          +iCRDEna  TCRDEna  :   ---   iCRDna    ---   TCRDna  CRDERia
          +iCSYEna  TCSYEna  :   ---   iCSYna    ---   TCSYna  CSYERia
          +
          +

          Note that CNAMEia, CRDERia, CSYERia, and their variants +are not used by astropy.wcs but are stored as auxiliary information.

          +
        • +
        • WCSHDR_CNAMn: Accept iCNAMn, iCRDEn, iCSYEn, +TCNAMn, TCRDEn, and TCSYEn, i.e. with a blank. +While non-standard, these are the obvious analogues of iCTYPn, +TCTYPn, etc.

          +
        • +
        • WCSHDR_AUXIMG: Allow the image-header form of an auxiliary WCS +keyword with representation-wide scope to provide a default value +for all images. This default may be overridden by the +column-specific form of the keyword.

          +

          For example, a keyword like EQUINOXa would apply to all image +arrays in a binary table, or all pixel list columns with alternate +representation a unless overridden by EQUIna.

          +

          Specifically the keywords are:

          +
          LATPOLEa  for LATPna
          +LONPOLEa  for LONPna
          +RESTFREQ  for RFRQna
          +RESTFRQa  for RFRQna
          +RESTWAVa  for RWAVna
          +
          +

          whose keyvalues are actually used by WCSLIB, and also keywords that +provide auxiliary information that is simply stored in the wcsprm +struct:

          +
          EPOCH         -       ... (No column-specific form.)
          +EPOCHa        -       ... Only if WCSHDR_EPOCHa is set.
          +EQUINOXa  for EQUIna
          +RADESYSa  for RADEna
          +RADECSYS  for RADEna  ... Only if WCSHDR_RADECSYS is set.
          +SPECSYSa  for SPECna
          +SSYSOBSa  for SOBSna
          +SSYSSRCa  for SSRCna
          +VELOSYSa  for VSYSna
          +VELANGLa  for VANGna
          +VELREF        -       ... (No column-specific form.)
          +VELREFa       -       ... Only if WCSHDR_VELREFa is set.
          +VSOURCEa  for VSOUna  ... Only if WCSHDR_VSOURCE is set.
          +WCSNAMEa  for WCSNna  ... Or TWCSna (see below).
          +ZSOURCEa  for ZSOUna
          +
          +DATE-AVG  for DAVGn
          +DATE-OBS  for DOBSn
          +MJD-AVG   for MJDAn
          +MJD-OBS   for MJDOBn
          +OBSGEO-X  for OBSGXn
          +OBSGEO-Y  for OBSGYn
          +OBSGEO-Z  for OBSGZn
          +
          +

          where the image-header keywords on the left provide default values +for the column specific keywords on the right.

          +

          Keywords in the last group, such as MJD-OBS, apply to all +alternate representations, so MJD-OBS would provide a default +value for all images in the header.

          +

          This auxiliary inheritance mechanism applies to binary table image +arrays and pixel lists alike. Most of these keywords have no +default value, the exceptions being LONPOLEa and LATPOLEa, +and also RADESYSa and EQUINOXa which provide defaults for +each other. Thus the only potential difficulty in using +WCSHDR_AUXIMG is that of erroneously inheriting one of these four +keywords.

          +

          Unlike WCSHDR_ALLIMG, the existence of one (or all) of these +auxiliary WCS image header keywords will not by itself cause a +Wcsprm object to be created for alternate +representation a. This is because they do not provide +sufficient information to create a non-trivial coordinate +representation when used in conjunction with the default values of +those keywords, such as CTYPEia, that are parameterized by axis +number.

          +
        • +
        • WCSHDR_ALLIMG: Allow the image-header form of all image header +WCS keywords to provide a default value for all image arrays in a +binary table (n.b. not pixel list). This default may be overridden +by the column-specific form of the keyword.

          +

          For example, a keyword like CRPIXja would apply to all image +arrays in a binary table with alternate representation a +unless overridden by jCRPna.

          +

          Specifically the keywords are those listed above for WCSHDR_AUXIMG +plus:

          +
          WCSAXESa  for WCAXna
          +
          +

          which defines the coordinate dimensionality, and the following +keywords which are parameterized by axis number:

          +
          CRPIXja   for jCRPna
          +PCi_ja    for ijPCna
          +CDi_ja    for ijCDna
          +CDELTia   for iCDEna
          +CROTAi    for iCROTn
          +CROTAia        -      ... Only if WCSHDR_CROTAia is set.
          +CUNITia   for iCUNna
          +CTYPEia   for iCTYna
          +CRVALia   for iCRVna
          +PVi_ma    for iVn_ma
          +PSi_ma    for iSn_ma
          +
          +CNAMEia   for iCNAna
          +CRDERia   for iCRDna
          +CSYERia   for iCSYna
          +
          +

          where the image-header keywords on the left provide default values +for the column specific keywords on the right.

          +

          This full inheritance mechanism only applies to binary table image +arrays, not pixel lists, because in the latter case there is no +well-defined association between coordinate axis number and column +number.

          +

          Note that CNAMEia, CRDERia, CSYERia, and their variants +are not used by pywcs but are stored in the Wcsprm +object as auxiliary information.

          +

          Note especially that at least one Wcsprm object will +be returned for each a found in one of the image header keywords +listed above:

          +
          +
            +
          • If the image header keywords for a are not inherited by +a binary table, then the struct will not be associated with any +particular table column number and it is up to the user to +provide an association.
          • +
          • If the image header keywords for a are inherited by a +binary table image array, then those keywords are considered to +be “exhausted” and do not result in a separate +Wcsprm object.
          • +
          +
          +
        • +
        +
        +
        +

        Header-writing relaxation constants

        +

        to_header and to_header_string +has a relax argument which may be either True, False or an +int.

        +
          +
        • If True, write all recognized extensions.
        • +
        • If False (default), none of the extensions (even those in the +errata) will be written.
        • +
        • If an int, is is a bit field to provide fine-grained control over +what non-standard WCS keywords to accept. The flag bits are subject +to change in future and should be set by using the constants +beginning with WCSHDO_ in the astropy.wcs module.
        • +
        +

        The flag bits are:

        +
          +
        • WCSHDO_none: Don’t use any extensions.

          +
        • +
        • WCSHDO_all: Write all recognized extensions, equivalent to setting +each flag bit.

          +
        • +
        • WCSHDO_safe: Write all extensions that are considered to be safe +and recommended.

          +
        • +
        • WCSHDO_DOBSn: Write DOBSn, the column-specific analogue of +DATE-OBS for use in binary tables and pixel lists. WCS Paper +III introduced DATE-AVG and DAVGn but by an oversight +DOBSn (the obvious analogy) was never formally defined by the +standard. The alternative to using DOBSn is to write +DATE-OBS which applies to the whole table. This usage is +considered to be safe and is recommended.

          +
        • +
        • WCSHDO_TPCn_ka: WCS Paper I defined

          +
            +
          • TPn_ka and TCn_ka for pixel lists

            +

            but WCS Paper II uses TPCn_ka in one example and subsequently +the errata for the WCS papers legitimized the use of

            +
          • +
          • TPCn_ka and TCDn_ka for pixel lists

            +

            provided that the keyword does not exceed eight characters. This +usage is considered to be safe and is recommended because of the +non-mnemonic terseness of the shorter forms.

            +
          • +
          +
        • +
        • WCSHDO_PVn_ma: WCS Paper I defined

          +
            +
          • iVn_ma and iSn_ma for bintables and

            +
          • +
          • TVn_ma and TSn_ma for pixel lists

            +

            but WCS Paper II uses iPVn_ma and TPVn_ma in the examples +and subsequently the errata for the WCS papers legitimized the use +of

            +
          • +
          • iPVn_ma and iPSn_ma for bintables and

            +
          • +
          • TPVn_ma and TPSn_ma for pixel lists

            +

            provided that the keyword does not exceed eight characters. This +usage is considered to be safe and is recommended because of the +non-mnemonic terseness of the shorter forms.

            +
          • +
          +
        • +
        • WCSHDO_CRPXna: For historical reasons WCS Paper I defined

          +
            +
          • jCRPXn, iCDLTn, iCUNIn, iCTYPn, and iCRVLn for +bintables and

            +
          • +
          • TCRPXn, TCDLTn, TCUNIn, TCTYPn, and TCRVLn for +pixel lists

            +

            for use without an alternate version specifier. However, because +of the eight-character keyword constraint, in order to accommodate +column numbers greater than 99 WCS Paper I also defined

            +
          • +
          • jCRPna, iCDEna, iCUNna, iCTYna and iCRVna for +bintables and

            +
          • +
          • TCRPna, TCDEna, TCUNna, TCTYna and TCRVna for +pixel lists

            +

            for use with an alternate version specifier (the a). Like the +PC, CD, PV, and PS keywords there is an obvious +tendency to confuse these two forms for column numbers up to 99. +It is very unlikely that any parser would reject keywords in the +first set with a non-blank alternate version specifier so this +usage is considered to be safe and is recommended.

            +
          • +
          +
        • +
        • WCSHDO_CNAMna: WCS Papers I and III defined

          +
            +
          • iCNAna, iCRDna, and iCSYna for bintables and

            +
          • +
          • TCNAna, TCRDna, and TCSYna for pixel lists

            +

            By analogy with the above, the long forms would be

            +
          • +
          • iCNAMna, iCRDEna, and iCSYEna for bintables and

            +
          • +
          • TCNAMna, TCRDEna, and TCSYEna for pixel lists

            +

            Note that these keywords provide auxiliary information only, none +of them are needed to compute world coordinates. This usage is +potentially unsafe and is not recommended at this time.

            +
          • +
          +
        • +
        • WCSHDO_WCSNna: Write WCSNna instead of TWCSna for pixel +lists. While the constructor treats WCSNna and TWCSna as +equivalent, other parsers may not. Consequently, this usage is +potentially unsafe and is not recommended at this time.

          +
        • +
        +
        +
        + + +
        +
        +
        +
        +
        + +

        Table Of Contents

        + + +

        Previous topic

        +

        UnitConverter

        +

        Next topic

        +

        astropy.wcs History

        +

        This Page

        + + + +
        +
        +
        +
        + + + + \ No newline at end of file From d48410452ddfba0297f42dd854b76c9e6b664ffd Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 19 Jan 2012 14:08:24 -0800 Subject: [PATCH 10/69] slightly more descriptive index.html blurb --- index.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index d515f474..29f8f251 100644 --- a/index.html +++ b/index.html @@ -56,7 +56,11 @@

        Navigation

        Welcome to Astropy’s Documentation!

        -

        The current Astropy documentation is incomplete, as the code is under development. For more information, see the github page for the project.

        +

        +Astropy is a community-driven package intended to contain much of the core functionality and some common tools needed for performing astronomy and astrophysics with Python. +

        +

        +While no releases have yet occured, development is occuring at the project's github page.

        • Overview
            From 04dfe32ac472f2bd55302db0eeeef870b1cac716 Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Sun, 4 Mar 2012 17:35:05 -0800 Subject: [PATCH 11/69] added references to astropy mailing lists --- index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.html b/index.html index 29f8f251..7ead97a2 100644 --- a/index.html +++ b/index.html @@ -61,6 +61,9 @@

            Welcome to Astropy’s Documentation!project's github page.

            +

            +For discussions and ideas regarding development of the Astropy package, see the astropy-dev mailing list. For broader discussion on python in astronomy and updates/general discussion on the Astropy project, there is also an astropy mailing list. +

            • Overview
                From b31119acc0d13f550f0b7bcf3292fc8527a0d754 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 18 Apr 2012 21:08:32 +0200 Subject: [PATCH 12/69] Updated website to new design (6bd80b5553a2d47d92b8c3a9fe5a6549504d3748 in astropy-website) --- _images/astropy_banner_96.png | Bin 0 -> 29833 bytes _images/branch_dropdown.png | Bin 16311 -> 0 bytes _images/forking_button.png | Bin 13092 -> 0 bytes ...291effbf8fa69d4aad95cc3ac035b2f6726a28.png | Bin 49775 -> 0 bytes ...ffbf8fa69d4aad95cc3ac035b2f6726a28.png.map | 2 - ...4563669cfd1729a6777088d6be9e21c8889310.png | Bin 50434 -> 0 bytes ...669cfd1729a6777088d6be9e21c8889310.png.map | 2 - ...33a0922f5fc94c2076bb1330e6d8bb39cf71c1.png | Bin 25253 -> 0 bytes ...922f5fc94c2076bb1330e6d8bb39cf71c1.png.map | 17 - ...035f78b7760b2f76f4df0f21b8be07cd18e555.png | Bin 25502 -> 0 bytes ...78b7760b2f76f4df0f21b8be07cd18e555.png.map | 17 - _images/pull_button.png | Bin 12893 -> 0 bytes _modules/astropy/config/configs.html | 540 --- _modules/astropy/config/data.html | 760 ---- _modules/astropy/config/paths.html | 278 -- _modules/astropy/io/vo/converters.html | 1285 ------- _modules/astropy/io/vo/exceptions.html | 1489 -------- _modules/astropy/io/vo/table.html | 340 -- _modules/astropy/io/vo/tree.html | 3178 ----------------- _modules/astropy/io/vo/ucd.html | 296 -- _modules/astropy/io/vo/unit.html | 164 - _modules/astropy/io/vo/util.html | 326 -- _modules/astropy/io/vo/validator/main.html | 267 -- _modules/astropy/io/vo/xmlutil.html | 229 -- _modules/astropy/tools/misc.html | 211 -- _modules/astropy/utils/collections.html | 156 - _modules/astropy/utils/console.html | 706 ---- _modules/astropy/utils/misc.html | 313 -- _modules/astropy/utils/xml/check.html | 178 - _modules/astropy/utils/xml/iterparser.html | 344 -- _modules/astropy/utils/xml/validate.html | 153 - _modules/astropy/utils/xml/writer.html | 383 -- _modules/astropy/wcs.html | 159 - _modules/index.html | 123 - _sources/configs.txt | 100 - _sources/contributing.txt | 35 + _sources/development/building_packaging.txt | 135 - _sources/development/codeguide.txt | 429 --- _sources/development/codeguide_emacs.txt | 203 -- _sources/development/docguide.txt | 587 --- _sources/development/index.txt | 19 - _sources/development/scripts.txt | 63 - _sources/development/testguide.txt | 444 --- .../workflow/development_workflow.txt | 30 - .../development_workflow_advanced.txt | 534 --- .../workflow/development_workflow_basic.txt | 133 - .../development/workflow/git_configure.txt | 168 - _sources/development/workflow/git_install.txt | 41 - .../development/workflow/git_resources.txt | 59 - _sources/development/workflow/index.txt | 78 - .../workflow/maintainer_workflow.txt | 105 - _sources/index.txt | 110 +- _sources/install.txt | 111 - _sources/overview.txt | 56 - _sources/team.txt | 50 + _sources/tools.txt | 27 - _sources/utils/api_collections.txt | 8 - _sources/utils/api_console.txt | 8 - _sources/utils/api_misc.txt | 8 - _sources/utils/api_xml.txt | 38 - _sources/utils/index.txt | 14 - _sources/{development => }/vision.txt | 50 +- _sources/vo/api.txt | 30 - _sources/vo/api_converters.txt | 13 - _sources/vo/api_exceptions.txt | 39 - _sources/vo/api_table.txt | 9 - _sources/vo/api_tree.txt | 13 - _sources/vo/api_ucd.txt | 10 - _sources/vo/api_unit.txt | 10 - _sources/vo/api_util.txt | 10 - _sources/vo/api_validator.txt | 11 - _sources/vo/api_xmlutil.txt | 9 - _sources/vo/index.txt | 10 - _sources/vo/intro_table.txt | 282 -- _sources/wcs/api.txt | 23 - _sources/wcs/api_distortion.txt | 10 - _sources/wcs/api_sip.txt | 10 - _sources/wcs/api_units.txt | 299 -- _sources/wcs/api_wcs.txt | 14 - _sources/wcs/api_wcsprm.txt | 26 - _sources/wcs/examples.txt | 22 - _sources/wcs/history.txt | 90 - _sources/wcs/index.txt | 31 - _sources/wcs/relax.txt | 365 -- _static/astropy.ico | Bin 0 -> 1150 bytes _static/astropy_word_26.png | Bin 0 -> 5320 bytes _static/astropyicon.ico | Bin 1150 -> 0 bytes _static/astropylogo.png | Bin 79223 -> 0 bytes _static/basic.css | 4 +- _static/bootstrap-dropdown.js | 55 + _static/bootstrap-scrollspy.js | 107 + _static/bootstrap-sphinx.css | 19 + _static/bootstrap.css | 2496 +++++++++++++ _static/default.css | 256 -- _static/fork_me_on_github.png | Bin 0 -> 9267 bytes _static/sidebar.js | 151 - _static/square_logo.png | Bin 0 -> 13917 bytes configs.html | 938 ----- contributing.html | 189 + development/building_packaging.html | 280 -- development/codeguide.html | 546 --- development/codeguide_emacs.html | 321 -- development/docguide.html | 667 ---- development/index.html | 142 - development/scripts.html | 184 - development/testguide.html | 566 --- development/vision.html | 233 -- .../workflow/development_workflow.html | 153 - .../development_workflow_advanced.html | 609 ---- .../workflow/development_workflow_basic.html | 262 -- development/workflow/git_configure.html | 289 -- development/workflow/git_install.html | 171 - development/workflow/git_resources.html | 196 - development/workflow/index.html | 207 -- development/workflow/maintainer_workflow.html | 225 -- genindex.html | 2052 +---------- index.html | 344 +- install.html | 245 -- np-modindex.html | 231 -- objects.inv | Bin 8529 -> 205 bytes overview.html | 209 -- py-modindex.html | 231 -- search.html | 188 +- searchindex.js | 2 +- team.html | 207 ++ tools.html | 250 -- utils/api_collections.html | 203 -- utils/api_console.html | 545 --- utils/api_misc.html | 292 -- utils/api_xml.html | 532 --- utils/index.html | 155 - vision.html | 256 ++ vo/api.html | 174 - vo/api_converters.html | 165 - vo/api_exceptions.html | 1034 ------ vo/api_table.html | 265 -- vo/api_tree.html | 1064 ------ vo/api_ucd.html | 205 -- vo/api_unit.html | 149 - vo/api_util.html | 226 -- vo/api_validator.html | 180 - vo/api_xmlutil.html | 204 -- vo/index.html | 144 - vo/intro_table.html | 439 --- wcs/api.html | 196 - wcs/api_distortion.html | 217 -- wcs/api_sip.html | 335 -- wcs/api_units.html | 991 ----- wcs/api_wcs.html | 1065 ------ wcs/api_wcsprm.html | 1943 ---------- wcs/examples.html | 240 -- wcs/history.html | 227 -- wcs/index.html | 193 - wcs/relax.html | 493 --- 154 files changed, 3965 insertions(+), 38287 deletions(-) create mode 100644 _images/astropy_banner_96.png delete mode 100644 _images/branch_dropdown.png delete mode 100644 _images/forking_button.png delete mode 100644 _images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png delete mode 100644 _images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png.map delete mode 100644 _images/inheritance-c64563669cfd1729a6777088d6be9e21c8889310.png delete mode 100644 _images/inheritance-c64563669cfd1729a6777088d6be9e21c8889310.png.map delete mode 100644 _images/inheritance-e033a0922f5fc94c2076bb1330e6d8bb39cf71c1.png delete mode 100644 _images/inheritance-e033a0922f5fc94c2076bb1330e6d8bb39cf71c1.png.map delete mode 100644 _images/inheritance-f7035f78b7760b2f76f4df0f21b8be07cd18e555.png delete mode 100644 _images/inheritance-f7035f78b7760b2f76f4df0f21b8be07cd18e555.png.map delete mode 100644 _images/pull_button.png delete mode 100644 _modules/astropy/config/configs.html delete mode 100644 _modules/astropy/config/data.html delete mode 100644 _modules/astropy/config/paths.html delete mode 100644 _modules/astropy/io/vo/converters.html delete mode 100644 _modules/astropy/io/vo/exceptions.html delete mode 100644 _modules/astropy/io/vo/table.html delete mode 100644 _modules/astropy/io/vo/tree.html delete mode 100644 _modules/astropy/io/vo/ucd.html delete mode 100644 _modules/astropy/io/vo/unit.html delete mode 100644 _modules/astropy/io/vo/util.html delete mode 100644 _modules/astropy/io/vo/validator/main.html delete mode 100644 _modules/astropy/io/vo/xmlutil.html delete mode 100644 _modules/astropy/tools/misc.html delete mode 100644 _modules/astropy/utils/collections.html delete mode 100644 _modules/astropy/utils/console.html delete mode 100644 _modules/astropy/utils/misc.html delete mode 100644 _modules/astropy/utils/xml/check.html delete mode 100644 _modules/astropy/utils/xml/iterparser.html delete mode 100644 _modules/astropy/utils/xml/validate.html delete mode 100644 _modules/astropy/utils/xml/writer.html delete mode 100644 _modules/astropy/wcs.html delete mode 100644 _modules/index.html delete mode 100644 _sources/configs.txt create mode 100644 _sources/contributing.txt delete mode 100644 _sources/development/building_packaging.txt delete mode 100644 _sources/development/codeguide.txt delete mode 100644 _sources/development/codeguide_emacs.txt delete mode 100644 _sources/development/docguide.txt delete mode 100644 _sources/development/index.txt delete mode 100644 _sources/development/scripts.txt delete mode 100644 _sources/development/testguide.txt delete mode 100644 _sources/development/workflow/development_workflow.txt delete mode 100644 _sources/development/workflow/development_workflow_advanced.txt delete mode 100644 _sources/development/workflow/development_workflow_basic.txt delete mode 100644 _sources/development/workflow/git_configure.txt delete mode 100644 _sources/development/workflow/git_install.txt delete mode 100644 _sources/development/workflow/git_resources.txt delete mode 100644 _sources/development/workflow/index.txt delete mode 100644 _sources/development/workflow/maintainer_workflow.txt delete mode 100644 _sources/install.txt delete mode 100644 _sources/overview.txt create mode 100644 _sources/team.txt delete mode 100644 _sources/tools.txt delete mode 100644 _sources/utils/api_collections.txt delete mode 100644 _sources/utils/api_console.txt delete mode 100644 _sources/utils/api_misc.txt delete mode 100644 _sources/utils/api_xml.txt delete mode 100644 _sources/utils/index.txt rename _sources/{development => }/vision.txt (77%) delete mode 100644 _sources/vo/api.txt delete mode 100644 _sources/vo/api_converters.txt delete mode 100644 _sources/vo/api_exceptions.txt delete mode 100644 _sources/vo/api_table.txt delete mode 100644 _sources/vo/api_tree.txt delete mode 100644 _sources/vo/api_ucd.txt delete mode 100644 _sources/vo/api_unit.txt delete mode 100644 _sources/vo/api_util.txt delete mode 100644 _sources/vo/api_validator.txt delete mode 100644 _sources/vo/api_xmlutil.txt delete mode 100644 _sources/vo/index.txt delete mode 100644 _sources/vo/intro_table.txt delete mode 100644 _sources/wcs/api.txt delete mode 100644 _sources/wcs/api_distortion.txt delete mode 100644 _sources/wcs/api_sip.txt delete mode 100644 _sources/wcs/api_units.txt delete mode 100644 _sources/wcs/api_wcs.txt delete mode 100644 _sources/wcs/api_wcsprm.txt delete mode 100644 _sources/wcs/examples.txt delete mode 100644 _sources/wcs/history.txt delete mode 100644 _sources/wcs/index.txt delete mode 100644 _sources/wcs/relax.txt create mode 100644 _static/astropy.ico create mode 100644 _static/astropy_word_26.png delete mode 100644 _static/astropyicon.ico delete mode 100644 _static/astropylogo.png create mode 100644 _static/bootstrap-dropdown.js create mode 100644 _static/bootstrap-scrollspy.js create mode 100644 _static/bootstrap-sphinx.css create mode 100644 _static/bootstrap.css delete mode 100644 _static/default.css create mode 100644 _static/fork_me_on_github.png delete mode 100644 _static/sidebar.js create mode 100644 _static/square_logo.png delete mode 100644 configs.html create mode 100644 contributing.html delete mode 100644 development/building_packaging.html delete mode 100644 development/codeguide.html delete mode 100644 development/codeguide_emacs.html delete mode 100644 development/docguide.html delete mode 100644 development/index.html delete mode 100644 development/scripts.html delete mode 100644 development/testguide.html delete mode 100644 development/vision.html delete mode 100644 development/workflow/development_workflow.html delete mode 100644 development/workflow/development_workflow_advanced.html delete mode 100644 development/workflow/development_workflow_basic.html delete mode 100644 development/workflow/git_configure.html delete mode 100644 development/workflow/git_install.html delete mode 100644 development/workflow/git_resources.html delete mode 100644 development/workflow/index.html delete mode 100644 development/workflow/maintainer_workflow.html delete mode 100644 install.html delete mode 100644 np-modindex.html delete mode 100644 overview.html delete mode 100644 py-modindex.html create mode 100644 team.html delete mode 100644 tools.html delete mode 100644 utils/api_collections.html delete mode 100644 utils/api_console.html delete mode 100644 utils/api_misc.html delete mode 100644 utils/api_xml.html delete mode 100644 utils/index.html create mode 100644 vision.html delete mode 100644 vo/api.html delete mode 100644 vo/api_converters.html delete mode 100644 vo/api_exceptions.html delete mode 100644 vo/api_table.html delete mode 100644 vo/api_tree.html delete mode 100644 vo/api_ucd.html delete mode 100644 vo/api_unit.html delete mode 100644 vo/api_util.html delete mode 100644 vo/api_validator.html delete mode 100644 vo/api_xmlutil.html delete mode 100644 vo/index.html delete mode 100644 vo/intro_table.html delete mode 100644 wcs/api.html delete mode 100644 wcs/api_distortion.html delete mode 100644 wcs/api_sip.html delete mode 100644 wcs/api_units.html delete mode 100644 wcs/api_wcs.html delete mode 100644 wcs/api_wcsprm.html delete mode 100644 wcs/examples.html delete mode 100644 wcs/history.html delete mode 100644 wcs/index.html delete mode 100644 wcs/relax.html diff --git a/_images/astropy_banner_96.png b/_images/astropy_banner_96.png new file mode 100644 index 0000000000000000000000000000000000000000..89ca2cef2f2d8a46272272f1f2b561c01477af57 GIT binary patch literal 29833 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 vz5(+>=_q85E_ty8+owyF(p8rKz|?`mh+; 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 literal 0 HcmV?d00001 diff --git a/_images/branch_dropdown.png b/_images/branch_dropdown.png deleted file mode 100644 index 1bb7a577732c91ee6aa31de8f81045b5622126b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16311 zcmY+LWmr|+^Y;M}4&5o;ol19icQ+#4hpt0+cL}IScO5{GPDQ0VrMv6dc>n${o)>U& z9rj*(owaAyn)%FkqSaJn(U6IeVPIg;4b9FGh%= z&Ue3i?|Sd5oT=s>!a}#RuHeguyJ_ zr%&ZC_KtNTNV!#Woc5Pkm>gf)rK^TW-b`%T3@M_Wlg+>oW~XY>r;f3s3X9@Al`Hh5 z&iso&m4;=JUdmn+qAF3D*7$%WvNG;+kSA(|^=* zonu2g&8mLXIa3IAN#Yx^G7ok)kW-yea=K}cd>ueHgHyBat)sr?lZa!x{CnwGdLFKZ z1DzC=7&Qk?P7PBU-aM;TO)Nr)nDcGDn<#Y!!kbh-E>D^d9Uc}^b>eow9oexA)W@DyeowcL4v~TY?EwF z)9zK#vAjCDnYND~<+6#+3k*+uE&_g)@4ra)o=veKLbvho$N~j`5xf)gevf>G~N|bKw(L|B7MpJ zGG_hC$Qb9>h-4{DZQmWS&=^x&kkrtap`Ec-#Ba#fw%GNW&HhE|L{iKzaozV>!8-M> z<`k>;u~y^uwo+p*P=$CpB=gSs8}w278#p!^Z~!D1Iem8+7!;hBA6S^2JVF>43K)4Q zaV;?HVLoCWuJqL)x!o{7y?m$@Cg2WIuT{tBx8Vy4klMO^_wxA{vo|OaqyT1mOf31jpFqiv?DerZ(X!qRg zyuzmaRVzA0(wP}9CYY)SWQ7eUZRzNcOeGBwrIi-LQiI2ZmHw6}HZ}r@12b^)aXkrK zv;fyJz{QAB%2Kdd!{P7c%LVg#TSe9Bh|(orApac8f|XY zj2c=kPV#RD3<~~@H!MLxXT8oOo6J|XUQN3m#T!ahu2vk1%Upe2M+2wHD*3WzArDe7 zYhyXAK?kN`5qz>#{jD5#jzeCh_}_|BAi!G`1b?oyV!$3*sUk-7My8I8id%{s-i9mRugkk*sSI5Nrm!>2hFJCHS

                )6PRZ_jTr)9djL4I)$bAGt{;Hy1$y<{qLd2H6zG^8pzYt9uj@NRV~-9$WY1_ zkp3|9H6I(w?{d_2?^N-Z&>L#D_qSywFmRtp!e*M8p z_;xcj)a4v|bXCyfFU255k553v(f=K?}WObW$#Sw}~RCho5&UN~=1Z;QTtfOR$26d4l zI?gxN&HnO2J@a1nk*)5$n*Z{M*}^41&AZx}F&yGW5mpiO{B)Hc7t7Wzm&4=8)L=WA zF=OJV?9_3{!+*0HR_3_SjA)=7vaL#EvJ!Y-g-R}BlpuJ-cYkt*$!655w(Nhd>~l3| zyY(s8DP^imk>I`G9Oz<7kv*MGIcGMI^l8^+ce%4eo24B0Y-8t+fNkbmV*hD)ELJh1gWM0m)gwV+Pw~mhjQ#?%M{WjcKHUs zyUs>BW#Lfa?&P_v{KZ~TCl>JdLb}f|qxJa}5jl9sx$E?k5qK?JquD{fBXvlTy^{t^ zAxj?6DBN|u?01!`kuT`oJV1;UQ`2>)@bOY|Y^3k#ue}7C5KFlV13DQxWWD?O@iQjL4B+&!QCA zD{`7F>b}*!Klj^ZC-lGD{p_|LO+RA#e5V^bJl|x0C}#OBo>Xu;kSrK6HS#FmdnNhy zeA^J^&1ju&jmb3HGSsI5l}u>%>FI2got5oyzNz8W1z^qf&c`zqx|0^c7BRfS1=!O# z?3L@{KTS6V6I<4(YfDVKpSJDwIf6p8stmMMgfF%17F+B31w^0oU3!tYd@tVb&X$+F z{V>bm@JHweL!N2SA0thI9z6vMCIyd$?(gr9 zyEFS^2^0%O0xCbo{1)|hK|cl=4aC2(9TbrGquBlY)bT?%PWz5W6zLeICiGM;tJZUW zx_L>6{^GGnJZv*Xk*#h;Ae6m;85h049V%ta@aD4^5&Kf&KHK*QbQC{d8p=T)=dterRacNk6<_VTf?RoyYx;1(a=acVwgQZjmmp zZiUTz;rA~&K(l9C^`mU5fYYx`h<-!Nz?dPF+FV*=ssI(o*`=Z9`)IxhbiOj z$v`mw-j@=q^NjH;*zaZ(?3{m7RYmx56?zrtG8&ZC3RVT|rf6;t8YUeK=9O-OdBUF8 zBFUW=u4gS1_19ED=0875PxlrdKucx8VtRF8rYeIbY&DZ zRP6MKI}RZ=RA=Z@#5<_b++x_xxSm+@#lf7Wioh;SERqcJ^M_f4bz`|tkw)V$ zuxwYN7|F5I*3*toC3?)pYTe#`0-<{rnqy+x)+sI$p(2kVDv3?vmtme368dF&fukq8 zPEZg!LLXFmdO%Kon($brm}%flM)t*aeDB?rpa$eNi+Ox5$1=!WMNob)i;mTtV<@rw zo;1}q^jpcQ2W4f#es#yh2Td}er>FasX9N4VS^|9DV$y9Sx!AJNU@^g8!>Xc}jUIx{ zhDPJoX88eEb2{=?HKWa*7N>mXegj0dda98ESm=5oz^+?wg0AD+;)|F%75;vM`o?jrnc9q67dn-^_q?B^zLnIf zH8QZn!}P)c4yePdLm|7qH&$3Qwif9-n!#+pu?$HA{{Vx|ayfL=8o{1me-nwJA~_K0 z6gnz??d{2T4979D#OVbdArlGI#@A~xmkFHp4!c}}Ug|&0hFT@Er1!}8Le$O(;Xs;a z5)eK$8VF_$^h}}S2W-Jvs#?rRVqS>u0FtBd*%0+>SWpP843#DJI!Wa^?cTaR;;Sb$ zg*2b@ab81e#JsROP^EfTqR?5CHd&nT$hX-LS=r>9cpd}}f9iPK=bI?+18VPCad=B~ z3zh7hpN#0${NczLgd~k&UBNYy==^;N7*n@)rlXJER1cqCrHXrepxVu`udbua#G;k~ z6~l<_teMwitsQ>r%lE$bFGf|PYYlMvHZXz{yy7`yj1TS=#x#egd!*c^!E}ItYb_{n zG0oqBW^yB=k_=f;;IYFq4a-7KT(a~c{GT(}^gjrruJ5CY?a3x_gOGywp&&_45K;vP zCeZ^M+B92Owwj5_FHLqI<3JAUDct?&Bw7rGbNultMH6VBiFFD?rGFCS5y>>}b+0`8 zn?%C3L-5uR;iiaX94C@9tTt@yv*NpTXa~6b<~Wk>6)~=O19b91O9+w<5LLv znI=6xKjeBy&m#u%H0CT(goRM{*!bdycotV?Texo=wun>7Z!$&2qT311O^{*^%mU1 zzWK#dj2#8L7IlG%K|~Q*A~)j`MRbE%B&nk2o`CI|Iy<3IN(K%m6npTwt>dM7P{cJk zLBqzH7vk_*mgdgU_76RldCov~k z&BwDlScl6^3nJtufg~%9J;~2q*X`G2Gq-33oqpHNeC>^CgZ{nxLBgZNx#9tR=lgdf z!YFa>vdaSeJCmc%jhtfqKL;9^c{3VKy1)r*o--518SH7Tsk#ZyQ!b>Evp$ZE1WGY@ zOSYhPwDld@_zZn)z-|JiSFyKH$!U%e;Juk*vR%SKd@&;QT zO0dy<=f}6^J40q=VHxVb;kWHV7~KMPWpp12y)>3sh)X9Hs4wa~6;q5soz7Z6WD`Op z)apVaR7`>Sd-5^GMU4ey!wVsdpX=}~ah=5&Z z(bpnPwoUvoOwDC;Fq4C3O$8r9q4tP#&SqMl$dEFg%kx}LeC@z_^$jFJL=IBN-{`|y zd$V1lV3Xdchj58Ci8>iEv){AsjT^u6-V%mCgeA&aXpsBLM~9Qn=nG09(lPfobeUlz zPK_XDDjsiuB=zd3#lGTNkAZ%*?yR;ECMO+KnX>)}5j<-B-kdM5N|#aBmn~%I8y;)X2MRv#k(m4oo=lV#;q=JSY7c(kym0 z;W%0t`8iRddwh=eu zO7^ZBi#L;l#FD$USLBq@KL)7VRzp#)+}F-yy%7Y@)%3Io5%u&igfEit8bR=BB*!?M z>IO;h5#Vk@9?Z2@sE8Tq^$=q7Z?B$Ox*x}hDIk))O=#w_ev7Y^zC>U$%BEo>Z;RbW zx{$;imn4eRPr`bZ!Euu57fFDL$G{o2^PS7nA!oZ1Qw*=uq}9l=+P+b2>aY5gVdV1I zGcjk>)H+CQ@XixbERw!0_#U6AHz;!M06t)#0hPI((h`i0vUif4IWQL1ZA!QkIyNRJ zeVt*bdkucV<9tQ87e$F=5KA52HrxF<@0Eb`s$iz5f%toE38K0bLyI9ZSX9yD#%R5_ z7m2B135+<=-9Ui?V#Uf*yAWCCf_S5^! zfHWVACt-MdCK9; zC4!zsU~k>Ll(mv!p_MX-KD7t_7+nMkkIn!;fYqlLYUK0LahU&mSI`_r zYmUPHa`s!H3O)>N+y(E9M8n0wb9i2YM^&czZ(0N6v=GT~A5!q4UPtqcv@w~r1tBet zal%1@o!0XYbTvT^!L)0n19XoBRf(;t0(%x~s0vwfVf%>`fot>zx8fUfq9UPFz6%qx z{tu^vRdpy42@Dv{u~+ADQ*1NO;PD|&lbfpqoXiac=G8KD{cC;HyH$v9L77}If;JF@XBGyGl7BJYdBeyMfw0LL1Gl*iAiV?fjJlIuKl>Dz8L#z1lk?h7&nPNIMUxX&j$&RyOrO;=M z=e`klq1`jTMd^L&I}FML6OD@&THY3RyA#nl^_vPOCGc= z?;9i%_&LsY-2%Lpbzwpc!B)*0&26d8+sKC32ZfjA&!bCIqUe6kq&KUA)9nXHCVT14RzitWLu2nSqx7?B za*fdzXx^B!n!bD*vPqfbg>y0-CZPxrpBG9v#0>XU=`1F1`yX}`!vawjnO9@t`u+os z!Bk1Q@ar0MP>#PQIivRB$!EJAILS#r_y5tPQV}>;##AewNK(f1e`Be^PvL~5snZ#b zo7^e<4>;{czaUQz+~XXY{rK|}@?|AewRHP`Q|Cg1H6Bm56Rtkg{)aq~Kz#?x;%g5oc~h0-nE$DMxDk(VT6DKHL4b$YfsEbOyffzu~?cg_HR>7QHXrr%;1O z#(-liQ5u^mK*snwpE8U2LnIN6UbzfZ3j6Z8R(fgAdwGu7`5hz#tyoQXWXzDpz)7pQ zdTaT6GlCV}xi)uOSTE(9uc^Z`1Ilj>KZksuVM)o)&#x~;S#GpTJ-DUjuj$fos=q3Y zg?LuZ+^QMKM)AcQ4f*&A>`!=d{~-xXR7@Q6k&-mOSXLywbE~f@#6H!&@xJ6#^*mel1SD=M8Run6ht2*|$9s9aZz^o2++JXzNGgMgej_ z@?INhxZC9?mCxU`$TI)iGkoSWk6)jZx26=?k~L@*=}OUqD1VLJ+*~a?8~$qT020_U>%IrtGQNJVYT1Oeb9O$_KCc5C z4F*LedK3Z{;BjB&ey;ah*-!A?u8*<e6*|x~eQ%-7EQQ+hKvu zav&l7NLVYoG>(h23#{}CN!4m&AbuK~Rx+OW-R6YgG4A5y)8qXp?LaU8LGAa=X+!7q z`2nsCVmO-=qDp|O#^F7n#J%e<|BgV!VHPX|WH@J~b#g$+X33~qooD3I^LpyDD)}hN zrIF88`m~#)BLbd|pN`HZV*N{%q3MJ6KIJLdYYa~7-!-PDPOWPQ6)@^=)c`W!@TjK* za=W?h*Gtz+`mH&oXLovbx$JkWpBS$;Yx;CX&^E27*?PUoy#yKq7{C7OpUsYjqhZ%8 zwdUV9pYD%aGBJM`cX&0K5D?TZcfSq&8d*1X3J2r>j}V4+z5B({&)5DPK1nUvqV|zl zr<(H&(20D3VJAzMIP&YZ6AhY;4SP%e4DJGp`>R9i=(^v!M6XH<)ag(N*wQW$yd}gp zM9H05ABG38AIHIzv#)%DWcrCM5(H^50KfLjUB!XR*&7qx$XWRgg4zG^&Yz#_aqnZuwG9^GDvif7xJnG0_o`; zA@yFdfqfdL80TJFiSB3El9c3Q2kFEgaJieBF&q?BQ zFUY<_8-K>PnIyUS3MYZYzSr%Sa!~rvNPTEa9#RQr`>Z9T&&{2tQkqmzNp$LZA^x;( zcr|pY?~P0tme}=FD@@e0>MDztfi~e-zmvhAs(=8v2J8nx z_Im@%KY4MFz>Qy?xDO=g8R!ErIoy5;+6f@JxRPI!eBX%)PS#ix-RGN@H`$%%dymof zd1t-aJV1Zn&DkGzD&R5evn+Ooia7BotkRy7oLrw!C(gDFU(pFE4Mo*?)~c`47l1z= z7M9D*SzIi+jk0nLGhj;i@Y9h_UL(ndJ*^}K zfbdyO(4(SGjR|W*yxZl5n80&Wl?;9oS$OE0+k#`uTpiblkZx%|xF2+ATVNWrtaP8x zHPUCmtcQ4%SP(CU3W7iTNyqbaJ}EkC_c`C@HHSHiMV>={D1FGg;Zm*{O#C&Fc*52= z3F4_23!1H~#jrP51{*%P1d8}EJv>%#u&59*E*2#(r~(t#q}c!U{(MPgRxEh0{BtFR zo*jZHBJ(mK2ew)kf-V6(_%In?t~&k)*~8AKPMMUXj*-W|Ho=>*@pPZ3Q0 zOm$Q1dhsF0M$a<0out%K62CzBh`+4b^ z0o!m1ydzm>pEr@qSY?Vn%H;6Do~ISuhgsS)!P-FUjd6(vv@B$;1Vxa zT#hJ_%}3g9A8BqM<#!w$$H>%~$+h{t4(RI`{JxcFo3(Q>YV@PG;&wVwcLze5(#}Olu;i^gCYx!5u_BSRM5fR4-$EBDJy1wb zktG$OVpeohv1H_Y&+w}l&oJ5GU^1Xgb^l}SCxn{JrIJrJok<(nvB8=AXz`8G6^_Um z4hDikTsLB{kkQ?fU`~cHl#nXm&FbhMz&g( zf8F&*VL~Pg#Pdi>WFVr$X)sj&IPg9(?XWY$5jub|{t;`W#wLw90Cr6u_uW=UBLm_D zbIv^>J#B-+d>h1dpv2Q|5i53X6cGWVAfqFZS1KxQMS3jjBgTt2_M%YoJ|zh3F$f|K z<{?2S*KZ6zd<0$RhQG6q7ynUfF1ZkSWD;E&a9A8*WJ{8HwaIRIH@0Rt2f;Kpd1dr> z(Rc&o6V%~eJ@a-W5(NLSh9qiT`)Wdg!e&H2N!1Wy}k668&T2D5RNchjL=$K zve&OJtv3|B4`zSTqLCtni}z`(i#&WHffwoJWA8JwaSBmODm;=pZ zSCvgTs2~<>;mGAev1kJi3PrV#PnTP2_iVUc6s5Bs_S=Z(9eF90nV%6UCb@xrVV*^& zgMVbtdP7b+?~ghTOFKITlEM6BxbD;-$8B)!L-swAY#I@UDP-`=8*8~+rEexcpsFK} z=`O>8tx_cNOa&+CY7b#qV{?&gTNf|>K@vh);RKF4C~fS(+K$qohsyFXL|Gi3%UPST z_Kxb6Jp2`$k5}&@EIye3q--CjZP)`=1QX?U-zn(z_X}U^j({0Y?#tR_MWDnisw3u{ z@TrXns>eUKuFtoXH;y>h5;%LH=!)hGRa(*|H&W&e&=i>nvi(Dyp$~Itk{$2fbQ*ooriD9wu_N?G452!;(C~Zx9>6Lea{y zbw|k9z&XxI&wYNw_hWrvwomap19iOO&V(Uh|9M+BGjs;x(UbZf_HqBH$4?IyUkZXx?sves?*m^J>y`M&2{D(yObUyVbpSSo(xkV(@i=00 zyI;)wDda@{W0b%Fm>U^}3bkngM7t-=Nb#V@^0QbHao;*A!UqdtUdnkJdun!)2dy|? zC6)e*md~Z{uXH5wYDAe{;^T!D$A`EjzoxBOv(Egh{x$!zm;fEVDB9YRj(yjS+6N@ zvVV&jA{&)}sYAuU9za%Z!Xm|>YE8UmxcJZp?OQrG$`~iwE@bSk#B!-dhdkm_Gl=pk zn%1>)a-B#l3L(-ak-7OCU`&cGqx5dr*+DgUceZv&?F(WNsKld}blM(u$zhaL_ zCjOR(vw0?^keRvfbmZAxufE(yre-q2!s4Sbz)gv8K)dXau$>M5wSOBzE%wmmAAV+@ zj#btGO$oKcNn~Ai`<`Al zgBwBt4~&Rpp>e#00ml$S(Hp9xzyfC-C%te3llGy}(N9mHq7<}=_`(g`bbWSYbDI)y z#l`N0qy;4A)Znp$0a}66VZ{cEHbpfB3JEp6PnI!btcVf&K%K-jV%3dQ^?N|6O%W3g zfDLdOvFh*|FfTl1t=3FJul$6n)@7}?ccB%;dd@zVkfg-U3}+W9w#SglL5Xoc?KCg` z6?HIFjPB~NX1fy;ZD)W>;H|O%RZ?q9{Z!rMNW*_3E-?vAIig9ajUA+2RaTmQtRJog z>!hUzTSPApg0_~Gf^fayJ@N>y$R-xA%Hp`pbJ5xBJR?)6)MhbH63=_5MI2SPsesw` zb+h_zdqp=xIjD;^pd8muHZ98ZtM2zf3lmHAmNQ3iq-f>eBtzhe(g8)B*gRFyNT0`2 zkcbh5tq7m=^3#O>NJH>nG4K#)%t>3_sMQG7`A^#agj>ikA#u8N9bU)Dx6>-0_|?doj~^sO?gGmm+8q?@^?tkIy+ACG6ovJ+5?tHGVqT+J36#UP+~b3~ zepf*@tF;1ts$%<0vTm0iWd*N8rikoJ#xL{=HjF^1nvRuo<{+Eh2az=cts{Tiu3H;v zthUF>#}?t8y9DE)p@($Ct^2mz%~CH~t0Kmrb>}ywQgu{QUGlHnx@N?=98c+p_}rpB zJ}sNp(^g1v@^{;_?pmZ_UYx2{Y?YAfME_KtYB%@UU8yJ#60wjk0P~ee$`f&!xA}`W zR^f75dpjCSvmKk{vbRTU9a8?%d0)C#?DR(?#rh`D^+4mcTl0-VtbnznzUcS@!>jvu znT4o>Q-fR=8W$VzpT;mSah+QV>$ zoq1(!j-ez@O{6&B9e-DVHqkq~CVxTOFo(IW!D&IS5#rtH_OF#It&$P(rcUQJ&hw0u z@kS0^MCw`zoS{Lzzu(D-)ucnuPAcqvb(q#9O^h=uUN>)RR<2a1c?ap?B)4oR<*T`e ziKp&umnbfHjn=orvW$IvlneBo-=PjZkgc`v=*>Ss<~t>;|do$5b= zNr)vUIN8^2iz6WZZH2DN({xGo?brt_pXXe>`Z>_k#)4Lc`9=nzbgjvr zF0*xa`*ex6wU5IMm3}MJAin!ro#*DzfM55uSdPpeMMXzyvtxmp@-a@hfW6Rho+Xlv zCK3(5{vEzA1A-A$iNef4D90i4Y+H?1;H*%i0 zzxJK~f!a{aAv{5G`KjXqO{^v5o56^_KtuLHLT9*ksGo6L%Vf`0&60S~6Y|m+ZSHGY zcgf>0tIzthcqpDi;A7sILh=@+PdRPrfzP>Y&H)`GHsdH5%JBq!rM}cS^?M(1=R>s( zl|jlh*v{3RbGhC~qp|kd^A!vO<3l{i42GY^S57|L;0}-DmRE~f|3LYNmEkFpnhWH` zawS?4-npYs1~kutwuPrkJhy&a7Nz3MYp0Ws?Nv9B=TJG0=b^5BO5bme>@`|DY8 zfGlR2uGNGf@#g=k`=p#hKsK>&q^VQ2LK!B*!ZTu?NMbdzKie3JHWR*4_3^aXfViK} zZJnvyQYc~BraE#3=TmjMJe`nE%LhCCTCN9$8adB!`_Cr-X?6k0?-K{^u1%ov^H!$m zCZJ$iu4zB+el{^^d|$WH1P(g5wM@M5+a@S?)Zu&FS$rJDV6unXf~ zSwf>TPZoYQvDd3mL9su>@Pn2keX42w^CE%@M;=sk?v!>vv3UPjFyiNYw zyx^2-(&;-KgU5`mVO)8*VA&i`C~5-6_>$-)E3juxnc zegv?eD7ige!|R`9K4-)9)(g#!w+7DU6)gB9+S$0xCNo#1Z{Yx$XSK)vwDR5cF}ppG zVM8afI3=swwuzZ95=5WCw}2dp%}5YXEIQ1KharT|_j!)+UCmloiyHN$en&s%p`6+;H7r2Z8X54M^qP4r{{<8d{D}7OGy$CCX z&d0df{Qk-rBFQiL?pM|Ox6Qd9olkDD2i?Y!0CfzvemvcwuiAbq!#VHlGx}evhVtAo zehEmP_t;9;owt|}efFPg_pFdo*r{SJc#6^@vwm24ek>Ha{H^J>=sGz3!aDAM|G{Ad zxT7~fD@K6nu{w8NW}p&se6wz_hU`Cs!3n=J#f9!&Q8_pH)vecIB~|f4tf*anN)rH@ z5vVz<4TP@IdKCZmMRp6w;W7c8pea6^5ksc2S2o_4=Z789s$dzrlgN|9sj^s9A}%T5 zEz$8VgG*Sc1qBVAx(~gWTQNn*gC6QSkDepLZ*Mjd75PLkHCTqp0i*_fe!AxZ>J-es zL-+Cl)#ktI1)wn<6~11y3}0DnbHA>*ig@ExdrtFwH`5JC3@g^cYy?yuP~H2 z__-qV^s-&|M}o{s?41Wwk0YQDrfRugP}+~X?hhW+OPl?eW1B=n_sUSy=nCy*dH{&D zw5}p7eyavv^%$nj1i|_L{ZY*2zO6KBq9zK|85_B%P7nI)w8{f&M8K|!V@g>qeeea& zvnM;eEjW5m{4&s{ARK+6fBnIHlOi#%6N~02C8R%-Qnx@o#xeZpMccQ7f5K4&Xb#l? zG|2wzvuY;syAMNvV9K^;1t>GP^&-*h#op&ScO?TdTfNbOTtGyQBZMG|bwo*C5MPJ^ zzx<*^O%%ENaFhzo=9DT>jB510;~4hzP~+-@lSTmzYB(;Zysnz0d($(fR)Abrbs+WwbXujncuq z%fJG4_%3p0JiP~$k!C(DJVmOCX$+JB_m}A%N6=Ax@;>&%gWu(;d7jhyJgfyISrX&{ z7wUb1tAQ*+i1CyoQGE>rgCC`@uf++O8HUny=m521S%5-}Sg{yPPcT={NVQShSs+}4 zLON5iwhE|lK$$ple(d`wJQvw0po`wjvP?i)+7LHsu!(Q_yU=7$(5?bv%;RFz{1i8q z%d1M}`?t8(|3wu%y)Rxzu~}T?i?kL;DyYNOx(dhq7i4Peci2QJ@<7kf25{nVwwbTm zqsZb=t|;Hf7|1@DC3&8pN_jKVLRofR?~dBQ2W)&ns|66eiZMQnk;q8jAL94Rv4TMP zL1KjF3poQXenCk(R9uEvo=E74fQ0K95h}_80V2o` zX!@$WvCB<*xd6KS8O=DJTy#0Y4G?dC*ijSu6QOd73H7gUXJ%#|_5GmvS*3|giJ@+X z=1aiO`OTQ zD_7nL62K=iU1e%3oRRC)E`Oqii3y1a1@g#c*FjQ^E`J}v?x|18Z%&aVMR87U0lGZb z27eUtDuyYC0`O3U0NU|^DBD1K?pSF@D(d)=!c-hw&brybCwt3HdI2JzUKc_oA!zwqa41}j} zC;hqSDfCVBP`0?$=e0NcU&7yAMLcVs+SQHTJ10dR;-0eYnKNg-Td#1Q^eTgSIovko zI`$5MtsG68yqsJD$%1d#p2&pc@y{2oQ|gc1cp)^D!CXI$!&2d$C>b-_63-_DRe^G) zJ^gQWDxe9a;TXNl7sqpgMgn8ag3ba3A;T2=Uh7|toq`w+!j5#m)@JU1V)50Gij37+ ze1-k(2;|*tUonpKG4wnkUoEZ)DtCE~&&jSp8>1KgJp;G0Ul+JLq&E`A9S1rzEXWj{ zW;ZPJ^#?<$)vI*mt@CD1=fQf%*9*=J|1y*$CQxZUmw7n}r<6&?x?&uFmu3ok<)Bi( z+Li6iv#A!;`6L#&>-xVE)L2iB8du`4#p^8JdG<*W3f6F`4*F6GYa#3Aj?Pr2; zz~ws$Xv$faBLnWgOrf(lglDV1y(IQFYnR-#$`%g*cN2K$Y+!6~Wf zBkmnezbgmxAok{>)hf;AdNadUPkNe@u^N?vwo|b!-jr8Z>ty>Ar)<7g2X-}@^n?8q*cx-cK z=WX5Ds0l{_g6h;8HrO?`5lZsh#kG7ss>*jZ7la+u%*BjXyrJt=gXx1A8(>+7;vU1g z{}d;sRB(3XN;eS~>awKPEyUlrT~<6`%z90L=9F|}jYu) zWRQN7Z3V4dG|U=sMKu`GTj>vg@{`_mxZZ)J$-#7GBd0QPOQK@nDQea>#~CoJ|4! zQVs%XVk~_&jt*fxLJ@^0SvN&!l+E?lqetF?%f3c7CPlxay(49O$u7}uE)ICN1bE=D zGQZSq$wzB}&Rk;Px7Bb}l1~;Gu_vgv*6y(%`W3_#B85E{;XAvb;Cn%bC0rUgy!;2 zivK^~ImA@6PVqASg!-T1`hvc2$#;sVC;YovP7q$h7p}nb_Wy)F<%wb=OgP6X-vS9u z{SM!CWLpBVd`M@_4Gf-hZ-YJ+J9o87=X~I`B_OQu;vRI_^-+8*jwDL~qUd@2$*U8G zvR)It1n^w);r1;BURr)W>njA*BudGMS#SN>{%fF8*y!BWAdTWY;e9x-JzZ^VzcLa@ zaCH$%Ro28S{Jd%lgx|e9cMf{|KsQW>uOlE0@e;&qaV@1+e2)m@MX((o)SP9$kGDJ) ziP)U{(g+sN;|4UjodJQT;ZxXAzd@HG0dST`Mn*V}j-)eh0p~u3`Ir|URBygJD9G^b zit}!Og7fZTxw{l?G02^|%O*Y}FvQlW z0hP9>%Ql{Wo^VB(RPX%l*pl;sC|B_8TPCwEn?KyjAMmgHdfA6Ir$+((%+84}RHDQF zUcFx*`4$n9p<9z=rVaw~e$-fnx0_o^Qxr;TWmdx}Jp8$;8BE3sOuBdHirM1VP|w%t z$I1jAWcG%kBcMpiLJYlDmtrGekM%Nr=i;KUn2whaL6Mis>uh@53~)qI!M=1vv%B+F z|1bh}d@viD%G;0s>;DA)%an?G;Ne*Rk4#3(h^5Pa#QJmgpKXf4Yh_!ReYQ{i=Vfwl z0hJnd{FjXX`b-f3nn?3X&^Y(MhR%;zfT6yZY7+YQ7%og$?f?I&OsP`TU$_1{he7}= z9{#2>L-(IizXu*eL#)pFA6r6|qB!L7%@g!?LhwrEc@gxz* zTHgUM)Ne)9WC0l7en!F`(4=#u!e##CAt(uPa59|jqfeXP>7H)$(t~j%>9?t!Zl%+1 zQ(n$T6ZEpS7(L)pet;g-9he0eusJ;IV6MJ@HV}dv3=AyGrIqYIi@+aG+%M4{F<>%t z?|;xg0O|h|=qZO<|D!6eU8S+n_6z=JW1B*BJ1^Av;UOe3F|l;<;X1@K-w;9Q*-S}B zRUs>D;*DpUn-n#d!xjVpl8dXkeZI$AhpwG7CpVV~r8+m)u(hxwm*t2%iSEslwYH9x zZab-kD)edkM9towQBP0r3pcwn)Pp8o8e#*-2Q&B`*EB{6durO|K`|Fo!xa zKHgvPw=3dsJQcn@e$IKbyB3?t0OEZ=-xX!&D!4s}&zTOm+?O4wi+gc}VJg`+!O?3k zHDbn^HhJW!p|KdL@A!kkE@DB13Md9_-*-TJg(KN?{+#IU)R96RIT;lbNv zw;sadd<5frA;88~-3{E?j0{t?nH`0$!O5LYwiq9+F6NIiX? zVR^m2c|M%|n6nwB)nuEl#Ldp$peM&=zexp_g0NrUtB$WqwA8sy{Ap+iU3D<^rl((w zhK>$DGx*M*gEiIAH@ZkeVY^}u)BaQgvg*%4RZwxotW}M1KNJCv6U5io z7Y?(LA2X=y^;WceCMPWV=V@s!b;q5LPaMkjGHk6$Ikkc3px{OQeQ^Y-4^Vg(MH z1;X3IsjAUoibXaK;;X1*Zj=7(mSM+Rsv8@z{}&NEr47ZfS)hniJCVTV7*I7JD2SG@ zN&_8JTBoXKdi@QML>Q+6EMf)9ROrSiX0zFre)w5tGngm8Jb= zYvF0-dtX?(Dkf&3uRh_;pwbd^Br4IKrQzq*cru+PL@rq-f{2Jn8ix(mN~bF4>-+O{ z?6lxJ0yHuahL^+N&L=#bCR^>NBBRZe4Z&peC;Fa-U*%Ry2rHfE5FL1rJp<{v1>QrH zUUfGxP(JL~{TTyBN1pe_o>pij(bkcjhTZ|{XH#kShty`5`XQ_J{c+-pTxaYk`&33MoajcDBan2lc@KN9%cwz8O&G7x&AkSo{p;(q(eWl!W};Y zE@?R4sbyQ3I&K1LdRVZ*-|3=(kxy5H<#IP(a&(nQVWTFCr8z^f^MXTd^*o|WM5coM zQu}Ycs>Gq!TiJmR7UBxSU*eJJLOuG_rG97@7rOlDHq)Cufu<#|Z4eU6DA?#Y} zhz+MR0&mg?L_(>&?of%4Z-XcVz?@6H!}V)_J`ixDNJmS34wo41752EHTlU=iwSL(t z$C??w>}gkRG8xJGo%ff!^$gmp(S*y1oc00dm9iwtm!Rv&<>Ff_d(I-s(@HQH@JZ4yMZW zQjs>jHuQePj3E-xx#d)%R({Es>ke2+Lti0ON4{3T@yj|ufAM-#XyL4mT`9t`jp>j$ za3q2@Nw_^8a-Jb2Y=6pbd*b zhp8kK7)-+hJ1^Cf+>G$z=)O$c<7JS~_$yEQ?P)}=AanMA_o}FL`_!e&${xE@zsBhP z!i0uQxJ?d?!K5(U7<%0X3pd!ZnB3<2e(_K$WKp9yX)~;`bD?+&;La+C)-v7I#Z77+ zg6Z0`Czuo%xjKfThYNg~(3@13B$m{`)EV-X9S0g9sG)MzvWiz0J%VUS6 zOob%eC8-6|STK=g75BzruSr;$z@5ME^MzYtV|_5E+Ff^FT5$#rq<8+X?>X6`G0wN+ zUxF}{&<~WE#sk#JeEQYA8ceW7hdX1-(LHv=S5nh{ILWQvCknS9N9RUgm&OdN>eJm! zE}20z(^OyQR7c3hmRH6ve;`m-P(5q&v)PZ;<;m(`{y2?1GGBtpB#;2-yP)}fV#f+j@>1$jvMc7yDD{4VI9+{gKL7DQmh9;s?&j>tw|XFRMAFw2J+S9O}8s4x-K zv)E-x4e0MPU$?fjwCwnNT0cyPDy-gUu^KpT?Jbd)$hifjzC#Cwpy9{rM@<`EK~Kswc{J85O&l83?Pt84XbKn(bM`G`+ZOvZc@FEw;jn!d*l@I#~=*5G4~c z@L|NTr}rgOkjm;|^e|<8`DwzXHPkd12AW7h0dH`WhV{T$OqjP|pD7y`8zv+!r(rP` zICMncklJvM@xY`SN<*OEjK|oyZnSVde|zD}n-|ZDBhUx;s9#Vj@n=9QC_q9mBDO&~ z;4?Y#>N0KPF>RR06T#o#U#rcf+{p2AqZK_0=4d*XDGucQ^d?8ZGswr?-F;`0Yg_#N z>C#~xjMnR{H*!JW=2@T)jI!_~)FmOZz&uez;g&ZV53Rlo2@PVWx7QA(=_jfnuSCjI zk|L?@Eo6y;phRQvPCWF7CR@$iIQ zZ78x5{*KrNvG4C_loRX&)NFuS+Z+>%P4;~3yJlWyD!NmF&tReHvGMTK zJkDp4mDdY9GWl6j-s=9fk*EV(z~+5z3Y_PPc^(H}*`hMQjxj6!C^43srHwhEQ>Fto zkBrJ+m92x#2W-NCaK>U}KF!!F1i&)O-DwA2R|9IJnguj+lF}(#p%(XE#vOC($8acn zaNwYOoqGow4#Cm!=uXPLnl3@{@#M0YLU}x%1s4^O_f`QvUK|Moy>KpQ6=h{3;)e9# zk@|jV(Z=wa3nD7VUId@hZ4X5??sC_evIy!vVwYP`6IopuOu(6$!*R`VHk{7>1$l;k z7YJa~A2>BW=ft=ih5fyMW+>|MygQw531DNK<$|4LQDTrZkq@UtqB3RMC7wz1KnZSz zZ`yhA$HWo5;^^Q%r$&H;U@{m+gOw{w_(@HOJ={W|$l|t|8{=gzuqwovlr8Tg0(Y_P zXat>Vn>t&rN<|veN~oocC0o_6KuMWMRKnkQ6N_EG$TQ;X0Hz_fFgJaB-a8LtD1d#Q zR$Ar^!ytq}%1dD4JWm#rxXTEe9ksdM9fI6Bo!Nkq-hj;1IH~dw9Fc@SRxzwR6F+>L zEifMGTm-9#hnx*Lr!b7%8~w4XI!(OA=%0`3dCU9`aO^~xpscf&5nSgo+P)Qd**yo6W<0rDZD~k=PlvGj9ZA;^NcCeG zd#cgKOnaivcWp;#h*9njUsHxX7FmzhxiXeq4+3deLlSOHAd7vS<`@W5+lj`*QnhO* zj)y*MCiZxJzdCM)6&5Y0bE09s`7YIp%gFBt&BG zD>`(Z4X;Fs47QLACqbjyS*v4vQ{|B+lFSrVWJkWFIUu3`s^WDse3ZIb2h#qzN0ko8NpBOx7gdntpL65)#|ch_tF<%MB@Ug z#a}*kC7tLr`bI}Y^c_uR27COw%S0_Ks0|Dc!(TyR;bLKh+}zyMeRHtAhleK)gwqd@ zd7A5rb=2Q@HxvVgUWq#*)9DmINDFISoeWL%;Pqf=-B{~vDUi4Xz~1)eE!R;pgN%2l z%#5K`E&~}0`;K#c4Wx0o?Da%q=Jw#wBD>;ng|P_5=oo&-Afc4_08J7XU6hk!P+X-+&i=! zHkt~N=6{-^a;H5I`PlX~L>c)ymr<=D`v_4|c)5WYv@s1!`0LO+oM=JXp11;_9PVQZBD0I#-RFXy^Lh#1F`Tee zSus=Jdg*4>z-;&vm-;#h1{RUEm7==jD3dEdxGvP>#F}9K)wDj+B(AR#9$dY-V)bqw zlITX#5eAh1jb{~&rBf~dSv(D>n6^sp+ni6NY!9#GWT-4sqGfWs<5PLP&|A?Hux_Ue zR{!g-V@dg)g-aR9=Jg>!gIxb(ghSZw@X*RAk&dLaDm$P9=Zt_50ZM={XZ2pCwL@=B zgRixJK3ZpdJiklnJL0i;fJD|yUQSL-T3R}MWzUc<@b>&~w}Fz?1V-~CUOv5kN$Ll>Mmk)_|gQfQj4x1ptUb|B?$kPZqGj>T4H(4{I2J7VZ zp5g53!PSu^%P;*Du4RZ=F#3tX$G>?N5Kw{tUhSBZ)Qi9nmtbDJHVAnI;t6L|7sxx2o&ONnr|put|njA^Qc5hlQf z`nq^eU%jD5FcU6j4|YQ<`kP(Eu5jfuI5pVT7T&7(7^6~`cZlM>Zd-Gy=ry0-L?38p z5b@QRY9(XSCZxNssTd&gR}G<*jTA661I+Z3T5go=pJb_0R2^gv>$j4T)Y?jmEzE-I zO$Ooo)d-9FD3K#gg9fD22e*HtjGj%6Z*L~p+Ft13=xPxZDQiUj$njN#F86x%Qq!1E zj%;Q^Xg0Ut{bTFjD#YL~6}Xf%abeH0BHMOA0Q+DzG9jT^Xtf|nZ z9#CTYPCD7)@oQ8Y_kuQ%WxQVxdLn@#qr0KS6SecK$A9s*dE~(W;;2cmwZL)y z$ZU2V)G*%AVk@Nzii|b^mueFa1sWe!+LsngL&r#>xv!HS>^AJx z;A&T>!NK<2<69ToO^O?VYnX8EPN!x2KhlWm)03_0e=LuF0wG_XF*Mr8cf7_gKU{l+ z?ufq67?$CDGQ^gDWD$VP$8(o)G`hmR+hzOmndekEM6oZybt51mKZC=fJzy5p_F`x%V|boEcv z=dqE`Ng)u=4eyhWg#J(qek+!b7#du08R_^`CQ->may*_UW%+mX@!?lz#~Szd-u@*2 z`(yOHvSVoT(a{n)rio*m3p?(kos*|PW_Fm6SZ8BMtU{#UlCW8qhxFQ-HKyOcAR6Js zHtOK+&|w{XIGFa zF^R_bDEZgHF@{{h6GnYPd!Yl(WHq+K$`8IaAbJ=IBP~uSbUv$rx=263+xI6mq4S9* z4cwA(|J6kZ(PAa}!5bGN$^b>NpX8jj(bSDqPy!+Q#r~Jd+}?7N8s71o;AH(xJ7&w+ zH@{SgaekznRb>8THIpNQ$t`RF=iH8@+qB?r}t_`#{)$1>)oF~U{Qig2XjGneZE zM0AyMHyx`diaS2;x5A|3ZnofTB6l06n$HOcpiTb6AMfgf$jSLLW|mN(f;y5GwmNF! z=Y`=HI1)v~ohmg3Gme#G1b+kr;@fWL@_T=MRDv&+jvD|?_enf1$3@r_xo;+Bdb_;7 zpw8{U0O(lyQ$T-5a?GH`RbxTTt_0uFb{>h9G-n`BW6O^P)L7`6vd_+M_u9+PE$1A* zC}*Ir=00x5PcP#^!dD1fqlyQ*luz`;A!<>kfz2c46Jp!v9fJdrKEl*4EbEDrwD7Fe%T%C?cj2&^WXT0M3H^zHc1_7jstE=A4bYrq7pUzIQ4 z_$Ce);M$wK?=4ER%GfC8+=ZMFSOqdX(l&^b_36!0k%hpd1{cZEC~-$}wml7T6sYCd zY(L$c-Y`YwGQ;+-F9xcd%GL(ON5UUaP-e=FQ^DP}CRr4p?%k|^u?NMtVew@sk@hAXIiUI-Qdp)v&;_QaAcG zQjk3`sN8l&(EeeA@pwBD7Jstdr#X_KBbmVhK%>*l9t59`CLP4EYfcK=uKoH6-og0? zTd%Bv@sXeN?>jilDjqdIUjF;O;%+>Wzi6i)9;)t=>G7)BZo8Bc7ytc5B8;n>E&Ju_ ziSZBK7y%jKzqiPYK7vYFWwdoWKQreAoP3CaW*gMHL~BpN9V4rr1#Ih#2r3f z&ppJ`+wvRPyN4=&ht`t0Y4-kPnfvJwGEgoE72``7qP@L4QT?g(ObCv=X1o!>6ZD9W z`mAIDWpz4MoS3IA7Z1Z};15r+iJmBhSU*?1s9wx z-)btOIZ`Uk;S8`2Fm&NA8ruBA$9vt2EnxMF9d^s62SC3#yof+oy5bn}izkI&rM4F0uQ z?2&Jj2^=yb3AEP1sOKCO22vWLf*Wep%%w#A%W|BkyB>MpHKj9a6u69S)L>7exMXH%YPYfE`l6Yt8zmdeC|>Y|GXfP(Ux@d4EXl%< zDJ#+bnJ2UG12W!05Xk(!xgv^{I@I43&|~Yr^)7DoKiLz_Ma8Ai`^LT|wqUHU<;asE zvj-s8#&vH#*TALKfA!t40A?Du7zhAfOSzL|6$?R?5B1X1Zh-TVu<`i#k*T(j@p35Y z(a=;>w}_hMd=Y@qiE1K>rxg{FUQ@wxzc)(J%nr47v~o@_Q zKom^>h_>X_4N}W)Xe85@F^C_olzhVF!X5H}D2c`Z7rC76pKOhL$(S-_7#L|y8T8}} zAs=m7doTP$XQ_1=_p6Wg@x@fV=4aRQuafUpeNLik+y(wfdDR#rlNxj7r{!UJM z3Ts2Akz)FdK`e-6NN+qO%jN!UaJ+_wsPE*PUjYy{l&nUlea5TTo&g!|Y{~xIM9Oqe zYm#UZCo8DQsuWC8DQ{Lr|6&Z-n^(i(y;F9_Nrb=S*)Dn3(QB{tcYdat`C%a z20_P|Z#zJ4dB|P9uaX3xorWuDDTm+|!Q)+bwo2DIXmVAU&^3fczd=+^PL=i|yXa6u z(wEahW)?}q#F_GtefK1$Gl>*~*!LL^Y@~tn=^}v8*^=ZV*4e#D7r6+PXU%q!8F&M@ zVLO@4kH=22o$y;4MU<^C>A|tAIygKQ*_*}PQei`oWHSqDl;4v(Fbmf1ul&`t6A4xm zuazB^X6t0wP*C;DY)*cp9g0+_+rq0o_|xbURVFpsAM#ofw5ObUpxBbkSCc&NET&vF zH&jSlc5|)C&uPn+V9Ob+ztkn*eF-P4G<>7ph7wJsoOzUf*90xAy-|W+V3!YOa)Ug~ zq)yGX_ua6|Pm+~xp{g>i>4AFAsn|Vlq}#!Pl+IW;3bi-3J6a}C7o`<0UTq?KKey2-?_xy#SJ&IFFk~?Qf*6W`{kin~*Z0&wyy&+ky4@ zTQztcHE4mL&F#saE^ndN-Pa&|}E>S*BT4#X|EL)<^+tELMemccd_+83zql}3!~Lp z@q<zaOntNkq4?qn|ww1-;{&+YsNsYE#!|4j- zwBki92sZ4Ub-Nw?j1WV@K6QYxL;Z{~xJ@c$c^@$?S$Y8G;w&L_^O|(L%*q>`BQyVe zk_sVgOcclW!X`N!DST&eD&F}B)5*8A8<`$D`+*Nj{Py2pnZg7-7=b^UrDjCT`)lb& zXSn1f5(bbrJzI7TZskVm-bi^DLw1bwl~$r^a7OcI8lh3Ean~;Ncv&1|*Eb7|?zhUr zf*nSRO@F~vtwZ*j%!p=7rFk@qYU=Qt%A-*W=$cLxVWWEPx_xxefG*D`3U3BXDk9-( zBcz9io9#Y|!PMZP3v zwQNcF1)OK0`YD%F=V66TE@E<_zM+=5D6x625Xr4t>M9QNKBe!^E6${KCcq03f2a^@ zE-~D@MUk%6Nc|(sjuS|Y$~a0(h27Alh7)iKvHd zO|b?{`fOL!y!)GAN23NP)P)!9dK@`MAU6mjwJd<-?>hGJLU59!`-BE_&u=a%-M6C5!?fkUeZggLI%N)|XVQBra?? zj!30!^7`4&pf9NxC8;3T5sDV(UMK&UdozSHR#bf`{gO-7Sm-kfbQUJ|dNZICClH9K zKW5x{*mZwfk6{FC_w8_Y(o{*5TgTGE7h4yO_R{lbe(uE$6iAk&tmXGZC(^`f{B)#1 z@~YtjW2jcbx9a<{L8EjfHQcJ*4~ysu652m?P&Mti`HIX7u4I;mQJVwo>B6ZYH=35X zl6$OmoihCUx5g#S*y?q0;2^k^W}6A>)*_-*83Cj-Sh?zsse%1-=9An&)XavRp=kCD zzvz>SBuOJcL1SFOi45#uSH!dQN;~$N>r;Pi;;|#Aio6+i#PIuafB62oBkf$Ov{r!S z$g>TL8Ju0so1I#$f0eLG0*!8-7C~a<3!H02?@jr!3@hoO*=G{-ctTF)@BV1u#FuMs z93OKF=Gqeuob`qU0U3OZcAa&)S#A92p7=azu6AM4d?g!N^g zh9?E7Q;m}T)1#6CR$??3DX7?*M#!JL}^*GBQNPi0HJ) zz3XI+gC@iiu|-8DF)zD%uPyl|U0(#5N>IL~7{sZ=&RWS~%gQYSI|`6#K{~`zdDGa` zLPSB_f@79(;7dP@{?9r&YzpNO%-S<4~OlITI?TqY5<0#xtE^%~NAnR08f^+>uXJ;}tF>e&@r zyn!JUpe&gBQ8b7f?4Ex6PNSpZToKt}0j$gC4lhBAHnC3~eNbpsQ1v_v0^vP~Wc**U z%NM4!`*+BJGIJ}56yaVtyTm!HNZv8&R8V;<&({}a@7k6OTXFEae3o;rFBNukAmul) zog={x`YN56Zrq?a7E^NJus(8(2Am_R?&1*Pz?J)%Z@&UeNd<$gbUD{(QV|Jl3hHfb zIXln0pX(=cqct+Y8+zt9#D}Kp1d35pfT88z3NK?~DH~I0zHu&$Os{FW%p>Xsd?S4=gr^dcGyOI}_h;4uL zc#P|1!>DQ6Bv?ASoeALQiI|J*c69jm)xca0eA+AhYrQsBuyy@%Gcupn1<+ zoxv?TD5|Ffhd3Q$*=YJ6-Nku33%8NevUd- z#{Fi1ZTus4rn%orpjDC;ic}YF<~NAf{HCby1wEb({+c0|gg4okNR1 zj%#wJ*MLM|QWP$}ZZCYM@ZIR-iff^EIl+@2748D>d&Iw52yRQ_sDeaw^q^o;>!HEB zvj(@luo}Se2~}Wyx0z>sbS@<%%$$;aB=ZcqD$Y}5jbFVbJGiR<-49zA0l_wY6w#!A zE|yRW4d0wK(1^c`T5AW1Wh)SVE=ge*d5ZC(gBBBXIdGVSP()!U;UbD>Tr4~eWdOMh z9Pr^QbW}BLyNC;*fA5;4DyjgE)V;r}hmB7SEvn+z>~>&{O}U^cBG8R2W(A%PSpQ(Q zrC@BJku7j^>&jhiM|}VO0RN|s_g5ndnSQMS*aeY09?tgJ$DmGTwITJif^+*#^JcA4 z@wuVNSHF}8;*NO_2w!?FM z`pORoPMi{JY!;yoW=&qK{+7fg5NE|Z>8TOe59kj}8CsZrGyI%zN5_5DV7FS2pmc`P z_-Kgy82qUx)QD*u)QUo`Ff%}JiRLH|*)K1bx~go5G+0RRtGjs^Vo|$2BKRB$aNP+>`oAjJOMU!Z%!P z_<)clvgvJ9?nxgBu57x?lSsdjM!TRBrUp?vR2467yN`k5vmyD(TKWdhVN`gd0cU8TDotYxqCpY;vM}U=||mMTr-T*uEkIZ^dCiwexvQfCq<&={<@IkHl?p zk#;dHLIMAI47&6^vZ{R2KLPa74?acv)bts(ee096kl5MndSR;7aEJVH zCr}Thfe?(MVVXImvCDoupfXEATMrRh5cE4UNzwnkhgwkmaWcH=M0JN zfrpR~tiVUn2=Zn0(R=m&&DwQu5p3+y$?7WP@U%hCN3=f6efcoU6APlo7itW}b};-Q z_-JxsMnPVnn%e{MDzT=9rb5o0-;oP;a5b8N{9v50gAT^w$?XQ+h+aq3nju+(L!se~ zz~?LkyBiB2wQ_hZp_Ez4y--5VO?)_GwoxCX6=fxs07f+e+3q^9jBV8ldo2tL`i@Ga zLyh*#FEI)xnBW|(FMTwixDk+Re-NC^eLIfi@;mw}OV#KVCmL&68B=FAW&dM0v4zJh zZHEY*wH`U4-DsaDu{-;Kt|csJ;769AeCSj@;_eTu+>9g8b94Eikj~s;x$5^?S1AbB zP<=WpmDw}pj@juD;?$vp*!0sf^%+G@i{4~2^#ZZ(9PYYXZl4^wDf8_ofmxo&jcn{? zQ{B?3_Yj6$TL@yI1>SLUQaR=UAHr$hcRNctGnF2DjZO$dFO(Wxc4Eil|qCy~F!fgE^^ znY3|pr$)g%{iCf0UP?L_UlxK2&3KWk{h4Ib_6pKf7Q8N|=jmWy(I5FF@Z#AL&$u*4 z7iZclJ{8CoQ(jQA@>ouE&OepaAI3+Rl-+xl#U6fPO_~%ZE_%r`J|Mv-V+0cD&LmDx zjZQ*?ZZ))$u}&%{e#=r*`$v{CZ5)U%Xlng`>c}o98ZN=6crip-P?ddv_lTQ}jiWYeyBJaCpSx)U(|L8MyT}a$ z5F{kmmr`lF>F`Py+_9&xBCli6`tFiU$U=}%94>8)1*F^Ksww0M-{p?q+#73l@V!&G z&tS5=1C6Ja`+wYzOm?GojH(x@TEgE|%m3!(Jw7`G*IYwASG0PLfSV-5a*c-i2tmqMV-h`}?-!U4K3V-S%kI07@SHi0wsxOb zrafr{L}$a7Ss|&)n8i=AdCv~n_cxzUnI1Ga%*rLl>hf^73F%*8PdXQ)pZY1J&BJM4 z2k`uzjn8SDj|qDSy7I-CRaBl|&HtOT5fHk_>6W!EI zS?|r{z@%%Ck%S~%hVu#T^*U~M;uUO=w+a^$d^#(do zOl%tU>OyPBdkOB#3ghM~ z)*~4iCi5bHx_L#WUr|^gt->2un|8weH%(d#j{(XoUP~HUDwS^cXvNb#KRXgwzz~zMMg^}BS2jxha(;`PX!%R_dMt%!C2j$Ke*0P; zI`xnlBD>{jf0GkrrOB-IZO}HDPug?{Dk)p z3lV&`Hu$`lgVEcLFqt;`At_xe`zBqx1!*xqQbnFs?E&B2DON@P2sYcRV6^1EUC?-4 zQmTbHNSYj#o<<6&8JSJB+KshSW|{nwefeo67#yQK(NH%Z_dd?%r1LM@J~VPQjTG(E zn3aRbc%Z|l1A@(^EHr$9I>VBagO3gzkjYX--DcTZPBzGbyyEHUwP()iwjQ0)X6Yvl zx!#k064jw&4RfSRkn9+G9S8#MB0iUbl*pOE#XwNgwX1gx{6j9KA~eS0EduV3?w|99 z;!#uTT47^<<`W15sZH5BzPvQo+N^A1f!feA&}m5NX+)dNIakNN=iO7+c6zZ3 zpPWe4TzBfBrk(EYRRthX|Fa|3%t4@gP{*rQdMI-R!(`}|<}^~Z3zSa=OA7MQIygW4 zp?h}GhfiO8@IEZT;+9U_%KwNt{hoo7Nlr@Y?<^}%GP(YLr#ym$8{4qC3;w6R{u5FK z!PNitx%hbVC;!t&|MM6V@zZTP^y^RjHwN-gTm1#-Vc0yAOj;iPe?euM+fWZ59sj5G pI{h~x;ncG$^MAG7Hq;kiGX{lA^2xWLe`7BoG7<{n)uKiL{|CB|K&Joz diff --git a/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png b/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png deleted file mode 100644 index fcf8eea5f910dd8327832888a374d647e2f182a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49775 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 TLu%G?J|q?77R$~p6%9WC2R(%6 diff --git a/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png.map b/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png.map deleted file mode 100644 index 5f7c3c74..00000000 --- a/_images/inheritance-3f291effbf8fa69d4aad95cc3ac035b2f6726a28.png.map +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/_images/inheritance-c64563669cfd1729a6777088d6be9e21c8889310.png b/_images/inheritance-c64563669cfd1729a6777088d6be9e21c8889310.png deleted file mode 100644 index 0dd34b6a7d314f238ae12db6eef5131326221a82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50434 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 - diff --git a/_images/inheritance-e033a0922f5fc94c2076bb1330e6d8bb39cf71c1.png b/_images/inheritance-e033a0922f5fc94c2076bb1330e6d8bb39cf71c1.png deleted file mode 100644 index 26a43f427b7faf662e1da6923c3edccd5da4260f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25253 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 bk=NI+z%8wz_=5dKJ|Ti - - - - - - - - - - - - - - - - diff --git a/_images/inheritance-f7035f78b7760b2f76f4df0f21b8be07cd18e555.png b/_images/inheritance-f7035f78b7760b2f76f4df0f21b8be07cd18e555.png deleted file mode 100644 index 1b16b2d9e955b566438cab240701eeea757aa2de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25502 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 UPFQ$? - - - - - - - - - - - - - - - - diff --git a/_images/pull_button.png b/_images/pull_button.png deleted file mode 100644 index e5031681b97bcc3b323a01653153c8d6bcfb5507..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12893 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 I#f$>~7cL{PD*ylh diff --git a/_modules/astropy/config/configs.html b/_modules/astropy/config/configs.html deleted file mode 100644 index aa853151..00000000 --- a/_modules/astropy/config/configs.html +++ /dev/null @@ -1,540 +0,0 @@ - - - - - - - - - - astropy.config.configs — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - -

                - -
                -
                -
                -
                - -

                Source code for astropy.config.configs

                -# Licensed under a 3-clause BSD style license - see LICENSE.rst
                -"""This module contains classes and functions to standardize access to
                -configuration files for Astropy and affiliated packages.
                -
                -.. note::
                -    The configuration system makes use of the 'configobj' package, which stores
                -    configuration in a text format like that used in the standard library
                -    `ConfigParser`. More information and documentation for configobj can be
                -    found at http://www.voidspace.org.uk/python/configobj.html.
                -"""
                -
                -from __future__ import division
                -from ..extern.configobj import configobj, validate
                -
                -__all__ = ['ConfigurationItem', 'InvalidConfigurationItemWarning',
                -            'get_config', 'save_config', 'reload_config']
                -
                -
                -
                [docs]class InvalidConfigurationItemWarning(Warning): - """ A Warning that is issued when the configuration value specified in the - astropy configuration file does not match the type expected for that - configuration value. - """ - -
                -
                [docs]class ConfigurationItem(object): - """ A setting and associated value stored in the astropy configuration - files. - - These objects are typically defined at the top of astropy subpackages - or affiliated packages, and store values or option settings that can be - modified by the user to - - Parameters - ---------- - name : str - The (case-sensitive) name of this parameter, as shown in the - configuration file. - defaultvalue - The default value for this item. If this is a list of strings, this item - will be interpreted as an 'options' value - this item must be one of - those values, and the first in the list will be taken as the default - value. - description : str or None - A description of this item (will be shown as a comment in the - configuration file) - cfgtype : str or None - A type specifier like those used as the *values* of a particular key in - a `configspec` file of `configobj`. If None, the type will be inferred - from the default value. - module : str or None - The full module name that this item is associated with. The first - element (e.g. 'astropy' if this is 'astropy.config.configs') will be - used to determine the name of the configuration file, while the - remaining items determine the section. If None, the package will be - inferred from the package within whiich this object's initializer is - called. - - Raises - ------ - RuntimeError - If `module` is None, but the module this item is created from cannot - be determined. - - Examples - -------- - The following example will create an item 'cfgoption = 42' in the - '[configs]' section of astropy.cfg (located in the directory that - `astropy.config.paths.get_config_dir` returns), or if the option is already - set, it will take the value from the configuration file:: - - from astropy.config import ConfigurationItem - - CFG_OPTION = ConfigurationItem('cfgoption',42,module='astropy.configs') - - If called as ``CFG_OPTION()``, this will return the value ``42``, or some - other integer if the ``astropy.cfg`` file specifies a different value. - - If this were in the ``astropy/configs/__init__.py`` file, the `module` - option would not be necessary, as it would automatically detect the correct - module. - - """ - - #this is used to make validation faster so a Validator object doesn't - #have to be created every time - _validator = validate.Validator() - - def __init__(self, name, defaultvalue='', description=None, cfgtype=None, - module=None): - from warnings import warn - from ..utils import find_current_module - - if module is None: - module = find_current_module(2) - if module is None: - msg1 = 'Cannot automatically determine get_config module, ' - msg2 = 'because it is not called from inside a valid module' - raise RuntimeError(msg1 + msg2) - else: - module = module.__name__ - - self.name = name - self.module = module - self.description = description - - #now determine cfgtype if it is not given - if cfgtype is None: - if isinstance(defaultvalue, list): - #it is an options list - dvstr = [str(v) for v in defaultvalue] - cfgtype = 'option(' + ', '.join(dvstr) + ')' - defaultvalue = dvstr[0] - elif isinstance(defaultvalue, bool): - cfgtype = 'boolean' - elif isinstance(defaultvalue, int): - cfgtype = 'integer' - elif isinstance(defaultvalue, float): - cfgtype = 'float' - else: - cfgtype = 'string' - defaultvalue = str(defaultvalue) - - self.cfgtype = cfgtype - - self._validate_val(defaultvalue) - self.defaultvalue = defaultvalue - - #note that the actual value is stored in the ConfigObj file for this - #package - - #this checks the current value to make sure it's valid for the type - #as well as updating the ConfigObj with the default value, if it's not - #actually in the ConfigObj - try: - self() - except TypeError as e: - # make sure it's a TypeError from __call__ - if 'Configuration value not valid:' in e.args[0]: - warn(InvalidConfigurationItemWarning(*e.args)) - else: - raise - -
                [docs] def set(self, value): - """ Sets the current value of this `ConfigurationItem`. - - This also updates the comments that give the description and type - information. - - .. note:: - This does *not* save the value of this `ConfigurationItem` to the - configuration file. To do that, use `ConfigurationItem.save` or - `save_config`. - - Parameters - ---------- - value - The value this item should be set to. - - Raises - ------ - TypeError - If the provided `value` is not valid for this `ConfigurationItem`. - """ - try: - value = self._validate_val(value) - except validate.ValidateError as e: - msg = 'Provided value for configuration item {0} not valid: {1}' - raise TypeError(msg.format(self.name, e.args[0])) - - sec = get_config(self.module) - - sec[self.name] = value - sec.comments[self.name] = self._generate_comments() -
                -
                [docs] def save(self, value=None): - """ Writes a value for this `ConfigurationItem` to the relevant - configuration file. - - This also writes updated versions of the comments that give the - description and type information. - - .. note:: - This only saves the value of this *particular* `ConfigurationItem`. - To save all configuration settings for this package at once, see - `save_config`. - - Parameters - ---------- - value - Save this value to the configuration file. If None, the current - value of this `ConfigurationItem` will be saved. - - Raises - ------ - TypeError - If the provided `value` is not valid for this `ConfigurationItem`. - """ - try: - value = self() if value is None else self._validate_val(value) - except validate.ValidateError as e: - msg = 'Provided value for configuration item {0} not valid: {1}' - raise TypeError(msg.format(self.name, e.args[0])) - - #Now find the ConfigObj that this is based on - baseobj = get_config(self.module) - secname = baseobj.name - cobj = baseobj - #a ConfigObj's parent is itself, so we look for the parent with that - while cobj.parent is not cobj: - cobj = cobj.parent - - #use the current on disk version, which will be modified with the - #given value and type/description - newobj = configobj.ConfigObj(cobj.filename) - if secname is not None: - if secname not in newobj: - newobj[secname] = {} - newsec = newobj[secname] - - newsec[self.name] = value - newsec.comments[self.name] = self._generate_comments() - newobj.write() -
                -
                [docs] def reload(self): - """ Reloads the value of this `ConfigurationItem` from the relevant - configuration file. - - Returns - ------- - val - The new value loaded from the configuration file. - """ - baseobj = get_config(self.module) - secname = baseobj.name - - cobj = baseobj - #a ConfigObj's parent is itself, so we look for the parent with that - while cobj.parent is not cobj: - cobj = cobj.parent - - newobj = configobj.ConfigObj(cobj.filename) - if secname is not None: - newobj = newobj[secname] - - baseobj[self.name] = newobj[self.name] -
                - def __call__(self): - """ Returns the value of this `ConfigurationItem` - - Returns - ------- - val - This item's value, with a type determined by the `cfgtype` - attribute. - - Raises - ------ - TypeError - If the configuration value as stored is not this item's type. - """ - - #get the value from the relevant `configobj.ConfigObj` object - sec = get_config(self.module) - if self.name not in sec: - self.set(self.defaultvalue) - val = sec[self.name] - - try: - return self._validate_val(val) - except validate.ValidateError as e: - raise TypeError('Configuration value not valid:' + e.args[0]) - - def _validate_val(self, val): - """ Validates the provided value based on cfgtype and returns the - type-cast value - - throws the underlying configobj exception if it fails - """ - #note that this will normally use the *class* attribute `_validator`, - #but if some arcane reason is needed for making a special one for an - #instance or sub-class, it will be used - return self._validator.check(self.cfgtype, val) - - def _generate_comments(self): - comments = [] - if self.description is not None: - comments.append(self.description) - if self.cfgtype is not None: - comments.append(self.cfgtype) - comments.append('') # adds a blank line after every entry - return comments - - -# this dictionary stores the master copy of the ConfigObj's for each -# root package
                -_cfgobjs = {} - - -
                [docs]def get_config(packageormod=None, reload=False): - """ Gets the configuration object or section associated with a particular - package or module. - - Parameters - ----------- - packageormod : str or None - The package for which to retrieve the configuration object. If a string, - it must be a valid package name, or if None, the package from which this - function is called will be used. - - Returns - ------- - cfgobj : `configobj.ConfigObj` or `configobj.Section` - If the requested package is a base package, this will be the - `configobj.ConfigObj` for that package, or if it is a subpackage or - module, it will return the relevant `configobj.Section` object. - - Raises - ------ - RuntimeError - If `package` is None, but the package this item is created from cannot - be determined. - - """ - from os.path import join - from .paths import get_config_dir - from ..utils import find_current_module - - if packageormod is None: - packageormod = find_current_module(2) - if packageormod is None: - msg1 = 'Cannot automatically determine get_config module, ' - msg2 = 'because it is not called from inside a valid module' - raise RuntimeError(msg1 + msg2) - else: - packageormod = packageormod.__name__ - - packageormodspl = packageormod.split('.') - rootname = packageormodspl[0] - secname = '.'.join(packageormodspl[1:]) - - cobj = _cfgobjs.get(rootname, None) - if cobj is None: - cfgfn = join(get_config_dir(), rootname + '.cfg') - _cfgobjs[rootname] = cobj = configobj.ConfigObj(cfgfn) - - if secname: # not the root package - if secname not in cobj: - cobj[secname] = {} - return cobj[secname] - else: - return cobj - -
                -
                [docs]def save_config(packageormod=None): - """ Saves all configuration settings to the configuration file for the - root package of the requested package/module. - - This overwrites any configuration items that have been changed in - `ConfigurationItem` objects that are based on the configuration file - determined by the *root* package of `packageormod` (e.g. 'astropy.cfg' for - the 'astropy.config.configs' module). - - .. note:: - To save only a single item, use the `ConfigurationItem.save` method - - this will save all options in the current session that may have been - changed. - - Parameters - ---------- - packageormod : str or None - The package or module name - see `get_config` for details. - """ - sec = get_config(packageormod) - #look for the section that is its own parent - that's the base object - while sec.parent is not sec: - sec = sec.parent - sec.write() - -
                -
                [docs]def reload_config(packageormod=None): - """ Reloads configuration settings from a configuration file for the root - package of the requested package/module. - - This overwrites any changes that may have been made in `ConfigurationItem` - objects. This applies for any items that are based on this file, which is - determined by the *root* package of `packageormod` (e.g. 'astropy.cfg' for - the 'astropy.config.configs' module). - - Parameters - ---------- - packageormod : str or None - The package or module name - see `get_config` for details. - """ - sec = get_config(packageormod) - #look for the section that is its own parent - that's the base object - while sec.parent is not sec: - sec = sec.parent - sec.reload() - -
                -def _generate_all_config_items(pkgornm=None, reset_to_default=False): - """ Given a root package name or package, this function simply walks through - all the subpackages and modules, which should populate any ConfigurationItem - objects defined at the module level. If `reset_to_default` is True, it also - sets all of the items to their default values, regardless of what the file's - value currently is. It then saves the `ConfigObj`. - - If `pkgname` is None, it determines the package based on the root package of - the function where this function is called. Be a bit cautious about this, - though - this might not always be what you want. - """ - from pkgutil import find_module, walk_packages - from types import ModuleType - - from ..utils import find_current_module - - if pkgornm is None: - pkgornm = find_current_module(1).__name__.split('.')[0] - - if isinstance(pkgornm, basestring): - package = find_module(pkgornm).load_module(pkgornm) - elif isinstance(pkgornm, ModuleType) and '__init__' in pkgornm.__file__: - package = pkgornm - else: - msg = '_generate_all_config_items was not given a package/package name' - raise TypeError(msg) - - for imper, nm, ispkg in walk_packages(package.__path__, - package.__name__ + '.'): - mod = imper.load_module(nm) - if reset_to_default: - for v in mod.__dict__.itervalues(): - if isinstance(v, ConfigurationItem): - v.set(v.defaultvalue) - save_config(package.__name__) -
                - -
                -
                -
                -
                -
                - - - -
                -
                -
                -
                - - - - \ No newline at end of file diff --git a/_modules/astropy/config/data.html b/_modules/astropy/config/data.html deleted file mode 100644 index da41c2ae..00000000 --- a/_modules/astropy/config/data.html +++ /dev/null @@ -1,760 +0,0 @@ - - - - - - - - - - astropy.config.data — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
                -
                -
                -
                - -

                Source code for astropy.config.data

                -# Licensed under a 3-clause BSD style license - see LICENSE.rst
                -""" This module contains helper functions for accessing, downloading, and
                -caching data files.
                -"""
                -
                -from __future__ import division
                -from .configs import ConfigurationItem
                -from sys import version_info
                -
                -__all__ = ['get_data_fileobj', 'get_data_filename', 'get_data_contents',
                -           'get_data_fileobjs', 'get_data_filenames', 'compute_hash',
                -           'clear_data_cache']
                -
                -DATAURL = ConfigurationItem(
                -    'dataurl', 'http://data.astropy.org/', 'URL for astropy remote data site.')
                -REMOTE_TIMEOUT = ConfigurationItem(
                -    'remote_timeout', 3., 'Time to wait for remote data query (in seconds).')
                -COMPUTE_HASH_BLOCK_SIZE = ConfigurationItem(
                -    'hash_block_size', 2 ** 16,  # 64K
                -    'Block size for computing MD5 file hashes.')
                -DATA_CACHE_DL_BLOCK_SIZE = ConfigurationItem(
                -    'data_dl_block_size', 2 ** 16,  # 64K
                -    'Number of bytes of remote data to download per step.')
                -DATA_CACHE_LOCK_ATTEMPTS = ConfigurationItem(
                -    'data_cache_lock_attempts', 3, 'Number of times to try to get the lock ' +
                -    'while accessing the data cache before giving up.')
                -
                -if version_info[0] < 3:
                -    #used for supporting with statements in get_data_fileobj
                -    def _fake_enter(self):
                -        return self
                -
                -    def _fake_exit(self, type, value, traceback):
                -        self.close()
                -
                -
                -
                [docs]def get_data_fileobj(dataname, cache=True): - """ - Retrieves a data file from the standard locations and provides the file as - a file-like object. - - Parameters - ---------- - dataname : str - Name/location of the desired data file. One of the following: - - * The name of a data file included in the source - distribution. The path is relative to the module - calling this function. For example, if calling from - `astropy.pkname`, use ``'data/file.dat'`` to get the - file in ``astropy/pkgname/data/file.dat``. Double-dots - can be used to go up a level. In the same example, use - ``'../data/file.dat'`` to get ``astropy/data/file.dat``. - * If a matching local file does not exist, the Astropy - data server will be queried for the file. - * A hash like that produced by `compute_hash` can be - requested, prefixed by 'hash/' - e.g. 'hash/395dd6493cc584df1e78b474fb150840'. The hash - will first be searched for locally, and if not found, - the Astropy data server will be queried. - * A URL to some other file. - - cache : bool - If True, the file will be downloaded and saved locally or the - already-cached local copy will be accessed. If False, the file-like - object will directly access the resource (e.g. if a remote URL is - accessed, an object like that from `urllib2.urlopen` is returned). - - Returns - ------- - fileobj : file-like - An object with the contents of the data file available via :func:`read`. - Can be used as part of a ``with`` statement, automatically closing - itself after the ``with`` block. - - Raises - ------ - urllib2.URLError - If a remote file cannot be found. - IOError - If problems occur writing or reading a local file. - - Examples - -------- - - This will retrieve a data file and its contents for the `astropy.wcs` - tests:: - - from astropy.config import get_data_fileobj - - with get_data_fileobj('data/3d_cd.hdr') as fobj: - fcontents = fobj.read() - - - This downloads a data file and its contents from a specified URL, and does - *not* cache it remotely:: - - from astropy.config import get_data_fileobj - - vegaurl = 'ftp://ftp.stsci.edu/cdbs/grid/k93models/standards/vega.fits' - with get_data_fileobj(vegaurl,False) as fobj: - fcontents = fobj.read() - - See Also - -------- - get_data_contents : returns the contents of a file or url as a bytes object - get_data_filename : returns a local name for a file containing the data - """ - from os.path import isdir, isfile - from urlparse import urlparse - from urllib2 import urlopen - from types import MethodType - - if cache: - return open(get_data_filename(dataname), 'rb') - else: - url = urlparse(dataname) - if url[0] != '': # url[0]==url.scheme, but url[0] is py 2.6-compat - #it's actually a url for a net location - urlres = urlopen(dataname, timeout=REMOTE_TIMEOUT()) - else: - datafn = _find_pkg_data_path(dataname) - if isdir(datafn): - raise IOError( - "Tried to access a data file that's actually " - "a package data directory") - elif isfile(datafn): - return open(datafn, 'rb') - else: - #not local file - need to get remote data - urlres = urlopen(DATAURL() + datafn, timeout=REMOTE_TIMEOUT()) - - if version_info[0] < 3: - #need to add in context managers to support with urlopen for <3.x - urlres.__enter__ = MethodType(_fake_enter, urlres) - urlres.__exit__ = MethodType(_fake_exit, urlres) - - return urlres - -
                -
                [docs]def get_data_filename(dataname): - """ - Retrieves a data file from the standard locations and provides the local - name of the file. - - This function is similar to `get_data_fileobj` but returns the file *name* - instead of a readable file-like object. This means that this function must - always cache remote files locally, unlike `get_data_fileobj`. - - Parameters - ---------- - dataname : str - Name/location of the desired data file. One of the following: - - * The name of a data file included in the source - distribution. The path is relative to the module - calling this function. For example, if calling from - `astropy.pkname`, use ``'data/file.dat'`` to get the - file in ``astropy/pkgname/data/file.dat``. Double-dots - can be used to go up a level. In the same example, use - ``'../data/file.dat'`` to get ``astropy/data/file.dat``. - * If a matching local file does not exist, the Astropy - data server will be queried for the file. - * A hash like that produced by `compute_hash` can be - requested, prefixed by 'hash/' - e.g. 'hash/395dd6493cc584df1e78b474fb150840'. The hash - will first be searched for locally, and if not found, - the Astropy data server will be queried. - * A URL to some other file. - - Raises - ------ - urllib2.URLError - If a remote file cannot be found. - IOError - If problems occur writing or reading a local file. - - Returns - ------- - filename : str - A file path on the local file system corresponding to the data - requested in `dataname`. - - Examples - -------- - - This will retrieve the contents of the data file for the `astropy.wcs` - tests:: - - from astropy.config import get_data_filename - - fn = get_data_filename('data/3d_cd.hdr') - with open(fn) as f: - fcontents = f.read() - - - This retrieves a data file by hash either locally or from the astropy data - server:: - - from astropy.config import get_data_filename - - fn = get_data_filename('hash/da34a7b07ef153eede67387bf950bb32') - with open(fn) as f: - fcontents = f.read() - - See Also - -------- - get_data_contents : returns the contents of a file or url as a bytes object - get_data_fileobj : returns a file-like object with the data - """ - from os.path import isdir, isfile - from urlparse import urlparse - - url = urlparse(dataname) - if url[0] != '': # url[0]==url.scheme, but url[0] is py 2.6-compat - #it's actually a url for a net location - return _cache_remote(dataname) - elif dataname.startswith('hash/'): - #first try looking for a local version if a hash is specified - hashfn = _find_hash_fn(dataname[5:]) - if hashfn is None: - return _cache_remote(DATAURL() + dataname) - else: - return hashfn - else: - datafn = _find_pkg_data_path(dataname) - if isdir(datafn): - raise IOError( - "Tried to access a data file that's actually " - "a package data directory") - elif isfile(datafn): - return datafn - else: - #look for the file on the data server - return _cache_remote(DATAURL() + dataname) - -
                -
                [docs]def get_data_contents(dataname, cache=True): - """ - Retrieves a data file from the standard locations and returns its - contents as a bytes object. - - Parameters - ---------- - dataname : str - Name/location of the desired data file. One of the following: - - * The name of a data file included in the source - distribution. The path is relative to the module - calling this function. For example, if calling from - `astropy.pkname`, use ``'data/file.dat'`` to get the - file in ``astropy/pkgname/data/file.dat``. Double-dots - can be used to go up a level. In the same example, use - ``'../data/file.dat'`` to get ``astropy/data/file.dat``. - * If a matching local file does not exist, the Astropy - data server will be queried for the file. - * A hash like that produced by `compute_hash` can be - requested, prefixed by 'hash/' - e.g. 'hash/395dd6493cc584df1e78b474fb150840'. The hash - will first be searched for locally, and if not found, - the Astropy data server will be queried. - * A URL to some other file. - - cache : bool - If True, the file will be downloaded and saved locally or the - already-cached local copy will be accessed. If False, the file-like - object will directly access the resource (e.g. if a remote URL is - accessed, an object like that from `urllib2.urlopen` is returned). - - Returns - ------- - contents : bytes - The complete contents of the file as a bytes object. - - Raises - ------ - urllib2.URLError - If a remote file cannot be found. - IOError - If problems occur writing or reading a local file. - - See Also - -------- - get_data_fileobj : returns a file-like object with the data - get_data_filename : returns a local name for a file containing the data - """ - with get_data_fileobj(dataname, cache=cache) as fd: - contents = fd.read() - return contents - -
                -
                [docs]def get_data_filenames(datadir, pattern='*'): - """ - Returns the path of all of the data files in a given directory - that match a given glob pattern. - - Parameters - ---------- - datadir : str - Name/location of the desired data files. One of the following: - - * The name of a directory included in the source - distribution. The path is relative to the module - calling this function. For example, if calling from - `astropy.pkname`, use ``'data'`` to get the - files in ``astropy/pkgname/data``. - * Remote URLs are not currently supported. - - pattern : str, optional - A UNIX-style filename glob pattern to match files. See the - `glob` module in the standard library for more information. - By default, matches all files. - - Returns - ------- - filenames : iterator of str - Paths on the local filesystem in *datadir* matching *pattern*. - - Examples - -------- - This will retrieve the contents of the data file for the `astropy.wcs` - tests:: - - from astropy.config import get_data_filenames - - for fn in get_data_filename('maps', '*.hdr'): - with open(fn) as f: - fcontents = f.read() - """ - import fnmatch - from os.path import isdir, isfile, join - from os import listdir - - path = _find_pkg_data_path(datadir) - if isfile(path): - raise IOError( - "Tried to access a data directory that's actually " - "a package data file") - elif isdir(path): - for filename in listdir(path): - if fnmatch.fnmatch(filename, pattern): - yield join(path, filename) - else: - raise IOError("Path not found") - -
                -
                [docs]def get_data_fileobjs(datadir, pattern='*'): - """ - Returns readable file objects for all of the data files in a given - directory that match a given glob pattern. - - Parameters - ---------- - datadir : str - Name/location of the desired data files. One of the following: - - * The name of a directory included in the source - distribution. The path is relative to the module - calling this function. For example, if calling from - `astropy.pkname`, use ``'data'`` to get the - files in ``astropy/pkgname/data`` - * Remote URLs are not currently supported - - pattern : str, optional - A UNIX-style filename glob pattern to match files. See the - `glob` module in the standard library for more information. - By default, matches all files. - - Returns - ------- - fileobjs : iterator of file objects - File objects for each of the files on the local filesystem in - *datadir* matching *pattern*. - - Examples - -------- - This will retrieve the contents of the data file for the `astropy.wcs` - tests:: - - from astropy.config import get_data_filenames - - for fd in get_data_filename('maps', '*.hdr'): - fcontents = fd.read() - """ - for fn in get_data_filenames(datadir, pattern): - with open(fn, 'rb') as fd: - yield fd - -
                -
                [docs]def compute_hash(localfn): - """ Computes the MD5 hash for a file. - - The hash for a data file is used for looking up data files in a unique - fashion. This is of particular use for tests; a test may require a - particular version of a particular file, in which case it can be accessed - via hash to get the appropriate version. - - Typically, if you wish to write a test that requires a particular data - file, you will want to submit that file to the astropy data servers, and - use e.g. ``get_data_filename('hash/a725fa6ba642587436612c2df0451956')``, - but with the hash for your file in place of the hash in the example. - - Parameters - ---------- - localfn : str - The path to the file for which the hash should be generated. - - Returns - ------- - md5hash : str - The hex digest of the MD5 hash for the contents of the `localfn` file. - - """ - import hashlib - - with open(localfn, 'rb') as f: - h = hashlib.md5() - block = f.read(COMPUTE_HASH_BLOCK_SIZE()) - while block: - h.update(block) - block = f.read(COMPUTE_HASH_BLOCK_SIZE()) - - return h.hexdigest() - -
                -def _find_pkg_data_path(dataname): - """ - Look for data in the source-included data directories and return the - path. - """ - from os.path import abspath, dirname, join - from ..utils.misc import find_current_module - - module = find_current_module(1, True) - rootpkgname = module.__package__.split('.')[0] - rootpkg = __import__(rootpkgname) - - module_path = dirname(module.__file__) - path = join(module_path, dataname) - - root_dir = dirname(rootpkg.__file__) - assert abspath(path).startswith(abspath(root_dir)), \ - ("attempted to get a local data file outside " - "of the " + rootpkgname + " tree") - - return path - - -def _find_hash_fn(hash): - """ - Looks for a local file by hash - returns file name if found and a valid - file, otherwise returns None. - """ - from os.path import isfile, join - - dldir, urlmapfn = _get_data_cache_locs() - hashfn = join(dldir, hash) - if isfile(hashfn): - return hashfn - else: - return None - - -def _cache_remote(remoteurl): - """ - Accepts a URL, downloads and caches the result returning the filename, with - a name determined by the file's MD5 hash. If present in the cache, just - returns the filename. - """ - import hashlib - from contextlib import closing - from os.path import join - from shutil import move - from urllib2 import urlopen - from ..utils.console import ProgressBarOrSpinner - - dldir, urlmapfn = _get_data_cache_locs() - _acquire_data_cache_lock() - try: - with _open_shelve(urlmapfn, True) as url2hash: - if str(remoteurl) in url2hash: - localpath = url2hash[str(remoteurl)] - else: - with closing(urlopen(remoteurl, - timeout=REMOTE_TIMEOUT())) as remote: - #save the file to a temporary file - tmpfn = join(dldir, 'cachedl.tmp') - hash = hashlib.md5() - - info = remote.info() - if 'Content-Length' in info: - try: - size = int(info['Content-Length']) - except ValueError: - size = None - else: - size = None - - dlmsg = "Downloading {0}".format(remoteurl) - with ProgressBarOrSpinner(size, dlmsg) as p: - with open(tmpfn, 'wb') as f: - bytes_read = 0 - block = remote.read(DATA_CACHE_DL_BLOCK_SIZE()) - while block: - f.write(block) - hash.update(block) - bytes_read += len(block) - p.update(bytes_read) - block = remote.read(DATA_CACHE_DL_BLOCK_SIZE()) - - localpath = join(dldir, hash.hexdigest()) - move(tmpfn, localpath) - url2hash[str(remoteurl)] = localpath - finally: - _release_data_cache_lock() - - return localpath - - -
                [docs]def clear_data_cache(hashorurl=None): - """ Clears the data file cache by deleting the local file(s). - - Parameters - ---------- - hashorurl : str or None - If None, the whole cache is cleared. Otherwise, either specifies a hash - for the cached file that is supposed to be deleted, or a URL that has - previously been downloaded to the cache. - - Raises - ------ - OSEerror - If the requested filename is not present in the data directory. - - """ - from os import unlink - from os.path import join, exists, abspath - from shutil import rmtree - - dldir, urlmapfn = _get_data_cache_locs() - _acquire_data_cache_lock() - try: - - if hashorurl is None: - if exists(dldir): - rmtree(dldir) - if exists(urlmapfn): - unlink(urlmapfn) - else: - with _open_shelve(urlmapfn, True) as url2hash: - filepath = join(dldir, hashorurl) - assert abspath(filepath).startswith(abspath(dldir)), \ - ("attempted to use clear_data_cache on a location" + - " that's not inside the data cache directory") - - if exists(filepath): - for k, v in url2hash.items(): - if v == filepath: - del url2hash[k] - unlink(filepath) - - elif hashorurl in url2hash: - filepath = url2hash[hashorurl] - del url2hash[hashorurl] - unlink(filepath) - - else: - msg = 'Could not find file or url {0}' - raise OSError(msg.format(hashorurl)) - finally: - _release_data_cache_lock() - -
                -def _get_data_cache_locs(): - """ Finds the path to the data cache directory. - - Returns - ------- - datadir : str - The path to the data cache directory. - shelveloc : str - The path to the shelve object that stores the cache info. - """ - from .paths import get_cache_dir - from os.path import exists, isdir, join - from os import mkdir - - datadir = join(get_cache_dir(), 'data') - shelveloc = join(get_cache_dir(), 'data_urlmap') - if not exists(datadir): - mkdir(datadir) - elif not isdir(datadir): - msg = 'Data cache directory {0} is not a directory' - raise IOError(msg.format(datadir)) - - if isdir(shelveloc): - msg = 'Data cache shelve object location {0} is a directory' - raise IOError(msg.format(shelveloc)) - - return datadir, shelveloc - - -def _open_shelve(shelffn, withclosing=False): - """ - opens a shelf in a way that is py3.x and py2.x compatible. If - `withclosing` is True, it will be opened with closing, allowing use like: - - with _open_shelve('somefile',True) as s: - ... - """ - import shelve - from contextlib import closing - from sys import version_info - - if version_info[0] > 2: - shelf = shelve.open(shelffn, protocol=2) - else: - shelf = shelve.open(shelffn + '.db', protocol=2) - - if withclosing: - return closing(shelf) - else: - return shelf - - -#the cache directory must be locked before any writes are performed. Same for -#the hash shelve, so this should be used for both. Note -def _acquire_data_cache_lock(): - from os.path import join - from os import mkdir - from time import sleep - - lockdir = join(_get_data_cache_locs()[0], 'lock') - for i in range(DATA_CACHE_LOCK_ATTEMPTS()): - try: - mkdir(lockdir) - except OSError: - sleep(1) - else: - return - msg = 'Unable to acquire lock for cache directory ({0} exists)' - raise RuntimeError(msg.format(lockdir)) - - -def _release_data_cache_lock(): - from os.path import join, exists, isdir - from os import rmdir - - lockdir = join(_get_data_cache_locs()[0], 'lock') - - if exists(lockdir) and isdir(lockdir): - rmdir(lockdir) - else: - msg = 'Error releasing lock. "{0}" either does not exist or is not ' +\ - 'a directory.' - raise RuntimeError(msg.format(lockdir)) -
                - -
                -
                -
                -
                -
                - - - -
                -
                -
                -
                - - - - \ No newline at end of file diff --git a/_modules/astropy/config/paths.html b/_modules/astropy/config/paths.html deleted file mode 100644 index 387a0a81..00000000 --- a/_modules/astropy/config/paths.html +++ /dev/null @@ -1,278 +0,0 @@ - - - - - - - - - - astropy.config.paths — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
                -
                -
                -
                - -

                Source code for astropy.config.paths

                -# Licensed under a 3-clause BSD style license - see LICENSE.rst
                -""" This module contains functions to determine where configuration and
                -data/cache files used by Astropy should be placed.
                -"""
                -
                -from __future__ import division
                -
                -__all__ = ['get_config_dir', 'get_cache_dir']
                -
                -
                -def _find_home():
                -    """ Locates and return the home directory (or best approximation) on this
                -    system.
                -
                -    Raises
                -    ------
                -    OSError
                -        If the home directory cannot be located - usually means you are running
                -        Astropy on some obscure platform that doesn't have standard home
                -        directories.
                -    """
                -    import os
                -    import sys
                -    from os import environ as env
                -
                -    # this is used below to make fix up encoding issues that sometimes crop up
                -    # in py2.x but not in py3.x
                -    if sys.version_info[0] < 3:
                -        decodepath = lambda pth: pth.decode(sys.getfilesystemencoding())
                -    else:
                -        decodepath = lambda pth: pth
                -
                -    #First find the home directory - this is inspired by the scheme ipython
                -    #uses to identify "home"
                -    if os.name == 'posix':
                -        # Linux, Unix, AIX, OS X
                -        if 'HOME' in env:
                -            homedir = decodepath(env['HOME'])
                -        else:
                -            raise OSError('Could not find unix home directory to search for' +\
                -                          ' astropy config dir')
                -    elif os.name == 'nt':  # This is for all modern Windows (NT or after)
                -        #Try for a network home first
                -        if 'HOMESHARE' in env:
                -            homedir = decodepath(env['HOMESHARE'])
                -        #See if there's a local home
                -        elif 'HOMEDRIVE' in env and 'HOMEPATH' in env:
                -            homedir = os.path.join(env['HOMEDRIVE'], env['HOMEPATH'])
                -            homedir = decodepath(homedir)
                -        #Maybe a user profile?
                -        elif 'USERPROFILE' in env:
                -            homedir = decodepath(os.path.join(env['USERPROFILE']))
                -        else:
                -            try:
                -                import _winreg as wreg
                -                key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
                -            'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
                -
                -                homedir = wreg.QueryValueEx(key, 'Personal')[0]
                -                homedir = decodepath(homedir)
                -                key.Close()
                -            except:
                -                #As a final possible resort, see if HOME is present
                -                if 'HOME' in env:
                -                    homedir = decodepath(env['HOME'])
                -                else:
                -                    raise OSError('Could not find windows home directory to' +\
                -                                  ' search for astropy config dir')
                -    else:
                -        #for other platforms, try HOME, although it probably isn't there
                -        if 'HOME' in env:
                -            homedir = decodepath(env['HOME'])
                -        else:
                -            raise OSError('Could not find a home directory to search for ' +\
                -                 'astropy config dir - are you on an unspported platform?')
                -    return homedir
                -
                -
                -
                [docs]def get_config_dir(create=True): - """ - Determines the Astropy configuration directory name and creates the - directory if it doesn't exist. - - This directory is typically ``$HOME/.astropy/config``, but if the - XDG_CONFIG_HOME environment variable is set and the - ``$XDG_CONFIG_HOME/astropy`` directory exists, it will be that directory. - If neither exists, the former will be created and symlinked to the latter. - - Returns - ------- - configdir : str - The absolute path to the configuration directory. - - """ - from os import path, environ - - #symlink will be set to this if the directory is created - linkto = None - #first look for XDG_CONFIG_HOME - xch = environ.get('XDG_CONFIG_HOME') - - if xch is not None: - xchpth = path.join(xch, 'astropy') - if not path.islink(xchpth): - if path.exists(xchpth): - return path.abspath(xchpth) - else: - linkto = xchpth - - return path.abspath(_find_or_create_astropy_dir('config', linkto)) - -
                -
                [docs]def get_cache_dir(): - """ - Determines the Astropy cache directory name and creates the directory if it - doesn't exist. - - This directory is typically ``$HOME/.astropy/cache``, but if the - XDG_CACHE_HOME environment variable is set and the - ``$XDG_CACHE_HOME/astropy`` directory exists, it will be that directory. - If neither exists, the former will be created and symlinked to the latter. - - Returns - ------- - cachedir : str - The absolute path to the cache directory. - - """ - from os import path, environ - - #symlink will be set to this if the directory is created - linkto = None - #first look for XDG_CACHE_HOME - xch = environ.get('XDG_CACHE_HOME') - - if xch is not None: - xchpth = path.join(xch, 'astropy') - if not path.islink(xchpth): - if path.exists(xchpth): - return path.abspath(xchpth) - else: - linkto = xchpth - - return path.abspath(_find_or_create_astropy_dir('cache', linkto)) - -
                -def _find_or_create_astropy_dir(dirnm, linkto): - from os import path, mkdir - import sys - - innerdir = path.join(_find_home(), '.astropy') - maindir = path.join(_find_home(), '.astropy', dirnm) - - if not path.exists(maindir): - #first create .astropy dir if needed - if not path.exists(innerdir): - mkdir(innerdir) - elif not path.isdir(innerdir): - msg = 'Intended Astropy directory {0} is actually a file.' - raise IOError(msg.format(innerdir)) - - mkdir(maindir) - - if (not sys.platform.startswith('win') and - linkto is not None and - not path.exists(linkto)): - from os import symlink - symlink(maindir, linkto) - - elif not path.isdir(maindir): - msg = 'Intended Astropy {0} directory {1} is actually a file.' - raise IOError(msg.format(dirnm, maindir)) - - return path.abspath(maindir) -
                - -
                -
                -
                -
                -
                - - - -
                -
                -
                -
                - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/converters.html b/_modules/astropy/io/vo/converters.html deleted file mode 100644 index 8363d432..00000000 --- a/_modules/astropy/io/vo/converters.html +++ /dev/null @@ -1,1285 +0,0 @@ - - - - - - - - - - astropy.io.vo.converters — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
                -
                -
                -
                - -

                Source code for astropy.io.vo.converters

                -"""
                -This module handles the conversion of various VOTABLE datatypes
                -to/from TABLEDATA_ and BINARY_ formats.
                -"""
                -
                -from __future__ import division, absolute_import
                -
                -# STDLIB
                -import re
                -from struct import unpack as struct_unpack
                -from struct import pack as struct_pack
                -import sys
                -
                -# THIRD-PARTY
                -import numpy as np
                -
                -# ASTROPY
                -from ...utils.xml.writer import xml_escape_cdata
                -
                -# LOCAL
                -from .exceptions import (vo_raise, vo_warn, warn_or_raise, W01, W26,
                -    W30, W31, W32, W39, W46, W47, W49, E01, E02, E03, E04, E05, E06)
                -from .util import IS_PY3K
                -
                -if not IS_PY3K:
                -    def bytes(s, encoding):
                -        return str(s)
                -
                -
                -__all__ = ['get_converter']
                -
                -
                -pedantic_array_splitter = re.compile(r" +")
                -array_splitter = re.compile(r"\s+|(?:\s*,\s*)")
                -"""
                -A regex to handle splitting values on either whitespace or commas.
                -
                -SPEC: Usage of commas is not actually allowed by the spec, but many
                -files in the wild use them.
                -"""
                -
                -_zero_int = bytes('\0\0\0\0', 'ascii')
                -_empty_bytes = bytes('', 'ascii')
                -_zero_byte = bytes('\0', 'ascii')
                -
                -
                -class Converter(object):
                -    """
                -    The base class for all converters.  Each subclass handles
                -    converting a specific VOTABLE data type to/from the TABLEDATA_ and
                -    BINARY_ on-disk representations.
                -    """
                -    def __init__(self, field, config={}, pos=None):
                -        """
                -        Parameters
                -        ----------
                -        field : `~astropy.io.vo.table.Field`
                -            object describing the datatype
                -
                -        config : dict
                -            The parser configuration dictionary
                -
                -        pos : tuple
                -            The position in the XML file where the FIELD object was
                -            found.  Used for error messages.
                -        """
                -        pass
                -
                -    @staticmethod
                -    def _parse_length(read):
                -        return struct_unpack(">I", read(4))[0]
                -
                -    @staticmethod
                -    def _write_length(length):
                -        return struct_pack(">I", int(length))
                -
                -    def parse(self, value, config={}, pos=None):
                -        """
                -        Convert the string *value* from the TABLEDATA_ format into an
                -        object with the correct native in-memory datatype and mask flag.
                -
                -        Parameters
                -        ----------
                -        value : str
                -            value in TABLEDATA format
                -
                -        Returns
                -        -------
                -        native : tuple (value, mask)
                -            The value as a Numpy array or scalar, and *mask* is True
                -            if the value is missing.
                -        """
                -        raise NotImplementedError(
                -            "This datatype must implement a 'parse' method.")
                -
                -    def parse_scalar(self, value, config={}, pos=None):
                -        """
                -        Parse a single scalar of the underlying type of the converter.
                -        For non-array converters, this is equivalent to parse.  For
                -        array converters, this is used to parse a single
                -        element of the array.
                -
                -        Parameters
                -        ----------
                -        value : str
                -            value in TABLEDATA format
                -
                -        Returns
                -        -------
                -        native : tuple (value, mask)
                -            The value as a Numpy array or scalar, and *mask* is True
                -            if the value is missing.
                -        """
                -        return self.parse(value, config, pos)
                -
                -    def output(self, value, mask):
                -        """
                -        Convert the object *value* (in the native in-memory datatype)
                -        to a string suitable for serializing in the TABLEDATA_ format.
                -
                -        Parameters
                -        ----------
                -        value : native type corresponding to this converter
                -            The value
                -
                -        mask : bool
                -            If `True`, will return the string representation of a
                -            masked value.
                -
                -        Returns
                -        -------
                -        tabledata_repr : str
                -        """
                -        raise NotImplementedError(
                -            "This datatype must implement a 'output' method.")
                -
                -    def binparse(self, read):
                -        """
                -        Reads some number of bytes from the BINARY_ format
                -        representation by calling the function *read*, and returns the
                -        native in-memory object representation for the datatype
                -        handled by *self*.
                -
                -        Parameters
                -        ----------
                -        read : function
                -            A function that given a number of bytes, returns a byte
                -            string.
                -
                -        Returns
                -        -------
                -        native : tuple (value, mask)
                -            The value as a Numpy array or scalar, and *mask* is True
                -            if the value is missing.
                -        """
                -        raise NotImplementedError(
                -            "This datatype must implement a 'binparse' method.")
                -
                -    def binoutput(self, value, mask):
                -        """
                -        Convert the object *value* in the native in-memory datatype to
                -        a string of bytes suitable for serialization in the BINARY_
                -        format.
                -
                -        Parameters
                -        ----------
                -        value : native type corresponding to this converter
                -            The value
                -
                -        mask : bool
                -            If `True`, will return the string representation of a
                -            masked value.
                -
                -        Returns
                -        -------
                -        bytes : byte string
                -            The binary representation of the value, suitable for
                -            serialization in the BINARY_ format.
                -        """
                -        raise NotImplementedError(
                -            "This datatype must implement a 'binoutput' method.")
                -
                -
                -class Char(Converter):
                -    """
                -    Handles the char datatype. (7-bit unsigned characters)
                -
                -    Missing values are not handled for string or unicode types.
                -    """
                -    default = _empty_bytes
                -
                -    def __init__(self, field, config={}, pos=None):
                -        Converter.__init__(self, field, config, pos)
                -
                -        if field.arraysize is None:
                -            vo_warn(W47, (), config, pos)
                -            field.arraysize = '1'
                -
                -        if field.arraysize == '*':
                -            self.format = 'O'
                -            self.binparse = self._binparse_var
                -            self.binoutput = self._binoutput_var
                -            self.arraysize = '*'
                -        else:
                -            if field.arraysize.endswith('*'):
                -                field.arraysize = field.arraysize[:-1]
                -            try:
                -                self.arraysize = int(field.arraysize)
                -            except ValueError:
                -                vo_raise(E01, (field.arraysize, 'char', field.ID), config)
                -            self.format = 'S%d' % self.arraysize
                -            self.binparse = self._binparse_fixed
                -            self.binoutput = self._binoutput_fixed
                -            self._struct_format = ">%ds" % self.arraysize
                -
                -        if config.get('pedantic'):
                -            self.parse = self._ascii_parse
                -        else:
                -            self.parse = self._str_parse
                -
                -    def _ascii_parse(self, value, config={}, pos=None):
                -        if self.arraysize != '*' and len(value) > self.arraysize:
                -            vo_warn(W46, ('char', self.arraysize), config, pos)
                -        return value.encode('ascii'), False
                -
                -    if IS_PY3K:
                -        def _str_parse(self, value, config={}, pos=None):
                -            if self.arraysize != '*' and len(value) > self.arraysize:
                -                vo_warn(W46, ('char', self.arraysize), config, pos)
                -            return bytes(value, 'ascii'), False
                -    else:
                -        def _str_parse(self, value, config={}, pos=None):
                -            if self.arraysize != '*' and len(value) > self.arraysize:
                -                vo_warn(W46, ('char', self.arraysize), config, pos)
                -            return str(value), False
                -
                -    if IS_PY3K:
                -        def output(self, value, mask):
                -            if mask:
                -                return ''
                -            if not isinstance(value, str):
                -                value = value.decode('ascii')
                -            return xml_escape_cdata(value)
                -    else:
                -        def output(self, value, mask):
                -            if mask:
                -                return ''
                -            return xml_escape_cdata(value).encode('ascii')
                -
                -    def _binparse_var(self, read):
                -        length = self._parse_length(read)
                -        return read(length), False
                -
                -    def _binparse_fixed(self, read):
                -        s = struct_unpack(self._struct_format, read(self.arraysize))[0]
                -        end = s.find(_zero_byte)
                -        if end != -1:
                -            return s[:end], False
                -        return s, False
                -
                -    def _binoutput_var(self, value, mask):
                -        if mask or value is None or value == '':
                -            return _zero_int
                -        return self._write_length(len(value)) + value
                -
                -    def _binoutput_fixed(self, value, mask):
                -        if mask:
                -            value = _empty_bytes
                -        return struct_pack(self._struct_format, value)
                -
                -
                -class UnicodeChar(Converter):
                -    """
                -    Handles the unicodeChar data type. UTF-16-BE.
                -
                -    Missing values are not handled for string or unicode types.
                -    """
                -    default = u''
                -
                -    def __init__(self, field, config={}, pos=None):
                -        Converter.__init__(self, field, config, pos)
                -
                -        if field.arraysize is None:
                -            vo_warn(W47, (), config, pos)
                -            field.arraysize = '1'
                -
                -        if field.arraysize == '*':
                -            self.format = 'O'
                -            self.binparse = self._binparse_var
                -            self.binoutput = self._binoutput_var
                -            self.arraysize = '*'
                -        else:
                -            try:
                -                self.arraysize = int(field.arraysize)
                -            except ValueError:
                -                vo_raise(E01, (field.arraysize, 'unicode', field.ID), config)
                -            self.format = 'U%d' % self.arraysize
                -            self.binparse = self._binparse_fixed
                -            self.binoutput = self._binoutput_fixed
                -            self._struct_format = ">%ds" % (self.arraysize * 2)
                -
                -    if IS_PY3K:
                -        def parse(self, value, config={}, pos=None):
                -            if self.arraysize != '*' and len(value) > self.arraysize:
                -                vo_warn(W46, ('unicodeChar', self.arraysize), config, pos)
                -            return value, False
                -    else:
                -        def parse(self, value, config={}, pos=None):
                -            value = unicode(value, 'utf-8')
                -            if self.arraysize != '*' and len(value) > self.arraysize:
                -                vo_warn(W46, ('unicodeChar', self.arraysize), config, pos)
                -            return value, False
                -
                -    if IS_PY3K:
                -        def output(self, value, mask):
                -            if mask:
                -                return ''
                -            return xml_escape_cdata(value)
                -    else:
                -        def output(self, value, mask):
                -            if mask:
                -                return ''
                -            return xml_escape_cdata(value).encode('utf-8')
                -
                -    def _binparse_var(self, read):
                -        length = self._parse_length(read)
                -        return read(length * 2).decode('utf_16_be'), False
                -
                -    def _binparse_fixed(self, read):
                -        s = struct_unpack(self._struct_format, read(self.arraysize * 2))[0]
                -        s = s.decode('utf_16_be')
                -        end = s.find('\0')
                -        if end != -1:
                -            return s[:end], False
                -        return s, False
                -
                -    def _binoutput_var(self, value, mask):
                -        if mask or value is None or value == '':
                -            return _zero_int
                -        encoded = value.encode('utf_16_be')
                -        return self._write_length(len(encoded) / 2) + encoded
                -
                -    def _binoutput_fixed(self, value, mask):
                -        if mask:
                -            value = u''
                -        return struct_pack(self._struct_format, value.encode('utf_16_be'))
                -
                -
                -class Array(Converter):
                -    """
                -    Handles both fixed and variable-lengths arrays.
                -    """
                -    def __init__(self, field, config={}, pos=None):
                -        Converter.__init__(self, field, config, pos)
                -
                -        if config.get('pedantic'):
                -            self._splitter = self._splitter_pedantic
                -        else:
                -            self._splitter = self._splitter_lax
                -
                -    def parse_scalar(self, value, config={}, pos=0):
                -        return self._base.parse_scalar(value, config, pos)
                -
                -    @staticmethod
                -    def _splitter_pedantic(value, config={}, pos=None):
                -        return pedantic_array_splitter.split(value)
                -
                -    @staticmethod
                -    def _splitter_lax(value, config={}, pos=None):
                -        if ',' in value:
                -            vo_warn(W01, (), config, pos)
                -        return array_splitter.split(value)
                -
                -
                -class VarArray(Array):
                -    """
                -    Handles variable lengths arrays (i.e. where *arraysize* is '*').
                -    """
                -    format = 'O'
                -
                -    def __init__(self, field, base, arraysize, config={}, pos=None):
                -        Array.__init__(self, field, config)
                -
                -        self._base = base
                -        self.default = np.array([], dtype=self._base.format)
                -
                -    def output(self, value, mask):
                -        output = self._base.output
                -        result = [output(x, m) for x, m in np.broadcast(value, mask)]
                -        return ' '.join(result)
                -
                -    def binparse(self, read):
                -        length = self._parse_length(read)
                -
                -        result = []
                -        result_mask = []
                -        binparse = self._base.binparse
                -        for i in xrange(length):
                -            val, mask = binparse(read)
                -            result.append(val)
                -            result_mask.append(mask)
                -        return (np.array(result),
                -                np.array(result_mask, dtype='bool'))
                -
                -    def binoutput(self, value, mask):
                -        if value is None or len(value) == 0:
                -            return _zero_int
                -
                -        length = len(value)
                -        result = [self._write_length(length)]
                -        binoutput = self._base.binoutput
                -        for x, m in zip(value, mask):
                -            result.append(binoutput(x, m))
                -        return _empty_bytes.join(result)
                -
                -
                -class ArrayVarArray(VarArray):
                -    """
                -    Handles an array of variable-length arrays, i.e. where *arraysize*
                -    ends in '*'.
                -    """
                -    def parse(self, value, config={}, pos=None):
                -        if value.strip() == '':
                -            return np.array([]), True
                -
                -        parts = self._splitter(value, config, pos)
                -        items = self._base._items
                -        parse_parts = self._base.parse_parts
                -        if len(parts) % items != 0:
                -            vo_raise(E02, (items, len(parts)), config, pos)
                -        result = []
                -        result_mask = []
                -        for i in xrange(0, len(parts), items):
                -            value, mask = parse_parts(parts[i:i+items], config, pos)
                -            result.append(value)
                -            result_mask.append(mask)
                -        return np.array(result), np.array(result_mask, dtype='bool')
                -
                -
                -class ScalarVarArray(VarArray):
                -    """
                -    Handles a variable-length array of numeric scalars.
                -    """
                -    def parse(self, value, config={}, pos=None):
                -        if value.strip() == '':
                -            return np.array([]), True
                -
                -        parts = self._splitter(value, config, pos)
                -
                -        parse = self._base.parse
                -        result = []
                -        result_mask = []
                -        for x in parts:
                -            value, mask = parse(x, config, pos)
                -            result.append(value)
                -            result_mask.append(mask)
                -        return (np.array(result, dtype=self._base.format),
                -                np.array(result_mask, dtype='bool'))
                -
                -
                -class NumericArray(Array):
                -    """
                -    Handles a fixed-length array of numeric scalars.
                -    """
                -    vararray_type = ArrayVarArray
                -
                -    def __init__(self, field, base, arraysize, config={}, pos=None):
                -        Array.__init__(self, field, config, pos)
                -
                -        self._base = base
                -        self._arraysize = arraysize
                -        self.format = "%s%s" % (tuple(arraysize), base.format)
                -
                -        self._items = 1
                -        for dim in arraysize:
                -            self._items *= dim
                -
                -        self._memsize = np.dtype(self.format).itemsize
                -        self._bigendian_format = '>' + self.format
                -
                -        self.default = (
                -            np.ones(arraysize, dtype=self._base.format) *
                -            self._base.default)
                -
                -    def parse(self, value, config={}, pos=None):
                -        parts = self._splitter(value, config, pos)
                -        if len(parts) != self._items:
                -            warn_or_raise(E02, E02, (self._items, len(parts)), config, pos)
                -        if config.get('pedantic'):
                -            return self.parse_parts(parts, config, pos)
                -        else:
                -            if len(parts) == self._items:
                -                pass
                -            elif len(parts) > self._items:
                -                parts = parts[:self._items]
                -            else:
                -                parts = (parts +
                -                         ([self._base.default] * (self._items - len(parts))))
                -            return self.parse_parts(parts, config, pos)
                -
                -    def parse_parts(self, parts, config={}, pos=None):
                -        base_parse = self._base.parse
                -        result = []
                -        result_mask = []
                -        for x in parts:
                -            value, mask = base_parse(x, config, pos)
                -            result.append(value)
                -            result_mask.append(mask)
                -        result = np.array(result, dtype=self._base.format).reshape(
                -            self._arraysize)
                -        result_mask = np.array(result_mask, dtype='bool').reshape(
                -            self._arraysize)
                -        return result, result_mask
                -
                -    def output(self, value, mask):
                -        base_output = self._base.output
                -        value = np.asarray(value)
                -        mask = np.asarray(mask)
                -        return ' '.join(base_output(x, m) for x, m in
                -                        zip(value.flat, mask.flat))
                -
                -    def binparse(self, read):
                -        result = np.fromstring(read(self._memsize),
                -                               dtype=self._bigendian_format)[0]
                -        result_mask = self._base.is_null(result)
                -        return result, result_mask
                -
                -    def binoutput(self, value, mask):
                -        filtered = self._base.filter_array(value, mask)
                -        if filtered.dtype.byteorder != '>':
                -            filtered = filtered.byteswap()
                -        return filtered.tostring()
                -
                -
                -class Numeric(Converter):
                -    """
                -    The base class for all numeric data types.
                -    """
                -    array_type = NumericArray
                -    vararray_type = ScalarVarArray
                -    null = None
                -
                -    def __init__(self, field, config={}, pos=None):
                -        Converter.__init__(self, field, config, pos)
                -
                -        self._memsize = np.dtype(self.format).itemsize
                -        self._bigendian_format = '>' + self.format
                -        if field.values.null is not None:
                -            self.null = np.asarray(field.values.null, dtype=self.format)
                -            self.default = self.null
                -            self.is_null = self._is_null
                -        else:
                -            self.is_null = np.isnan
                -
                -    def binparse(self, read):
                -        result = np.fromstring(read(self._memsize),
                -                               dtype=self._bigendian_format)
                -        return result[0], self.is_null(result[0])
                -
                -    def _is_null(self, value):
                -        return value == self.null
                -
                -
                -class FloatingPoint(Numeric):
                -    """
                -    The base class for floating-point datatypes.
                -    """
                -    default = np.nan
                -
                -    def __init__(self, field, config={}, pos=None):
                -        Numeric.__init__(self, field, config, pos)
                -
                -        precision = field.precision
                -        if precision is None:
                -            self._output_format = '%g'
                -        elif precision.startswith("E"):
                -            self._output_format = "%%.%dE" % (int(precision[1:]))
                -        elif precision.startswith("F"):
                -            self._output_format = "%%.%dg" % (int(precision[1:]))
                -        else:
                -            self._output_format = "%%.%dg" % (int(precision))
                -
                -        self.nan = np.array(np.nan, self.format)
                -
                -        if self.null is None:
                -            self._null_output = 'NaN'
                -            self._null_binoutput = self.binoutput(self.nan, False)
                -            self.filter_array = self._filter_nan
                -        else:
                -            self._null_output = self.output(np.asarray(self.null), False)
                -            self._null_binoutput = self.binoutput(np.asarray(self.null), False)
                -            self.filter_array = self._filter_null
                -
                -        if config.get('pedantic'):
                -            self.parse = self._parse_pedantic
                -        else:
                -            self.parse = self._parse_permissive
                -
                -    def _parse_pedantic(self, value, config={}, pos=None):
                -        if value.strip() == '':
                -            return self.null, True
                -        f = float(value)
                -        return f, self.is_null(f)
                -
                -    def _parse_permissive(self, value, config={}, pos=None):
                -        try:
                -            f = float(value)
                -            return f, self.is_null(f)
                -        except ValueError:
                -            # IRSA VOTables use the word 'null' to specify empty values,
                -            # but this is not defined in the VOTable spec.
                -            if value.strip() != '':
                -                vo_warn(W30, value, config, pos)
                -            return self.null, True
                -
                -    def output(self, value, mask):
                -        if mask:
                -            return self._null_output
                -        if np.isfinite(value):
                -            return self._output_format % value
                -        elif np.isnan(value):
                -            return 'NaN'
                -        elif np.isposinf(value):
                -            return '+InF'
                -        elif np.isneginf(value):
                -            return '-InF'
                -        # Should never raise
                -        vo_raise("Invalid floating point value '%s'" % value)
                -
                -    def binoutput(self, value, mask):
                -        if mask:
                -            return self._null_binoutput
                -
                -        if value.dtype.byteorder != '>':
                -            value = value.byteswap()
                -        return value.tostring()
                -
                -    def _filter_nan(self, value, mask):
                -        return np.where(mask, np.nan, value)
                -
                -    def _filter_null(self, value, mask):
                -        return np.where(mask, self.null, value)
                -
                -
                -class Double(FloatingPoint):
                -    """
                -    Handles the double datatype.  Double-precision IEEE
                -    floating-point.
                -    """
                -    format = 'f8'
                -
                -
                -class Float(FloatingPoint):
                -    """
                -    Handles the float datatype.  Single-precision IEEE floating-point.
                -    """
                -    format = 'f4'
                -
                -
                -class Integer(Numeric):
                -    """
                -    The base class for all the integral datatypes.
                -    """
                -    default = 0
                -
                -    def __init__(self, field, config={}, pos=None):
                -        Numeric.__init__(self, field, config, pos)
                -
                -    def parse(self, value, config={}, pos=None):
                -        mask = False
                -        if isinstance(value, basestring):
                -            value = value.lower()
                -            if value == '':
                -                warn_or_raise(W49, W49, (), config, pos)
                -                if self.null is not None:
                -                    value = self.null
                -                else:
                -                    value = self.default
                -            elif value == 'nan':
                -                mask = True
                -                if self.null is None:
                -                    warn_or_raise(W31, W31, (), config, pos)
                -                    value = self.default
                -                else:
                -                    value = self.null
                -            elif value.startswith('0x'):
                -                value = int(value[2:], 16)
                -            else:
                -                value = int(value, 10)
                -        else:
                -            value = int(value)
                -        if self.null is not None and value == self.null:
                -            mask = True
                -        return value, mask
                -
                -    def output(self, value, mask):
                -        if mask:
                -            if self.null is None:
                -                warn_or_raise(W31, W31, (), config, pos)
                -                return 'NaN'
                -            return str(self.null)
                -        return str(value)
                -
                -    def binoutput(self, value, mask):
                -        if mask:
                -            if self.null is None:
                -                vo_raise(W31, (), config, pos)
                -            else:
                -                value = self.null
                -        if value.dtype.byteorder != '>':
                -            value = value.byteswap()
                -        return value.tostring()
                -
                -    def filter_array(self, value, mask):
                -        if np.any(mask):
                -            if self.null is not None:
                -                return np.where(mask, self.null, value)
                -            else:
                -                vo_raise(W31, (), config, pos)
                -        return value
                -
                -
                -class UnsignedByte(Integer):
                -    """
                -    Handles the unsignedByte datatype.  Unsigned 8-bit integer.
                -    """
                -    format = 'u1'
                -
                -
                -class Short(Integer):
                -    """
                -    Handles the short datatype.  Signed 16-bit integer.
                -    """
                -    format = 'i2'
                -
                -
                -class Int(Integer):
                -    """
                -    Handles the int datatype.  Signed 32-bit integer.
                -    """
                -    format = 'i4'
                -
                -
                -class Long(Integer):
                -    """
                -    Handles the long datatype.  Signed 64-bit integer.
                -    """
                -    format = 'i8'
                -
                -
                -class ComplexArrayVarArray(VarArray):
                -    """
                -    Handles an array of variable-length arrays of complex numbers.
                -    """
                -    def __init__(self, field, base, arraysize, config={}, pos=None):
                -        VarArray.__init__(self, field, base, arraysize, config, pos)
                -
                -    def parse(self, value, config={}, pos=None):
                -        if value.strip() == '':
                -            return np.array([]), True
                -
                -        parts = self._splitter(value, config, pos)
                -        items = self._base._items
                -        parse_parts = self._base.parse_parts
                -        if len(parts) % items != 0:
                -            vo_raise(E02, (items, len(parts)), config, pos)
                -        result = []
                -        result_mask = []
                -        for i in xrange(0, len(parts), items):
                -            value, mask = parse_parts(parts[i:i + items], config, pos)
                -            result.append(value)
                -            result_mask.append(mask)
                -        return np.array(result), np.array(result_mask, dtype='bool')
                -
                -
                -class ComplexVarArray(VarArray):
                -    """
                -    Handles a variable-length array of complex numbers.
                -    """
                -    def __init__(self, field, base, arraysize, config={}, pos=None):
                -        VarArray.__init__(self, field, base, arraysize, config, pos)
                -
                -    def parse(self, value, config={}, pos=None):
                -        if value.strip() == '':
                -            return np.array([]), True
                -
                -        parts = self._splitter(value, config, pos)
                -        parse_parts = self._base.parse_parts
                -        result = []
                -        result_mask = []
                -        for i in xrange(0, len(parts), 2):
                -            value = [float(x) for x in parts[i:i + 2]]
                -            value, mask = parse_parts(value, config, pos)
                -            result.append(value)
                -            result_mask.append(mask)
                -        return (np.array(result, dtype=self._base.format),
                -                np.array(result_mask, dtype='bool'))
                -
                -
                -class ComplexArray(NumericArray):
                -    """
                -    Handles a fixed-size array of complex numbers.
                -    """
                -    vararray_type = ComplexArrayVarArray
                -
                -    def __init__(self, field, base, arraysize, config={}, pos=None):
                -        NumericArray.__init__(self, field, base, arraysize, config, pos)
                -        self._items *= 2
                -
                -    def parse(self, value, config={}, pos=None):
                -        parts = self._splitter(value, config, pos)
                -        if parts == ['']:
                -            parts = []
                -        return self.parse_parts(parts, config, pos)
                -
                -    def parse_parts(self, parts, config={}, pos=None):
                -        if len(parts) != self._items:
                -            vo_raise(E02, (self._items, len(parts)), config, pos)
                -        base_parse = self._base.parse_parts
                -        result = []
                -        result_mask = []
                -        for i in xrange(0, self._items, 2):
                -            value = [float(x) for x in parts[i:i + 2]]
                -            value, mask = base_parse(value, config, pos)
                -            result.append(value)
                -            result_mask.append(mask)
                -        result = np.array(
                -            result, dtype=self._base.format).reshape(self._arraysize)
                -        result_mask = np.array(
                -            result_mask, dtype='bool').reshape(self._arraysize)
                -        return result, result_mask
                -
                -
                -class Complex(FloatingPoint, Array):
                -    """
                -    The base class for complex numbers.
                -    """
                -    array_type = ComplexArray
                -    vararray_type = ComplexVarArray
                -    default = np.nan
                -
                -    def __init__(self, field, config={}, pos=None):
                -        FloatingPoint.__init__(self, field, config, pos)
                -        Array.__init__(self, field, config, pos)
                -
                -        self._output_format = self._output_format + " " + self._output_format
                -
                -    def parse(self, value, config={}, pos=None):
                -        if value.strip() == '':
                -            return np.nan, True
                -        splitter = self._splitter
                -        parts = [float(x) for x in splitter(value, config, pos)]
                -        if len(parts) != 2:
                -            vo_raise(E03, (value,), config, pos)
                -        return self.parse_parts(parts, config, pos)
                -    _parse_permissive = parse
                -    _parse_pedantic = parse
                -
                -    def parse_parts(self, parts, config={}, pos=None):
                -        value = complex(*parts)
                -        return value, self.is_null(value)
                -
                -    def output(self, value, mask):
                -        if mask:
                -            if self.null is None:
                -                return 'NaN'
                -            else:
                -                value = self.null
                -        return self._output_format % (value.real, value.imag)
                -
                -
                -class FloatComplex(Complex):
                -    """
                -    Handle floatComplex datatype.  Pair of single-precision IEEE
                -    floating-point numbers.
                -    """
                -    format = 'c8'
                -
                -
                -class DoubleComplex(Complex):
                -    """
                -    Handle doubleComplex datatype.  Pair of double-precision IEEE
                -    floating-point numbers.
                -    """
                -    format = 'c16'
                -
                -
                -class BitArray(NumericArray):
                -    """
                -    Handles an array of bits.
                -    """
                -    vararray_type = ArrayVarArray
                -
                -    def __init__(self, field, base, arraysize, config={}, pos=None):
                -        NumericArray.__init__(self, field, base, arraysize, config, pos)
                -
                -        self._bytes = ((self._items - 1) // 8) + 1
                -
                -    @staticmethod
                -    def _splitter_pedantic(value, config={}, pos=None):
                -        return list(re.sub('\s', '', value))
                -
                -    @staticmethod
                -    def _splitter_lax(value, config={}, pos=None):
                -        if ',' in value:
                -            vo_warn(W01, (), config, pos)
                -        return list(re.sub('\s|,', '', value))
                -
                -    def output(self, value, mask):
                -        value = np.asarray(value)
                -        mapping = {False: '0', True: '1'}
                -        return ''.join(mapping[x] for x in value.flat)
                -
                -    def binparse(self, read):
                -        data = read(self._bytes)
                -        results = []
                -        for byte in data:
                -            if not IS_PY3K:
                -                byte = ord(byte)
                -            for bit_no in range(7, -1, -1):
                -                bit = byte & (1 << bit_no)
                -                bit = (bit != 0)
                -                results.append(bit)
                -                if len(results) == self._items:
                -                    break
                -            if len(results) == self._items:
                -                break
                -
                -        result = np.array(results, dtype='b1').reshape(self._arraysize)
                -        result_mask = np.zeros(self._arraysize, dtype='b1')
                -        return result, result_mask
                -
                -    def binoutput(self, value, mask):
                -        if np.any(mask):
                -            vo_warn(W39)
                -
                -        x = value
                -        value = value.flat
                -        bit_no = 7
                -        byte = 0
                -        bytes = []
                -        for v in value:
                -            if v:
                -                byte |= 1 << bit_no
                -            if bit_no == 0:
                -                bytes.append(byte)
                -                bit_no = 7
                -                byte = 0
                -            else:
                -                bit_no -= 1
                -        if bit_no != 7:
                -            bytes.append(byte)
                -
                -        assert len(bytes) == self._bytes
                -
                -        return struct_pack("%sB" % len(bytes), *bytes)
                -
                -
                -class Bit(Converter):
                -    """
                -    Handles the bit datatype.
                -    """
                -    format = 'b1'
                -    array_type = BitArray
                -    vararray_type = ScalarVarArray
                -    default = False
                -    binary_one = bytes(chr(0x8), 'ascii')
                -    binary_zero = bytes(chr(0), 'ascii')
                -
                -    def __init__(self, field, config={}, pos=None):
                -        Converter.__init__(self, field, config, pos)
                -
                -    def parse(self, value, config={}, pos=None):
                -        mapping = {'1': True, '0': False}
                -        if value is False or value.strip() == '':
                -            warn_or_raise(W49, W49, (), config, pos)
                -            return False, True
                -        else:
                -            try:
                -                return mapping[value], False
                -            except KeyError:
                -                vo_raise(E04, (value,), config, pos)
                -
                -    def output(self, value, mask):
                -        if mask:
                -            vo_warn(W39)
                -
                -        if value:
                -            return '1'
                -        else:
                -            return '0'
                -
                -    def binparse(self, read):
                -        data = read(1)
                -        return (ord(data) & 0x8) != 0, False
                -
                -    def binoutput(self, value, mask):
                -        if mask:
                -            vo_warn(W39)
                -
                -        if value:
                -            return self.binary_one
                -        return self.binary_zero
                -
                -
                -class BooleanArray(NumericArray):
                -    """
                -    Handles an array of boolean values.
                -    """
                -    vararray_type = VarArray
                -
                -    def __init__(self, field, base, arraysize, config={}, pos=None):
                -        NumericArray.__init__(self, field, base, arraysize, config, pos)
                -
                -    def binparse(self, read):
                -        data = read(self._items)
                -        binparse = self._base.binparse_value
                -        result = []
                -        result_mask = []
                -        for char in data:
                -            if not IS_PY3K:
                -                char = ord(char)
                -            value, mask = binparse(char)
                -            result.append(value)
                -            result_mask.append(mask)
                -        result = np.array(result, dtype='b1').reshape(
                -            self._arraysize)
                -        result_mask = np.array(result_mask, dtype='b1').reshape(
                -            self._arraysize)
                -        return result, result_mask
                -
                -    def binoutput(self, value, mask):
                -        binoutput = self._base.binoutput
                -        value = np.asarray(value)
                -        mask = np.asarray(mask)
                -        result = [binoutput(x, m)
                -                  for x, m in np.broadcast(value.flat, mask.flat)]
                -        return _empty_bytes.join(result)
                -
                -
                -class Boolean(Converter):
                -    """
                -    Handles the boolean datatype.
                -    """
                -    format = 'b1'
                -    array_type = BooleanArray
                -    vararray_type = VarArray
                -    default = False
                -    binary_question_mark = bytes('?', 'ascii')
                -    binary_true = bytes('T', 'ascii')
                -    binary_false = bytes('F', 'ascii')
                -
                -    def __init__(self, field, config={}, pos=None):
                -        Converter.__init__(self, field, config, pos)
                -
                -    def parse(self, value, config={}, pos=None):
                -        if value is False:
                -            return False, True
                -        mapping = {'TRUE'  : (True, False),
                -                   'FALSE' : (False, False),
                -                   '1'     : (True, False),
                -                   '0'     : (False, False),
                -                   'T'     : (True, False),
                -                   'F'     : (False, False),
                -                   '\0'    : (False, True),
                -                   ' '     : (False, True),
                -                   '?'     : (False, True),
                -                   ''      : (False, True)}
                -        try:
                -            return mapping[value.upper()]
                -        except KeyError:
                -            vo_raise(E05, (value,), config, pos)
                -
                -    def output(self, value, mask):
                -        if mask:
                -            return '?'
                -        if value:
                -            return 'T'
                -        return 'F'
                -
                -    def binparse(self, read):
                -        value = ord(read(1))
                -        return self.binparse_value(value)
                -
                -    _binparse_mapping = {
                -        ord('T')  : (True, False),
                -        ord('t')  : (True, False),
                -        ord('1')  : (True, False),
                -        ord('F')  : (False, False),
                -        ord('f')  : (False, False),
                -        ord('0')  : (False, False),
                -        ord('\0') : (False, True),
                -        ord(' ')  : (False, True),
                -        ord('?')  : (False, True)}
                -
                -    def binparse_value(self, value):
                -        try:
                -            return self._binparse_mapping[value]
                -        except KeyError:
                -            vo_raise(E05, (value,))
                -
                -    def binoutput(self, value, mask):
                -        if mask:
                -            return self.binary_question_mark
                -        if value:
                -            return self.binary_true
                -        return self.binary_false
                -
                -
                -converter_mapping = {
                -    'double'        : Double,
                -    'float'         : Float,
                -    'bit'           : Bit,
                -    'boolean'       : Boolean,
                -    'unsignedByte'  : UnsignedByte,
                -    'short'         : Short,
                -    'int'           : Int,
                -    'long'          : Long,
                -    'floatComplex'  : FloatComplex,
                -    'doubleComplex' : DoubleComplex,
                -    'char'          : Char,
                -    'unicodeChar'   : UnicodeChar }
                -
                -
                -
                [docs]def get_converter(field, config={}, pos=None): - """ - Factory function to get an appropriate converter instance for a - given field. - - Parameters - ---------- - field : astropy.io.vo.tree.Field - - config : dict, optional - Parser configuration dictionary - - pos : tuple - Position in the input XML file. Used for error messages. - - Returns - ------- - converter : astropy.io.vo.converters.Converter - """ - if field.datatype not in converter_mapping: - vo_raise(E06, (field.datatype, field.ID), config) - - cls = converter_mapping[field.datatype] - converter = cls(field, config, pos) - - arraysize = field.arraysize - - # With numeric datatypes, special things need to happen for - # arrays. - if (field.datatype not in ('char', 'unicodeChar') and - arraysize is not None): - if arraysize[-1] == '*': - arraysize = arraysize[:-1] - last_x = arraysize.rfind('x') - if last_x == -1: - arraysize = '' - else: - arraysize = arraysize[:last_x] - fixed = False - else: - fixed = True - - if arraysize != '': - arraysize = [int(x) for x in arraysize.split("x")] - arraysize.reverse() - else: - arraysize = [] - - if arraysize != []: - converter = converter.array_type( - field, converter, arraysize, config) - - if not fixed: - converter = converter.vararray_type( - field, converter, arraysize, config) - - return converter
                -
                - -
                -
                -
                -
                -
                - - - -
                -
                -
                -
                - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/exceptions.html b/_modules/astropy/io/vo/exceptions.html deleted file mode 100644 index 06968ead..00000000 --- a/_modules/astropy/io/vo/exceptions.html +++ /dev/null @@ -1,1489 +0,0 @@ - - - - - - - - - - astropy.io.vo.exceptions — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
                -
                -
                -
                - -

                Source code for astropy.io.vo.exceptions

                -# -*- coding: utf-8 -*-
                -u"""
                -.. _warnings:
                -
                -Warnings
                ---------
                -
                -.. note::
                -    Most of the following warnings indicate violations of the VOTable
                -    specification.  They should be reported to the authors of the
                -    tools that produced the VOTable file.
                -
                -    To control the warnings emitted, use the standard Python
                -    :mod:`warnings` module.  Most of these are of the type
                -    `VOTableSpecWarning`.
                -
                -{warnings}
                -
                -.. _exceptions:
                -
                -Exceptions
                -----------
                -
                -.. note::
                -
                -    This is a list of many of the fatal exceptions emitted by vo.table
                -    when the file does not conform to spec.  Other exceptions may be
                -    raised due to unforeseen cases or bugs in vo.table itself.
                -
                -{exceptions}
                -"""
                -
                -from __future__ import division, absolute_import
                -
                -# STDLIB
                -import io
                -import re
                -import sys
                -from warnings import warn
                -
                -# LOCAL
                -from .util import IS_PY3K
                -
                -
                -__all__ = [
                -    'warn_or_raise', 'vo_raise', 'vo_reraise', 'vo_warn',
                -    'warn_unknown_attrs', 'parse_vowarning', 'VOWarning'
                -    'VOTableChangeWarning', 'VOTableSpecWarning',
                -    'UnimplementedWarning', 'IOWarning', 'VOTableSpecError']
                -
                -
                -MAX_WARNINGS = 10
                -
                -
                -def _format_message(message, name, config={}, pos=None):
                -    if pos is None:
                -        pos = ('?', '?')
                -    filename = config.get('filename', '?')
                -    return '%s:%s:%s: %s: %s' % (filename, pos[0], pos[1], name, message)
                -
                -
                -def _suppressed_warning(warning, config):
                -    warning_class = type(warning)
                -    config.setdefault('_warning_counts', {}).setdefault(warning_class, 0)
                -    config['_warning_counts'][warning_class] += 1
                -    message_count = config['_warning_counts'][warning_class]
                -    if message_count <= MAX_WARNINGS:
                -        if message_count == MAX_WARNINGS:
                -            warning.formatted_message += \
                -                ' (suppressing further warnings of this type...)'
                -        warn(warning)
                -
                -
                -
                [docs]def warn_or_raise(warning_class, exception_class=None, args=(), config={}, - pos=None): - """ - Warn or raise an exception, depending on the pedantic setting. - """ - if config.get('pedantic'): - if exception_class is None: - exception_class = warning_class - vo_raise(exception_class, args, config, pos) - else: - vo_warn(warning_class, args, config, pos) - -
                -
                [docs]def vo_raise(exception_class, args=(), config={}, pos=None): - """ - Raise an exception, with proper position information if available. - """ - raise exception_class(args, config, pos) - -
                -
                [docs]def vo_reraise(exc, config={}, pos=None, additional=''): - """ - Raise an exception, with proper position information if available. - - Restores the original traceback of the exception, and should only - be called within an "except:" block of code. - """ - message = _format_message(str(exc), exc.__class__.__name__, config, pos) - if message.split()[0] == str(exc).split()[0]: - message = str(exc) - if len(additional): - message += ' ' + additional - exc.args = (message,) - raise exc - -
                -
                [docs]def vo_warn(warning_class, args=(), config={}, pos=None): - """ - Warn, with proper position information if available. - """ - warning = warning_class(args, config, pos) - _suppressed_warning(warning, config) - -
                -def warn_unknown_attrs(element, attrs, config, pos, good_attr=[]): - for attr in attrs: - if attr not in good_attr: - vo_warn(W48, (attr, element), config, pos) - - -_warning_pat = re.compile( - (r":?(?P<nline>[0-9?]+):(?P<nchar>[0-9?]+): " + - r"((?P<warning>[WE]\d+): )?(?P<rest>.*)$")) - - -
                [docs]def parse_vowarning(line): - """ - Parses the vo warning string back into its parts. - """ - result = {} - match = _warning_pat.search(line) - if match: - result['warning'] = warning = match.group('warning') - if warning is not None: - result['is_warning'] = (warning[0].upper() == 'W') - result['is_exception'] = (warning[0].upper() == 'E') - result['number'] = int(match.group('warning')[1:]) - result['doc_url'] = "vo/api_exceptions.html#%s" % warning.lower() - else: - result['is_warning'] = False - result['is_exception'] = False - result['is_other'] = True - result['number'] = None - result['doc_url'] = None - result['nline'] = int(match.group('nline')) - result['nchar'] = int(match.group('nchar')) - result['message'] = match.group('rest') - result['is_something'] = True - else: - result['warning'] = None - result['is_warning'] = False - result['is_exception'] = False - result['is_other'] = False - result['is_something'] = False - - return result - -
                -
                [docs]class VOWarning(Warning): - """ - The base class of all VO warnings and exceptions. Handles the - formatting of the message with a warning or exception code, - filename, line and column number. - """ - default_args = () - - def __init__(self, args, config={}, pos=None): - msg = self.message % args - self.formatted_message = _format_message( - msg, self.__class__.__name__, config, pos) - - def __str__(self): - return self.formatted_message - - @classmethod - def get_short_name(cls): - if len(cls.default_args): - return cls.message % cls.default_args - return cls.message - -
                -
                [docs]class VOTableChangeWarning(VOWarning, SyntaxWarning): - """ - Warning emitted when a change has been made to the input XML file. - """ - pass - -
                -
                [docs]class VOTableSpecWarning(VOWarning, SyntaxWarning): - """ - Warning emitted when the input XML file violates the spec, but - there is an obvious workaround. - """ - pass - -
                -
                [docs]class UnimplementedWarning(VOWarning, SyntaxWarning): - """ - Warning emitted when the a feature of VOTABLE is not implemented. - """ - pass - -
                -
                [docs]class IOWarning(VOWarning, RuntimeWarning): - """ - Warning emitted when a network or IO error occurred, but the - system is able to recover using a cached copy of the data or some - other fallback. - """ - pass - -
                -
                [docs]class VOTableSpecError(VOWarning, ValueError): - """ - Error raised when the input XML file violates the spec and there - is no good workaround. - """ - pass - -
                -class W01(VOTableSpecWarning): - """ - The VOTable spec states: - - If a cell contains an array or complex number, it should be - encoded as multiple numbers separated by whitespace. - - Many VOTable files in the wild use commas as a separator instead, - and ``vo.table`` supports this convention when not in - :ref:`pedantic-mode`. - - `vo.table` always outputs files using only spaces, regardless of - how they were input. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#toc-header-35>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:TABLEDATA>`__ - """ - - message = "Array uses commas rather than whitespace" - - -class W02(VOTableSpecWarning): - """ - XML ids must match the following regular expression:: - - ^[A-Za-z_][A-Za-z0-9_\.\-]*$ - - The VOTable 1.1 says the following: - - According to the XML standard, the attribute ``ID`` is a - string beginning with a letter or underscore (``_``), followed - by a sequence of letters, digits, or any of the punctuation - characters ``.`` (dot), ``-`` (dash), ``_`` (underscore), or - ``:`` (colon). - - However, this is in conflict with the XML standard, which says - colons may not be used. VOTable 1.1's own schema does not allow a - colon here. Therefore, ``vo.table`` disallows the colon. - - VOTable 1.2 corrects this error in the specification. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, - `XML Names <http://www.w3.org/TR/REC-xml/#NT-Name>`__ - """ - - message = "%s attribute '%s' is invalid. Must be a standard XML id" - default_args = ('x', 'y') - - -class W03(VOTableChangeWarning): - """ - The VOTable 1.1 spec says the following about ``name`` vs. ``ID`` - on ``FIELD`` and ``VALUE`` elements: - - ``ID`` and ``name`` attributes have a different role in - VOTable: the ``ID`` is meant as a *unique identifier* of an - element seen as a VOTable component, while the ``name`` is - meant for presentation purposes, and need not to be unique - throughout the VOTable document. The ``ID`` attribute is - therefore required in the elements which have to be - referenced, but in principle any element may have an ``ID`` - attribute. ... In summary, the ``ID`` is different from the - ``name`` attribute in that (a) the ``ID`` attribute is made - from a restricted character set, and must be unique throughout - a VOTable document whereas names are standard XML attributes - and need not be unique; and (b) there should be support in the - parsing software to look up references and extract the - relevant element with matching ``ID``. - - It is further recommended in the VOTable 1.2 spec: - - While the ``ID`` attribute has to be unique in a VOTable - document, the ``name`` attribute need not. It is however - recommended, as a good practice, to assign unique names within - a ``TABLE`` element. This recommendation means that, between a - ``TABLE`` and its corresponding closing ``TABLE`` tag, - ``name`` attributes of ``FIELD``, ``PARAM`` and optional - ``GROUP`` elements should be all different. - - Since ``vo.table`` requires a unique identifier for each of its - columns, ``ID`` is used for the column name when present. - However, when ``ID`` is not present, (since it is not required by - the specification) ``name`` is used instead. However, ``name`` - must be cleansed by replacing invalid characters (such as - whitespace) with underscores. - - .. note:: - This warning does not indicate that the input file is invalid - with respect to the VOTable specification, only that the - column names in the record array may not match exactly the - ``name`` attributes specified in the file. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ - """ - - message = "Implictly generating an ID from a name '%s' -> '%s'" - default_args = ('x', 'y') - - -class W04(VOTableSpecWarning): - """ - The ``content-type`` attribute must use MIME content-type syntax as - defined in `RFC 2046 <http://tools.ietf.org/html/rfc2046>`__. - - The current check for validity is somewhat over-permissive. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:link>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:link>`__ - """ - - message = "content-type '%s' must be a valid MIME content type" - default_args = ('x',) - - -class W05(VOTableSpecWarning): - """ - The attribute must be a valid URI as defined in `RFC 2396 - <http://www.ietf.org/rfc/rfc2396.txt>`_. - """ - - message = "'%s' is not a valid URI" - default_args = ('x',) - - -class W06(VOTableSpecWarning): - """ - This warning is emitted when a ``ucd`` attribute does not match - the syntax of a `unified content descriptor - <http://vizier.u-strasbg.fr/doc/UCD.htx>`__. - - If the VOTable version is 1.2 or later, the UCD will also be - checked to ensure it conforms to the controlled vocabulary defined - by UCD1+. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:ucd>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:ucd>`__ - """ - - message = "Invalid UCD '%s': %s" - default_args = ('x', 'explanation') - - -class W07(VOTableSpecWarning): - """ - As astro year field is a Besselian or Julian year matching the - regular expression:: - - ^[JB]?[0-9]+([.][0-9]*)?$ - - Defined in this XML Schema snippet:: - - <xs:simpleType name="astroYear"> - <xs:restriction base="xs:token"> - <xs:pattern value="[JB]?[0-9]+([.][0-9]*)?"/> - </xs:restriction> - </xs:simpleType> - """ - - message = "Invalid astroYear in %s: '%s'" - default_args = ('x', 'y') - - -class W08(VOTableSpecWarning): - """ - To avoid local-dependent number parsing differences, ``vo.table`` - may require a string or unicode string where a numeric type may - make more sense. - """ - - if IS_PY3K: - message = "'%s' must be a str or bytes object" - else: - message = "'%s' must be a str or unicode object" - default_args = ('x',) - - -class W09(VOTableSpecWarning): - """ - The VOTable specification uses the attribute name ``ID`` (with - uppercase letters) to specify unique identifiers. Some - VOTable-producing tools use the more standard lowercase ``id`` - instead. ``vo.table`` accepts ``id`` and emits this warning when - not in ``pedantic`` mode. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ - """ - - message = "ID attribute not capitalized" - - -class W10(VOTableSpecWarning): - """ - The parser has encountered an element that does not exist in the - specification, or appears in an invalid context. Check the file - against the VOTable schema (with a tool such as `xmllint - <http://xmlsoft.org/xmllint.html>`__. If the file validates - against the schema, and you still receive this warning, this may - indicate a bug in ``vo.table``. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ - """ - - message = "Unknown tag '%s'. Ignoring" - default_args = ('x',) - - -class W11(VOTableSpecWarning): - """ - Earlier versions of the VOTable specification used a ``gref`` - attribute on the ``LINK`` element to specify a `GLU reference - <http://simbad3.u-strasbg.fr/glu/glu.htx>`__. New files should - specify a ``glu:`` protocol using the ``href`` attribute. - - Since ``vo.table`` does not currently support GLU references, it - likewise does not automatically convert the ``gref`` attribute to - the new form. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:link>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:link>`__ - """ - - message = "The gref attribute on LINK is deprecated in VOTable 1.1" - - -class W12(VOTableChangeWarning): - """ - In order to name the columns of the Numpy record array, each - ``FIELD`` element must have either an ``ID`` or ``name`` attribute - to derive a name from. Strictly speaking, according to the - VOTable schema, the ``name`` attribute is required. However, if - ``name`` is not present by ``ID`` is, and *pedantic mode* is off, - ``vo.table`` will continue without a ``name`` defined. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ - """ - - message = ( - "'%s' element must have at least one of 'ID' or 'name' attributes") - default_args = ('x',) - - -class W13(VOTableSpecWarning): - """ - Some VOTable files in the wild use non-standard datatype names. These - are mapped to standard ones using the following mapping:: - - string -> char - unicodeString -> unicodeChar - int16 -> short - int32 -> int - int64 -> long - float32 -> float - float64 -> double - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ - """ - - message = "'%s' is not a valid VOTable datatype, should be '%s'" - default_args = ('x', 'y') - - -# W14: Deprecated - - -class W15(VOTableSpecWarning): - """ - The ``name`` attribute is required on every ``FIELD`` element. - However, many VOTable files in the wild omit it and provide only - an ``ID`` instead. In this case, when *pedantic mode* is off, - ``vo.table`` will copy the ``name`` attribute to a new ``ID`` - attribute. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ - """ - - message = "%s element missing required 'name' attribute" - default_args = ('x',) - -# W16: Deprecated - - -class W17(VOTableSpecWarning): - """ - A ``DESCRIPTION`` element can only appear once within its parent - element. - - According to the schema, it may only occur once (`1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__) - - However, it is a `proposed extension - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:addesc>`__ - to VOTable 1.2. - """ - - message = "%s element contains more than one DESCRIPTION element" - default_args = ('x',) - - -class W18(VOTableSpecWarning): - """ - The number of rows explicitly specified in the ``nrows`` attribute - does not match the actual number of rows (``TR`` elements) present - in the ``TABLE``. This may indicate truncation of the file, or an - internal error in the tool that produced it. If *pedantic mode* - is off, parsing will proceed, with the loss of some performance. - - **References:** `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC10>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC10>`__ - """ - - message = 'TABLE specified nrows=%s, but table contains %s rows' - default_args = ('x', 'y') - - -class W19(VOTableSpecWarning): - """ - The column fields as defined using ``FIELD`` elements do not match - those in the headers of the embedded FITS file. If *pedantic - mode* is off, the embedded FITS file will take precedence. - """ - - message = ( - 'The fields defined in the VOTable do not match those in the ' + - 'embedded FITS file') - - -class W20(VOTableSpecWarning): - """ - If no version number is explicitly given in the VOTable file, the - parser assumes it is written to the VOTable 1.1 specification. - """ - - message = 'No version number specified in file. Assuming %s' - default_args = ('1.1',) - - -class W21(UnimplementedWarning): - """ - Unknown issues may arise using ``vo.table`` with VOTable files - from a version other than 1.1 or 1.2. - """ - - message = ( - 'vo.table is designed for VOTable version 1.1 and 1.2, but ' + - 'this file is %s') - default_args = ('x',) - - -class W22(VOTableSpecWarning): - """ - Version 1.0 of the VOTable specification used the ``DEFINITIONS`` - element to define coordinate systems. Version 1.1 now uses - ``COOSYS`` elements throughout the document. - - **References:** `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:definitions>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:definitions>`__ - """ - - message = 'The DEFINITIONS element is deprecated in VOTable 1.1. Ignoring' - - -class W23(IOWarning): - """ - Raised when the VO service database can not be updated (possibly - due to a network outage). This is only a warning, since an older - and possible out-of-date VO service database was available - locally. - """ - - message = "Unable to update service information for '%s'" - default_args = ('x',) - - -class W24(VOWarning, FutureWarning): - """ - The VO catalog database retrieved from the www is designed for a - newer version of vo.table. This may cause problems or limited - features performing service queries. Consider upgrading vo.table - to the latest version. - """ - - message = "The VO catalog database is for a later version of vo.table" - - -class W25(IOWarning): - """ - A VO service query failed due to a network error or malformed - arguments. Another alternative service may be attempted. If all - services fail, an exception will be raised. - """ - - message = "'%s' failed with: %s" - default_args = ('service', '...') - - -class W26(VOTableSpecWarning): - """ - The given element was not supported inside of the given element - until the specified VOTable version, however the version declared - in the file is for an earlier version. These attributes may not - be written out to the file. - """ - - message = "'%s' inside '%s' added in VOTable %s" - default_args = ('child', 'parent', 'X.X') - - -class W27(VOTableSpecWarning): - """ - The ``COOSYS`` element was deprecated in VOTABLE version 1.2 in - favor of a reference to the Space-Time Coordinate (STC) data - model (see `utype - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:utype>`__ - and the IVOA note `referencing STC in VOTable - <http://ivoa.net/Documents/latest/VOTableSTC.html>`__. - """ - - message = "COOSYS deprecated in VOTable 1.2" - - -class W28(VOTableSpecWarning): - """ - The given attribute was not supported on the given element until the - specified VOTable version, however the version declared in the file is - for an earlier version. These attributes may not be written out to - the file. - """ - - message = "'%s' on '%s' added in VOTable %s" - default_args = ('attribute', 'element', 'X.X') - - -class W29(VOTableSpecWarning): - """ - Some VOTable files specify their version number in the form "v1.0", - when the only supported forms in the spec are "1.0". - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ - """ - - message = "Version specified in non-standard form '%s'" - default_args = ('v1.0',) - - -class W30(VOTableSpecWarning): - """ - Some VOTable files write missing floating-point values in non-standard - ways, such as "null" and "-". In non-pedantic mode, any non-standard - floating-point literals are treated as missing values. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ - """ - - message = "Invalid literal for float '%s'. Treating as empty." - default_args = ('x',) - - -class W31(VOTableSpecWarning): - """ - Since NaN's can not be represented in integer fields directly, a null - value must be specified in the FIELD descriptor to support reading - NaN's from the tabledata. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ - """ - - message = "NaN given in an integral field without a specified null value" - - -class W32(VOTableSpecWarning): - """ - Each field in a table must have a unique ID. If two or more fields - have the same ID, some will be renamed to ensure that all IDs are - unique. - - From the VOTable 1.2 spec: - - The ``ID`` and ``ref`` attributes are defined as XML types - ``ID`` and ``IDREF`` respectively. This means that the - contents of ``ID`` is an identifier which must be unique - throughout a VOTable document, and that the contents of the - ``ref`` attribute represents a reference to an identifier - which must exist in the VOTable document. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ - """ - - message = "Duplicate ID '%s' renamed to '%s' to ensure uniqueness" - default_args = ('x', 'x_2') - - -class W33(VOTableChangeWarning): - """ - Each field in a table must have a unique name. If two or more - fields have the same name, some will be renamed to ensure that all - names are unique. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__ - """ - - message = "Column name '%s' renamed to '%s' to ensure uniqueness" - default_args = ('x', 'x_2') - - -class W34(VOTableSpecWarning): - """ - The attribute requires the value to be a valid XML token, as - defined by `XML 1.0 - <http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-Nmtoken>`__. - """ - - message = "'%s' is an invalid token for attribute '%s'" - default_args = ('x', 'y') - - -class W35(VOTableSpecWarning): - """ - The ``name`` and ``value`` attributes are required on all ``INFO`` - elements. - - **References:** `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC32>` - """ - - message = "'%s' attribute required for INFO elements" - default_args = ('x',) - - -class W36(VOTableSpecWarning): - """ - If the field specifies a ``null`` value, that value must conform - to the given ``datatype``. - - **References:** `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>` - """ - - message = "null value '%s' does not match field datatype, setting to 0" - default_args = ('x',) - - -class W37(UnimplementedWarning): - """ - The 3 datatypes defined in the VOTable specification and supported by - vo.table are ``TABLEDATA``, ``BINARY`` and ``FITS``. - - **References:** `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:data>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:data>` - """ - - message = "Unsupported data format '%s'" - default_args = ('x',) - - -class W38(VOTableSpecWarning): - """ - The only encoding for local binary data supported by the VOTable - specification is base64. - """ - - message = "Inline binary data must be base64 encoded, got '%s'" - default_args = ('x',) - - -class W39(VOTableSpecWarning): - """ - Bit values do not support masking. This warning is raised upon - setting masked data in a bit column. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ - """ - - message = "Bit values can not be masked" - - -class W40(VOTableSpecWarning): - """ - This is a terrible hack to support Simple Image Access Protocol - results from `<archive.noao.edu>`__. It creates a field for the - coordinate projection type of type "double", which - actually contains character data. We have to hack the field - to store character data, or we can't read it in. A warning - will be raised when this happens. - """ - - message = "'cprojection' datatype repaired" - - -class W41(VOTableSpecWarning): - """ - An XML namespace was specified on the ``VOTABLE`` element, but the - namespace does not match what is expected for a ``VOTABLE`` file. - - The ``VOTABLE`` namespace is:: - - http://www.ivoa.net/xml/VOTable/vX.X - - where "X.X" is the version number. - - Some files in the wild set the namespace to the location of the - VOTable schema, which is not correct and will not pass some - validating parsers. - """ - - message = ( - "An XML namespace is specified, but is incorrect. Expected " + - "'%s', got '%s'") - default_args = ('x', 'y') - - -class W42(VOTableSpecWarning): - """ - The root element should specify a namespace. - - The ``VOTABLE`` namespace is:: - - http://www.ivoa.net/xml/VOTable/vX.X - - where "X.X" is the version number. - """ - - message = "No XML namespace specified" - - -class W43(VOTableSpecWarning): - """ - Referenced elements should be defined before referees. From the - VOTable 1.2 spec: - - In VOTable1.2, it is further recommended to place the ID - attribute prior to referencing it whenever possible. - """ - - message = "%s ref='%s' which has not already been defined" - default_args = ('element', 'x',) - - -class W44(VOTableSpecWarning): - """ - ``VALUES`` elements that reference another element should not have - their own content. - - From the VOTable 1.2 spec: - - The ``ref`` attribute of a ``VALUES`` element can be used to - avoid a repetition of the domain definition, by referring to a - previously defined ``VALUES`` element having the referenced - ``ID`` attribute. When specified, the ``ref`` attribute - defines completely the domain without any other element or - attribute, as e.g. ``<VALUES ref="RAdomain"/>`` - """ - - message = "VALUES element with ref attribute has content ('%s')" - default_args = ('element',) - - -class W45(VOWarning, ValueError): - """ - The ``content-role`` attribute on the ``LINK`` element must be one of - the following:: - - query, hints, doc, location - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ - """ - - message = "content-role attribute '%s' invalid" - default_args = ('x',) - - -class W46(VOTableSpecWarning): - """ - The given char or unicode string is too long for the specified - field length. - """ - - message = "%s value is too long for specified length of %s" - default_args = ('char or unicode', 'x') - - -class W47(VOTableSpecWarning): - """ - If no arraysize is specified on a char field, the default of '1' - is implied, but this is rarely what is intended. - """ - - message = "Missing arraysize indicates length 1" - - -class W48(VOTableSpecWarning): - """ - The attribute is not defined in the specification. - """ - - message = "Unknown attribute '%s' on %s" - default_args = ('attribute', 'element') - - -class W49(VOTableSpecWarning): - """ - Empty cell illegal for integer fields. - - If a \"null\" value was specified for the cell, it will be used - for the value, otherwise, 0 will be used. - """ - - message = "Empty cell illegal for integer fields." - - -class W50(VOTableSpecWarning): - """ - Invalid unit string as defined in the `Standards for Astronomical - Catalogues, Version 2.0 - <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_. - """ - - message = "Invalid unit string '%s'" - default_args = ('x',) - - -class E01(VOWarning, ValueError): - """ - The size specifier for a ``char`` or ``unicode`` field must be - only a number followed, optionally, by an asterisk. - Multi-dimensional size specifiers are not supported for these - datatypes. - - Strings, which are defined as a set of characters, can be - represented in VOTable as a fixed- or variable-length array of - characters:: - - <FIELD name="unboundedString" datatype="char" arraysize="*"/> - - A 1D array of strings can be represented as a 2D array of - characters, but given the logic above, it is possible to define a - variable-length array of fixed-length strings, but not a - fixed-length array of variable-length strings. - """ - - message = "Invalid size specifier '%s' for a %s field (in field '%s')" - default_args = ('x', 'char/unicode', 'y') - - -class E02(VOWarning, ValueError): - """ - The number of array elements in the data does not match that specified - in the FIELD specifier. - """ - - message = ( - "Incorrect number of elements in array. " + - "Expected multiple of %s, got %s") - default_args = ('x', 'y') - - -class E03(VOWarning, ValueError): - """ - Complex numbers should be two values separated by whitespace. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ - """ - - message = "'%s' does not parse as a complex number" - default_args = ('x',) - - -class E04(VOWarning, ValueError): - """ - A ``bit`` array should be a string of '0's and '1's. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ - """ - - message = "Invalid bit value '%s'" - default_args = ('x',) - - -class E05(VOWarning, ValueError): - """ - A ``boolean`` value should be one of the following strings (case - insensitive) in the ``TABLEDATA`` format:: - - 'TRUE', 'FALSE', '1', '0', 'T', 'F', '\\0', ' ', '?' - - and in ``BINARY`` format:: - - 'T', 'F', '1', '0', '\\0', ' ', '?' - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ - """ - - message = "Invalid boolean value '%s'" - default_args = ('x',) - - -class E06(VOWarning, ValueError): - """ - The supported datatypes are:: - - double, float, bit, boolean, unsignedByte, short, int, long, - floatComplex, doubleComplex, char, unicodeChar - - The following non-standard aliases are also supported, but in - these case :ref:`W13 <W13>` will be raised:: - - string -> char - unicodeString -> unicodeChar - int16 -> short - int32 -> int - int64 -> long - float32 -> float - float64 -> double - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__ - """ - - message = "Unknown datatype '%s' on field '%s'" - default_args = ('x', 'y') - -# E07: Deprecated - - -class E08(VOWarning, ValueError): - """ - The ``type`` attribute on the ``VALUES`` element must be either - ``legal`` or ``actual``. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`__ - """ - - message = "type must be 'legal' or 'actual', but is '%s'" - default_args = ('x',) - - -class E09(VOWarning, ValueError): - """ - The ``MIN``, ``MAX`` and ``OPTION`` elements must always have a - ``value`` attribute. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`__ - """ - - message = "'%s' must have a value attribute" - default_args = ('x',) - - -class E10(VOWarning, ValueError): - """ - From VOTable 1.1 and later, ``FIELD`` and ``PARAM`` elements must have - a ``datatype`` field. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:FIELD>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#elem:FIELD>`__ - """ - - message = "'datatype' attribute required on all '%s' elements" - default_args = ('FIELD',) - - -class E11(VOWarning, ValueError): - """ - The precision attribute is meant to express the number of significant - digits, either as a number of decimal places (e.g. ``precision="F2"`` or - equivalently ``precision="2"`` to express 2 significant figures - after the decimal point), or as a number of significant figures - (e.g. ``precision="E5"`` indicates a relative precision of 10-5). - - It is validated using the following regular expression:: - - [EF]?[1-9][0-9]* - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:form>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:form>`__ - """ - - message = "precision '%s' is invalid" - default_args = ('x',) - - -class E12(VOWarning, ValueError): - """ - The width attribute is meant to indicate to the application the - number of characters to be used for input or output of the - quantity. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:form>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:form>`__ - """ - - message = "width must be a positive integer, got '%s'" - default_args = ('x',) - - -class E13(VOWarning, ValueError): - u""" - From the VOTable 1.2 spec: - - A table cell can contain an array of a given primitive type, - with a fixed or variable number of elements; the array may - even be multidimensional. For instance, the position of a - point in a 3D space can be defined by the following:: - - <FIELD ID="point_3D" datatype="double" arraysize="3"/> - - and each cell corresponding to that definition must contain - exactly 3 numbers. An asterisk (\*) may be appended to - indicate a variable number of elements in the array, as in:: - - <FIELD ID="values" datatype="int" arraysize="100*"/> - - where it is specified that each cell corresponding to that - definition contains 0 to 100 integer numbers. The number may - be omitted to specify an unbounded array (in practice up to - =~2×10⁹ elements). - - A table cell can also contain a multidimensional array of a - given primitive type. This is specified by a sequence of - dimensions separated by the ``x`` character, with the first - dimension changing fastest; as in the case of a simple array, - the last dimension may be variable in length. As an example, - the following definition declares a table cell which may - contain a set of up to 10 images, each of 64×64 bytes:: - - <FIELD ID="thumbs" datatype="unsignedByte" arraysize="64×64×10*"/> - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:dim>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:dim>`__ - """ - - message = "Invalid arraysize attribute '%s'" - default_args = ('x',) - - -class E14(VOWarning, ValueError): - """ - All ``PARAM`` elements must have a ``value`` attribute. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:FIELD>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#elem:FIELD>`__ - """ - - message = "value attribute is required for all PARAM elements" - - -class E15(VOWarning, ValueError): - """ - All ``COOSYS`` elements must have an ``ID`` attribute. - - Note that the VOTable 1.1 specification says this attribute is - optional, but its corresponding schema indicates it is required. - - In VOTable 1.2, the ``COOSYS`` element is deprecated. - """ - - message = "ID attribute is required for all COOSYS elements" - - -class E16(VOTableSpecWarning): - """ - The ``system`` attribute on the ``COOSYS`` element must be one of the - following:: - - 'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic', - 'supergalactic', 'xy', 'barycentric', 'geo_app' - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:COOSYS>`__ - """ - - message = "Invalid system attribute '%s'" - default_args = ('x',) - - -class E17(VOWarning, ValueError): - """ - ``extnum`` attribute must be a positive integer. - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ - """ - - message = "extnum must be a positive integer" - - -class E18(VOWarning, ValueError): - """ - The ``type`` attribute of the ``RESOURCE`` element must be one of - "results" or "meta". - - **References**: `1.1 - <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__, - `1.2 - <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__ - """ - - message = "type must be 'results' or 'meta', not '%s'" - default_args = ('x',) - - -class E19(VOWarning, ValueError): - """ - Raised either when the file doesn't appear to be XML, or the root - element is not VOTABLE. - """ - - message = "File does not appear to be a VOTABLE" - - -class E20(VOTableSpecError): - """ - The table had only *x* fields defined, but the data itself has more - columns than that. - """ - - message = "Data has more columns than are defined in the header (%s)" - default_args = ('x',) - - -class E21(VOWarning, ValueError): - """ - The table had *x* fields defined, but the data itself has only *y* - columns. - """ - - message = "Data has fewer columns (%s) than are defined in the header (%s)" - default_args = ('x', 'y') - - -def _get_warning_and_exception_classes(prefix): - classes = [] - for key, val in globals().iteritems(): - if re.match(prefix + "[0-9]{2}", key): - classes.append((key, val)) - classes.sort() - return classes - - -def _build_doc_string(): - from textwrap import dedent - - def generate_set(prefix): - classes = _get_warning_and_exception_classes(prefix) - - out = io.StringIO() - - for name, cls in classes: - out.write(u".. _%s:\n\n" % name) - msg = "%s: %s" % (cls.__name__, cls.get_short_name()) - if not isinstance(msg, unicode): - msg = msg.decode('utf-8') - out.write(msg) - out.write(u'\n') - out.write(u'~' * len(msg)) - out.write(u'\n\n') - doc = cls.__doc__ - if not isinstance(doc, unicode): - doc = doc.decode('utf-8') - out.write(dedent(doc)) - out.write(u'\n\n') - - return out.getvalue() - - warnings = generate_set(u'W') - exceptions = generate_set(u'E') - - return {u'warnings': warnings, - u'exceptions': exceptions} - -__doc__ = __doc__.format(**_build_doc_string()) - -__all__.extend([x[0] for x in _get_warning_and_exception_classes(u'W')]) -__all__.extend([x[0] for x in _get_warning_and_exception_classes(u'E')]) -
                - -
                -
                -
                -
                -
                - - - -
                -
                -
                -
                - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/table.html b/_modules/astropy/io/vo/table.html deleted file mode 100644 index 2b26f90e..00000000 --- a/_modules/astropy/io/vo/table.html +++ /dev/null @@ -1,340 +0,0 @@ - - - - - - - - - - astropy.io.vo.table — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
                -
                -
                -
                - -

                Source code for astropy.io.vo.table

                -"""
                -This file contains a contains the high-level functions to read a
                -VOTable file.
                -"""
                -
                -from __future__ import division, absolute_import
                -
                -# STDLIB
                -import io
                -import sys
                -import warnings
                -
                -# LOCAL
                -from . import exceptions
                -from . import tree
                -from . import util
                -from ...utils.xml import iterparser
                -from ...config import ConfigurationItem
                -
                -
                -__all__ = ['parse', 'parse_single_table', 'validate']
                -
                -
                -PEDANTIC = ConfigurationItem(
                -    'pedantic',
                -    True,
                -    'When True, treat fixable violations of the VOTable spec as exceptions.')
                -
                -
                -
                [docs]def parse(source, columns=None, invalid='exception', pedantic=None, - chunk_size=tree.DEFAULT_CHUNK_SIZE, table_number=None, - filename=None, - _debug_python_based_parser=False): - """ - Parses a VOTABLE_ xml file (or file-like object), and returns a - `~astropy.io.vo.tree.VOTable` object, with nested - `~astropy.io.vo.tree.Resource` instances and - `~astropy.io.vo.tree.Table` instances. - - Parameters - ---------- - source : str or readable file-like object - Path or file object containing a VOTABLE_ xml file. - - columns : sequence of str, optional - List of field names to include in the output. The default is - to include all fields. - - invalid : str, optional - One of the following values: - - - 'exception': throw an exception when an invalid value is - encountered (default) - - - 'mask': mask out invalid values - - pedantic : bool, optional - When `True`, raise an error when the file violates the spec, - otherwise issue a warning. Warnings may be controlled using - the standard Python mechanisms. See the `warnings` - module in the Python standard library for more information. - When not provided, uses the configuration setting - `astropy.io.vo.pedantic`, which defaults to True. - - chunk_size : int, optional - The number of rows to read before converting to an array. - Higher numbers are likely to be faster, but will consume more - memory. - - table_number : int, optional - The number of table in the file to read in. If `None`, all - tables will be read. If a number, 0 refers to the first table - in the file, and only that numbered table will be parsed and - read in. - - filename : str, optional - A filename, URL or other identifier to use in error messages. - If *filename* is None and *source* is a string (i.e. a path), - then *source* will be used as a filename for error messages. - Therefore, *filename* is only required when source is a - file-like object. - - Returns - ------- - votable : `astropy.io.vo.tree.VOTableFile` object - - See also - -------- - astropy.io.vo.exceptions : The exceptions this function may raise. - """ - invalid = invalid.lower() - assert invalid in ('exception', 'mask') - - if pedantic is None: - pedantic = PEDANTIC() - - config = { - 'columns' : columns, - 'invalid' : invalid, - 'pedantic' : pedantic, - 'chunk_size' : chunk_size, - 'table_number' : table_number, - 'filename' : filename} - - if filename is None and isinstance(source, basestring): - config['filename'] = source - - with iterparser.get_xml_iterator( - source, - _debug_python_based_parser=_debug_python_based_parser) as iterator: - return tree.VOTableFile( - config=config, pos=(1, 1)).parse(iterator, config) - -
                -
                [docs]def parse_single_table(source, **kwargs): - """ - Parses a VOTABLE_ xml file (or file-like object), reads only the - first TABLE_ element, and returns a `~astropy.io.vo.tree.Table` - instance. - - See `parse` for a description of the keyword arguments. - - Returns - ------- - votable : `astropy.io.vo.tree.Table` object - """ - if kwargs.get('table_number') is None: - kwargs['table_number'] = 0 - - votable = parse(source, **kwargs) - - return votable.get_first_table() - -
                -
                [docs]def validate(filename, output=sys.stdout, xmllint=False): - """ - Prints a validation report for the given file. - - Parameters - ---------- - filename : str path - Path to a VOTABLE_ xml file. - - output : writable file-like object, optional - Where to output the report. Defaults to `sys.stdout`. - If `None`, the output will be returned as a string. - - xmllint : bool, optional - When `True`, also send the file to `xmllint` for schema and - DTD validation. Requires that `xmllint` is installed. The - default is `False`. - - Returns - ------- - is_valid : bool or str - Returns `True` if no warnings were found. If `output` is - `None`, the return value will be a string. - """ - import textwrap - from ...utils.console import print_code_line, color_print - - return_as_str = False - if output is None: - output = io.StringIO() - - lines = [] - votable = None - - # This is a special variable used by the Python warnings - # infrastructure to keep track of warnings that have already been - # seen. Since we want to get every single warning out of this, we - # have to delete it first. - if hasattr(exceptions, '__warningregistry__'): - del exceptions.__warningregistry__ - - with io.open(filename, 'rb') as input: - with warnings.catch_warnings(record=True) as warning_lines: - warnings.resetwarnings() - warnings.simplefilter("always", append=True) - try: - votable = parse(input, pedantic=False, filename=filename) - except ValueError as e: - lines.append(str(e)) - lines = [str(x.message) for x in warning_lines] + lines - - output.write(u"Validation report for {0}\n\n".format(filename)) - - if len(lines): - xml_lines = iterparser.xml_readlines(filename) - - for warning in lines: - w = exceptions.parse_vowarning(warning) - - if not w['is_something']: - output.write(warning) - output.write(u'\n\n') - else: - line = xml_lines[w['nline'] - 1] - warning = w['warning'] - if warning.startswith('W'): - color = 'yellow' - else: - color = 'red' - color_print( - u'{0:d}: '.format(w['nline']), '', - warning, color, - u': ', '', - textwrap.fill( - w['message'], - initial_indent=u' ', - subsequent_indent=u' ').lstrip(), - file=output) - print_code_line(line, w['nchar'], file=output) - output.write(u'\n') - else: - output.write(u'astropy.io.vo found no violations.\n\n') - - success = 0 - if xmllint: - if votable is None: - version = "1.1" - else: - version = votable.version - success, stdout, stderr = xmlutil.validate_schema( - filename, version) - - if success != 0: - output.write( - u'xmllint schema violations:\n\n') - output.write(stderr) - else: - output.write(u'xmllint passed\n') - - if return_as_str: - return output.getvalue() - return len(lines) == 0 and success == 0 -
                - -
                -
                -
                -
                -
                - - - -
                -
                -
                -
            - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/tree.html b/_modules/astropy/io/vo/tree.html deleted file mode 100644 index 72fc8485..00000000 --- a/_modules/astropy/io/vo/tree.html +++ /dev/null @@ -1,3178 +0,0 @@ - - - - - - - - - - astropy.io.vo.tree — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
            -
            -
            -
            - -

            Source code for astropy.io.vo.tree

            -# TODO: Test FITS parsing
            -
            -from __future__ import division, absolute_import
            -
            -from .util import IS_PY3K
            -
            -# STDLIB
            -import base64
            -import codecs
            -import io
            -from math import ceil
            -from operator import attrgetter
            -import re
            -import sys
            -import urllib2
            -if IS_PY3K:
            -    string_types = (str, bytes)
            -else:
            -    string_types = (str, unicode)
            -
            -# THIRD-PARTY
            -import numpy as np
            -try:
            -    import pyfits
            -    _has_pyfits = True
            -except ImportError:
            -    _has_pyfits = False
            -
            -# LOCAL
            -from ... import __version__ as astropy_version
            -from ...utils.collections import HomogeneousList
            -from ...utils.xml.writer import XMLWriter
            -
            -from . import converters
            -from .exceptions import (warn_or_raise, vo_warn, vo_raise, vo_reraise,
            -    warn_unknown_attrs, UnimplementedWarning, VOTableChangeWarning,
            -    W06, W07, W08, W09, W10, W11, W12, W13, W15, W17, W18, W19, W20,
            -    W21, W22, W26, W27, W28, W29, W32, W33, W35, W36, W37, W38, W40,
            -    W41, W42, W43, W44, W45, W48, E06, E08, E09, E10, E11, E12, E13,
            -    E14, E15, E16, E17, E18, E19, E20, E21)
            -from . import ucd as ucd_mod
            -from .unit import check_unit
            -from . import util
            -from . import xmlutil
            -
            -try:
            -    from . import tablewriter
            -    _has_c_tabledata_writer = True
            -except ImportError:
            -    _has_c_tabledata_writer = False
            -
            -
            -__all__ = [
            -    'Link', 'Info', 'Values', 'Field', 'Param', 'CooSys',
            -    'FieldRef', 'ParamRef', 'Group', 'Table', 'Resource',
            -    'VOTableFile'
            -    ]
            -
            -
            -# The default number of rows to read in each chunk before converting
            -# to an array.
            -DEFAULT_CHUNK_SIZE = 256
            -RESIZE_AMOUNT = 1.5
            -
            -######################################################################
            -# FACTORY FUNCTIONS
            -
            -
            -def _lookup_by_id_factory(iterator, element_name, doc):
            -    """
            -    Creates a function useful for looking up an element by ID.
            -
            -    Parameters
            -    ----------
            -    iterator : generator
            -        A generator that iterates over some arbitrary set of elements
            -
            -    element_name : str
            -        The XML element name of the elements being iterated over (used
            -        for error messages only).
            -
            -    doc : str
            -        A docstring to apply to the generated function.
            -
            -    Returns
            -    -------
            -    factory : function
            -        A function that looks up an element by ID
            -    """
            -    def lookup_by_id(self, ref, before=None):
            -        """
            -        Given an XML id *ref*, finds the first element in the iterator
            -        with the attribute ID == *ref*.  If *before* is provided, will
            -        stop searching at the object *before*.  This is important,
            -        since "forward references" are not allowed in the VOTABLE
            -        format.
            -        """
            -        for element in getattr(self, iterator)():
            -            if element is before:
            -                if element.ID == ref:
            -                    vo_raise(
            -                        "%s references itself" % element_name,
            -                        element._config, element._pos, KeyError)
            -                break
            -            if element.ID == ref:
            -                return element
            -        raise KeyError(
            -            "No %s with ID '%s' found before the referencing %s" %
            -            (element_name, ref, element_name))
            -
            -    lookup_by_id.__doc__ = doc
            -    return lookup_by_id
            -
            -
            -def _lookup_by_id_or_name_factory(iterator, element_name, doc):
            -    """
            -    Like `_lookup_by_id_factory`, but also looks in the "name" attribute.
            -    """
            -    def lookup_by_id(self, ref, before=None):
            -        """
            -        Given an key *ref*, finds the first element in the iterator
            -        with the attribute ID == *ref* or name == *ref*.  If *before*
            -        is provided, will stop searching at the object *before*.  This
            -        is important, since "forward references" are not allowed in
            -        the VOTABLE format.
            -        """
            -        for element in getattr(self, iterator)():
            -            if element is before:
            -                if ref in (element.ID, element.name):
            -                    vo_raise(
            -                        "%s references itself" % element_name,
            -                        element._config, element._pos, KeyError)
            -                break
            -            if ref in (element.ID, element.name):
            -                return element
            -        raise KeyError(
            -            "No %s with ID or name '%s' found before the referencing %s" %
            -            (element_name, ref, element_name))
            -
            -    lookup_by_id.__doc__ = doc
            -    return lookup_by_id
            -
            -
            -######################################################################
            -# ATTRIBUTE CHECKERS
            -def check_astroyear(year, field, config={}, pos=None):
            -    """
            -    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if *year* is
            -    not a valid astronomical year as defined by the VOTABLE standard.
            -
            -    Parameters
            -    ----------
            -    year : str
            -        An astronomical year string
            -
            -    field : str
            -        The name of the field this year was found in (used for error
            -        message)
            -
            -    config, pos : optional
            -        Information about the source of the value
            -    """
            -    if (year is not None and
            -        re.match(r"^[JB]?[0-9]+([.][0-9]*)?$", year) is None):
            -        warn_or_raise(W07, W07, (field, year), config, pos)
            -        return False
            -    return True
            -
            -
            -def check_string(string, attr_name, config={}, pos=None):
            -    """
            -    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if
            -    *string* is not a string or Unicode string.
            -
            -    Parameters
            -    ----------
            -    string : str
            -        An astronomical year string
            -
            -    field : str
            -        The name of the field this year was found in (used for error
            -        message)
            -
            -    config, pos : optional
            -        Information about the source of the value
            -    """
            -    if string is not None and not isinstance(string, string_types):
            -        warn_or_raise(W08, W08, attr_name, config, pos)
            -        return False
            -    return True
            -
            -
            -def resolve_id(ID, id, config={}, pos=None):
            -    if ID is None and id is not None:
            -        warn_or_raise(W09, W09, (), config, pos)
            -        return id
            -    return ID
            -
            -
            -def check_ucd(ucd, config={}, pos=None):
            -    """
            -    Warns or raises a `~astropy.io.vo.exceptions.VOTableSpecError`
            -    if *ucd* is not a valid `unified content descriptor`_ string as
            -    defined by the VOTABLE standard.
            -
            -    Parameters
            -    ----------
            -    ucd : str
            -        A UCD string.
            -
            -    config, pos : optional
            -        Information about the source of the value
            -    """
            -    if config.get('version_1_1_or_later'):
            -        try:
            -            ucd_mod.parse_ucd(
            -                ucd,
            -                check_controlled_vocabulary=config.get(
            -                    'version_1_2_or_later', False),
            -                has_colon=config.get('version_1_2_or_later', False))
            -        except ValueError as e:
            -            # This weird construction is for Python 3 compatibility
            -            if config.get('pedantic'):
            -                vo_raise(W06, (ucd, unicode(e)), config, pos)
            -            else:
            -                vo_warn(W06, (ucd, unicode(e)), config, pos)
            -                return False
            -    return True
            -
            -
            -######################################################################
            -# PROPERTY MIXINS
            -class _IDProperty(object):
            -    @property
            -    def ID(self):
            -        """
            -        The XML ID_ of the element.  May be ``None`` or a string
            -        conforming to XML ID_ syntax.
            -        """
            -        return self._ID
            -
            -    @ID.setter
            -    def ID(self, ID):
            -        xmlutil.check_id(ID, 'ID', self._config, self._pos)
            -        self._ID = ID
            -
            -    @ID.deleter
            -    def ID(self):
            -        self._ID = None
            -
            -
            -class _NameProperty(object):
            -    @property
            -    def name(self):
            -        """An optional name for the element."""
            -        return self._name
            -
            -    @name.setter
            -    def name(self, name):
            -        xmlutil.check_token(name, 'name', self._config, self._pos)
            -        self._name = name
            -
            -    @name.deleter
            -    def name(self):
            -        self._name = None
            -
            -
            -class _XtypeProperty(object):
            -    @property
            -    def xtype(self):
            -        """Extended data type information."""
            -        return self._xtype
            -
            -    @xtype.setter
            -    def xtype(self, xtype):
            -        if xtype is not None and not self._config.get('version_1_2_or_later'):
            -            warn_or_raise(
            -                W28, W28, ('xtype', self._element_name, '1.2'),
            -                self._config, self._pos)
            -        check_string(xtype, 'xtype', self._config, self._pos)
            -        self._xtype = xtype
            -
            -    @xtype.deleter
            -    def xtype(self):
            -        self._xtype = None
            -
            -
            -class _UtypeProperty(object):
            -    _utype_in_v1_2 = False
            -
            -    @property
            -    def utype(self):
            -        """The usage-specific or `unique type`_ of the element."""
            -        return self._utype
            -
            -    @utype.setter
            -    def utype(self, utype):
            -        if (self._utype_in_v1_2 and
            -            utype is not None and
            -            not self._config.get('version_1_2_or_later')):
            -            warn_or_raise(
            -                W28, W28, ('utype', self._element_name, '1.2'),
            -                config, pos)
            -        check_string(utype, 'utype', self._config, self._pos)
            -        self._utype = utype
            -
            -    @utype.deleter
            -    def utype(self):
            -        self._utype = None
            -
            -
            -class _UcdProperty(object):
            -    _ucd_in_v1_2 = False
            -
            -    @property
            -    def ucd(self):
            -        """The `unified content descriptor`_ for the element."""
            -        return self._ucd
            -
            -    @ucd.setter
            -    def ucd(self, ucd):
            -        if ucd is not None and ucd.strip() == '':
            -            ucd = None
            -        if ucd is not None:
            -            if (self._ucd_in_v1_2 and
            -                not self._config.get('version_1_2_or_later')):
            -                warn_or_raise(
            -                    W28, W28, ('ucd', self._element_name, '1.2'),
            -                    config, pos)
            -            check_ucd(ucd, self._config, self._pos)
            -        self._ucd = ucd
            -
            -    @ucd.deleter
            -    def ucd(self):
            -        self._ucd = None
            -
            -
            -class _DescriptionProperty(object):
            -    @property
            -    def description(self):
            -        """
            -        An optional string describing the element.  Corresponds to the
            -        DESCRIPTION_ element.
            -        """
            -        return self._description
            -
            -    @description.setter
            -    def description(self, description):
            -        self._description = description
            -
            -    @description.deleter
            -    def description(self):
            -        self._description = None
            -
            -
            -######################################################################
            -# ELEMENT CLASSES
            -
            [docs]class Element(object): - """ - A base class for all classes that represent XML elements in the - VOTABLE file. - """ - def _add_unknown_tag(self, iterator, tag, data, config, pos): - warn_or_raise(W10, W10, tag, config, pos) - - def _ignore_add(self, iterator, tag, data, config, pos): - warn_unknown_attrs(tag, data.iterkeys(), config, pos) - - def _add_definitions(self, iterator, tag, data, config, pos): - if config.get('version_1_1_or_later'): - warn_or_raise(W22, W22, (), config, pos) - warn_unknown_attrs(tag, data.iterkeys(), config, pos) - -
            -
            [docs]class SimpleElement(Element): - """ - A base class for simple elements, such as FIELD, PARAM and INFO - that don't require any special parsing or outputting machinery. - """ - def __init__(self): - Element.__init__(self) - -
            [docs] def parse(self, iterator, config): - for start, tag, data, pos in iterator: - if start and tag != self._element_name: - self._add_unknown_tag(iterator, tag, data, config, pos) - elif tag == self._element_name: - break - - return self -
            -
            [docs] def to_xml(self, w, **kwargs): - w.element(self._element_name, - attrib=w.object_attrs(self, self._attr_list)) - -
            -
            [docs]class SimpleElementWithContent(SimpleElement): - """ - A base class for simple elements, such as FIELD, PARAM and INFO - that don't require any special parsing or outputting machinery. - """ - def __init__(self): - SimpleElement.__init__(self) - - self._content = None - -
            [docs] def to_xml(self, w, **kwargs): - w.element(self._element_name, self._content, - attrib=w.object_attrs(self, self._attr_list)) -
            - @property - def content(self): - """The content of the element.""" - return self._content - - @content.setter - def content(self, content): - check_string(content, 'content', self._config, self._pos) - self._content = content - - @content.deleter -
            [docs] def content(self): - self._content = None - -
            - -
            [docs]class Info(SimpleElementWithContent, _IDProperty, _XtypeProperty, - _UtypeProperty): - """ - A class for storing INFO elements, which contain arbitrary - key-value pairs for extensions to the standard. - - The keyword arguments correspond to setting members of the same - name, documented below. - """ - _element_name = 'INFO' - _attr_list_11 = ['ID', 'name', 'value'] - _attr_list_12 = _attr_list_11 + ['xtype', 'ref', 'unit', 'ucd', 'utype'] - _utype_in_v1_2 = True - - def __init__(self, ID=None, name=None, value=None, id=None, xtype=None, - ref=None, unit=None, ucd=None, utype=None, - config={}, pos=None, **extra): - self._config = config - self._pos = pos - - SimpleElementWithContent.__init__(self) - - self.ID = (resolve_id(ID, id, config, pos) or - xmlutil.fix_id(name, config, pos)) - self.name = name - self.value = value - self.xtype = xtype - self.ref = ref - self.unit = unit - self.ucd = ucd - self.utype = utype - - if config.get('version_1_2_or_later'): - self._attr_list = self._attr_list_12 - else: - self._attr_list = self._attr_list_11 - if xtype is not None: - warn_unknown_attrs('INFO', ['xtype'], config, pos) - if ref is not None: - warn_unknown_attrs('INFO', ['ref'], config, pos) - if unit is not None: - warn_unknown_attrs('INFO', ['unit'], config, pos) - if ucd is not None: - warn_unknown_attrs('INFO', ['ucd'], config, pos) - if utype is not None: - warn_unknown_attrs('INFO', ['utype'], config, pos) - - warn_unknown_attrs('INFO', extra.iterkeys(), config, pos) - - @property - def name(self): - """[*required*] The key of the key-value pair.""" - return self._name - - @name.setter -
            [docs] def name(self, name): - if name is None: - warn_or_raise(W35, W35, ('name'), self._config, self._pos) - xmlutil.check_token(name, 'name', self._config, self._pos) - self._name = name -
            - @property - def value(self): - """ - [*required*] The value of the key-value pair. (Always stored - as a string or unicode string). - """ - return self._value - - @value.setter -
            [docs] def value(self, value): - if value is None: - warn_or_raise(W35, W35, ('value'), self._config, self._pos) - check_string(value, 'value', self._config, self._pos) - self._value = value -
            - @property - def content(self): - """The content inside the INFO element.""" - return self._content - - @content.setter - def content(self, content): - check_string(content, 'content', self._config, self._pos) - self._content = content - - @content.deleter -
            [docs] def content(self): - self._content = None -
            - @property - def ref(self): - """ - Refer to another INFO_ element by ID_, defined previously in - the document. - """ - return self._ref - - @ref.setter - def ref(self, ref): - if ref is not None and not self._config.get('version_1_2_or_later'): - warn_or_raise(W28, W28, ('ref', 'INFO', '1.2'), config, pos) - xmlutil.check_id(ref, 'ref', self._config, self._pos) - # TODO: actually apply the reference - # if ref is not None: - # try: - # other = self._votable.get_values_by_id(ref, before=self) - # except KeyError: - # vo_raise( - # "VALUES ref='%s', which has not already been defined." % - # self.ref, self._config, self._pos, KeyError) - # self.null = other.null - # self.type = other.type - # self.min = other.min - # self.min_inclusive = other.min_inclusive - # self.max = other.max - # self.max_inclusive = other.max_inclusive - # self._options[:] = other.options - self._ref = ref - - @ref.deleter -
            [docs] def ref(self): - self._ref = None -
            - @property - def unit(self): - """A string specifying the units_ for the INFO_.""" - return self._unit - - @unit.setter - def unit(self, unit): - if unit is not None and not self._config.get('version_1_2_or_later'): - warn_or_raise(W28, W28, ('unit', 'INFO', '1.2'), config, pos) - check_unit(unit, 'unit', self._config, self._pos) - self._unit = unit - - @unit.deleter -
            [docs] def unit(self): - self._unit = None - -
            -
            [docs]class Values(Element, _IDProperty): - """ - A class to represent the VALUES_ element, used within FIELD_ and - PARAM_ elements to define the domain of values. - - The keyword arguments correspond to setting members of the same - name, documented below. - """ - def __init__(self, votable, field, ID=None, null=None, ref=None, - type="legal", id=None, config={}, pos=None, **extras): - self._config = config - self._pos = pos - - Element.__init__(self) - - self._votable = votable - self._field = field - self.ID = resolve_id(ID, id, config, pos) - self.null = null - self._ref = ref - self.type = type - - self.min = None - self.max = None - self.min_inclusive = True - self.max_inclusive = True - self._options = [] - - warn_unknown_attrs('VALUES', extras.iterkeys(), config, pos) - - @property - def null(self): - """ - For integral datatypes, *null* is used to define the value - used for missing values. - """ - return self._null - - @null.setter - def null(self, null): - if null is not None and isinstance(null, string_types): - try: - null_val = self._field.converter.parse_scalar( - null, self._config, self._pos)[0] - except: - warn_or_raise(W36, W36, null, self._config, self._pos) - null_val = self._field.converter.parse_scalar( - '0', self._config, self._pos)[0] - else: - null_val = null - self._null = null_val - - @null.deleter -
            [docs] def null(self): - self._null = None -
            - @property - def type(self): - """ - [*required*] Defines the applicability of the domain defined - by this VALUES_ element. Must be one of the following - strings: - - - 'legal': The domain of this column applies in general to - this datatype. (default) - - - 'actual': The domain of this column applies only to the - data enclosed in the parent table. - """ - return self._type - - @type.setter -
            [docs] def type(self, type): - if type not in ('legal', 'actual'): - vo_raise(E08, type, self._config, self._pos) - self._type = type -
            - @property - def ref(self): - """ - Refer to another VALUES_ element by ID_, defined previously in - the document, for MIN/MAX/OPTION information. - """ - return self._ref - - @ref.setter - def ref(self, ref): - xmlutil.check_id(ref, 'ref', self._config, self._pos) - if ref is not None: - try: - other = self._votable.get_values_by_id(ref, before=self) - except KeyError: - warn_or_raise(W43, W43, ('VALUES', self.ref), self._config, - self._pos) - ref = None - else: - self.null = other.null - self.type = other.type - self.min = other.min - self.min_inclusive = other.min_inclusive - self.max = other.max - self.max_inclusive = other.max_inclusive - self._options[:] = other.options - self._ref = ref - - @ref.deleter -
            [docs] def ref(self): - self._ref = None -
            - @property - def min(self): - """ - The minimum value of the domain. See :attr:`min_inclusive`. - """ - return self._min - - @min.setter - def min(self, min): - if hasattr(self._field, 'converter') and min is not None: - self._min = self._field.converter.parse(min)[0] - else: - self._min = min - - @min.deleter -
            [docs] def min(self): - self._min = None -
            - @property - def min_inclusive(self): - """When `True`, the domain includes the minimum value.""" - return self._min_inclusive - - @min_inclusive.setter - def min_inclusive(self, inclusive): - if inclusive == 'yes': - self._min_inclusive = True - elif inclusive == 'no': - self._min_inclusive = False - else: - self._min_inclusive = bool(inclusive) - - @min_inclusive.deleter -
            [docs] def min_inclusive(self): - self._min_inclusive = True -
            - @property - def max(self): - """ - The maximum value of the domain. See :attr:`max_inclusive`. - """ - return self._max - - @max.setter - def max(self, max): - if hasattr(self._field, 'converter') and max is not None: - self._max = self._field.converter.parse(max)[0] - else: - self._max = max - - @max.deleter -
            [docs] def max(self): - self._max = None -
            - @property - def max_inclusive(self): - """When `True`, the domain includes the maximum value.""" - return self._max_inclusive - - @max_inclusive.setter - def max_inclusive(self, inclusive): - if inclusive == 'yes': - self._max_inclusive = True - elif inclusive == 'no': - self._max_inclusive = False - else: - self._max_inclusive = bool(inclusive) - - @max_inclusive.deleter -
            [docs] def max_inclusive(self): - self._max_inclusive = True -
            - @property -
            [docs] def options(self): - """ - A list of string key-value tuples defining other OPTION - elements for the domain. All options are ignored -- they are - stored for round-tripping purposes only. - """ - return self._options -
            -
            [docs] def parse(self, iterator, config): - if self.ref is not None: - for start, tag, data, pos in iterator: - if start: - warn_or_raise(W44, W44, tag, config, pos) - else: - if tag != 'VALUES': - warn_or_raise(W44, W44, tag, config, pos) - break - else: - for start, tag, data, pos in iterator: - if start: - if tag == 'MIN': - if 'value' not in data: - vo_raise(E09, 'MIN', config, pos) - self.min = data['value'] - self.min_inclusive = data.get('inclusive', 'yes') - warn_unknown_attrs( - 'MIN', data.iterkeys(), config, pos, - ['value', 'inclusive']) - elif tag == 'MAX': - if 'value' not in data: - vo_raise(E09, 'MAX', config, pos) - self.max = data['value'] - self.max_inclusive = data.get('inclusive', 'yes') - warn_unknown_attrs( - 'MAX', data.iterkeys(), config, pos, - ['value', 'inclusive']) - elif tag == 'OPTION': - if 'value' not in data: - vo_raise(E09, 'OPTION', config, pos) - xmlutil.check_token( - data.get('name'), 'name', config, pos) - self.options.append( - (data.get('name'), data.get('value'))) - warn_unknown_attrs( - 'OPTION', data.iterkeys(), config, pos, - ['data', 'name']) - elif tag == 'VALUES': - break - - return self -
            -
            [docs] def is_defaults(self): - # If there's nothing meaningful or non-default to write, - # don't write anything. - return (self.ref is None and self.null is None and self.ID is None and - self.max is None and self.min is None and self.options == []) -
            -
            [docs] def to_xml(self, w, **kwargs): - def yes_no(value): - if value: - return 'yes' - return 'no' - - if self.is_defaults(): - return - - if self.ref is not None: - w.element('VALUES', attrib=w.object_attrs(self, ['ref'])) - else: - with w.tag('VALUES', - attrib=w.object_attrs( - self, ['ID', 'null', 'ref'])): - if self.min is not None: - w.element( - 'MIN', - value=self._field.converter.output(self.min, False), - inclusive=yes_no(self.min_inclusive)) - if self.max is not None: - w.element( - 'MAX', - value=self._field.converter.output(self.max, False), - inclusive=yes_no(self.max_inclusive)) - for name, value in self.options: - w.element( - 'OPTION', - name=name, - value=value) - -
            -
            [docs]class Field(SimpleElement, _IDProperty, _NameProperty, _XtypeProperty, - _UtypeProperty, _UcdProperty): - """ - A class that represents the FIELD_ element, which describes the - datatype of a particular column of data. - - The keyword arguments correspond to setting members of the same - name, documented below. - - If *ID* is provided, it is used for the column name in the - resulting recarray of the table. If no *ID* is provided, *name* - is used instead. If neither is provided, an exception will be - raised. - """ - _attr_list_11 = ['ID', 'name', 'datatype', 'arraysize', 'ucd', - 'unit', 'width', 'precision', 'utype', 'ref'] - _attr_list_12 = _attr_list_11 + ['xtype'] - _element_name = 'FIELD' - - def __init__(self, votable, ID=None, name=None, datatype=None, - arraysize=None, ucd=None, unit=None, width=None, - precision=None, utype=None, ref=None, type=None, id=None, - xtype=None, - config={}, pos=None, **extra): - self._config = config - self._pos = pos - - SimpleElement.__init__(self) - - if config.get('version_1_2_or_later'): - self._attr_list = self._attr_list_12 - else: - self._attr_list = self._attr_list_11 - if xtype is not None: - warn_unknown_attrs(self._element_name, ['xtype'], config, pos) - - # TODO: REMOVE ME ---------------------------------------- - # This is a terrible hack to support Simple Image Access - # Protocol results from archive.noao.edu. It creates a field - # for the coordinate projection type of type "double", which - # actually contains character data. We have to hack the field - # to store character data, or we can't read it in. A warning - # will be raised when this happens. - if (not config.get('pedantic') and name == 'cprojection' and - ID == 'cprojection' and ucd == 'VOX:WCS_CoordProjection' and - datatype == 'double'): - datatype = 'char' - arraysize = '3' - vo_warn(W40, (), config, pos) - # ---------------------------------------- - - self.description = None - self._votable = votable - - self.ID = (resolve_id(ID, id, config, pos) or - xmlutil.fix_id(name, config, pos)) - self.name = name - if name is None: - if (self._element_name == 'PARAM' and - not config.get('version_1_1_or_later')): - pass - else: - warn_or_raise(W15, W15, self._element_name, config, pos) - self.name = self.ID - - if self._ID is None and name is None: - vo_raise(W12, self._element_name, config, pos) - - datatype_mapping = { - 'string' : 'char', - 'unicodeString' : 'unicodeChar', - 'int16' : 'short', - 'int32' : 'int', - 'int64' : 'long', - 'float32' : 'float', - 'float64' : 'double'} - - if datatype in datatype_mapping: - warn_or_raise(W13, W13, (datatype, datatype_mapping[datatype]), - config, pos) - datatype = datatype_mapping[datatype] - - self.ref = ref - self.datatype = datatype - self.arraysize = arraysize - self.ucd = ucd - self.unit = unit - self.width = width - self.precision = precision - self.utype = utype - self.type = type - self._links = HomogeneousList(Link) - self.title = self.name - self.values = Values(self._votable, self) - self.xtype = xtype - - self._setup(config, pos) - - warn_unknown_attrs(self._element_name, extra.iterkeys(), config, pos) - - @classmethod -
            [docs] def uniqify_names(cls, fields): - """ - Make sure that all names and titles in a list of fields are - unique, by appending numbers if necessary. - """ - unique = {} - for field in fields: - i = 2 - new_id = field.ID - while new_id in unique: - new_id = field.ID + "_%d" % i - i += 1 - if new_id != field.ID: - vo_warn(W32, (field.ID, new_id), field._config, field._pos) - field.ID = new_id - unique[new_id] = field.ID - - for field in fields: - i = 2 - if field.name is None: - new_name = field.ID - implicit = True - else: - new_name = field.name - implicit = False - if new_name != field.ID: - while new_name in unique: - new_name = field.name + " %d" % i - i += 1 - - if (not implicit and - new_name != field.name): - vo_warn(W33, (field.name, new_name), field._config, field._pos) - field._unique_name = new_name - unique[new_name] = field.name -
            - def _setup(self, config, pos): - if self.values._ref is not None: - self.values.ref = self.values._ref - self.converter = converters.get_converter(self, config, pos) - - @property - def datatype(self): - """ - [*required*] The datatype of the column. Valid values (as - defined by the spec) are: - - 'boolean', 'bit', 'unsignedByte', 'short', 'int', 'long', - 'char', 'unicodeChar', 'float', 'double', 'floatComplex', or - 'doubleComplex' - - Many VOTABLE files in the wild use 'string' instead of 'char', - so that is also a valid option, though 'string' will always be - converted to 'char' when writing the file back out. - """ - return self._datatype - - @datatype.setter -
            [docs] def datatype(self, datatype): - if datatype is None: - if self._config.get('version_1_1_or_later'): - vo_raise(E10, self._element_name, self._config, self._pos) - else: - datatype = 'char' - if datatype not in converters.converter_mapping: - vo_raise(E06, (datatype, self.ID), self._config, self._pos) - self._datatype = datatype -
            - @property - def precision(self): - """ - Along with :attr:`width`, defines the `numerical accuracy`_ - associated with the data. These values are used to limit the - precision when writing floating point values back to the XML - file. Otherwise, it is purely informational -- the Numpy - recarray containing the data itself does not use this - information. - """ - return self._precision - - @precision.setter - def precision(self, precision): - if precision is not None and not re.match("^[FE]?[0-9]+$", precision): - vo_raise(E11, precision, self._config, self._pos) - self._precision = precision - - @precision.deleter -
            [docs] def precision(self): - self._precision = None -
            - @property - def width(self): - """ - Along with :attr:`precision`, defines the `numerical - accuracy`_ associated with the data. These values are used to - limit the precision when writing floating point values back to - the XML file. Otherwise, it is purely informational -- the - Numpy recarray containing the data itself does not use this - information. - """ - return self._width - - @width.setter - def width(self, width): - if width is not None: - width = int(width) - if width <= 0: - vo_raise(E12, width, self._config, self._pos) - self._width = width - - @width.deleter -
            [docs] def width(self): - self._width = None - - # ref on FIELD and PARAM behave differently than elsewhere -- here - # they're just informational, such as to refer to a coordinate - # system.
            - @property - def ref(self): - """ - On FIELD_ elements, ref is used only for informational - purposes, for example to refer to a COOSYS_ element. - """ - return self._ref - - @ref.setter - def ref(self, ref): - xmlutil.check_id(ref, 'ref', self._config, self._pos) - self._ref = ref - - @ref.deleter -
            [docs] def ref(self): - self._ref = None -
            - @property - def unit(self): - """A string specifying the units_ for the FIELD_.""" - return self._unit - - @unit.setter - def unit(self, unit): - check_unit(unit, 'unit', self._config, self._pos) - self._unit = unit - - @unit.deleter -
            [docs] def unit(self): - self._unit = None -
            - @property - def arraysize(self): - """ - Specifies the size of the multidimensional array if this - FIELD_ contains more than a single value. - - See `multidimensional arrays`_. - """ - return self._arraysize - - @arraysize.setter - def arraysize(self, arraysize): - if (arraysize is not None and - not re.match("^([0-9]+x)*[0-9]*[*]?(s\W)?$", arraysize)): - vo_raise(E13, arraysize, self._config, self._pos) - self._arraysize = arraysize - - @arraysize.deleter -
            [docs] def arraysize(self): - self._arraysize = None -
            - @property - def type(self): - """ - The type attribute on FIELD_ elements is reserved for future - extensions. - """ - return self._type - - @type.setter - def type(self, type): - self._type = type - - @type.deleter -
            [docs] def type(self): - self._type = None -
            - @property - def values(self): - """ - A :class:`Values` instance (or ``None``) defining the domain - of the column. - """ - return self._values - - @values.setter - def values(self, values): - assert values is None or isinstance(values, Values) - self._values = values - - @values.deleter -
            [docs] def values(self): - self._values = None -
            - @property - -
            [docs] def parse(self, iterator, config): - for start, tag, data, pos in iterator: - if start: - if tag == 'VALUES': - self.values.__init__( - self._votable, self, config=config, pos=pos, **data) - self.values.parse(iterator, config) - elif tag == 'LINK': - link = Link(config=config, pos=pos, **data) - self.links.append(link) - link.parse(iterator, config) - elif tag == 'DESCRIPTION': - warn_unknown_attrs( - 'DESCRIPTION', data.iterkeys(), config, pos) - elif tag != self._element_name: - self._add_unknown_tag(iterator, tag, data, config, pos) - else: - if tag == 'DESCRIPTION': - if self.description is not None: - warn_or_raise( - W17, W17, self._element_name, config, pos) - self.description = data or None - elif tag == self._element_name: - break - - if self.description is not None: - self.title = " ".join(x.strip() for x in - self.description.split("\n")) - else: - self.title = self.name - - self._setup(config, pos) - - return self -
            -
            [docs] def to_xml(self, w, **kwargs): - with w.tag(self._element_name, - attrib=w.object_attrs(self, self._attr_list)): - if self.description is not None: - w.element("DESCRIPTION", self.description, wrap=True) - if not self.values.is_defaults(): - self.values.to_xml(w, **kwargs) - for link in self.links: - link.to_xml(w, **kwargs) - -
            -
            [docs]class Param(Field): - """ - A class to represent the PARAM_ element, which are constant-valued - columns in the data. - - :class:`Param` objects are a subclass of :class:`Field`, and have - all of its methods and members. Additionally, it defines :attr:`value`. - """ - _attr_list_11 = Field._attr_list_11 + ['value'] - _attr_list_12 = Field._attr_list_12 + ['value'] - _element_name = 'PARAM' - - def __init__(self, votable, ID=None, name=None, value=None, datatype=None, - arraysize=None, ucd=None, unit=None, width=None, - precision=None, utype=None, type=None, id=None, config={}, - pos=None, **extra): - self._value = value - Field.__init__(self, votable, ID=ID, name=name, datatype=datatype, - arraysize=arraysize, ucd=ucd, unit=unit, - precision=precision, utype=utype, type=type, - id=id, config=config, pos=pos, **extra) - - @property - def value(self): - """ - [*required*] The constant value of the parameter. Its type is - determined by the :attr:`~Field.datatype` member. - """ - return self._value - - @value.setter -
            [docs] def value(self, value): - if value is None: - vo_raise(E14, (), self._config, self._pos) - if ((IS_PY3K and isinstance(value, unicode)) or - (not IS_PY3K and isinstance(value, string_types))): - self._value = self.converter.parse( - value, self._config, self._pos)[0] - else: - self._value = value -
            - def _setup(self, config, pos): - Field._setup(self, config, pos) - self.value = self._value - -
            [docs] def to_xml(self, w, **kwargs): - tmp_value = self._value - self._value = self.converter.output(tmp_value, False) - # We must always have a value - if self._value in (None, ''): - self._value = " " - Field.to_xml(self, w, **kwargs) - self._value = tmp_value - -
            -
            [docs]class CooSys(SimpleElement): - """ - A class representing the COOSYS_ element, which defines a - coordinate system. - - The keyword arguments correspond to setting members of the same - name, documented below. - """ - _attr_list = ['ID', 'equinox', 'epoch', 'system'] - _element_name = 'COOSYS' - - def __init__(self, ID=None, equinox=None, epoch=None, system=None, id=None, - config={}, pos=None, **extra): - self._config = config - self._pos = pos - - if config.get('version_1_2_or_later'): - warn_or_raise(W27, W27, (), config, pos) - - SimpleElement.__init__(self) - - self.ID = resolve_id(ID, id, config, pos) - self.equinox = equinox - self.epoch = epoch - self.system = system - - warn_unknown_attrs('COOSYS', extra.iterkeys(), config, pos) - - @property - def ID(self): - """ - [*required*] The XML ID of the COOSYS_ element, used for - cross-referencing. May be ``None`` or a string conforming to - XML ID_ syntax. - """ - return self._ID - - @ID.setter -
            [docs] def ID(self, ID): - if self._config.get('version_1_1_or_later'): - if ID is None: - vo_raise(E15, (), self._config, self._pos) - xmlutil.check_id(ID, 'ID', self._config, self._pos) - self._ID = ID -
            - @property - def system(self): - """ - Specifies the type of coordinate system. Valid choices are: - - 'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic', - 'supergalactic', 'xy', 'barycentric', or 'geo_app' - """ - return self._system - - @system.setter - def system(self, system): - if system not in ('eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', - 'galactic', 'supergalactic', 'xy', 'barycentric', - 'geo_app'): - warn_or_raise(E16, E16, system, self._config, self._pos) - self._system = system - - @system.deleter -
            [docs] def system(self): - self._system = None -
            - @property - def equinox(self): - """ - A parameter required to fix the equatorial or ecliptic systems - (as e.g. "J2000" as the default "eq_FK5" or "B1950" as the - default "eq_FK4"). - """ - return self._equinox - - @equinox.setter - def equinox(self, equinox): - check_astroyear(equinox, 'equinox', self._config, self._pos) - self._equinox = equinox - - @equinox.deleter -
            [docs] def equinox(self): - self._equinox = None -
            - @property - def epoch(self): - """ - Specifies the epoch of the positions. It must be a string - specifying an astronomical year. - """ - return self._epoch - - @epoch.setter - def epoch(self, epoch): - check_astroyear(epoch, 'epoch', self._config, self._pos) - self._epoch = epoch - - @epoch.deleter -
            [docs] def epoch(self): - self._epoch = None - -
            -
            [docs]class FieldRef(SimpleElement, _UtypeProperty, _UcdProperty): - """ - A class representing the FIELDref_ element, which is used inside - of GROUP_ elements to refer to FIELD_ elements defined elsewhere. - """ - _attr_list_11 = ['ref'] - _attr_list_12 = _attr_list_11 + ['ucd', 'utype'] - _element_name = "FIELDref" - _utype_in_v1_2 = True - _ucd_in_v1_2 = True - - def __init__(self, table, ref, ucd=None, utype=None, config={}, pos=None, - **extra): - """ - *table* is the :class:`Table` object that this :class:`FieldRef` - is a member of. - - *ref* is the ID to reference a :class:`Field` object defined - elsewhere. - """ - self._config = config - self._pos = pos - - SimpleElement.__init__(self) - self._table = table - self.ref = ref - self.ucd = ucd - self.utype = utype - - if config.get('version_1_2_or_later'): - self._attr_list = self._attr_list_12 - else: - self._attr_list = self._attr_list_11 - if ucd is not None: - warn_unknown_attrs(self._element_name, ['ucd'], config, pos) - if utype is not None: - warn_unknown_attrs(self._element_name, ['utype'], config, pos) - - @property - def ref(self): - """The ID_ of the FIELD_ that this FIELDref_ references.""" - return self._ref - - @ref.setter - def ref(self, ref): - xmlutil.check_id(ref, 'ref', self._config, self._pos) - self._ref = ref - - @ref.deleter -
            [docs] def ref(self): - self._ref = None -
            -
            [docs] def get_ref(self): - """ - Lookup the :class:`Field` instance that this :class:`FieldRef` - references. - """ - for field in self._table._votable.iter_fields_and_params(): - if isinstance(field, Field) and field.ID == self.ref: - return field - vo_raise( - "No field named '%s'" % self.ref, - self._config, self._pos, KeyError) - -
            -
            [docs]class ParamRef(SimpleElement, _UtypeProperty, _UcdProperty): - """ - A class representing the PARAMref_ element, which is used inside - of GROUP_ elements to refer to PARAM_ elements defined elsewhere. - - The keyword arguments correspond to setting members of the same - name, documented below. - - It contains the following publicly-accessible members: - - *ref*: An XML ID refering to a <PARAM> element. - """ - _attr_list_11 = ['ref'] - _attr_list_12 = _attr_list_11 + ['ucd', 'utype'] - _element_name = "PARAMref" - _utype_in_v1_2 = True - _ucd_in_v1_2 = True - - def __init__(self, table, ref, ucd=None, utype=None, config={}, pos=None): - self._config = config - self._pos = pos - - Element.__init__(self) - self._table = table - self.ref = ref - self.ucd = ucd - self.utype = utype - - if config.get('version_1_2_or_later'): - self._attr_list = self._attr_list_12 - else: - self._attr_list = self._attr_list_11 - if ucd is not None: - warn_unknown_attrs(self._element_name, ['ucd'], config, pos) - if utype is not None: - warn_unknown_attrs(self._element_name, ['utype'], config, pos) - - @property - def ref(self): - """The ID_ of the PARAM_ that this PARAMref_ references.""" - return self._ref - - @ref.setter - def ref(self, ref): - xmlutil.check_id(ref, 'ref', self._config, self._pos) - self._ref = ref - - @ref.deleter -
            [docs] def ref(self): - self._ref = None -
            -
            [docs] def get_ref(self): - """ - Lookup the :class:`Param` instance that this :class:`PARAMref` - references. - """ - for param in self._table._votable.iter_fields_and_params(): - if isinstance(param, Param) and param.ID == self.ref: - return param - vo_raise( - "No params named '%s'" % self.ref, - self._config, self._pos, KeyError) - -
            -
            [docs]class Group(Element, _IDProperty, _NameProperty, _UtypeProperty, - _UcdProperty, _DescriptionProperty): - """ - Stores information about the grouping of FIELD_ and PARAM_ - elements. - - This information is currently ignored by the vo package---that is - the columns in the recarray are always flat---but the grouping - information is stored so that it can be written out again to the - XML file. - - The keyword arguments correspond to setting members of the same - name, documented below. - """ - - def __init__(self, table, ID=None, name=None, ref=None, ucd=None, - utype=None, id=None, config={}, pos=None, **extra): - self._config = config - self._pos = pos - - Element.__init__(self) - self._table = table - - self.ID = (resolve_id(ID, id, config, pos) - or xmlutil.fix_id(name, config, pos)) - self.name = name - self.ref = ref - self.ucd = ucd - self.utype = utype - self.description = None - - self._entries = HomogeneousList( - (FieldRef, ParamRef, Group, Param)) - - warn_unknown_attrs('GROUP', extra.iterkeys(), config, pos) - - @property - def ref(self): - """ - Currently ignored, as it's not clear from the spec how this is - meant to work. - """ - return self._ref - - @ref.setter - def ref(self, ref): - xmlutil.check_id(ref, 'ref', self._config, self._pos) - self._ref = ref - - @ref.deleter -
            [docs] def ref(self): - self._ref = None -
            - @property -
            [docs] def entries(self): - """ - [read-only] A list of members of the GROUP_. This list may - only contain objects of type :class:`Param`, :class:`Group`, - :class:`ParamRef` and :class:`FieldRef`. - """ - return self._entries -
            - def _add_fieldref(self, iterator, tag, data, config, pos): - fieldref = FieldRef(self._table, config=config, pos=pos, **data) - self.entries.append(fieldref) - - def _add_paramref(self, iterator, tag, data, config, pos): - paramref = ParamRef(self._table, config=config, pos=pos, **data) - self.entries.append(paramref) - - def _add_param(self, iterator, tag, data, config, pos): - if isinstance(self._table, VOTableFile): - votable = self._table - else: - votable = self._table._votable - param = Param(votable, config=config, pos=pos, **data) - self.entries.append(param) - param.parse(iterator, config) - - def _add_group(self, iterator, tag, data, config, pos): - group = Group(self._table, config=config, pos=pos, **data) - self.entries.append(group) - group.parse(iterator, config) - -
            [docs] def parse(self, iterator, config): - tag_mapping = { - 'FIELDref' : self._add_fieldref, - 'PARAMref' : self._add_paramref, - 'PARAM' : self._add_param, - 'GROUP' : self._add_group, - 'DESCRIPTION' : self._ignore_add} - - for start, tag, data, pos in iterator: - if start: - tag_mapping.get(tag, self._add_unknown_tag)( - iterator, tag, data, config, pos) - else: - if tag == 'DESCRIPTION': - if self.description is not None: - warn_or_raise(W17, W17, 'GROUP', config, pos) - self.description = data or None - elif tag == 'GROUP': - break - return self -
            -
            [docs] def to_xml(self, w, **kwargs): - with w.tag( - 'GROUP', - attrib=w.object_attrs( - self, ['ID', 'name', 'ref', 'ucd', 'utype'])): - if self.description is not None: - w.element("DESCRIPTION", self.description, wrap=True) - for entry in self.entries: - entry.to_xml(w, **kwargs) -
            -
            [docs] def iter_fields_and_params(self): - """ - Recursively iterate over all :class:`Param` elements in this - :class:`Group`. - """ - for entry in self.entries: - if isinstance(entry, Param): - yield entry - elif isinstance(entry, Group): - for field in entry.iter_fields_and_params(): - yield field -
            -
            [docs] def iter_groups(self): - """ - Recursively iterate over all sub-:class:`Group` instances in - this :class:`Group`. - """ - for entry in self.entries: - if isinstance(entry, Group): - yield entry - for group in entry.iter_groups(): - yield group - -
            -
            [docs]class Table(Element, _IDProperty, _NameProperty, _UcdProperty, - _DescriptionProperty): - """ - A class to store a TABLE_ element, which optionally contains data. - - It contains the following publicly-accessible members, all of - which are mutable: - - *array*: A Numpy recarray of the data itself, where each row - is a row of votable data, and columns are named and typed - based on the <FIELD> elements of the table. - - *mask*: A Numpy recarray of only boolean values, set to *True* - wherever a value is undefined. - - If the Table contains no data, (for example, its enclosing - :class:`Resource` has :attr:`~Resource.type` == 'meta') *array* - and *mask* will be zero-length arrays. - - .. note:: - In a future version of the vo package, the *array* and *mask* - elements will likely be combined into a single Numpy masked - record array. However, there are a number of deficiencies the - current implementation of Numpy that prevent this. - - The keyword arguments correspond to setting members of the same - name, documented below. - """ - def __init__(self, votable, ID=None, name=None, ref=None, ucd=None, - utype=None, nrows=None, id=None, config={}, pos=None, - **extra): - self._config = config - self._pos = pos - self._empty = False - - Element.__init__(self) - self._votable = votable - - self.ID = (resolve_id(ID, id, config, pos) - or xmlutil.fix_id(name, config, pos)) - self.name = name - xmlutil.check_id(ref, 'ref', config, pos) - self._ref = ref - self.ucd = ucd - self.utype = utype - if nrows is not None: - nrows = int(nrows) - assert nrows >= 0 - self._nrows = nrows - self.description = None - self.format = 'tabledata' - - self._fields = HomogeneousList(Field) - self._params = HomogeneousList(Param) - self._groups = HomogeneousList(Group) - self._links = HomogeneousList(Link) - self._infos = HomogeneousList(Info) - - self.array = np.array([]) - self.mask = np.array([]) - - warn_unknown_attrs('TABLE', extra.iterkeys(), config, pos) - - @property - def ref(self): - return self._ref - - @ref.setter - def ref(self, ref): - """ - Refer to another TABLE, previously defined, by the *ref* ID_ - for all metadata (FIELD_, PARAM_ etc.) information. - """ - # When the ref changes, we want to verify that it will work - # by actually going and looking for the referenced table. - # If found, set a bunch of properties in this table based - # on the other one. - xmlutil.check_id(ref, 'ref', self._config, self._pos) - if ref is not None: - try: - table = self._votable.get_table_by_id(ref, before=self) - except KeyError: - warn_or_raise( - W43, W43, ('TABLE', self.ref), self._config, self._pos) - ref = None - else: - self._fields = table.fields - self._params = table.params - self._groups = table.groups - self._links = table.links - else: - del self._fields[:] - del self._params[:] - del self._groups[:] - del self._links[:] - self._ref = ref - - @ref.deleter -
            [docs] def ref(self): - self._ref = None -
            - @property - def format(self): - """ - [*required*] The serialization format of the table. Must be - one of: - - 'tabledata' (TABLEDATA_), 'binary' (BINARY_), 'fits' (FITS_). - - Note that the 'fits' format, since it requires an external - file, can not be written out. Any file read in with 'fits' - format will be read out, by default, in 'tabledata' format. - """ - return self._format - - @format.setter -
            [docs] def format(self, format): - format = format.lower() - if format == 'fits': - vo_raise("fits format can not be written out, only read.", - self._config, self._pos, NotImplementedError) - if format not in ('tabledata', 'binary'): - vo_raise("Invalid format '%s'" % format, - self._config, self._pos) - self._format = format -
            - @property -
            [docs] def nrows(self): - """ - [*immutable*] The number of rows in the table, as specified in - the XML file. - """ - return self._nrows -
            - @property -
            [docs] def fields(self): - """ - A list of :class:`Field` objects describing the types of each - of the data columns. - """ - return self._fields -
            - @property -
            [docs] def params(self): - """ - A list of parameters (constant-valued columns) for the - table. Must contain only :class:`Param` objects. - """ - return self._params -
            - @property -
            [docs] def groups(self): - """ - A list of :class:`Group` objects describing how the columns - and parameters are grouped. Currently this information is - only kept around for round-tripping and informational - purposes. - """ - return self._groups -
            - @property - - @property -
            [docs] def infos(self): - """ - A list of :class:`Info` objects for the table. Allows for - post-operational diagnostics. - """ - return self._infos -
            -
            [docs] def is_empty(self): - """ - Returns True if this table doesn't contain any real data - because it was skipped over by the parser (through use of the - `table_number` kwarg). - """ - return self._empty -
            -
            [docs] def create_arrays(self, nrows=0, config={}): - """ - Create new arrays to hold the data based on the current set of - fields, and store them in the *array* and *mask* member - variables. Any data in existing arrays will be lost. - - *nrows*, if provided, is the number of rows to allocate. - """ - if nrows is None: - nrows = 0 - - fields = self.fields - - if len(fields) == 0: - array = np.recarray((nrows,), dtype='O') - mask = np.zeros((nrows,), dtype='b') - else: - # for field in fields: field._setup(config) - Field.uniqify_names(fields) - - dtype = [] - for x in fields: - if x._unique_name == x.ID: - id = x.ID - else: - id = (x._unique_name, x.ID) - dtype.append((id, x.converter.format)) - - array = np.recarray((nrows,), dtype=dtype) - descr_mask = [] - for d in array.dtype.descr: - new_type = (d[1][1] == 'O' and 'O') or 'bool' - if len(d) == 2: - descr_mask.append((d[0], new_type)) - elif len(d) == 3: - descr_mask.append((d[0], new_type, d[2])) - mask = np.zeros((nrows,), dtype=descr_mask) - - self.array = array - self.mask = mask -
            - def _resize_strategy(self, size): - """ - Return a new (larger) size based on size, used for - reallocating an array when it fills up. This is in its own - function so the resizing strategy can be easily replaced. - """ - # Once we go beyond 0, make a big step -- after that use a - # factor of 1.5 to help keep memory usage compact - if size == 0: - return 512 - return int(ceil(size * RESIZE_AMOUNT)) - - def _add_field(self, iterator, tag, data, config, pos): - field = Field(self._votable, config=config, pos=pos, **data) - self.fields.append(field) - field.parse(iterator, config) - - def _add_param(self, iterator, tag, data, config, pos): - param = Param(self._votable, config=config, pos=pos, **data) - self.params.append(param) - param.parse(iterator, config) - - def _add_group(self, iterator, tag, data, config, pos): - group = Group(self, config=config, pos=pos, **data) - self.groups.append(group) - group.parse(iterator, config) - - def _add_link(self, iterator, tag, data, config, pos): - link = Link(config=config, pos=pos, **data) - self.links.append(link) - link.parse(iterator, config) - -
            [docs] def parse(self, iterator, config): - columns = config.get('columns') - - # If we've requested to read in only a specific table, skip - # all others - table_number = config.get('table_number') - current_table_number = config.get('_current_table_number') - skip_table = False - if current_table_number is not None: - config['_current_table_number'] += 1 - if (table_number is not None and - table_number != current_table_number): - skip_table = True - self._empty = True - - if self.ref is not None: - # This table doesn't have its own datatype descriptors, it - # just references those from another table. - - # This is to call the property setter to go and get the - # referenced information - self.ref = self.ref - - for start, tag, data, pos in iterator: - if start: - if tag == 'DATA': - warn_unknown_attrs( - 'DATA', data.iterkeys(), config, pos) - break - else: - if tag == 'TABLE': - return self - elif tag == 'DESCRIPTION': - if self.description is not None: - warn_or_raise(W17, W17, 'RESOURCE', config, pos) - self.description = data or None - else: - tag_mapping = { - 'FIELD' : self._add_field, - 'PARAM' : self._add_param, - 'GROUP' : self._add_group, - 'LINK' : self._add_link, - 'DESCRIPTION' : self._ignore_add} - - for start, tag, data, pos in iterator: - if start: - if tag == 'DATA': - warn_unknown_attrs( - 'DATA', data.iterkeys(), config, pos) - break - - tag_mapping.get(tag, self._add_unknown_tag)( - iterator, tag, data, config, pos) - else: - if tag == 'DESCRIPTION': - if self.description is not None: - warn_or_raise(W17, W17, 'RESOURCE', config, pos) - self.description = data or None - elif tag == 'TABLE': - # For error checking purposes - Field.uniqify_names(self.fields) - return self - - self.create_arrays(nrows=self._nrows, config=config) - fields = self.fields - names = [x.ID for x in fields] - # Deal with a subset of the columns, if requested. - if not columns: - colnumbers = range(len(fields)) - else: - if isinstance(columns, string_types): - columns = [columns] - columns = np.asarray(columns) - if issubclass(columns.dtype.type, np.integer): - if np.any(columns < 0) or np.any(columns > len(fields)): - raise ValueError( - "Some specified column numbers out of range") - colnumbers = columns - elif issubclass(columns.dtype.type, np.character): - try: - colnumbers = [names.index(x) for x in columns] - except ValueError: - raise ValueError( - "Columns '%s' not found in fields list" % columns) - else: - raise TypeError("Invalid columns list") - - if not skip_table: - for start, tag, data, pos in iterator: - if start: - if tag == 'TABLEDATA': - warn_unknown_attrs( - 'TABLEDATA', data.iterkeys(), config, pos) - self.array, self.mask = self._parse_tabledata( - iterator, colnumbers, fields, config) - break - elif tag == 'BINARY': - warn_unknown_attrs( - 'BINARY', data.iterkeys(), config, pos) - self.array, self.mask = self._parse_binary( - iterator, colnumbers, fields, config) - break - elif tag == 'FITS': - warn_unknown_attrs( - 'FITS', data.iterkeys(), config, pos, ['extnum']) - try: - extnum = int(data.get('extnum', 0)) - if extnum < 0: - raise ValueError() - except ValueError: - vo_raise(E17, (), config, pos) - self.array, self.mask = self._parse_fits( - iterator, extnum, config) - break - else: - warn_or_raise(W37, W37, tag, config, pos) - break - - for start, tag, data, pos in iterator: - if not start and tag == 'DATA': - break - - for start, tag, data, pos in iterator: - if tag == 'INFO': - if start: - if not config.get('version_1_2_or_later'): - warn_or_raise( - W26, W26, ('INFO', 'TABLE', '1.2'), config, pos) - info = Info(config=config, pos=pos, **data) - self.infos.append(info) - info.parse(iterator, config) - else: - info.content = data - elif not start and tag == 'TABLE': - break - - return self -
            - def _parse_tabledata(self, iterator, colnumbers, fields, config): - # Since we don't know the number of rows up front, we'll - # reallocate the record array to make room as we go. This - # prevents the need to scan through the XML twice. The - # allocation is by factors of 1.5. - invalid = config.get('invalid', 'exception') - - array = self.array - mask = self.mask - # Need to have only one reference so that we can resize the - # array - del self.array - del self.mask - - parsers = [field.converter.parse for field in fields] - binparsers = [field.converter.binparse for field in fields] - - numrows = 0 - alloc_rows = len(array) - colnumbers_bits = [i in colnumbers for i in range(len(fields))] - row_default = [x.converter.default for x in fields] - mask_default = [True] * len(fields) - array_chunk = [] - mask_chunk = [] - chunk_size = config.get('chunk_size', DEFAULT_CHUNK_SIZE) - for start, tag, data, pos in iterator: - if tag == 'TR': - # Now parse one row - row = row_default[:] - row_mask = mask_default[:] - i = 0 - for start, tag, data, pos in iterator: - if start: - binary = (data.get('encoding', None) == 'base64') - warn_unknown_attrs( - tag, data.iterkeys(), config, pos, ['encoding']) - else: - if tag == 'TD': - if i >= len(fields): - vo_raise(E20, len(fields), config, pos) - - if colnumbers_bits[i]: - try: - if binary: - if IS_PY3K: - rawdata = base64.b64decode( - data.encode('ascii')) - else: - rawdata = data.decode('base64') - buf = io.BytesIO(rawdata) - buf.seek(0) - try: - value, mask_value = binparsers[i]( - buf.read) - except Exception as e: - vo_reraise( - e, config, pos, - "(in row %d, col '%s')" % - (len(array_chunk), - fields[i].ID)) - else: - try: - value, mask_value = parsers[i]( - data, config, pos) - except Exception as e: - vo_reraise( - e, config, pos, - "(in row %d, col '%s')" % - (len(array_chunk), - fields[i].ID)) - except Exception as e: - if invalid == 'exception': - vo_reraise(e, config, pos) - else: - row[i] = value - row_mask[i] = mask_value - elif tag == 'TR': - break - else: - self._add_unknown_tag( - iterator, tag, data, config, pos) - i += 1 - - if i < len(fields): - vo_raise(E21, (i, len(fields)), config, pos) - - array_chunk.append(tuple(row)) - mask_chunk.append(tuple(row_mask)) - - if len(array_chunk) == chunk_size: - while numrows + chunk_size > alloc_rows: - alloc_rows = self._resize_strategy(alloc_rows) - if alloc_rows != len(array): - array.resize((alloc_rows,)) - mask.resize((alloc_rows,)) - array[numrows:numrows + chunk_size] = array_chunk - mask[numrows:numrows + chunk_size] = mask_chunk - numrows += chunk_size - array_chunk = [] - mask_chunk = [] - - elif not start and tag == 'TABLEDATA': - break - - # Now, resize the array to the exact number of rows we need and - # put the last chunk values in there. - if len(array_chunk): - alloc_rows = numrows + len(array_chunk) - array.resize((alloc_rows,)) - mask.resize((alloc_rows,)) - array[numrows:] = array_chunk - mask[numrows:] = mask_chunk - numrows += len(array_chunk) - - if (self.nrows is not None and - self.nrows >= 0 and - self.nrows != numrows): - warn_or_raise(W18, W18, (self.nrows, numrows), config, pos) - self._nrows = numrows - - return array, mask - - def _parse_binary(self, iterator, colnumbers, fields, config): - fields = self.fields - - have_local_stream = False - for start, tag, data, pos in iterator: - if tag == 'STREAM': - if start: - warn_unknown_attrs( - 'STREAM', data.iterkeys(), config, pos, - ['type', 'href', 'actuate', 'encoding', 'expires', - 'rights']) - if 'href' not in data: - have_local_stream = True - if data.get('encoding', None) != 'base64': - warn_or_raise( - W38, W38, data.get('encoding', None), - config, pos) - else: - href = data['href'] - xmlutil.check_anyuri(href, config, pos) - encoding = data.get('encoding', None) - else: - buffer = data - break - - if have_local_stream: - buffer = base64.b64decode(buffer.encode('ascii')) - string_io = io.BytesIO(buffer) - string_io.seek(0) - read = string_io.read - else: - if not (href.startswith('http') or - href.startswith('ftp') or - href.startswith('file')): - vo_raise( - "The vo package only supports remote data through http, " + - "ftp or file", - self._config, self._pos, NotImplementedError) - fd = urllib2.urlopen(href) - if encoding is not None: - if encoding == 'gzip': - from ...utils.compat import gzip - fd = gzip.GzipFile(href, 'rb', fileobj=fd) - elif encoding == 'base64': - fd = codecs.EncodedFile(fd, 'base64') - else: - vo_raise( - "Unknown encoding type '%s'" % encoding, - self._config, self._pos, NotImplementedError) - read = fd.read - - def careful_read(length): - result = read(length) - if len(result) != length: - raise EOFError - return result - - array = self.array - mask = self.mask - # Need to have only one reference so that we can resize the - # array - del self.array - del self.mask - - binparsers = [field.converter.binparse for field in fields] - - numrows = 0 - alloc_rows = len(array) - while True: - # Resize result arrays if necessary - if numrows >= alloc_rows: - alloc_rows = self._resize_strategy(alloc_rows) - array.resize((alloc_rows,)) - mask.resize((alloc_rows,)) - - row_data = [] - row_mask_data = [] - try: - for i, binparse in enumerate(binparsers): - try: - value, value_mask = binparse(careful_read) - except EOFError: - raise - except Exception as e: - vo_reraise(e, config, pos, - "(in row %d, col '%s')" % - (numrows, fields[i].ID)) - row_data.append(value) - row_mask_data.append(value_mask) - except EOFError: - break - - row = [x.converter.default for x in fields] - row_mask = [False] * len(fields) - for i in colnumbers: - row[i] = row_data[i] - row_mask[i] = row_mask_data[i] - - array[numrows] = tuple(row) - mask[numrows] = tuple(row_mask) - numrows += 1 - - array = np.resize(array, (numrows,)) - mask = np.resize(mask, (numrows,)) - - return array, mask - - def _parse_fits(self, iterator, extnum, config): - if not _has_pyfits: - vo_raise( - "Input file contains FITS data, but pyfits is not installed.", - config, None, ImportError) - - for start, tag, data, pos in iterator: - if tag == 'STREAM': - if start: - warn_unknown_attrs( - 'STREAM', data.iterkeys(), config, pos, - ['type', 'href', 'actuate', 'encoding', 'expires', - 'rights']) - href = data['href'] - encoding = data.get('encoding', None) - else: - break - - if not (href.startswith('http') or - href.startswith('ftp') or - href.startswith('file')): - vo_raise( - "The vo package only supports remote data through http, " - "ftp or file", - self._config, self._pos, NotImplementedError) - - fd = urllib2.urlopen(href) - if encoding is not None: - if encoding == 'gzip': - from ...utils.compat import gzip - fd = gzip.GzipFile(href, 'r', fileobj=fd) - elif encoding == 'base64': - fd = codecs.EncodedFile(fd, 'base64') - else: - vo_raise( - "Unknown encoding type '%s'" % encoding, - self._config, self._pos, NotImplementedError) - - fits = pyfits.open(fd) - - array = fits[int(extnum)].data - if array.dtype != self.array.dtype: - warn_or_raise(W19, W19, (), self._config, self._pos) - - return array, self.mask - -
            [docs] def to_xml(self, w, **kwargs): - with w.tag( - 'TABLE', - attrib=w.object_attrs( - self, - ('ID', 'name', 'ref', 'ucd', 'utype', 'nrows'))): - - if self.description is not None: - w.element("DESCRIPTION", self.description, wrap=True) - - for element_set in (self.fields, self.params): - for element in element_set: - element._setup({}, None) - - if self.ref is None: - for element_set in (self.fields, self.params, self.groups, - self.links): - for element in element_set: - element.to_xml(w, **kwargs) - - if len(self.array): - with w.tag('DATA'): - if self.format == 'fits': - self.format = 'tabledata' - - if self.format == 'tabledata': - self._write_tabledata(w, **kwargs) - elif self.format == 'binary': - self._write_binary(w, **kwargs) - - if self.ref is None and kwargs['version_1_2_or_later']: - for element in self._infos: - element.to_xml(w, **kwargs) -
            - def _write_tabledata(self, w, **kwargs): - fields = self.fields - array = self.array - mask = self.mask - - write_null_values = kwargs.get('write_null_values', False) - with w.tag('TABLEDATA'): - w._flush() - if (_has_c_tabledata_writer and - not kwargs.get('_debug_python_based_parser')): - fields = [field.converter.output for field in fields] - indent = len(w._tags) - 1 - tablewriter.write_tabledata(w.write, array, mask, fields, - write_null_values, indent, 1 << 8) - else: - write = w.write - indent_spaces = w.get_indentation_spaces() - if not IS_PY3K: - indent_spaces = indent_spaces.encode('ascii') - tr_start = indent_spaces + "<TR>\n" - tr_end = indent_spaces + "</TR>\n" - td = indent_spaces + " <TD>%s</TD>\n" - td_empty = indent_spaces + " <TD/>\n" - fields = [(i, field.converter.output) - for i, field in enumerate(fields)] - for row in xrange(len(array)): - write(tr_start) - array_row = array[row] - mask_row = mask[row] - for i, output in fields: - masked = mask_row[i] - if not np.all(masked) or write_null_values: - try: - val = output(array_row[i], masked) - except Exception as e: - vo_reraise(e, config, pos, - "(in row %d, col '%s')" % - (row, fields[i].ID)) - write(td % val) - else: - write(td_empty) - write(tr_end) - - def _write_binary(self, w, **kwargs): - fields = self.fields - array = self.array - mask = self.mask - - with w.tag('BINARY'): - with w.tag('STREAM', encoding='base64'): - fields = [(i, field.converter.binoutput) - for (i, field) in enumerate(fields)] - - data = io.BytesIO() - for row in xrange(len(array)): - array_row = array[row] - array_mask = mask[row] - for i, converter in fields: - try: - chunk = converter(array_row[i], array_mask[i]) - except Exception as e: - vo_reraise(e, config, pos, - "(in row %d, col '%s')" % - (row, fields[i].ID)) - data.write(chunk) - - w._flush() - if IS_PY3K: - w.write(base64.b64encode(data.getvalue()).decode('ascii')) - else: - w.write(data.getvalue().encode('base64')) - -
            [docs] def iter_fields_and_params(self): - """ - Recursively iterate over all FIELD and PARAM elements in the - TABLE. - """ - for param in self.params: - yield param - for field in self.fields: - yield field - for group in self.groups: - for field in group.iter_fields_and_params(): - yield field -
            - get_field_by_id = _lookup_by_id_factory( - 'iter_fields_and_params', 'FIELD or PARAM', - """ - Looks up a FIELD or PARAM element by the given ID. - """) - - get_field_by_id_or_name = _lookup_by_id_or_name_factory( - 'iter_fields_and_params', 'FIELD or PARAM', - """ - Looks up a FIELD or PARAM element by the given ID or name. - """) - -
            [docs] def iter_groups(self): - """ - Recursively iterate over all GROUP elements in the TABLE. - """ - for group in self.groups: - yield group - for g in group.iter_groups(): - yield g -
            - get_group_by_id = _lookup_by_id_factory( - 'iter_groups', 'GROUP', - """ - Looks up a GROUP element by the given ID. Used by the group's - "ref" attribute - """) - -
            -
            [docs]class Resource(Element, _IDProperty, _NameProperty, _UtypeProperty, - _DescriptionProperty): - """ - A class to store the information in a RESOURCE_ element. Each - resource may contain zero-or-more TABLE_ elements and zero-or-more - nested RESOURCE_ elements. - - The keyword arguments correspond to setting members of the same - name, documented below. - """ - def __init__(self, name=None, ID=None, utype=None, type='results', - id=None, config={}, pos=None, **kwargs): - self._config = config - self._pos = pos - - Element.__init__(self) - self.name = name - self.ID = resolve_id(ID, id, config, pos) - self.utype = utype - self.type = type - self._extra_attributes = kwargs - self.description = None - - self._coordinate_systems = HomogeneousList(CooSys) - self._params = HomogeneousList(Param) - self._infos = HomogeneousList(Info) - self._links = HomogeneousList(Link) - self._tables = HomogeneousList(Table) - self._resources = HomogeneousList(Resource) - - warn_unknown_attrs('RESOURCE', kwargs.iterkeys(), config, pos) - - @property - def type(self): - """ - [*required*] The type of the resource. Must be either: - - - 'results': This resource contains actual result values - (default) - - - 'meta': This resource contains only datatype descriptions - (FIELD_ elements), but no actual data. - """ - return self._type - - @type.setter -
            [docs] def type(self, type): - if type not in ('results', 'meta'): - vo_raise(E18, type, self._config, self._pos) - self._type = type -
            - @property -
            [docs] def extra_attributes(self): - """ - A dictionary of string keys to string values containing any - extra attributes of the RESOURCE_ element that are not defined - in the specification. (The specification explicitly allows - for extra attributes here, but nowhere else.) - """ - return self._extra_attributes -
            - @property -
            [docs] def coordinate_systems(self): - """ - A list of coordinate system definitions (COOSYS_ elements) for - the RESOURCE_. Must contain only `CooSys` objects. - """ - return self._coordinate_systems -
            - @property -
            [docs] def infos(self): - """ - A list of informational parameters (key-value pairs) for the - resource. Must only contain `Info` objects. - """ - return self._infos -
            - @property -
            [docs] def params(self): - """ - A list of parameters (constant-valued columns) for the - resource. Must contain only `Param` objects. - """ - return self._params -
            - @property - - @property -
            [docs] def tables(self): - """ - A list of tables in the resource. Must contain only - `Table` objects. - """ - return self._tables -
            - @property -
            [docs] def resources(self): - """ - A list of nested resources inside this resource. Must contain - only `Resource` objects. - """ - return self._resources -
            - def _add_table(self, iterator, tag, data, config, pos): - table = Table(self._votable, config=config, pos=pos, **data) - self.tables.append(table) - table.parse(iterator, config) - - def _add_info(self, iterator, tag, data, config, pos): - info = Info(config=config, pos=pos, **data) - self.infos.append(info) - info.parse(iterator, config) - - def _add_param(self, iterator, tag, data, config, pos): - param = Param(self._votable, config=config, pos=pos, **data) - self.params.append(param) - param.parse(iterator, config) - - def _add_coosys(self, iterator, tag, data, config, pos): - coosys = CooSys(config=config, pos=pos, **data) - self.coordinate_systems.append(coosys) - coosys.parse(iterator, config) - - def _add_resource(self, iterator, tag, data, config, pos): - resource = Resource(config=config, pos=pos, **data) - self.resources.append(resource) - resource.parse(self._votable, iterator, config) - - def _add_link(self, iterator, tag, data, config, pos): - link = Link(config=config, pos=pos, **data) - self.links.append(link) - link.parse(iterator, config) - -
            [docs] def parse(self, votable, iterator, config): - self._votable = votable - - tag_mapping = { - 'TABLE' : self._add_table, - 'INFO' : self._add_info, - 'PARAM' : self._add_param, - 'COOSYS' : self._add_coosys, - 'RESOURCE' : self._add_resource, - 'LINK' : self._add_link, - 'DESCRIPTION' : self._ignore_add - } - - for start, tag, data, pos in iterator: - if start: - tag_mapping.get(tag, self._add_unknown_tag)( - iterator, tag, data, config, pos) - elif tag == 'DESCRIPTION': - if self.description is not None: - warn_or_raise(W17, W17, 'RESOURCE', config, pos) - self.description = data or None - elif tag == 'INFO': - self.infos[-1].content = data - - del self._votable - - return self -
            -
            [docs] def to_xml(self, w, **kwargs): - attrs = w.object_attrs(self, ('ID', 'type', 'utype')) - attrs.update(self.extra_attributes) - with w.tag('RESOURCE', attrib=attrs): - if self.description is not None: - w.element("DESCRIPTION", self.description, wrap=True) - for element_set in (self.coordinate_systems, self.params, - self.infos, self.links, self.tables, - self.resources): - for element in element_set: - element.to_xml(w, **kwargs) -
            -
            [docs] def iter_tables(self): - """ - Recursively iterates over all tables in the resource and - nested resources. - """ - for table in self.tables: - yield table - for resource in self.resources: - for table in resource.iter_tables(): - yield table -
            -
            [docs] def iter_fields_and_params(self): - """ - Recursively iterates over all FIELD_ and PARAM_ elements in - the resource, its tables and nested resources. - """ - for param in self.params: - yield param - for table in self.tables: - for param in table.iter_fields_and_params(): - yield param - for resource in self.resources: - for param in resource.iter_fields_and_params(): - yield param -
            -
            [docs] def iter_coosys(self): - """ - Recursively iterates over all the COOSYS_ elements in the - resource and nested resources. - """ - for coosys in self.coordinate_systems: - yield coosys - for resource in self.resources: - for coosys in resource.iter_coosys(): - yield coosys - -
            -
            [docs]class VOTableFile(Element, _IDProperty, _DescriptionProperty): - """ - A class to represent the top-level VOTABLE_ element. - - The keyword arguments correspond to setting members of the same - name, documented below. - - *version* is settable at construction time only, since conformance - tests for building the rest of the structure depend on it. - """ - - def __init__(self, ID=None, id=None, config={}, pos=None, version="1.2"): - self._config = config - self._pos = pos - - Element.__init__(self) - self.ID = resolve_id(ID, id, config, pos) - self.description = None - - self._coordinate_systems = HomogeneousList(CooSys) - self._params = HomogeneousList(Param) - self._infos = HomogeneousList(Info) - self._resources = HomogeneousList(Resource) - self._groups = HomogeneousList(Group) - - version = str(version) - assert version in ("1.0", "1.1", "1.2") - self._version = version - - @property -
            [docs] def version(self): - """ - The version of the VOTable specification that the file uses. - """ - return self._version -
            - @property -
            [docs] def coordinate_systems(self): - """ - A list of coordinate system descriptions for the file. Must - contain only `CooSys` objects. - """ - return self._coordinate_systems -
            - @property -
            [docs] def params(self): - """ - A list of parameters (constant-valued columns) that apply to - the entire file. Must contain only `Param` objects. - """ - return self._params -
            - @property -
            [docs] def infos(self): - """ - A list of informational parameters (key-value pairs) for the - entire file. Must only contain `Info` objects. - """ - return self._infos -
            - @property -
            [docs] def resources(self): - """ - A list of resources, in the order they appear in the file. - Must only contain `Resource` objects. - """ - return self._resources -
            - @property -
            [docs] def groups(self): - """ - A list of groups, in the order they appear in the file. Only - supported as a child of the VOTABLE element in VOTable 1.2 or - later. - """ - return self._groups -
            - def _add_param(self, iterator, tag, data, config, pos): - param = Param(self, config=config, pos=pos, **data) - self.params.append(param) - param.parse(iterator, config) - - def _add_resource(self, iterator, tag, data, config, pos): - resource = Resource(config=config, pos=pos, **data) - self.resources.append(resource) - resource.parse(self, iterator, config) - - def _add_coosys(self, iterator, tag, data, config, pos): - coosys = CooSys(config=config, pos=pos, **data) - self.coordinate_systems.append(coosys) - coosys.parse(iterator, config) - - def _add_info(self, iterator, tag, data, config, pos): - info = Info(config=config, pos=pos, **data) - self.infos.append(info) - info.parse(iterator, config) - - def _add_group(self, iterator, tag, data, config, pos): - if not config.get('version_1_2_or_later'): - warn_or_raise(W26, W26, ('GROUP', 'VOTABLE', '1.2'), config, pos) - group = Group(self, config=config, pos=pos, **data) - self.groups.append(group) - group.parse(iterator, config) - -
            [docs] def parse(self, iterator, config): - config['_current_table_number'] = 0 - - for start, tag, data, pos in iterator: - if start: - if tag == 'xml': - pass - elif tag == 'VOTABLE': - if 'version' not in data: - warn_or_raise(W20, W20, self.version, config, pos) - config['version'] = self.version - else: - config['version'] = self._version = data['version'] - if config['version'].lower().startswith('v'): - warn_or_raise( - W29, W29, config['version'], config, pos) - self._version = config['version'] = \ - config['version'][1:] - if config['version'] not in ('1.1', '1.2'): - vo_warn(W21, config['version'], config, pos) - - if 'xmlns' in data: - correct_ns = ('http://www.ivoa.net/xml/VOTable/v%s' % - config['version']) - if data['xmlns'] != correct_ns: - vo_warn( - W41, (correct_ns, data['xmlns']), config, pos) - else: - vo_warn(W42, (), config, pos) - - break - else: - vo_raise(E19, (), config, pos) - config['version_1_1_or_later'] = \ - util.version_compare(config['version'], '1.1') >= 0 - config['version_1_2_or_later'] = \ - util.version_compare(config['version'], '1.2') >= 0 - - tag_mapping = { - 'PARAM' : self._add_param, - 'RESOURCE' : self._add_resource, - 'COOSYS' : self._add_coosys, - 'INFO' : self._add_info, - 'DEFINITIONS' : self._add_definitions, - 'DESCRIPTION' : self._ignore_add, - 'GROUP' : self._add_group} - - for start, tag, data, pos in iterator: - if start: - tag_mapping.get(tag, self._add_unknown_tag)( - iterator, tag, data, config, pos) - elif tag == 'DESCRIPTION': - if self.description is not None: - warn_or_raise(W17, W17, 'VOTABLE', config, pos) - self.description = data or None - elif tag == 'INFO': - self.infos[-1].content = data - return self -
            -
            [docs] def to_xml(self, fd, write_null_values=False, - _debug_python_based_parser=False, - _astropy_version=None): - """ - Write to an XML file. - - Parameters - ---------- - fd : str path or writable file-like object - Where to write the file. - - write_null_values : bool - When `True`, write the 'null' value (specified in the null - attribute of the VALUES element for each FIELD) for empty - values. When False (default), simply write no value. - """ - kwargs = { - 'write_null_values': write_null_values, - 'version': self.version, - 'version_1_1_or_later': - util.version_compare(self.version, '1.1') >= 0, - 'version_1_2_or_later': - util.version_compare(self.version, '1.2') >= 0, - '_debug_python_based_parser': _debug_python_based_parser} - - with util.convert_to_writable_filelike(fd) as fd: - w = XMLWriter(fd) - version = self.version - if _astropy_version is None: - lib_version = astropy_version - else: - lib_version = _astropy_version - - xml_header = """ -<?xml version="1.0" encoding="utf-8"?> -<!-- Produced with astropy.io.vo version %(lib_version)s - http://www.astropy.org/ -->\n""" - w.write(xml_header.lstrip() % locals()) - - with w.tag('VOTABLE', - {'version': version, - 'xmlns:xsi': - "http://www.w3.org/2001/XMLSchema-instance", - 'xsi:noNamespaceSchemaLocation': - "http://www.ivoa.net/xml/VOTable/v%s" % version, - 'xmlns': - "http://www.ivoa.net/xml/VOTable/v%s" % version}): - if self.description is not None: - w.element("DESCRIPTION", self.description, wrap=True) - element_sets = [self.coordinate_systems, self.params, - self.infos, self.resources] - if kwargs['version_1_2_or_later']: - element_sets[0] = self.groups - for element_set in element_sets: - for element in element_set: - element.to_xml(w, **kwargs) -
            -
            [docs] def iter_tables(self): - """ - Iterates over all tables in the VOTable file in a "flat" way, - ignoring the nesting of resources etc. - """ - for resource in self.resources: - for table in resource.iter_tables(): - yield table -
            -
            [docs] def get_first_table(self): - """ - Often, you know there is only one table in the file, and - that's all you need. This method returns that first table. - """ - for table in self.iter_tables(): - if not table.is_empty(): - return table - raise IndexError("No table found in VOTABLE file.") -
            - get_table_by_id = _lookup_by_id_factory( - 'iter_tables', 'TABLE', - """ - Looks up a TABLE element by the given ID. Used by the table - "ref" attribute. - """) - -
            [docs] def get_table_by_index(self, idx): - """ - Get a table by its ordinal position in the file. - """ - for i, table in enumerate(self.iter_tables()): - if i == idx: - return table - raise IndexError("No table at index %d found in VOTABLE file." % idx) -
            -
            [docs] def iter_fields_and_params(self): - """ - Recursively iterate over all FIELD and PARAM elements in the - VOTABLE file. - """ - for resource in self.resources: - for field in resource.iter_fields_and_params(): - yield field -
            - get_field_by_id = _lookup_by_id_factory( - 'iter_fields_and_params', 'FIELD', - """ - Looks up a FIELD element by the given ID. Used by the field's - "ref" attribute. - """) - - get_field_by_id_or_name = _lookup_by_id_or_name_factory( - 'iter_fields_and_params', 'FIELD', - """ - Looks up a FIELD element by the given ID or name. - """) - -
            [docs] def iter_values(self): - """ - Recursively iterate over all VALUES_ elements in the VOTABLE - file. - """ - for field in self.iter_fields_and_params(): - yield field.values -
            - get_values_by_id = _lookup_by_id_factory( - 'iter_values', 'VALUES', - """ - Looks up a VALUES element by the given ID. Used by the values - "ref" attribute. - """) - -
            [docs] def iter_groups(self): - """ - Recursively iterate over all GROUP elements in the VOTABLE - file. - """ - for table in self.iter_tables(): - for group in table.iter_groups(): - yield group -
            - get_group_by_id = _lookup_by_id_factory( - 'iter_groups', 'GROUP', - """ - Looks up a GROUP element by the given ID. Used by the group's - "ref" attribute - """) - -
            [docs] def iter_coosys(self): - """ - Recursively iterate over all COOSYS elements in the VOTABLE - file. - """ - for coosys in self.coordinate_systems: - yield coosys - for resource in self.resources: - for coosys in resource.iter_coosys(): - yield coosys -
            - get_coosys_by_id = _lookup_by_id_factory( - 'iter_coosys', 'COOSYS', - """Looks up a COOSYS element by the given ID.""") - -
            [docs] def set_all_tables_format(self, format): - """ - Set the output storage format of all tables in the file. - """ - for table in self.iter_tables(): - table.format = format
            -
            - -
            -
            -
            -
            -
            - - - -
            -
            -
            -
            - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/ucd.html b/_modules/astropy/io/vo/ucd.html deleted file mode 100644 index 84a9b9d3..00000000 --- a/_modules/astropy/io/vo/ucd.html +++ /dev/null @@ -1,296 +0,0 @@ - - - - - - - - - - astropy.io.vo.ucd — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
            -
            -
            -
            - -

            Source code for astropy.io.vo.ucd

            -"""
            -This file contains routines to verify the correctness of UCD strings.
            -"""
            -
            -from __future__ import with_statement, absolute_import
            -
            -#STDLIB
            -import os
            -import re
            -import sys
            -
            -#LOCAL
            -from ... import config
            -
            -__all__ = ['parse_ucd', 'check_ucd']
            -
            -
            -class UCDWords:
            -    """
            -    A class to manage the list of acceptable UCD words.  Works by
            -    reading in a data file exactly as provided by IVOA.  This file
            -    resides in data/ucd1p-words.txt.
            -    """
            -    def __init__(self):
            -        self._primary = set()
            -        self._secondary = set()
            -        self._descriptions = {}
            -        self._capitalization = {}
            -
            -        with config.get_data_fileobj("data/ucd1p-words.txt") as fd:
            -            for line in fd.readlines():
            -                if sys.version_info[0] >= 3:
            -                    type, name, descr = [
            -                        x.strip().decode('ascii') for x in line.split(b'|')]
            -                else:
            -                    type, name, descr = [x.strip() for x in line.split('|')]
            -                name_lower = name.lower()
            -                if type in 'QPEV':
            -                    self._primary.add(name_lower)
            -                if type in 'QSEV':
            -                    self._secondary.add(name_lower)
            -                self._descriptions[name_lower] = descr
            -                self._capitalization[name_lower] = name
            -
            -    def is_primary(self, name):
            -        """
            -        Returns True if *name* is a valid primary name.
            -        """
            -        return name.lower() in self._primary
            -
            -    def is_secondary(self, name):
            -        """
            -        Returns True if *name* is a valid secondary name.
            -        """
            -        return name.lower() in self._secondary
            -
            -    def get_description(self, name):
            -        """
            -        Returns the official English description of the given UCD
            -        *name*.
            -        """
            -        return self._descriptions[name.lower()]
            -
            -    def normalize_capitalization(self, name):
            -        """
            -        Returns the standard capitalization form of the given name.
            -        """
            -        return self._capitalization[name.lower()]
            -
            -_ucd_singleton = None
            -
            -
            -
            [docs]def parse_ucd(ucd, check_controlled_vocabulary=False, has_colon=False): - """ - Parse the UCD into its component parts. - - Parameters - ---------- - ucd : str - The UCD string - - check_controlled_vocabulary : bool, optional - If `True`, then each word in the UCD will be verified against - the UCD1+ controlled vocabulary, (as required by the VOTable - specification version 1.2), otherwise not. - - has_colon : bool, optional - If `True`, the UCD may contain a colon (as defined in earlier - versions of the standard). - - Returns - ------- - parts : list - The result is a list of tuples of the form: - - (*namespace*, *word*) - - If no namespace was explicitly specified, *namespace* will be - returned as ``'ivoa'`` (i.e., the default namespace). - - Raises - ------ - ValueError : *ucd* is invalid - """ - global _ucd_singleton - if _ucd_singleton is None: - _ucd_singleton = UCDWords() - - if has_colon: - m = re.search('[^A-Za-z0-9_.:;\-]', ucd) - else: - m = re.search('[^A-Za-z0-9_.;\-]', ucd) - if m is not None: - raise ValueError("UCD has invalid character '%s' in '%s'" % - (m.group(0), ucd)) - - word_component_re = '[A-Za-z0-9][A-Za-z0-9\-_]*' - word_re = '%s(\.%s)*' % (word_component_re, word_component_re) - - parts = ucd.split(';') - words = [] - for i, word in enumerate(parts): - colon_count = word.count(':') - if colon_count == 1: - ns, word = word.split(':', 1) - if not re.match(word_component_re, ns): - raise ValueError("Invalid namespace '%s'" % ns) - ns = ns.lower() - elif colon_count > 1: - raise ValueError("Too many colons in '%s'" % word) - else: - ns = 'ivoa' - - if not re.match(word_re, word): - raise ValueError("Invalid word '%s'" % word) - - if ns == 'ivoa' and check_controlled_vocabulary: - if i == 0: - if not _ucd_singleton.is_primary(word): - if _ucd_singleton.is_secondary(word): - raise ValueError( - "Secondary word '%s' is not valid as a primary " - "word" % word) - else: - raise ValueError("Unknown word '%s'" % word) - else: - if not _ucd_singleton.is_secondary(word): - if _ucd_singleton.is_primary(word): - raise ValueError( - "Primary word '%s' is not valid as a secondary " - "word" % word) - else: - raise ValueError("Unknown word '%s'" % word) - - try: - normalized_word = _ucd_singleton.normalize_capitalization(word) - except KeyError: - normalized_word = word - words.append((ns, normalized_word)) - - return words - -
            -
            [docs]def check_ucd(ucd, check_controlled_vocabulary=False, has_colon=False): - """ - Returns False if *ucd* is not a valid `unified content - descriptor`_. - - Parameters - ---------- - ucd : str - The UCD string - - check_controlled_vocabulary : bool, optional - If `True`, then each word in the UCD will be verified against - the UCD1+ controlled vocabulary, (as required by the VOTable - specification version 1.2), otherwise not. - - Returns - ------- - valid : bool - """ - if ucd is None: - return True - - try: - parse_ucd(ucd, - check_controlled_vocabulary=check_controlled_vocabulary, - has_colon=has_colon) - except ValueError as e: - return False - return True
            -
            - -
            -
            -
            -
            -
            - - - -
            -
            -
            -
            - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/unit.html b/_modules/astropy/io/vo/unit.html deleted file mode 100644 index 7b8a414f..00000000 --- a/_modules/astropy/io/vo/unit.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - astropy.io.vo.unit — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
            -
            -
            -
            - -

            Source code for astropy.io.vo.unit

            -"""
            -Tools to verify the syntax of unit attributes according to the
            -`Standards for Astronomical Catalogues, Version 2.0
            -<http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_
            -"""
            -
            -# STDLIB
            -import re
            -
            -# LOCAL
            -from .exceptions import warn_or_raise, W50
            -
            -
            -__all__ = ['unit_names', 'unit_prefixes', 'is_unit', 'check_unit']
            -
            -
            -unit_names = """
            -    - % a A AU arcmin arcsec barn bit byte C cd ct D d deg eV F g h H
            -    Hz J Jy K lm lx m mag mas min mol N Ohm Pa pc pix rad Ry s S
            -    solLum solMass solRad Sun sr T V W Wb yr
            -    """.split()
            -
            -
            -unit_prefixes = """
            -    d c m u n p f a z y da h k M G T P E Z Y
            -    """.split()
            -
            -
            -_unit_name_regex = '|'.join('(?:{0})'.format(x) for x in unit_names)
            -_unit_prefix_regex = '|'.join('(?:{0})'.format(x) for x in unit_prefixes)
            -
            -
            -
            [docs]def is_unit(s): - """ - Returns `True` if *s* is a valid unit string as defined by - `Standards for Astronomical Catalogues, Version 2.0 - <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_ - """ - number = r'[+\-]?[0-9]+(?:\.[0-9]*)?(?:[+\-][0-9]+)?' - factor = r'{0}(?:x{0})?'.format(number) - unit = r'(?:{0})?(?:{1})'.format(_unit_prefix_regex, _unit_name_regex) - bracketed_unit = r'(?:{0})|(?:\[{0}\])'.format(unit) - expression = ( - r'^(?P<factor>{0})?(?P<unit>{1})(?P<subunit>[/.]{1})?(?P<power>{2})?$'.format( - factor, bracketed_unit, number)) - - match = re.match(expression, s) - return match is not None - -
            -
            [docs]def check_unit(unit, attr_name, config={}, pos=None): - """ - Raises a `ValueError` if *unit* is not a valid unit as defined by - `Standards for Astronomical Catalogues, Version 2.0 - <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_ - """ - if (unit is not None and not is_unit(unit)): - warn_or_raise(W50, W50, unit, config, pos) - return False - return True -
            - -
            -
            -
            -
            -
            - - - -
            -
            -
            -

        - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/util.html b/_modules/astropy/io/vo/util.html deleted file mode 100644 index d4345d3a..00000000 --- a/_modules/astropy/io/vo/util.html +++ /dev/null @@ -1,326 +0,0 @@ - - - - - - - - - - astropy.io.vo.util — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.io.vo.util

        -"""
        -Various utilities and cookbook-like things.
        -"""
        -
        -from __future__ import division, with_statement, absolute_import
        -
        -# STDLIB
        -import collections
        -import contextlib
        -from distutils import version
        -import io
        -import re
        -import sys
        -import time
        -
        -
        -__all__ = [
        -    'convert_to_writable_filelike',
        -    'stc_reference_frames',
        -    'coerce_range_list_param',
        -    'is_callable'
        -    ]
        -
        -
        -IS_PY3K = sys.hexversion >= 0x03000000
        -
        -
        -@contextlib.contextmanager
        -
        [docs]def convert_to_writable_filelike(fd): - """ - Returns a writable file-like object suitable for streaming output. - - Parameters - ---------- - fd : file path string or writable file-like object - May be: - - - a file path, in which case it is opened, and the file - object is returned. - - - an object with a :meth:`write` method, in which case that - object. - - Returns - ------- - fd : writable file-like object - """ - if isinstance(fd, basestring): - if IS_PY3K: - if fd.endswith('.gz'): - from ...utils.compat import gzip - with gzip.GzipFile(fd, 'wb') as real_fd: - encoded_fd = io.TextIOWrapper(real_fd, encoding='utf8') - yield encoded_fd - encoded_fd.flush() - real_fd.flush() - return - else: - with io.open(fd, 'w', encoding='utf8') as real_fd: - yield real_fd - return - else: - if fd.endswith('.gz'): - from ...utils.compat import gzip - with gzip.GzipFile(fd, 'wb') as real_fd: - yield real_fd - real_fd.flush() - return - else: - with open(fd, 'wb') as real_fd: - yield real_fd - return - elif hasattr(fd, 'write'): - assert is_callable(fd.write) - yield fd - return - else: - raise TypeError("Can not be coerced to writable file-like object") - - -# <http://www.ivoa.net/Documents/REC/DM/STC-20071030.html>
        -stc_reference_frames = set([ - 'FK4', 'FK5', 'ECLIPTIC', 'ICRS', 'GALACTIC', 'GALACTIC_I', 'GALACTIC_II', - 'SUPER_GALACTIC', 'AZ_EL', 'BODY', 'GEO_C', 'GEO_D', 'MAG', 'GSE', 'GSM', - 'SM', 'HGC', 'HGS', 'HEEQ', 'HRTN', 'HPC', 'HPR', 'HCC', 'HGI', - 'MERCURY_C', 'VENUS_C', 'LUNA_C', 'MARS_C', 'JUPITER_C_III', - 'SATURN_C_III', 'URANUS_C_III', 'NEPTUNE_C_III', 'PLUTO_C', 'MERCURY_G', - 'VENUS_G', 'LUNA_G', 'MARS_G', 'JUPITER_G_III', 'SATURN_G_III', - 'URANUS_G_III', 'NEPTUNE_G_III', 'PLUTO_G', 'UNKNOWNFrame']) - - -
        [docs]def coerce_range_list_param(p, frames=None, numeric=True): - """ - Coerces and/or verifies the object *p* into a valid - range-list-format parameter as defined in `Section 8.7.2 of Simple - Spectral Access Protocol - <http://www.ivoa.net/Documents/REC/DAL/SSA-20080201.html>`_. - - Parameters - ---------- - p : str or sequence - May be a string as passed verbatim to the service expecting a - range-list, or a sequence. If a sequence, each item must be - either: - - - a numeric value - - - a named value, such as, for example, 'J' for named - spectrum (if the *numeric* kwarg is False) - - - a 2-tuple indicating a range - - - the last item my be a string indicating the frame of - reference - - frames : sequence of str, optional - A sequence of acceptable frame of reference keywords. If not - provided, the default set in `set_reference_frames` will be - used. - - numeric : bool, optional - TODO - - Returns - ------- - parts : tuple - The result is a tuple: - - a string suitable for passing to a service as a range-list - argument - - - an integer counting the number of elements - """ - def str_or_none(x): - if x is None: - return '' - if numeric: - x = float(x) - return str(x) - - def numeric_or_range(x): - if isinstance(x, tuple) and len(x) == 2: - return '%s/%s' % (str_or_none(x[0]), str_or_none(x[1])) - else: - return str_or_none(x) - - def is_frame_of_reference(x): - return isinstance(x, basestring) - - if p is None: - return None, 0 - - elif isinstance(p, (tuple, list)): - has_frame_of_reference = len(p) > 1 and is_frame_of_reference(p[-1]) - if has_frame_of_reference: - points = p[:-1] - else: - points = p[:] - - out = ','.join([numeric_or_range(x) for x in points]) - length = len(points) - if has_frame_of_reference: - if frames is not None and p[-1] not in frames: - raise ValueError( - "'%s' is not a valid frame of reference" % p[-1]) - out += ';' + p[-1] - length += 1 - - return out, length - - elif isinstance(p, basestring): - number = r'([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)?' - if not numeric: - number = r'(' + number + ')|([A-Z_]+)' - match = re.match( - '^' + number + r'([,/]' + number + - r')+(;(?P<frame>[<A-Za-z_0-9]+))?$', - p) - - if match is None: - raise ValueError("'%s' is not a valid range list" % p) - - frame = match.groupdict()['frame'] - if frames is not None and frame is not None and frame not in frames: - raise ValueError( - "'%s' is not a valid frame of reference" % frame) - return p, p.count(',') + p.count(';') + 1 - - try: - float(p) - return str(p), 1 - except TypeError: - raise ValueError("'%s' is not a valid range list" % p) - -
        -def version_compare(a, b): - """ - Compare two VOTable version identifiers. - """ - def version_to_tuple(v): - if v[0].lower() == 'v': - v = v[1:] - return version.StrictVersion(v) - av = version_to_tuple(a) - bv = version_to_tuple(b) - # Can't use cmp because it was removed from Python 3.x - return (av > bv) - (av < bv) - - -if IS_PY3K: - def is_callable(o): - """ - Abstracts away the different ways to test for a callable object in - Python 2.x and 3.x. - """ - return isinstance(o, collections.Callable) -else: -
        [docs] def is_callable(o): - """ - Abstracts away the different ways to test for a callable object in - Python 2.x and 3.x. - """ - return callable(o) -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/validator/main.html b/_modules/astropy/io/vo/validator/main.html deleted file mode 100644 index d128f4d5..00000000 --- a/_modules/astropy/io/vo/validator/main.html +++ /dev/null @@ -1,267 +0,0 @@ - - - - - - - - - - astropy.io.vo.validator.main — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.io.vo.validator.main

        -"""
        -Validates a large collection of web-accessible VOTable files,
        -and generates a report as a directory tree of HTML files.
        -"""
        -from __future__ import print_function
        -
        -# STDLIB
        -import os
        -import sys
        -
        -# LOCAL
        -from ....config import get_data_filename
        -from . import html
        -from . import result
        -
        -
        -__all__ = ['make_validation_report']
        -
        -
        -
        -def get_srcdir():
        -    return os.path.dirname(__file__)
        -
        -
        -def get_urls(destdir, s):
        -    import gzip
        -
        -    types = ['good', 'broken', 'incorrect']
        -
        -    seen = set()
        -    urls = []
        -    for type in types:
        -        filename = get_data_filename(
        -            'astropy/io/vo/validator/urls/cone.{0}.dat.gz'.format(type))
        -        with gzip.open(filename, 'rb') as fd:
        -            for url in fd.readlines():
        -                s.next()
        -                url = url.strip()
        -                if url not in seen:
        -                    with result.Result(url, root=destdir) as r:
        -                        r['expected'] = type
        -                    urls.append(url)
        -                seen.add(url)
        -
        -    return urls
        -
        -
        -def download(args):
        -    url, destdir = args
        -    with result.Result(url, root=destdir) as r:
        -        r.download_xml_content()
        -
        -
        -def validate_vo(args):
        -    url, destdir = args
        -    with result.Result(url, root=destdir) as r:
        -        r.validate_vo()
        -
        -
        -def votlint_validate(args):
        -    path_to_stilts_jar, url, destdir = args
        -    with result.Result(url, root=destdir) as r:
        -        if r['network_error'] is None:
        -            r.validate_with_votlint(path_to_stilts_jar)
        -
        -
        -def write_html_result(args):
        -    url, destdir = args
        -    with result.Result(url, root=destdir) as r:
        -        html.write_result(r)
        -
        -
        -def write_subindex(args):
        -    subset, destdir, total = args
        -    html.write_index_table(destdir, *subset, total=total)
        -
        -
        -
        [docs]def make_validation_report( - urls=None, destdir='astropy.io.vo.validator.results', multiprocess=True, - stilts=None): - """ - Validates a large collection of web-accessible VOTable files, - and generates a report as a directory tree of HTML files. - - Parameters - ---------- - urls : list of strings, optional - If provided, is a list of HTTP urls to download VOTable files - from. If not provided, a built-in set of ~22,000 urls - compiled by HEASARC will be used. - - destdir : path, optional - The directory to write the report to. By default, this is a - directory called `astropy.io.vo.validator.results` in the - current directory. If the directory does not exist, it will - be created. - - multiprocess : bool, optional - If `True` (default), perform validations in parallel using all - of the cores on this machine. - - stilts : path, optional - To perform validation with `votlint` from the the Java-based - `STILTS <http://www.star.bris.ac.uk/~mbt/stilts/>`_ VOTable - parser, in addition to `astropy.io.vo`, set this to the path - of the `stilts.jar` file. `java` on the system shell path - will be used to run it. - - Notes - ----- - Downloads of each given URL will be performed only once and cached - locally in *destdir*. To refresh the cache, remove *destdir* - first. - """ - from ....utils.console import (color_print, ProgressBar, Spinner) - - if stilts is not None: - if not os.path.exists(stilts): - raise ValueError( - '{0} does not exist.'.format(stilts)) - - destdir = os.path.abspath(destdir) - - if urls is None: - with Spinner('Loading URLs', 'green') as s: - urls = get_urls(destdir, s) - else: - color_print('Marking URLs', 'green') - for url in ProgressBar.iterate(urls): - with result.Result(url, root=destdir) as r: - r['expected'] = type - - args = [(url, destdir) for url in urls] - - color_print('Downloading VO files', 'green') - ProgressBar.map( - download, args, multiprocess=multiprocess) - - color_print('Validating VO files', 'green') - ProgressBar.map( - validate_vo, args, multiprocess=multiprocess) - - if stilts is not None: - color_print('Validating with votlint', 'green') - votlint_args = [(stilts, x, destdir) for x in urls] - ProgressBar.map( - votlint_validate, votlint_args, multiprocess=multiprocess) - - - color_print('Generating HTML files', 'green') - ProgressBar.map( - write_html_result, args, multiprocess=multiprocess) - - with Spinner('Grouping results', 'green') as s: - subsets = result.get_result_subsets(urls, destdir, s) - - color_print('Generating index', 'green') - html.write_index(subsets, urls, destdir) - - color_print('Generating subindices', 'green') - subindex_args = [(subset, destdir, len(urls)) for subset in subsets] - ProgressBar.map( - write_subindex, subindex_args, multiprocess=multiprocess)
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/io/vo/xmlutil.html b/_modules/astropy/io/vo/xmlutil.html deleted file mode 100644 index f6f4aed8..00000000 --- a/_modules/astropy/io/vo/xmlutil.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - astropy.io.vo.xmlutil — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.io.vo.xmlutil

        -"""
        -Various XML-related utilities
        -"""
        -
        -from __future__ import division, absolute_import
        -
        -# STDLIB
        -import io
        -import os
        -
        -# ASTROPY
        -from ...utils.xml import check as xml_check
        -from ...utils.xml import validate
        -
        -# LOCAL
        -from . import util
        -from .util import IS_PY3K
        -from .exceptions import (warn_or_raise, vo_warn, vo_raise,
        -     VOTableChangeWarning, W02, W03, W04, W05, W34)
        -from ... import config
        -
        -
        -__all__ = [
        -    'check_id', 'fix_id', 'check_token', 'check_mime_content_type',
        -    'check_anyuri', 'validate_schema'
        -    ]
        -
        -
        -
        [docs]def check_id(ID, name='ID', config={}, pos=None): - """ - Raises a `astropy.io.vo.exceptions.VOTableSpecError` if *ID* is not a - valid XML ID_. *name* is the name of the attribute being checked - (used only for error messages). - """ - if (ID is not None and not xml_check.check_id(ID)): - warn_or_raise(W02, W02, (name, ID), config, pos) - return False - return True - -
        -
        [docs]def fix_id(ID, config={}, pos=None): - """ - Given an arbitrary string, create one that can be used as an xml - id. This is rather simplistic at the moment, since it just - replaces non-valid characters with underscores. - """ - if ID is None: - return None - corrected = xml_check.fix_id(ID) - if corrected != ID: - vo_warn(W03, (ID, corrected), config, pos) - return corrected - -
        -_token_regex = r"(?![\r\l\t ])[^\r\l\t]*(?![\r\l\t ])" - - -
        [docs]def check_token(token, attr_name, config={}, pos=None): - """ - Raises a `ValueError` if *token* is not a valid XML token, as - defined by XML Schema Part 2. - """ - if (token is not None and not xml_check.check_token(token)): - return False - return True - -
        -
        [docs]def check_mime_content_type(content_type, config={}, pos=None): - """ - Raises a `astropy.io.vo.exceptions.VOTableSpecError` if - *content_type* is not a valid MIME content type (syntactically at - least), as defined by RFC 2045. - """ - if (content_type is not None and - not xml_check.check_mime_content_type(content_type)): - warn_or_raise(W04, W04, content_type, config, pos) - return False - return True - -
        -
        [docs]def check_anyuri(uri, config={}, pos=None): - """ - Raises a `astropy.io.vo.exceptions.VOTableSpecError` if *uri* is - not a valid URI as defined in RFC 2396. - """ - if (uri is not None and not xml_check.check_anyuri(uri)): - warn_or_raise(W05, W05, uri, config, pos) - return False - return True - -
        -
        [docs]def validate_schema(filename, version='1.2'): - """ - Validates the given file against the appropriate VOTable schema. - - Parameters - ---------- - filename : str - The path to the XML file to validate - - version : str - The VOTABLE version to check, which must be a string \"1.0\", - \"1.1\", or \"1.2\". - - For version \"1.0\", it is checked against a DTD, since that - version did not have an XML Schema. - - Returns - ------- - returncode, stdout, stderr : int, str, str - Returns the returncode from xmllint and the stdout and stderr - as strings - """ - import subprocess - - assert version in ('1.0', '1.1', '1.2') - - if version in ('1.1', '1.2'): - schema_path = config.get_data_filename( - 'data/VOTable.v{0}.xsd'.format(version)) - else: - schema_path = config.get_data_filename( - 'data/VOTable.dtd') - - return validate.validate_schema(filename, schema_path)
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/tools/misc.html b/_modules/astropy/tools/misc.html deleted file mode 100644 index eaf2e21d..00000000 --- a/_modules/astropy/tools/misc.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - - - - - - - astropy.tools.misc — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.tools.misc

        -# Licensed under a 3-clause BSD style license - see LICENSE.rst
        -"""
        -This module contains simple algorithmic functionality common in astronomy or
        -used in multiple places throughout Astropy, but are not complex enough to
        -necessarily warrant their own module.
        -
        -This package should generally not be used directly.  Everything in `__all__` is
        -imported into `astropy.tools`, and hence that package should be used for
        -access.
        -"""
        -
        -import numpy as np  # needed for some defaults
        -
        -__all__ = ['sigma_clip']
        -
        -
        -
        [docs]def sigma_clip(data, sig=3, iters=1, cenfunc=np.median, varfunc=np.var, - maout=False): - """ Perform sigma-clipping on the provided data. - - This performs the sigma clipping algorithm - i.e. the data will be iterated - over, each time rejecting points that are more than a specified number of - standard deviations discrepant. - - Parameters - ---------- - data : array-like - The data to be sigma-clipped (any shape). - sig : float - The number of standard deviations (*not* variances) to use as the - clipping limit. - iters : int or None - The number of iterations to perform clipping for, or None to clip until - convergence is achieved (i.e. continue until the last iteration clips - nothing). - cenfunc : callable - The technique to compute the center for the clipping. Must be a - callable that takes in a 1D data array and outputs the central value. - Defaults to the median. - varfunc : callable - The technique to compute the variance about the center. Must be a - callable that takes in a 1D data array and outputs the width estimator - that will be interpreted as a variance. Defaults to the variance. - maout : bool or 'copy' - If True, a masked array will be returned. If the special string - 'inplace', the masked array will contain the same array as `data`, - otherwise the array data will be copied. - - Returns - ------- - filtereddata : `numpy.ndarray` or `numpy.masked.MaskedArray` - If `maout` is True, this is a masked array with a shape matching the - input that is masked where the algorithm has rejected those values. - Otherwise, a 1D array of values including only those that are not - clipped. - mask : boolean array - Only present if `maout` is False. A boolean array with a shape matching - the input `data` that is False for rejected values and True for all - others. - - Examples - -------- - - This will generate random variates from a Gaussian distribution and return - only the points that are within 2 *sample* standard deviation from the - median:: - - >>> from astropy.tools.alg import sigma_clip - >>> from numpy.random import randn - >>> randvar = randn(10000) - >>> data,mask = sigma_clip(randvar,2,1) - - This will clipping on a similar distribution, but for 3 sigma relative to - the sample *mean*, will clip until converged, and produces a - `numpy.masked.MaskedArray`:: - - >>> from astropy.tools.alg import sigma_clip - >>> from numpy.random import randn - >>> from numpy import mean - >>> randvar = randn(10000) - >>> maskedarr = sigma_clip(randvar,3,None,mean,maout=True) - - """ - data = np.array(data, copy=False) - oldshape = data.shape - data = data.ravel() - - mask = np.ones(data.size, bool) - if iters is None: - i = -1 - lastrej = sum(mask) + 1 - while(sum(mask) != lastrej): - i += 1 - lastrej = sum(mask) - do = data - cenfunc(data[mask]) - mask = do * do <= varfunc(data[mask]) * sig ** 2 - iters = i + 1 - #TODO: ?print iters to the log if iters was None? - else: - for i in range(iters): - do = data - cenfunc(data[mask]) - mask = do * do <= varfunc(data[mask]) * sig ** 2 - - if maout: - return np.ma.MaskedArray(data, ~mask, copy=maout != 'inplace') - else: - return data[mask], mask.reshape(oldshape)
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/utils/collections.html b/_modules/astropy/utils/collections.html deleted file mode 100644 index 05c27d81..00000000 --- a/_modules/astropy/utils/collections.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - - - astropy.utils.collections — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.utils.collections

        -# Licensed under a 3-clause BSD style license - see LICENSE.rst
        -"""
        -A number of specialized collection classes.
        -"""
        -
        -
        -
        [docs]class HomogeneousList(list): - """ - A subclass of list that contains only elements of a given type or - types. If an item that is not of the specified type is added to - the list, a `TypeError` is raised. - """ -
        [docs] def __init__(self, types, values=[]): - """ - Parameters - ---------- - types : sequence of types - The types to accept. - - values : sequence, optional - An initial set of values. - """ - self._types = types - list.__init__(self, values) -
        - def _assert(self, x): - if not isinstance(x, self._types): - raise TypeError( - "homogeneous list must contain only objects of type '%s'" % - (self._types)) - -
        [docs] def __iadd__(self, other): - for x in other: - self._assert(x) - return list.__iadd__(self, other) -
        -
        [docs] def __setitem__(self, x): - self._assert(x) - return list.__setitem__(self, x) -
        -
        [docs] def append(self, x): - self._assert(x) - return list.append(self, x) -
        -
        [docs] def insert(self, i, x): - self._assert(x) - return list.insert(self, i, x) -
        -
        [docs] def extend(self, x): - for item in x: - self._assert(item) - return list.extend(self, x)
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/utils/console.html b/_modules/astropy/utils/console.html deleted file mode 100644 index 99012bf3..00000000 --- a/_modules/astropy/utils/console.html +++ /dev/null @@ -1,706 +0,0 @@ - - - - - - - - - - astropy.utils.console — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.utils.console

        -# -*- coding: utf-8 -*-
        -# Licensed under a 3-clause BSD style license - see LICENSE.rst
        -"""
        -Utilities for prettifying output to the console.
        -"""
        -from __future__ import division, print_function
        -
        -import io
        -import re
        -import math
        -import sys
        -import time
        -
        -
        -from ..config.configs import ConfigurationItem
        -
        -
        -__all__ = [
        -    'isatty', 'color_print', 'human_time', 'ProgressBar', 'Spinner',
        -    'print_code_line', 'ProgressBarOrSpinner']
        -
        -
        -USE_COLOR = ConfigurationItem(
        -    'use_color', True,
        -    'When True, use ANSI color escape sequences when writing to the console.')
        -USE_UNICODE = ConfigurationItem(
        -    'use_unicode', True,
        -    'Use Unicode characters when drawing progress bars etc. at the console.')
        -
        -
        -
        [docs]def isatty(file): - """ - Returns `True` if `file` is a tty. - - Most built-in Python file-like objects have an `isatty` member, - but some user-defined types may not, so this assumes those are not - ttys. - """ - if hasattr(file, 'isatty'): - return file.isatty() - return False - -
        -
        [docs]def color_print(*args, **kwargs): - """ - Prints colors and styles to the terminal uses ANSI escape - sequences:: - - color_print('This is the color ', 'default', 'GREEN', 'green') - - Parameters - ---------- - positional args : strings - The positional arguments come in pairs (*msg*, *color*), where - *msg* is the string to display and *color* is the color to - display it in. - - *color* is an ANSI terminal color name. Must be one of: - black, red, green, brown, blue, magenta, cyan, lightgrey, - default, darkgrey, lightred, lightgreen, yellow, lightblue, - lightmagenta, lightcyan, white, or '' (the empty string). - - file : writeable file-like object, optional - Where to write to. Defaults to `sys.stdout`. If file is not - a tty (as determined by calling its `isatty` member, if one - exists), no coloring will be included. - - end : str, optional - The ending of the message. Defaults to ``\\n``. The end will - be printed after resetting any color or font state. - """ - color_mapping = { - 'black': '0;30', - 'red': '0;31', - 'green': '0;32', - 'brown': '0;33', - 'blue': '0;34', - 'magenta': '0;35', - 'cyan': '0;36', - 'lightgrey': '0;37', - 'default': '0;39', - 'darkgrey': '1;30', - 'lightred': '1;31', - 'lightgreen': '1;32', - 'yellow': '1;33', - 'lightblue': '1;34', - 'lightmagenta': '1;35', - 'lightcyan': '1;36', - 'white': '1;37'} - - file = kwargs.get('file', sys.stdout) - end = kwargs.get('end', u'\n') - - write = file.write - if isatty(file) and USE_COLOR(): - for i in xrange(0, len(args), 2): - msg = args[i] - if i + 1 == len(args): - color = '' - else: - color = args[i + 1] - - if isinstance(msg, bytes): - msg = msg.decode('ascii') - - if color == u'' or color is None: - write(msg) - else: - color_code = color_mapping.get(color, '0;39') - write(u'\033[{0}m{1}\033[0m'.format( - color_code, msg)) - - write(end) - else: - for i in xrange(0, len(args), 2): - msg = args[i] - if isinstance(msg, bytes): - msg = msg.decode('ascii') - write(msg) - write(end) - -
        -def strip_ansi_codes(s): - """ - Remove ANSI color codes from the string. - """ - return re.sub('\033\[([0-9]+)(;[0-9]+)*m', '', s) - - -
        [docs]def human_time(seconds): - """ - Returns a human-friendly time string that is always exactly 6 - characters long. - - Depending on the number of seconds given, can be one of:: - - 1w 3d - 2d 4h - 1h 5m - 1m 4s - 15s - - Will be in color if console coloring is turned on. - - Parameters - ---------- - seconds : int - The number of seconds to represent - - Returns - ------- - time : str - A human-friendly representation of the given number of seconds - that is always exactly 6 characters. - """ - units = [ - (u'y', 60 * 60 * 24 * 7 * 52), - (u'w', 60 * 60 * 24 * 7), - (u'd', 60 * 60 * 24), - (u'h', 60 * 60), - (u'm', 60), - (u's', 1), - ] - - seconds = int(seconds) - - if seconds < 60: - return u' {0:02d}s'.format(seconds) - for i in xrange(len(units) - 1): - unit1, limit1 = units[i] - unit2, limit2 = units[i + 1] - if seconds >= limit1: - return u'{0:02d}{1}{2:02d}{3}'.format( - seconds // limit1, unit1, - (seconds % limit1) // limit2, unit2) - return u' ~inf' - -
        -
        [docs]class ProgressBar: - """ - A class to display a progress bar in the terminal. - - It is designed to be used with the `with` statement:: - - with ProgressBar(len(items)) as bar: - for item in enumerate(items): - bar.update() - """ -
        [docs] def __init__(self, total, file=sys.stdout): - """ - Parameters - ---------- - total : int - The number of increments in the process being tracked. - - file : writable file-like object, optional - The file to write the progress bar to. Defaults to - `sys.stdout`. If `file` is not a tty (as determined by - calling its `isatty` member, if any), the scrollbar will - be completely silent. - """ - if not isatty(file): - self.update = self._silent_update - self._silent = True - else: - self._silent = False - - self._total = total - self._file = file - self._start_time = time.time() - terminal_width = 78 - if sys.platform.startswith('linux'): - import subprocess - p = subprocess.Popen( - 'stty size', - shell=True, - stdout=subprocess.PIPE) - stdout, stderr = p.communicate() - parts = stdout.split() - if len(parts) == 2: - rows, cols = parts - terminal_width = int(cols) - self._bar_length = terminal_width - 36 - num_scale = int(math.floor(math.log(self._total) / math.log(1000))) - if num_scale > 7: - self._suffix = '?' - else: - suffixes = u' kMGTPEH' - self._suffix = suffixes[num_scale] - self._num_scale = int(math.pow(1000, num_scale)) - self.update(0) -
        -
        [docs] def __enter__(self): - return self -
        -
        [docs] def __exit__(self, exc_type, exc_value, traceback): - if not self._silent: - if exc_type is None: - self.update(self._total) - self._file.write('\n') - self._file.flush() -
        -
        [docs] def update(self, value=None): - """ - Update the progress bar to the given value (out of the total - given to the constructor. - """ - if value is None: - value = self._current_value = self._current_value + 1 - else: - self._current_value = value - if self._total == 0: - frac = 1.0 - else: - frac = float(value) / float(self._total) - - file = self._file - write = file.write - - bar_fill = int(float(self._bar_length) * frac) - write(u'\r|') - color_print(u'=' * bar_fill, 'blue', file=file, end=u'') - if bar_fill < self._bar_length: - color_print(u'>', 'green', file=file, end=u'') - write(u'-' * (self._bar_length - bar_fill - 1)) - write(u'|') - - if value >= self._total: - t = time.time() - self._start_time - prefix = u' ' - elif value <= 0: - t = None - prefix = u'' - else: - t = ((time.time() - self._start_time) * (1.0 - frac)) / frac - prefix = u' ETA ' - write(u' {0:>3d}/{1:>3d}{2}'.format( - value // self._num_scale, - self._total // self._num_scale, - self._suffix)) - write(u' ({0:>6s}%)'.format(u'{0:.2f}'.format(frac * 100.0))) - write(prefix) - if t is not None: - write(human_time(t)) - self._file.flush() -
        - def _silent_update(self, value=None): - pass - - @classmethod -
        [docs] def map(cls, function, items, multiprocess=False, file=sys.stdout): - """ - Does a `map` operation while displaying a progress bar with - percentage complete:: - - def work(i): - print(i) - - ProgressBar.map(work, range(50)) - - Parameters - ---------- - function : function - Function to call for each step - - items : sequence - Sequence where each element is a tuple of arguments to pass to - *function*. - - multiprocess : bool, optional - If `True`, use the `multiprocessing` module to distribute each - task to a different processor core. - - file : writeable file-like object, optional - The file to write the progress bar to. Defaults to - `sys.stdout`. If `file` is not a tty (as determined by - calling its `isatty` member, if any), the scrollbar will - be completely silent. - """ - with cls(len(items), file=file) as bar: - step_size = max(200, bar._bar_length) - steps = max(int(float(len(items)) / step_size), 1) - if not multiprocess: - for i, item in enumerate(items): - function(item) - if (i % steps) == 0: - bar.update(i) - else: - import multiprocessing - p = multiprocessing.Pool() - for i, _ in enumerate( - p.imap_unordered(function, items, steps)): - bar.update(i) -
        - @classmethod -
        [docs] def iterate(cls, items, file=sys.stdout): - """ - Iterate over a sequence while indicating progress with a progress - bar in the terminal:: - - for item in ProgressBar.iterate(items): - pass - - Parameters - ---------- - items : sequence - A sequence of items to iterate over - - file : writeable file-like object, optional - The file to write the progress bar to. Defaults to - `sys.stdout`. If `file` is not a tty (as determined by - calling its `isatty` member, if any), the scrollbar will - be completely silent. - - Returns - ------- - generator : - A generator over `items` - """ - with cls(len(items), file=file) as bar: - for item in items: - yield item - bar.update() - -
        -
        [docs]class Spinner(): - """ - A class to display a spinner in the terminal. - - It is designed to be used with the `with` statement:: - - with Spinner("Reticulating splines", "green") as s: - for item in enumerate(items): - s.next() - """ - _default_unicode_chars = u"◓◑◒◐" - _default_ascii_chars = u"-/|\\" - -
        [docs] def __init__(self, msg, color='default', file=sys.stdout, step=1, chars=None): - """ - Parameters - ---------- - msg : str - The message to print - - color : str, optional - An ANSI terminal color name. Must be one of: black, red, - green, brown, blue, magenta, cyan, lightgrey, default, - darkgrey, lightred, lightgreen, yellow, lightblue, - lightmagenta, lightcyan, white. - - file : writeable file-like object, optional - The file to write the spinner to. Defaults to - `sys.stdout`. If `file` is not a tty (as determined by - calling its `isatty` member, if any), the scrollbar will - be completely silent. - - step : int, optional - Only update the spinner every *step* steps - - chars : str, optional - The character sequence to use for the spinner - """ - self._msg = msg - self._color = color - self._file = file - self._step = step - if chars is None: - if USE_UNICODE: - chars = self._default_unicode_chars - else: - chars = self._default_ascii_chars - self._chars = chars - - self._silent = not isatty(file) -
        - def _iterator(self): - chars = self._chars - index = 0 - file = self._file - write = file.write - flush = file.flush - - while True: - write(u'\r') - color_print(self._msg, self._color, file=file, end=u'') - write(u' ') - write(chars[index]) - flush() - yield - - for i in xrange(self._step): - yield - - index += 1 - if index == len(chars): - index = 0 - -
        [docs] def __enter__(self): - if self._silent: - return self._silent_iterator() - else: - return self._iterator() -
        -
        [docs] def __exit__(self, exc_type, exc_value, traceback): - file = self._file - write = file.write - flush = file.flush - - if not self._silent: - write(u'\r') - color_print(self._msg, self._color, file=file, end=u'') - if exc_type is None: - color_print(u' [Done]', 'green', file=file) - else: - color_print(u' [Failed]', 'red', file=file) - flush() -
        - def _silent_iterator(self): - color_print(self._msg, self._color, file=self._file, end=u'') - self._file.flush() - - while True: - yield - -
        -
        [docs]class ProgressBarOrSpinner: - """ - A class that displays either a `ProgressBar` or `Spinner` - depending on whether the total size of the operation is - known or not. - - It is designed to be used with the `with` statement:: - - if file.has_length(): - length = file.get_length() - else: - length = None - bytes_read = 0 - with ProgressBarOrSpinner(length) as bar: - while file.read(blocksize): - bytes_read += blocksize - bar.update(bytes_read) - """ - -
        [docs] def __init__(self, total, msg, color='default', file=sys.stdout): - """ - Parameters - ---------- - total : int or None - If an int, the number of increments in the process being - tracked and a `ProgressBar` is displayed. If `None`, a - `Spinner` is displayed. - - msg : str - The message to display above the `ProgressBar` or - alongside the `Spinner`. - - color : str, optional - The color of `msg`, if any. Must be an ANSI terminal - color name. Must be one of: black, red, green, brown, - blue, magenta, cyan, lightgrey, default, darkgrey, - lightred, lightgreen, yellow, lightblue, lightmagenta, - lightcyan, white. - - file : writable file-like object, optional - The file to write the to. Defaults to `sys.stdout`. If - `file` is not a tty (as determined by calling its `isatty` - member, if any), only `msg` will be displayed: the - `ProgressBar` or `Spinner` will be silent. - """ - if total is None or not isatty(file): - self._is_spinner = True - self._obj = Spinner(msg, color=color, file=file) - else: - self._is_spinner = False - color_print(msg, color, file=file) - self._obj = ProgressBar(total, file=file) -
        -
        [docs] def __enter__(self): - self._iter = self._obj.__enter__() - return self -
        -
        [docs] def __exit__(self, exc_type, exc_value, traceback): - return self._obj.__exit__(exc_type, exc_value, traceback) -
        -
        [docs] def update(self, value): - """ - Update the progress bar to the given value (out of the total - given to the constructor. - """ - if self._is_spinner: - self._iter.next() - else: - self._obj.update(value) - -
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/utils/misc.html b/_modules/astropy/utils/misc.html deleted file mode 100644 index 2c24a4c9..00000000 --- a/_modules/astropy/utils/misc.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - - - - - astropy.utils.misc — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.utils.misc

        -# Licensed under a 3-clause BSD style license - see LICENSE.rst
        -"""
        -This package contains smallish general-purpose utilities that don't have a
        -clear other module to live in.
        -
        -This module should not be used directly, as everything in `__all__`` is
        -imported into `astropy.utils`
        -"""
        -from __future__ import absolute_import
        -
        -__all__ = ['find_current_module', 'fnpickle', 'fnunpickle']
        -
        -
        -
        [docs]def find_current_module(depth=1, finddiff=False): - """ Determines the module/package this function is called from. - - Parameters - ---------- - depth : int - Specifies how far back to go in the call stack (0-indexed, so that - passing in 0 gives back `astropy.utils.misc`). - finddiff : bool - If True, once the module at `depth` is determined, a search will be - performed up the call stack until a *different* module is found - from the one at `depth`. - - Returns - ------- - mod : module or None - The module object or None if the package cannot be found. The name of - the module is available as the ``__name__`` attribute of the returned - object (if it isn't None). - - Examples - -------- - The examples below assume that there are two modules in a package named - `pkg`. ``mod1.py``:: - - def find1(): - from astropy.utils import find_current_module - print find_current_module(1).__name__ - def find2(): - from astropy.utils import find_current_module - cmod = find_current_module(2) - if cmod is None: - print 'None' - else: - print cmod.__name__ - def find_diff(): - from astropy.utils import find_current_module - print find_current_module(0,True).__name__ - - ``mod2.py``:: - - def find(): - from .mod1 import find2 - find2() - - With these modules in place, the following occurs:: - - >>> from pkg import mod1, mod2 - >>> from astropy.utils import find_current_module - >>> mod1.find1() - pkg.mod1 - >>> mod1.find2() - None - >>> mod2.find() - pkg.mod2 - >>> find_current_module(0) - <module 'astropy.utils.misc' from 'astropy/utils/misc.py'> - >>> mod1.find_diff() - pkg.mod1 - - """ - from inspect import currentframe - - # using a patched version of getmodule because the py 3.1 and 3.2 stdlib - # is broken if the list of modules changes during import - from .compat import inspect_getmodule - - frm = currentframe() - for i in range(depth): - frm = frm.f_back - if frm is None: - return None - - if finddiff: - currmod = inspect_getmodule(frm) - while frm: - frmb = frm.f_back - modb = inspect_getmodule(frmb) - if modb is not currmod: - return modb - frm = frmb - else: - return inspect_getmodule(frm) - -
        -
        [docs]def fnunpickle(fileorname, number=0, usecPickle=True): - """ Unpickle pickled objects from a specified file and return the contents. - - Parameters - ---------- - fileorname : str or `file`-like - The file name or file from which to unpickle objects. If a file object, - it should have been opened in binary mode. - number : int - If 0, a single object will be returned (the first in the file). If >0, - this specifies the number of objects to be unpickled, and a list will be - returned with exactly that many objects. If <0, all objects in the file - will be unpickled and returned as a list. - usecPickle : bool - If True, the :mod:`cPickle` module is to be used in place of - :mod:`pickle` (cPickle is faster). This only applies for python 2.x. - - Raises - ------ - EOFError - If `number` is >0 and there are fewer than `number` objects in the - pickled file. - - Returns - ------- - contents : obj or list - If `number` is 0, this is a individual object - the first one unpickled - from the file. Otherwise, it is a list of objects unpickled from the - file. - - """ - import sys - - if usecPickle and sys.version_info[0] < 3: - import cPickle as pickle - else: - import pickle - - if isinstance(fileorname, basestring): - f = open(fileorname, 'rb') - close = True - else: - f = fileorname - close = False - - try: - if number > 0: # get that number - res = [] - for i in range(number): - res.append(pickle.load(f)) - elif number < 0: # get all objects - res = [] - eof = False - while not eof: - try: - res.append(pickle.load(f)) - except EOFError: - eof = True - else: # number==0 - res = pickle.load(f) - finally: - if close: - f.close() - - return res - -
        -
        [docs]def fnpickle(object, fileorname, usecPickle=True, protocol=None, append=False): - """Pickle an object to a specified file. - - Parameters - ---------- - object - The python object to pickle. - fileorname : str or `file`-like - The filename or file into which the `object` should be pickled. If a - file object, it should have been opened in binary mode. - usecPickle : bool - If True (default), the :mod:`cPickle` module is to be used in place of - :mod:`pickle` (cPickle is faster). This only applies for python 2.x. - protocol : int or None - Pickle protocol to use - see the :mod:`pickle` module for details on - these options. If None, the most recent protocol will be used. - append : bool - If True, the object is appended to the end of the file, otherwise the - file will be overwritten (if a file object is given instead of a - file name, this has no effect). - - """ - import sys - - if usecPickle and sys.version_info[0] < 3: - import cPickle as pickle - else: - import pickle - - if protocol is None: - protocol = pickle.HIGHEST_PROTOCOL - - if isinstance(fileorname, basestring): - f = open(fileorname, 'ab' if append else 'wb') - close = True - else: - f = fileorname - close = False - - try: - pickle.dump(object, f, protocol=protocol) - finally: - if close: - f.close()
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/utils/xml/check.html b/_modules/astropy/utils/xml/check.html deleted file mode 100644 index e0cefee4..00000000 --- a/_modules/astropy/utils/xml/check.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - - - astropy.utils.xml.check — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.utils.xml.check

        -# Licensed under a 3-clause BSD style license - see LICENSE.rst
        -"""
        -A collection of functions for checking various XML-related strings for
        -standards compliance.
        -"""
        -
        -import re
        -import urlparse
        -
        -
        -
        [docs]def check_id(ID): - """ - Returns `True` if *ID* is a valid XML ID. - """ - return re.match(r"^[A-Za-z_][A-Za-z0-9_\.\-]*$", ID) is not None - -
        -
        [docs]def fix_id(ID): - """ - Given an arbitrary string, create one that can be used as an xml - id. This is rather simplistic at the moment, since it just - replaces non-valid characters with underscores. - """ - if re.match(r"^[A-Za-z_][A-Za-z0-9_\.\-]*$", ID): - return ID - if len(ID): - corrected = ID - if not len(corrected) or re.match('^[^A-Za-z_]$', corrected[0]): - corrected = '_' + corrected - corrected = (re.sub(r"[^A-Za-z_]", '_', corrected[0]) + - re.sub(r"[^A-Za-z0-9_\.\-]", "_", corrected[1:])) - return corrected - return '' -
        -_token_regex = r"(?![\r\l\t ])[^\r\l\t]*(?![\r\l\t ])" - - -
        [docs]def check_token(token): - """ - Returns `True` if *token* is a valid XML token, as defined by XML - Schema Part 2. - """ - return (token == '' or - re.match( - "[^\r\n\t ]?([^\r\n\t ]| [^\r\n\t ])*[^\r\n\t ]?$", token) - is not None) - -
        -
        [docs]def check_mime_content_type(content_type): - """ - Returns `True` if *content_type* is a valid MIME content type - (syntactically at least), as defined by RFC 2045. - """ - ctrls = ''.join(chr(x) for x in xrange(0, 0x20)) - token_regex = '[^()<>@,;:\\\"/[\]?= %s\x7f]+' % ctrls - return re.match( - r'(?P<type>%s)/(?P<subtype>%s)$' % (token_regex, token_regex), - content_type) is not None - -
        -
        [docs]def check_anyuri(uri): - """ - Returns `True` if *uri* is a valid URI as defined in RFC 2396. - """ - if (re.match( - (r"(([a-zA-Z][0-9a-zA-Z+\-\.]*:)?/{0,2}[0-9a-zA-Z;" + - r"/?:@&=+$\.\-_!~*'()%]+)?(#[0-9a-zA-Z;/?:@&=+$\.\-_!~*'()%]+)?"), - uri) is None): - return False - try: - urlparse.urlparse(uri) - except: - return False - return True
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/utils/xml/iterparser.html b/_modules/astropy/utils/xml/iterparser.html deleted file mode 100644 index 3c7a8d27..00000000 --- a/_modules/astropy/utils/xml/iterparser.html +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - - - astropy.utils.xml.iterparser — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.utils.xml.iterparser

        -# Licensed under a 3-clause BSD style license - see LICENSE.rst
        -"""
        -This module includes a fast iterator-based XML parser.
        -"""
        -
        -# STDLIB
        -import collections
        -import contextlib
        -import io
        -import sys
        -
        -
        -__all__ = ['get_xml_iterator', 'get_xml_encoding', 'xml_readlines']
        -
        -
        -############################################################
        -# TODO: Refactor this into a py3k compatibility module
        -IS_PY3K = (sys.version_info[0] >= 3)
        -
        -if IS_PY3K:
        -    def is_callable(o):
        -        """
        -        Abstracts away the different ways to test for a callable object in
        -        Python 2.x and 3.x.
        -        """
        -        return isinstance(o, collections.Callable)
        -else:
        -    def is_callable(o):
        -        """
        -        Abstracts away the different ways to test for a callable object in
        -        Python 2.x and 3.x.
        -        """
        -        return callable(o)
        -############################################################
        -
        -
        -@contextlib.contextmanager
        -def _convert_to_fd_or_read_function(fd):
        -    """
        -    Returns a function suitable for streaming input, or a file object.
        -
        -    This function is only useful if passing off to C code where:
        -
        -       - If it's a real file object, we want to use it as a real
        -         C file object to avoid the Python overhead.
        -
        -       - If it's not a real file object, it's much handier to just
        -         have a Python function to call.
        -
        -    Parameters
        -    ----------
        -    fd : object
        -        May be:
        -
        -            - a file object, in which case it is returned verbatim.
        -
        -            - a function that reads from a stream, in which case it is
        -              returned verbatim.
        -
        -            - a file path, in which case it is opened.  If it ends in
        -              `.gz`, it is assumed to be a gzipped file, and the
        -              :meth:`read` method on the file object is returned.
        -              Otherwise, the raw file object is returned.
        -
        -           - an object with a :meth:`read` method, in which case that
        -             method is returned.
        -
        -    Returns
        -    -------
        -    fd : context-dependent
        -        See above.
        -    """
        -    if not sys.platform.startswith('win'):
        -        if IS_PY3K:
        -            if isinstance(fd, io.IOBase):
        -                yield fd
        -                return
        -        else:
        -            if isinstance(fd, file):
        -                yield fd
        -                return
        -    if is_callable(fd):
        -        yield fd
        -        return
        -    elif isinstance(fd, basestring):
        -        if fd.endswith('.gz'):
        -            from ...utils.compat import gzip
        -            with gzip.GzipFile(fd, 'rb') as real_fd:
        -                yield real_fd.read
        -                return
        -        else:
        -            with open(fd, 'rb') as real_fd:
        -                if sys.platform.startswith('win'):
        -                    # On Windows, we can't pass a real file descriptor
        -                    # to the C level, so we pass the read method
        -                    yield real_fd.read
        -                    return
        -                yield real_fd
        -                return
        -    elif hasattr(fd, 'read'):
        -        assert is_callable(fd.read)
        -        yield fd.read
        -        return
        -    else:
        -        raise TypeError("Can not be coerced to read function")
        -
        -
        -def _fast_iterparse(fd, buffersize=2 ** 10):
        -    from xml.parsers import expat
        -
        -    if not is_callable(fd):
        -        read = fd.read
        -    else:
        -        read = fd
        -
        -    queue = []
        -    text = []
        -
        -    def start(name, attr):
        -        queue.append((True, name, attr,
        -                      (parser.CurrentLineNumber, parser.CurrentColumnNumber)))
        -        del text[:]
        -
        -    def end(name):
        -        queue.append((False, name, ''.join(text).strip(),
        -                      (parser.CurrentLineNumber, parser.CurrentColumnNumber)))
        -
        -    parser = expat.ParserCreate()
        -    if not IS_PY3K:
        -        parser.returns_unicode = False
        -    parser.specified_attributes = True
        -    parser.StartElementHandler = start
        -    parser.EndElementHandler = end
        -    parser.CharacterDataHandler = text.append
        -    Parse = parser.Parse
        -
        -    data = read(buffersize)
        -    while data:
        -        Parse(data, False)
        -        for elem in queue:
        -            yield elem
        -        del queue[:]
        -        data = read(buffersize)
        -
        -    Parse('', True)
        -    for elem in queue:
        -        yield elem
        -
        -
        -# Try to import the C version of the iterparser, otherwise fall back
        -# to the Python implementation above.
        -_slow_iterparse = _fast_iterparse
        -try:
        -    from . import _iterparser
        -    _fast_iterparse = _iterparser.IterParser
        -except ImportError:
        -    pass
        -
        -
        -@contextlib.contextmanager
        -
        [docs]def get_xml_iterator(source, _debug_python_based_parser=False): - """ - Returns an iterator over the elements of an XML file. - - The iterator doesn't ever build a tree, so it is much more memory - and time efficient than the alternative in `cElementTree`. - - Parameters - ---------- - fd : readable file-like object or read function - - Returns - ------- - parts : iterator - - The iterator returns 4-tuples (*start*, *tag*, *data*, *pos*): - - - *start*: when `True` is a start element event, otherwise - an end element event. - - - *tag*: The name of the element - - - *data*: Depends on the value of *event*: - - - if *start* == `True`, data is a dictionary of - attributes - - - if *start* == `False`, data is a string containing - the text content of the element - - - *pos*: Tuple (*line*, *col*) indicating the source of the - event. - """ - with _convert_to_fd_or_read_function(source) as fd: - if _debug_python_based_parser: - context = _slow_iterparse(fd) - else: - context = _fast_iterparse(fd) - yield iter(context) - -
        -
        [docs]def get_xml_encoding(source): - """ - Determine the encoding of an XML file by reading its header. - - Parameters - ---------- - source : readable file-like object, read function or str path - - Returns - ------- - encoding : str - """ - with get_xml_iterator(source) as iterator: - start, tag, data, pos = iterator.next() - if not start or tag != 'xml': - raise IOError('Invalid XML file') - - return data['encoding'] - -
        -
        [docs]def xml_readlines(source): - """ - Get the lines from a given XML file. Correctly determines the - encoding and always returns unicode. - - Parameters - ---------- - source : readable file-like object, read function or str path - - Returns - ------- - lines : list of unicode - """ - encoding = get_xml_encoding(source) - - with io.open(source, 'rt', encoding=encoding) as input: - xml_lines = input.readlines() - - return xml_lines
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/utils/xml/validate.html b/_modules/astropy/utils/xml/validate.html deleted file mode 100644 index 03e452c9..00000000 --- a/_modules/astropy/utils/xml/validate.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - astropy.utils.xml.validate — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.utils.xml.validate

        -# Licensed under a 3-clause BSD style license - see LICENSE.rst
        -"""
        -Functions to do XML schema and DTD validation.  At the moment, this
        -makes a subprocess call to xmllint.  This could use a Python-based
        -library at some point in the future, if something appropriate could be
        -found.
        -"""
        -
        -import os
        -
        -
        -
        [docs]def validate_schema(filename, schema_file): - """ - Validates an XML file against a schema or DTD. - - Parameters - ---------- - filename : str - The path to the XML file to validate - - schema : str - The path to the XML schema or DTD - - Returns - ------- - returncode, stdout, stderr : int, str, str - Returns the returncode from xmllint and the stdout and stderr - as strings - """ - import subprocess - - base, ext = os.path.splitext(schema_file) - if ext == '.xsd': - schema_part = '--schema ' + schema_file - elif ext == '.dtd': - schema_part = '--dtdvalid ' + schema_file - else: - raise TypeError("schema_file must be a path to an XML Schema or DTD") - - p = subprocess.Popen( - "xmllint --noout --nonet %s %s" % (schema_part, filename), - shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - - if p.returncode == 127: - raise OSError( - "xmllint not found, so can not validate schema") - - return p.returncode, stdout, stderr
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/utils/xml/writer.html b/_modules/astropy/utils/xml/writer.html deleted file mode 100644 index 511a3461..00000000 --- a/_modules/astropy/utils/xml/writer.html +++ /dev/null @@ -1,383 +0,0 @@ - - - - - - - - - - astropy.utils.xml.writer — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.utils.xml.writer

        -# Licensed under a 3-clause BSD style license - see LICENSE.rst
        -"""
        -Contains a class that makes it simple to stream out well-formed and
        -nicely-indented XML.
        -"""
        -
        -# STDLIB
        -import contextlib
        -import textwrap
        -
        -
        -
        [docs]def xml_escape_cdata(s): - """ - Escapes &, < and > in an XML CDATA string. - """ - s = s.replace(u"&", u"&amp;") - s = s.replace(u"<", u"&lt;") - s = s.replace(u">", u"&gt;") - return s - -
        -
        [docs]def xml_escape(s): - """ - Escapes &, ', ", < and > in an XML attribute value. - """ - s = s.replace(u"&", u"&amp;") - s = s.replace(u"'", u"&apos;") - s = s.replace(u"\"", u"&quot;") - s = s.replace(u"<", u"&lt;") - s = s.replace(u">", u"&gt;") - return s - -
        -
        [docs]class XMLWriter: - """ - A class to write well-formed and nicely indented XML. - - Use like this:: - - w = XMLWriter(fh) - with w.tag('html'): - with w.tag('body'): - w.data('This is the content') - - Which produces:: - - <html> - <body> - This is the content - </body> - </html> - """ - -
        [docs] def __init__(self, file): - """ - Parameters - ---------- - file : writable file-like object. - """ - self.write = file.write - if hasattr(file, "flush"): - self.flush = file.flush - self._open = 0 # true if start tag is open - self._tags = [] - self._data = [] - self._indentation = u" " * 64 - - try: - from astropy.io.vo import iterparser - self.xml_escape_cdata = iterparser.escape_xml_cdata - self.xml_escape = iterparser.escape_xml - except ImportError: - self.xml_escape_cdata = xml_escape_cdata - self.xml_escape = xml_escape -
        - def _flush(self, indent=True, wrap=False): - """ - Flush internal buffers. - """ - if self._open: - if indent: - self.write(u">\n") - else: - self.write(u">") - self._open = 0 - if self._data: - data = u''.join(self._data) - if wrap: - indent = self.get_indentation_spaces(1) - data = textwrap.fill( - data, - initial_indent=indent, - subsequent_indent=indent) - self.write('\n') - self.write(self.xml_escape_cdata(data)) - self.write('\n') - self.write(self.get_indentation_spaces()) - else: - self.write(self.xml_escape_cdata(data)) - self._data = [] - -
        [docs] def start(self, tag, attrib={}, **extra): - """ - Opens a new element. Attributes can be given as keyword - arguments, or as a string/string dictionary. The method - returns an opaque identifier that can be passed to the - :meth:`close` method, to close all open elements up to and - including this one. - - Parameters - ---------- - tag : str - The element name - - attrib : dict of str -> str - Attribute dictionary. Alternatively, attributes can - be given as keyword arguments. - - Returns - ------- - id : int - Returns an element identifier. - """ - self._flush() - # This is just busy work -- we know our tag names are clean - # tag = xml_escape_cdata(tag) - self._data = [] - self._tags.append(tag) - self.write(self.get_indentation_spaces(-1)) - self.write(u"<%s" % tag) - if attrib or extra: - attrib = attrib.copy() - attrib.update(extra) - attrib = attrib.items() - attrib.sort() - for k, v in attrib: - if not v == '' and v is not None: - # This is just busy work -- we know our keys are clean - # k = xml_escape_cdata(k) - v = self.xml_escape(v) - self.write(u" %s=\"%s\"" % (k, v)) - self._open = 1 - - return len(self._tags) -
        - @contextlib.contextmanager -
        [docs] def tag(self, tag, attrib={}, **extra): - """ - A convenience method for use with the `with` statement:: - - with writer.tag('foo'): - writer.element('bar') - # </foo> is implicitly closed here - - Parameters are the same as to `start`. - """ - self.start(tag, attrib, **extra) - yield - self.end(tag) -
        -
        [docs] def comment(self, comment): - """ - Adds a comment to the output stream. - - Parameters - ---------- - comment : str - Comment text, as a Unicode string. - """ - self._flush() - self.write(self.get_indentation_spaces()) - self.write(u"<!-- %s -->\n" % self.xml_escape_cdata(comment)) -
        -
        [docs] def data(self, text): - """ - Adds character data to the output stream. - - Parameters - ---------- - text : str - Character data, as a Unicode string. - """ - self._data.append(text) -
        -
        [docs] def end(self, tag=None, indent=True, wrap=False): - """ - Closes the current element (opened by the most recent call to - `start`). - - Parameters - ---------- - tag : str - Element name. If given, the tag must match the start tag. - If omitted, the current element is closed. - """ - if tag: - assert self._tags, "unbalanced end(%s)" % tag - assert tag == self._tags[-1],\ - "expected end(%s), got %s" % (self._tags[-1], tag) - else: - assert self._tags, "unbalanced end()" - tag = self._tags.pop() - if self._data: - self._flush(indent, wrap) - elif self._open: - self._open = 0 - self.write(u"/>\n") - return - if indent: - self.write(self.get_indentation_spaces()) - self.write(u"</%s>\n" % tag) -
        -
        [docs] def close(self, id): - """ - Closes open elements, up to (and including) the element identified - by the given identifier. - - Parameters - ---------- - id : int - Element identifier, as returned by the `start` method. - """ - while len(self._tags) > id: - self.end() -
        -
        [docs] def element(self, tag, text=None, wrap=False, attrib={}, **extra): - """ - Adds an entire element. This is the same as calling `start`, - `data`, and `end` in sequence. The `text` argument - can be omitted. - """ - self.start(tag, attrib, **extra) - if text: - self.data(text) - self.end(indent=False, wrap=wrap) -
        -
        [docs] def flush(self): - pass # replaced by the constructor -
        -
        [docs] def get_indentation(self): - """ - Returns the number of indentation levels the file is currently - in. - """ - return len(self._tags) -
        -
        [docs] def get_indentation_spaces(self, offset=0): - """ - Returns a string of spaces that matches the current - indentation level. - """ - return self._indentation[:len(self._tags) + offset] -
        - @staticmethod -
        [docs] def object_attrs(obj, attrs): - """ - Converts an object with a bunch of attributes on an object - into a dictionary for use by the `XMLWriter`. - - Parameters - ---------- - obj : object - Any Python object - - attrs : sequence of str - Attribute names to pull from the object - - Returns - ------- - attrs : dict - Maps attribute names to the values retrieved from - `obj.attr`. If any of the attributes is `None`, it will - not appear in the output dictionary. - """ - d = {} - for attr in attrs: - if getattr(obj, attr) is not None: - d[attr.replace('_', '-')] = str(getattr(obj, attr)) - return d
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/astropy/wcs.html b/_modules/astropy/wcs.html deleted file mode 100644 index 3c58fd9f..00000000 --- a/_modules/astropy/wcs.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - - - astropy.wcs — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - -
        -
        -
        -
        - -

        Source code for astropy.wcs

        -"""
        -.. _wcslib: http://www.atnf.csiro.au/~mcalabre/WCS/
        -.. _pyfits: http://www.stsci.edu/resources/software_hardware/pyfits
        -.. _Paper IV: http://www.atnf.csiro.au/people/mcalabre/WCS/index.html
        -.. _SIP: http://irsa.ipac.caltech.edu/data/SPITZER/docs/files/spitzer/shupeADASS.pdf
        -.. _ds9: http://hea-www.harvard.edu/RD/ds9/
        -
        -astropy.wcs provides transformations following the `SIP`_ conventions,
        -`Paper IV`_ table lookup distortion, and the core WCS functionality
        -provided by `wcslib`_.  Each of these transformations can be used
        -independently or together in a standard pipeline.
        -
        -The basic workflow is as follows:
        -
        -    1. ``from astropy import wcs``
        -
        -    2. Call the `wcs.WCS` constructor with a `pyfits`_ header
        -       and/or hdulist object.
        -
        -    3. Optionally, if the FITS file uses any deprecated or
        -       non-standard features, you may need to call one of the
        -       `~astropy.wcs.WCS.fix` methods on the object.
        -
        -    4. Use one of the following transformation methods:
        -
        -       - `~WCS.all_pix2sky`: Perform all three transformations from
        -         pixel to sky coordinates.
        -
        -       - `~WCS.wcs_pix2sky`: Perform just the core WCS transformation
        -         from pixel to sky coordinates.
        -
        -       - `~WCS.wcs_sky2pix`: Perform just the core WCS transformation
        -         from sky to pixel coordinates.
        -
        -       - `~WCS.sip_pix2foc`: Convert from pixel to focal plane
        -         coordinates using the `SIP`_ polynomial coefficients.
        -
        -       - `~WCS.sip_foc2pix`: Convert from focal plane to pixel
        -         coordinates using the `SIP`_ polynomial coefficients.
        -
        -       - `~WCS.p4_pix2foc`: Convert from pixel to focal plane
        -         coordinates using the table lookup distortion method
        -         described in `Paper IV`_.
        -
        -       - `~WCS.det2im`: Convert from detector coordinates to image
        -         coordinates.  Commonly used for narrow column correction.
        -"""
        -
        -from __future__ import division  # confidence high
        -
        -from .wcs import *
        -
        -
        -
        [docs]class Wcsprm(Wcsprm): - pass
        -
        - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/_modules/index.html b/_modules/index.html deleted file mode 100644 index 53d853a6..00000000 --- a/_modules/index.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - Overview: module code — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/_sources/configs.txt b/_sources/configs.txt deleted file mode 100644 index 95e92ddf..00000000 --- a/_sources/configs.txt +++ /dev/null @@ -1,100 +0,0 @@ -Configuration system Documentation -================================== - -The astropy configuration system is designed to give users control of various -parameters used in astropy or affiliated packages without delving into the -source code to make those changes. - -.. todo:: - Move this portion of the documentation to a more appropriate place when a - doc reorg happens - -For Users ---------- - -To see the configuration options, look for your astropy configuration file. -You can find it by doing:: - - from astropy.config import get_config_dir - - print get_config_dir() - -And you should see the location of your configuration directory. The standard -scheme generally puts your configuration directory in ``$HOME/.astropy/config``, -but if you've set the environment variable `XDG_CONFIG_HOME` and the -``$XDG_CONFIG_HOME/astropy`` directory exists, it will instead be there. - -Once you've found the configuration file, open it with your favorite editor. -It should have all of the sections you might want, with descriptions and the -type of the value that is accepted. Feel free to edit this as you wish, and -any of these changes will be reflected when you next start Astropy. Or, if you -want to see your changes immediately in your current Astropy session, just do:: - - from astropy.config import reload_config() - - reload_config() - -.. warning:: - The above is not true yet, because the setup doesn't automatically - populate the configuration files. Hopefully it will be true soon, though. - The :func:`astropy.config.configs._generate_all_config_items` function will - already do this, basically, but there has to be some thought about how to - make driver scripts that actually do this for each user, and coordinate - when they get run so that everything is already built. - - - - -For Developers --------------- -The Reference guide below describes the full interface - this is a summary of -typical practices. The most common way to use the configuration system is as -follows:: - - """ This is the docstring at the beginning of a module - """ - from astropy.config import ConfigurationItem - - SOME_OPTION = ConfigurationItem('some_opt',1,'A description.') - ANOTHER_OPTION = ConfigurationItem('anno_opt','a string val', - 'A longer description of what this does.') - - ... implementation ... - def some_func(): - #to get the value of these options, I might do: - something = SOME_OPTION()+2 - return ANOTHER_OPTION()+' Also, I added text.' - -It is highly recommended that any configuration items be placed at the top of a -module like this, as they can then be easily found when viewing the source code -and the automated tools to generate the default configuration files can also -locate these items. - - - -Reference/API -------------- -Below are the reference documentation for the three main config sub-packages: -`astropy.config.paths`, `astropy.config.configs`, and `astropy.config.data`. -Note that all the public classes and functions in these sub-packages are -imported into `astropy.config`, so the recommended usage is simply -``from astropy.config import foo``. - -`astropy.config.paths` -^^^^^^^^^^^^^^^^^^^^^^ - -.. automodule:: astropy.config.paths - :members: - -`astropy.config.configs` -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. automodule:: astropy.config.configs - :members: - - -`astropy.config.data` -^^^^^^^^^^^^^^^^^^^^^ - -.. automodule:: astropy.config.data - :members: \ No newline at end of file diff --git a/_sources/contributing.txt b/_sources/contributing.txt new file mode 100644 index 00000000..f273b4c5 --- /dev/null +++ b/_sources/contributing.txt @@ -0,0 +1,35 @@ +Contributing to Astropy +======================= + +.. _`issue tracker`: http://github.com/astropy/astropy/issues +.. _`astropy-dev`: http://groups.google.com/group/astropy-dev +.. _`contributing`: http://astropy.readthedocs.org/en/latest/development/workflow/index.html + +There are many different ways you can contribute to the Astropy project! + +Report issues +------------- + +Even if you don't have time to contribute code or documentation, please make +sure you report any issues with the package, the documentation, or this +website, to the Astropy `issue tracker`_! + +Contribute code +--------------- + +If you are interested in contributing fixes, code or documentation to Astropy +(whether the core package or affiliated packages), you can join the +`astropy-dev`_ mailing list, and head over to the documentation pages on +`contributing`_ to Astropy. You can either send us a patch, or (preferably) +work on a fork of Astropy and submit the changes via a pull request. + +Develop an affiliated package +----------------------------- + +Whether you have an idea for a new Astronomy package, or already have a +package that you want to integrate with the Astropy project, you can develop +an affiliated package! After joining the `astropy-dev`_ list and notifying +other developers of your intent to develop an affiliated package, you can head +over `here `_ for instructions on +getting started! We can even create a repository for your affiliated package +in the `astropy` organization on GitHub! \ No newline at end of file diff --git a/_sources/development/building_packaging.txt b/_sources/development/building_packaging.txt deleted file mode 100644 index 45b31e82..00000000 --- a/_sources/development/building_packaging.txt +++ /dev/null @@ -1,135 +0,0 @@ -=============================================== -Building, Cython/C Extensions, and Distribution -=============================================== - -The build process currently uses the -`Distribute `_ package to build and -install the astropy core (and any affiliated packages that use the template). -The user doesn't necessarily need to have `distribute` installed, as it will -automatically bootstrap itself using the ``distribute_setup.py`` file in the -source distribution if it isn't installed for the user. - -Customizing setup/build for subpackages ---------------------------------------- - -As is typical, there is a single ``setup.py`` file that's used for the whole -`astropy` package. To customize setup parameters for a given sub-package, a -``setup_package.py`` file can be defined inside a package, and if it is present, -the setup process will look for the following functions to customize the build -process: - -* :func:`get_package_data` - This function, if defined, should return a dictionary mapping the name of - the subpackage(s) that need package data to a list of data file paths - (possibly including wildcards) relative to the path of the package's source - code. e.g. if the source distribution has a needed data file - ``astropy/wcs/tests/data/3d_cd.hdr``, this function should return - ``{'astropy.wcs.tests:'['data/3d_cd.hdr']}``. See the ``package_data`` - option of the :func:`distutils.core.setup` function. - - It is recommended that all such data be in a directory named "data" inside - the package within which it is supposed to be used, and package data should - be accessed via the `astropy.config.data.get_data_filename` and - `astropy.config.data.get_data_fileobj` functions. - -* :func:`get_extensions` - This provides information for building C or Cython extensions. If defined, - it should return a list of `distutils.core.Extension` objects controlling - the Cython/C build process (see below for more detail). - -* :func:`get_legacy_alias` - This function allows for the creation of `shims` that allow a - subpackage to be imported under another name. For example, - `astropy.io.fits` used to be available under the namespace - `pyfits`. For backward compatibility, it is helpful to have it - still importable under the old name. Under most circumstances, - this function should call `astropy.setup_helpers.add_legacy_alias` - to generate a legacy module and then return what it returns. - -The `astropy.setup_helpers` modules includes a :func:`update_package_files` -function which automatically searches the given source path for -``setup_package.py`` modules and calls each of the above functions, if they -exist. This makes it easy for affiliated packages to use this machinery in -their own ``setup.py``. - -.. _building-c-or-cython-extensions: - -C or Cython Extensions ----------------------- - -Astropy supports using C extensions for wrapping C libraries and Cython for -speeding up computationally-intensive calculations. Both Cython and C extension -building can be customized using the :func:`get_extensions` function of the -``setup_package.py`` file. If defined, this function must return a list of -`distutils.core.Extension` objects. The creation process is left to the -subpackage designer, and can be customized however is relevant for the -extensions in the subpackage. - -While C extensions must always be defined through the :func:`get_extensions` -mechanism, Cython files (ending in ``.pyx``) are automatically located and -loaded in separate extensions if they are not in :func:`get_extensions`. For -Cython extensions located in this way, headers for numpy C functions are -included in the build, but no other external headers are included. ``.pyx`` -files present in the extensions returned by :func:`get_extensions` are not -included in the list of extensions automatically generated extensions. Note -that this allows disabling a Cython file by providing an extension that -includes the Cython file, but giving it the special `name` 'cython_skip'. Any -extension with this package name will not be built by ``setup.py``. - -.. note:: - - If an :class:`~distutils.core.Extension` object is provided for Cython - source files using the :func:`get_extensions` mechanism, it is very - important that the ``.pyx`` files be given as the `source`, rather than the - ``.c`` files generated by Cython. - -Installing C header files -````````````````````````` - -If your C extension needs to be linked from other third-party C code, -you probably want to install its header files along side the Python module. - - 1) Create an `include` directory inside of your package for - all of the header files. - - 2) Use the :func:`get_package_data` hook in `setup_package.py` to - install those header files. For example, the `astropy.wcs` - package has this:: - - def get_package_data(): - return {'astropy.wcs': ['include/*.h']} - -Release -------- - -There have been no releases of the core package yet, so this isn't fully -defined. Some important items that are expected to be involved: - -* The release process should be done by automated script. -* Documentation is currently hosted at http://readthedocs.org/docs/astropy, - and tested at https://jenkins.shiningpanda.com/astropy/job/astropy-doc/, - automatically updated with every commit to github master. -* c files generated by Cython should never be stored in source, but instead - generated during the release process. The setup script will always use these - generated c files for release versions (instead of the .pyx Cython file). - -There is a central `setup.py`. It defines which Python packages to -install. Each package does not have its own standalone `setup.py`. - -Each package that needs to build C extensions has a module -`setup_package.py` that contains a function `get_extensions()` which -returns a list of `distutils.core.Extension` objects defining any -extensions to be built. - -There are a set of helper functions for commonly occurring things when -building C extensions (e.g. finding the Numpy headers and library) in -`astropy.setup_helpers`. - -Future directions ------------------ - -We plan to switch to a newer packaging scheme when it's more stable, the -upcoming standard library `packaging` module, derived from the -`distutils2 `_ -project. Until it's working right, however, we will be using `distribute` and -`distutils`. diff --git a/_sources/development/codeguide.txt b/_sources/development/codeguide.txt deleted file mode 100644 index 91dae5ec..00000000 --- a/_sources/development/codeguide.txt +++ /dev/null @@ -1,429 +0,0 @@ -========================= -Coding Guidelines (Draft) -========================= - -.. warning:: - This document is currently in Draft form and is subject to change. - -This section describes requirements and guidelines that affiliated packages -will have to follow before being considered for integration as a module in the -core package. - -Interface and Dependencies --------------------------- - -* The package should meet the interface requirements set out by the - coordination committee. - -* Packages implementing many classes/functions not relevant to the component - requested will not be accepted - the package should only include the - required functionality and relevant extensions. - -* Packages must be compatible with Python 2.6, 2.7, and 3.x (for 3.x - compatibility, the `2to3 tool `_ - will be used). - -* The package should be importable with no dependencies other than components - already in the Astropy core, the `Python Standard Library (v2.6) - `_, NumPy_, SciPy_, - and Matplotlib_ (versions for these packages will be specified in the - Astropy ``setup.py`` file and on PyPI_). - -* The package should be importable from the source tree at build time. - This means that, for example, if the package relies on C extensions - that have yet to be built, the Python code is still importable, even - if none of its functionality will work. - -* Additional dependencies are allowed for sub-modules or in function calls, - but they must be noted in the package documentation and should only affect - the relevant component. - -* General utilities necessary for but not specific to the package should be - placed in the :mod:`packagename.utils` module. These utilities will be moved - to the :mod:`astropy.utils` module when the package is integrated into the - core package. If a utility is already present in :mod:`astropy.utils`, the - package should always use that utility instead of re-implementing it in - :mod:`packagename.utils`. - -Documentation and Testing -------------------------- - -* Docstrings must be present for all public classes/methods/functions, and - must follow the form outlined in the :doc:`docguide` document. - -* Unit tests are encouraged for all public methods and functions, and should - adhere to the standards set in the :doc:`testguide` document. - -Data and Configuration ----------------------- - -* Packages can include data in a directory named `data` inside a subpackage - source directory as long as it is less than about 100 kb. These data should - always be accessed via the :func:`astropy.config.get_data_fileobj` or - :func:`astropy.config.get_data_filename` functions. If the data exceeds this - size, it should be hosted outside the source code repository, either at a - third-party location on the internet or the astropy data server. In either - case, it should always be downloaded using the - :func:`astropy.config.get_data_fileobj` or - :func:`astropy.config.get_data_filename` functions. If a specific version of - a data file is needed, the hash mechanism described in :doc:`/configs` should - be used. - -* All persistent configuration should use the - `astropy.config.ConfigurationItem` mechanism. Such configuration items - should be placed at the top of the module or package that makes use of them, - and supply a description sufficient for users to understand what the setting - changes. - - -Coding Style/Conventions ------------------------- - -* The code will follow the standard `PEP8 Style Guide for Python Code - `_. In particular, this includes - using only 4 spaces for indentation, and never tabs. - -* One exception is to be made from the PEP8 style: new style relative imports - of the form ``from . import modname`` are allowed and required for Astropy, - as opposed to absolute (as PEP8 suggets) or the simpler ``import modname`` - syntax. This is primarily due to improved relative import support since PEP8 - was developed, and to simplify the process of moving modules. - -.. note:: There are multiple options for testing PEP8 compliance of code, - see :doc:`testguide` for more information. - - See :doc:`codeguide_emacs` for some configuration options for - Emacs that helps in ensuring conformance to PEP8. - -* Astropy source code should contain a comment at the beginning of the file (or - imppediately after the ``#!/usr/bin env python`` command, if relevant) - pointing to the license for the Astropy source code. This line should say:: - - # Licensed under a 3-clause BSD style license - see LICENSE.rst - -* The ``import numpy as np``, ``import matplotlib as mpl``, and ``import - matplotlib.pyplot as plt`` naming conventions should be used wherever - relevant. ``from packagename import *`` should never be used, except as a - tool to flatten the namespace of a module. An example of the allowed usage - is given in :ref:`import-star-example`. - -* Classes should either use direct variable access, or python’s property - mechanism for setting object instance variables. ``get_value``/``set_value`` - style methods should be used only when getting and setting the values - requires a computationally-expensive operation. :ref:`prop-get-set-example` - below illustrates this guideline. - -* All new classes should be new-style classes inheriting from :class:`object` - (in Python 3 this is a non-issue as all classes are new-style by default). - The one exception to this rule is older classes in third-party libraries such - the Python standard library or numpy. - -* Classes should use the builtin :func:`super` function when making calls to - methods in their super-class(es) unless there are specific reasons not to. - :func:`super` should be used consistently in all subclasses since it does not - work otherwise. :ref:`super-vs-direct-example` illustrates why this is - important. - -* Multiple inheritance should be avoided in general without good reason. - Mulitple inheritance is complicated to implement well, which is why many - object-oriented languages, like Java, do not allow it at all. Python does - enable multiple inheritance through use of the - `C3 Linearization `_ - algorithm, which provides a consistent method resolution ordering. - Non-trivial multiple-inheritance schemes should not be attempted without - good justification, or without understanding how C3 is used to determine - method resolution order. However, trivial multiple inheritance using - orthogonal base classes, known as the 'mixin' pattern, may be used. - -* ``__init__.py`` files for modules should not contain any significant - implementation code. ``__init__.py`` can contain docstrings and code for - organizing the module layout, however (e.g. ``from submodule import *`` - in accord with the guideline above). If a module is small enough that - it fits in one file, it should simple be a single file, rather than a - directory with an ``__init__.py`` file. - -* When try...except blocks are used to catch exceptions, the ``as`` syntax - should always be used, because this is available in all supported versions of - python and is less ambiguous syntax (see :ref:`try-except-as-example`). - -* Affiliated packages are required to follow the layout and documentation form - of the template package included in the core package source distribution. - -* Command-line scripts should follow the form outlined in the :doc:`scripts` - document. - -Including C Code ----------------- - -* C extensions are only allowed when they provide a significant performance - enhancement over pure python, or a robust C library already exists to - provided the needed functionality. When C extensions are used, the Python - interface must meet the aforementioned python interface guidelines. - -* The use of Cython_ is strongly recommended for C extensions, as per the - example in the template package. Cython_ extensions should store ``.pyx`` - files in the source code repository, but they should be compiled to ``.c`` - files that are updated in the repository when important changes are made to - the ``.pyx`` file. - -* If a C extension has a dependency on an external C library, the source code - for the library should be bundled with the Astropy core, provided the - license for the C library is compatible with the Astropy license. - Additionally, the package must be compatible with using a system-installed - library in place of the library included in Astropy. - -* In cases where C extensions are needed but Cython_ cannot be used, the `PEP 7 - Style Guide for C Code `_ is - recommended. - -* C extensions (Cython_ or otherwise) should provide the necessary information - for building the extension via the mechanisms described in - :ref:`building-c-or-cython-extensions`. - -Requirements Specific to Affiliated Packages --------------------------------------------- - -* Affiliated packages must be registered on the `Python Package Index - `_, with proper metadata for downloading and - installing the source package. - -* The :mod:`astropy` root package name should not be used by affiliated - packages - it is reserved for use by the core package. Recommended naming - conventions for an affiliated package are either simply :mod:`packagename` - or :mod:`awastropy.packagename` ("affiliated with Astropy"). - -Examples --------- - -This section shows a few examples (not all of which are correct!) to -illustrate points from the guidelines. These will be moved into the template -project once it has been written. - -.. _prop-get-set-example: - -Properties vs. get\_/set\_ -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This example shows a sample class illustrating the guideline regarding the use -of properties as opposed to getter/setter methods. - -Let's assuming you've defined a :class:`Star` class and create an instance -like this:: - - >>> s = Star(B=5.48, V=4.83) - -You should always use attribute syntax like this:: - - >>> s.color = 0.4 - >>> print s.color - 0.4 - -Rather than like this:: - - >>> s.set_color(0.4) #Bad form! - >>> print s.get_color() #Bad form! - 0.4 - -Using python properties, attribute syntax can still do anything possible with -a get/set method. For lengthy or complex calculations, however, use a method:: - - >>> print s.compute_color(5800, age=5e9) - 0.4 - -.. _super-vs-direct-example: - -super() vs. Direct Calling -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This example shows why the use of :func:`super` leads to a more consistent -method resolution order than manually calling methods of the super classes in a -multiple inheritance case:: - - # This is dangerous and bug-prone! - - class A(object): - def method(self): - print 'Doing A' - - - class B(A): - def method(self): - print 'Doing B' - A.method(self) - - - class C(A): - def method(self): - print 'Doing C' - A.method(self) - - class D(C, B): - def method(self): - print 'Doing D' - C.method(self) - B.method(self) - -if you then do:: - - >>> b = B() - >>> b.method() - -you will see:: - - Doing B - Doing A - -which is what you expect, and similarly for C. However, if you do:: - - >>> d = D() - >>> d.method() - -you might expect to see the methods called in the order D, B, C, A but instead -you see:: - - Doing D - Doing C - Doing A - Doing B - Doing A - - -because both ``B.method()`` and ``C.method()`` call ``A.method()`` unaware of -the fact that they're being called as part of a chain in a hierarchy. When -``C.method()`` is called it is unaware that it's being called from a subclass -that inherts from both ``B`` and ``C``, and that ``B.method()`` should be -called next. By calling :func:`super` the entire method resolution order for -``D`` is precomputed, enabling each superclass to cooperatively determine which -class should be handed control in the next :func:`super` call:: - - # This is safer - - class A(object): - def method(self): - print 'Doing A' - - class B(A): - def method(self): - print 'Doing B' - super(B, self).method() - - - class C(A): - def method(self): - print 'Doing C' - super(C, self).method() - - class D(C, B): - def method(self): - print 'Doing D' - super(D, self).method() - -:: - - >>> d = D() - >>> d.method() - Doing D - Doing C - Doing B - Doing A - -As you can see, each superclass's method is entered only once. For this to -work it is very important that each method in a class that calls its -superclass's version of that method use :func:`super` instead of calling the -method directly. In the most common case of single-inheritance, using -``super()`` is functionally equivalent to calling the superclass's method -directly. But as soon as a class is used in a multiple-inheritance -hierarchy it must use ``super()`` in order to cooperate with other classes in -the hierarchy. - -.. note:: For more info on the pros and cons of using super, see - http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ - or http://keithdevens.com/weblog/archive/2011/Mar/16/Python.super) - -.. _import-star-example: - -Acceptable use of ``from module import *`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``from module import *`` is discouraged in a module that contains -implementation code, as it impedes clarity and often imports unused variables. -It can, however, be used for a package that is laid out in the following -manner:: - - packagename - packagename/__init__.py - packagename/submodule1.py - packagename/submodule2.py - -In this case, ``packagename/__init__.py`` may be:: - - """ - A docstring describing the package goes here - """ - from submodule1 import * - from submodule2 import * - -This allows functions or classes in the submodules to be used directly as -``packagename.foo`` rather than ``packagename.submodule1.foo``. If this is -used, it is strongly recommended that the submodules make use of the __all__ -variable to specify which modules should be imported. Thus, submodule2.py -might read:: - - from numpy import array,linspace - - __all__ = ('foo','AClass') - - def foo(bar): - #the function would be defined here - pass - - class AClass(object): - #the class is defined here - pass - -This ensures that ``from submodule import *`` only imports :func:`foo` and -:class:`AClass`, but not :class:`numpy.array` or :func:`numpy.linspace`. - -.. _try-except-as-example: - -try...except block "as" syntax -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Catching of exceptions should always use this syntax:: - - try: - ... some code that might produce a variety of exceptions ... - except ImportError as e: - if 'somemodule' in e.args[0]" - #for whatever reason, failed import of somemodule is ok - pass - else: - raise - except ValueError, TypeError as e: - msg = 'Hit an input problem, which is ok,' - msg2 = 'but we're printing it here just so you know:' - print msg, msg2, e - -This avoids the old style syntax of ``except ImportError, e`` or -``except (ValueError,TypeError), e``, which is dangerous because it's easy to -instead accidentally do something like ``except ValueError,TypeError``, which -won't catch `TypeError`. - - -Additional Resources --------------------- - -Further tips and hints relating to the coding guidelines are included below. - -.. toctree:: - :maxdepth: 1 - - codeguide_emacs - - - -.. _Numpy: http://numpy.scipy.org/ -.. _Scipy: http://www.scipy.org/ -.. _matplotlib: http://matplotlib.sourceforge.net/ -.. _Cython: http://cython.org/ -.. _PyPI: http://pypi.python.org/pypi diff --git a/_sources/development/codeguide_emacs.txt b/_sources/development/codeguide_emacs.txt deleted file mode 100644 index 0a071a31..00000000 --- a/_sources/development/codeguide_emacs.txt +++ /dev/null @@ -1,203 +0,0 @@ -============================================= - Emacs setup for following coding guidelines -============================================= - -.. _flymake: http://www.emacswiki.org/emacs/FlyMake -.. _pyflakes: http://pypi.python.org/pypi/pyflakes -.. _pep8: http://pypi.python.org/pypi/pep8 - -The Astropy coding guidelines are listed in :doc:`codeguide`. This -document will describe some configuration options for Emacs, that will -help in ensuring that Python code satisfies the guidelines. Emacs can -be configured in several different ways. So instead of providing a drop -in configuration file, only the individual configurations are presented -below. - -For this setup we will need flymake_, pyflakes_ and the pep8_ Python -script, in addition to `python-mode`. - -Flymake comes with Emacs 23. The rest can be obtained from their -websites, or can be installed using `easy_install` or `pip`. - -Global settings -=============== - -No tabs -------- - -This setting will cause all tabs to be replaced with spaces. The number -of spaces to use is set in the :ref:`basic settings` section below. - -.. code-block:: scheme - - ;; Don't use TABS for indentations. - (setq-default indent-tabs-mode nil) - -Maximum number of characters in a line --------------------------------------- - -Emacs will automatically insert a new line after "fill-column" number -of columns. PEP8 specifies a maximum of 79, but this can be set to a -smaller value also, for example 72. - -.. code-block:: scheme - - ;; Set the number to the number of columns to use. - (setq-default fill-column 79) - - ;; Add Autofill mode to mode hooks. - (add-hook 'text-mode-hook 'turn-on-auto-fill) - - ;; Show line number in the mode line. - (line-number-mode 1) - - ;; Show column number in the mode line. - (column-number-mode 1) - -Syntax highlighting -------------------- - -Enable syntax highlighting. This will also highlight lines that form a -region. - -.. code-block:: scheme - - (global-font-lock-mode 1) - -Python specific settings -======================== - -.. _`basic settings`: - -Basic settings --------------- - -Indentation is automatically added. When a tab is pressed it is -replaced with 4 spaces. When backspace is pressed on an empty line, the -cursor will jump to the previous indentation level. - -.. code-block:: scheme - - (load-library "python") - - (autoload 'python-mode "python-mode" "Python Mode." t) - (add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)) - (add-to-list 'interpreter-mode-alist '("python" . python-mode)) - - (setq interpreter-mode-alist - (cons '("python" . python-mode) - interpreter-mode-alist) - python-mode-hook - '(lambda () (progn - (set-variable 'py-indent-offset 4) - (set-variable 'indent-tabs-mode nil)))) - -Highlight the column where a line must stop -------------------------------------------- - -The "fill-column" column is highlighted in red. For this to work, -download `column-marker.el -`_ and place it in the -Emacs configuration directory. - -.. code-block:: scheme - - ;; Highlight character at "fill-column" position. - (require 'column-marker) - (set-face-background 'column-marker-1 "red") - (add-hook 'python-mode-hook - (lambda () (interactive) - (column-marker-1 fill-column))) - -Flymake -------- - -Flymake will mark lines that do not satisfy syntax requirements in -red. When cursor is on such a line a message is displayed in the -mini-buffer. When mouse pointer is on such a line a "tool tip" message -is also shown. - -For flymake to work with `pep8` and `pyflakes`, create an -executable file named `pychecker` with the following contents. This -file must be in the system path. - -.. code-block:: sh - - #!/bin/bash - - pyflakes "$1" - pep8 --ignore=E221,E701,E202 --repeat "$1" - true - -Add the following code to Emacs configurations. - -.. code-block:: scheme - - ;; Setup for Flymake code checking. - (require 'flymake) - (load-library "flymake-cursor") - - ;; Script that flymake uses to check code. This script must be - ;; present in the system path. - (setq pycodechecker "pychecker") - - (when (load "flymake" t) - (defun flymake-pycodecheck-init () - (let* ((temp-file (flymake-init-create-temp-buffer-copy - 'flymake-create-temp-inplace)) - (local-file (file-relative-name - temp-file - (file-name-directory buffer-file-name)))) - (list pycodechecker (list local-file)))) - (add-to-list 'flymake-allowed-file-name-masks - '("\\.py\\'" flymake-pycodecheck-init))) - - (add-hook 'python-mode-hook 'flymake-mode) - -.. note:: - - Flymake will save files with suffix *_flymake* in the current - directory. If it crashes for some reason, then these files will not - get deleted. - - Sometimes there is a delay in refreshing the results. - -Delete trailing white spaces and blank lines --------------------------------------------- - -To manually delete trailing whitespaces, press `C-t C-w`, which will -run the command "delete-whitespaces`. This command is also run when a -file is saved, and hence all trailing whitespaces will be deleted on -saving a Python file. - -To make sure that all "words" are separated by only one space, type -`M-SPC` (use the ALT key since `M-SPC` sometimes brings up a context -menu.). - -To collapse a set of blank lines to one blank line, place the cursor on -one of these and press `C-x C-o`. This is useful for deleting multiple -black lines at the end of a file. - -.. code-block:: scheme - - ;; Remove trailing whitespace manually by typing C-t C-w. - (add-hook 'python-mode-hook - (lambda () - (local-set-key (kbd "C-t C-w") - 'delete-trailing-whitespace))) - - ;; Automatically remove trailing whitespace when file is saved. - (add-hook 'python-mode-hook - (lambda() - (add-hook 'local-write-file-hooks - '(lambda() - (save-excursion - (delete-trailing-whitespace)))))) - - ;; Use M-SPC (use ALT key) to make sure that words are separated by - ;; just one space. Use C-x C-o to collapse a set of empty lines - ;; around the cursor to one empty line. Useful for deleting all but - ;; one blank line at end of file. To do this go to end of file (M->) - ;; and type C-x C-o. - -.. LocalWords: whitespaces diff --git a/_sources/development/docguide.txt b/_sources/development/docguide.txt deleted file mode 100644 index 83b6800a..00000000 --- a/_sources/development/docguide.txt +++ /dev/null @@ -1,587 +0,0 @@ -================================ -Documentation Guidelines (Draft) -================================ - -.. warning:: - This document is currently in Draft form and is subject to change. - -TODO: Detailed information about building the documentation should be -added here. - -Astropy Documentation Rules and Recommendations ------------------------------------------------ - -This section describes the standards for documentation format affiliated -packages that must follow for consideration of integration into the core -module, as well as the standard Astropy docstring format. - -* Documentation shall use the Sphinx documentation tool. - -* The template package will provide a recommended general structure for - documentation. - -* Docstrings must be provided for all public classes, methods, and functions. - -* Docstrings will be incorporated into the documentation using a version of - numpydoc included with Astropy, and should follow the NumPy_/SciPy_ - docstring standards, included below. - -* Examples and/or tutorials are strongly encouraged for typical use-cases of a - particular module or class. - -* Any external package dependencies aside from NumPy_, SciPy_, or Matplotlib_ - must be explicitly mentioned in the documentation. - -* Configuration options using the :mod:`astropy.config` mechanisms must be - explicitly mentioned in the documentation. - -NumPy/SciPy Docstring Rules ---------------------------- - -The original source for these docstring standards is the NumPy_ project, and -the associated numpydoc_ tools. The most up-to-date version of these standards -can be found at `numpy's github site -`_. The -guidelines below have been adapted to the Astropy pacakge. - -.. _NumPy: http://numpy.scipy.org/ -.. _numpydoc: http://pypi.python.org/pypi/numpydoc/0.3.1 -.. _Matplotlib: http://matplotlib.sourceforge.net/ - -Overview -^^^^^^^^ - -In general, we follow the standard Python style conventions as described here: - - * `Style Guide for C Code `_ - * `Style Guide for Python Code `_ - * `Docstring Conventions `_ - -Additional PEPs of interest regarding documentation of code: - - * `Docstring Processing Framework `_ - * `Docutils Design Specification `_ - -Use a code checker: - - * `pylint `_ - * `pyflakes `_ - * `pep8.py `_ - -The following import conventions are used throughout the Astropy source -and documentation:: - - import numpy as np - import matplotlib as mpl - import matplotlib.pyplot as plt - -Do not abbreviate ``scipy``. There is no motivating use case to abbreviate -it in the real world, so we avoid it in the documentation to avoid -confusion. - -It is not necessary to do ``import numpy as np`` at the beginning of -an example. However, some sub-modules, such as ``fft``, are not -imported by default, and you have to include them explicitly:: - - import numpy.fft - -after which you may use it:: - - np.fft.fft2(...) - -Docstring Standard -^^^^^^^^^^^^^^^^^^ - -A documentation string (docstring) is a string that describes a module, -function, class, or method definition. The docstring is a special attribute -of the object (``object.__doc__``) and, for consistency, is surrounded by -triple double quotes, i.e.:: - - """This is the form of a docstring. - - It can be spread over several lines. - - """ - -NumPy_ and SciPy_ have defined a common convention for docstrings that -provides for consistency, while also allowing our toolchain to produce -well-formatted reference guides. This format should be used for Astropy -docstrings. - -This docstring standard uses `re-structured text (reST) -`_ syntax and is rendered -using Sphinx_ (a pre-processor that understands the particular -documentation style we are using). While a rich set of markup is -available, we limit ourselves to a very basic subset, in order to -provide docstrings that are easy to read on text-only terminals. - -A guiding principle is that human readers of the text are given -precedence over contorting docstrings so our tools produce nice output. -Rather than sacrificing the readability of the docstrings, we have -written pre-processors to assist Sphinx_ in its task. - -The length of docstring lines should be kept to 75 characters to -facilitate reading the docstrings in text terminals. - -Sections -^^^^^^^^ - -The sections of the docstring are: - -1. **Short summary** - - A one-line summary that does not use variable names or the function - name, e.g. - - :: - - def add(a, b): - """The sum of two numbers. - - """ - - The function signature is normally found by introspection and - displayed by the help function. For some functions (notably those - written in C) the signature is not available, so we have to specify - it as the first line of the docstring:: - - """ - add(a, b) - - The sum of two numbers. - - """ - -2. **Deprecation warning** - - A section (use if applicable) to warn users that the object is deprecated. - Section contents should include: - - * In what Astropy version the object was deprecated, and when it will - be removed. - - * Reason for deprecation if this is useful information (e.g., object - is superseded, duplicates functionality found elsewhere, etc.). - - * New recommended way of obtaining the same functionality. - - This section should use the note Sphinx directive instead of an - underlined section header. - - :: - - .. note:: Deprecated in Astropy 1.2 - `ndobj_old` will be removed in Astropy 2.0, it is replaced by - `ndobj_new` because the latter works also with array subclasses. - -3. **Extended summary** - - A few sentences giving an extended description. This section should be used - to clarify *functionality*, not to discuss implementation detail or - background theory, which should rather be explored in the **notes** section - below. You may refer to the parameters and the function name, but parameter - descriptions still belong in the **parameters** section. - -4. **Parameters** - - Description of the function arguments, keywords and their respective types. - - :: - - Parameters - ---------- - x : type - Description of parameter `x`. - - Enclose variables in single backticks. - - For the parameter types, be as precise as possible. Below are a few - examples of parameters and their types. - - :: - - Parameters - ---------- - filename : str - copy : bool - dtype : data-type - iterable : iterable object - shape : int or tuple of int - files : list of str - - If it is not necessary to specify a keyword argument, use ``optional``:: - - x : int, optional - - Optional keyword parameters have default values, which are displayed as - part of the function signature. They can also be detailed in the - description:: - - Description of parameter `x` (the default is -1, which implies summation - over all axes). - - When a parameter can only assume one of a fixed set of values, those values - can be listed in braces:: - - order : {'C', 'F', 'A'} - Description of `order`. - - When two or more input parameters have exactly the same type, shape and - description, they can be combined:: - - x1, x2 : array_like - Input arrays, description of `x1`, `x2`. - -5. **Returns** - - Explanation of the returned values and their types, of the same format as - **parameters**. - -6. **Other parameters** - - An optional section used to describe infrequently used parameters. It - should only be used if a function has a large number of keyword parameters, - to prevent cluttering the **parameters** section. - -7. **Raises** - - An optional section detailing which errors get raised and under what - conditions:: - - Raises - ------ - InvalidWCSException - If the WCS information is invalid. - - This section should be used judiciously, i.e only for errors that are - non-obvious or have a large chance of getting raised. - -8. **See Also** - - An optional section used to refer to related code. This section can be very - useful, but should be used judiciously. The goal is to direct users to - other functions they may not be aware of, or have easy means of discovering - (by looking at the module docstring, for example). Routines whose - docstrings further explain parameters used by this function are good - candidates. - - As an example, for a hypothetical function ``astropy.wcs.sky2pix`` - converting sky to pixel coordinates, we would have:: - - See Also - -------- - pix2sky : Convert pixel to sky coordinates - - When referring to functions in the same sub-module, no prefix is needed, - and the tree is searched upwards for a match. - - Prefix functions from other sub-modules appropriately. E.g., whilst - documenting a hypothetical ``astropy.vo`` module, refer to a function in - ``table`` by - - :: - - table.read : Read in a VO table - - When referring to an entirely different module:: - - astropy.coords : Coordinate handling routines - - Functions may be listed without descriptions, and this is preferable if the - functionality is clear from the function name:: - - See Also - -------- - func_a : Function a with its description. - func_b, func_c_, func_d - func_e - -9. **Notes** - - An optional section that provides additional information about the code, - possibly including a discussion of the algorithm. This section may include - mathematical equations, written in `LaTeX `_ - format:: - - The FFT is a fast implementation of the discrete Fourier transform: - - .. math:: X(e^{j\omega } ) = x(n)e^{ - j\omega n} - - Equations can also be typeset underneath the math directive:: - - The discrete-time Fourier time-convolution property states that - - .. math:: - - x(n) * y(n) \Leftrightarrow X(e^{j\omega } )Y(e^{j\omega } )\\ - another equation here - - Math can furthermore be used inline, i.e. - - :: - - The value of :math:`\omega` is larger than 5. - - Variable names are displayed in typewriter font, obtained by using - ``\mathtt{var}``:: - - We square the input parameter `alpha` to obtain - :math:`\mathtt{alpha}^2`. - - Note that LaTeX is not particularly easy to read, so use equations - sparingly. - - Images are allowed, but should not be central to the explanation; users - viewing the docstring as text must be able to comprehend its meaning - without resorting to an image viewer. These additional illustrations are - included using:: - - .. image:: filename - - where filename is a path relative to the reference guide source directory. - -10. **References** - - References cited in the **notes** section may be listed here, - e.g. if you cited the article below using the text ``[1]_``, - include it as in the list as follows:: - - .. [1] O. McNoleg, "The integration of GIS, remote sensing, - expert systems and adaptive co-kriging for environmental habitat - modelling of the Highland Haggis using object-oriented, fuzzy-logic - and neural-network techniques," Computers & Geosciences, vol. 22, - pp. 585-588, 1996. - - which renders as - - .. [1] O. McNoleg, "The integration of GIS, remote sensing, - expert systems and adaptive co-kriging for environmental habitat - modelling of the Highland Haggis using object-oriented, fuzzy-logic - and neural-network techniques," Computers & Geosciences, vol. 22, - pp. 585-588, 1996. - - Referencing sources of a temporary nature, like web pages, is discouraged. - References are meant to augment the docstring, but should not be required - to understand it. References are numbered, starting from one, in the order - in which they are cited. - -11. **Examples** - - An optional section for examples, using the `doctest - `_ format. This section - is meant to illustrate usage, not to provide a testing framework -- for - that, use the ``tests/`` directory. While optional, this section is very - strongly encouraged. - - When multiple examples are provided, they should be separated by blank - lines. Comments explaining the examples should have blank lines both above - and below them:: - - >>> astropy.wcs.sky2pix(233.2, -12.3) - (134.5, 233.1) - - Comment explaining the second example - - >>> astropy.coords.fk5_to_gal("00:42:44.33 +41:16:07.5") - (121.1743, -21.5733) - - For tests with a result that is random or platform-dependent, mark the - output as such:: - - >>> astropy.coords.randomize_position(244.9, 44.2, radius=0.1) - (244.855, 44.13) #random - - You can run examples using:: - - >>> astropy.test(doctests=True) - - It is not necessary to use the doctest markup ```` to indicate - empty lines in the output. Note that the option to run the examples through - ``numpy.test`` is provided for checking if the examples work, not for - making the examples part of the testing framework. - - The examples may assume that ``import numpy as np`` is executed before the - example code Additional examples may make use of *matplotlib* - for plotting, but should import it explicitly, e.g., ``import - matplotlib.pyplot as plt``. - -Documenting classes -^^^^^^^^^^^^^^^^^^^ - -Class docstrings -```````````````` - -Use the same sections as outlined above (all except ``Returns`` are -applicable). The constructor (``__init__``) should also be documented here, -the **parameters** section of the docstring details the constructors -parameters. - -An ``Attributes`` section, located below the **parameters** section, may be -used to describe class variables:: - - Attributes - ---------- - x : float - The X coordinate. - y : float - The Y coordinate. - -Attributes that are properties and have their own docstrings can be simply -listed by name:: - - Attributes - ---------- - real - imag - x : float - The X coordinate - y : float - The Y coordinate - -In general, it is not necessary to list class methods. Those that are not part -of the public API have names that start with an underscore. In some cases, -however, a class may have a great many methods, of which only a few are -relevant (e.g., subclasses of ndarray). Then, it becomes useful to have an -additional ``Methods`` section:: - - class Table(ndarray): - """ - A class to represent tables of data - - ... - - Attributes - ---------- - columns : list - List of columns - - Methods - ------- - read(filename) - Read a table from a file - sort(column, order='ascending') - Sort by `column` - """ - -If it is necessary to explain a private method (use with care!), it can be -referred to in the **extended summary** or the **notes**. Do not list private -methods in the Methods section. - -Note that ``self`` is *not* listed as the first parameter of methods. - -Method docstrings -````````````````` - -Document these as you would any other function. Do not include ``self`` in the -list of parameters. If a method has an equivalent function (which is the case -for many ndarray methods for example), the function docstring should contain -the detailed documentation, and the method docstring should refer to it. Only -put brief summary and See Also sections in the method docstring. - -Documenting class instances -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Instances of classes that are part of the Astropy API may require some care. -To give these instances a useful docstring, we do the following: - -* Single instance: If only a single instance of a class is exposed, document - the class. Examples can use the instance name. - -* Multiple instances: If multiple instances are exposed, docstrings for each - instance are written and assigned to the instances' ``__doc__`` attributes - at run time. The class is documented as usual, and the exposed instances can - be mentioned in the Notes and See Also sections. - -Documenting constants -^^^^^^^^^^^^^^^^^^^^^ - -Use the same sections as outlined for functions where applicable:: - - 1. summary - 2. extended summary (optional) - 3. see also (optional) - 4. references (optional) - 5. examples (optional) - -Docstrings for constants will not be visible in text terminals -(constants are of immutable type, so docstrings can not be assigned -to them like for for class instances), but will appear in the -documentation built with Sphinx. - -Documenting modules -^^^^^^^^^^^^^^^^^^^ - -Each module should have a docstring with at least a summary line. Other -sections are optional, and should be used in the same order as for documenting -functions when they are appropriate:: - - 1. summary - 2. extended summary - 3. routine listings - 4. see also - 5. notes - 6. references - 7. examples - -Routine listings are encouraged, especially for large modules, for which it is -hard to get a good overview of all functionality provided by looking at the -source file(s) or the __all__ dict. - -Note that license and author info, while often included in source files, do not -belong in docstrings. - -Other points to keep in mind -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -* Notes and Warnings : If there are points in the docstring that deserve - special emphasis, the reST directives for a note or warning can be used - in the vicinity of the context of the warning (inside a section). Syntax: - - :: - - .. warning:: Warning text. - - .. note:: Note text. - - Use these sparingly, as they do not look very good in text terminals - and are not often necessary. One situation in which a warning can - be useful is for marking a known bug that is not yet fixed. - -* Questions and Answers : For general questions on how to write docstrings - that are not answered in this document, refer to - ``_. - -* array_like : For functions that take arguments which can have not only - a type `ndarray`, but also types that can be converted to an ndarray - (i.e. scalar types, sequence types), those arguments can be documented - with type `array_like`. - -Common reST concepts -^^^^^^^^^^^^^^^^^^^^ - -For paragraphs, indentation is significant and indicates indentation in the -output. New paragraphs are marked with a blank line. - -Use *italics*, **bold**, and ``courier`` if needed in any explanations (but -not for variable names and doctest code or multi-line code). Variable, module -and class names should be written between single back-ticks (```astropy```). - -A more extensive example of reST markup can be found in `this example document -`_; the `quick -reference `_ is -useful while editing. - -Line spacing and indentation are significant and should be carefully followed. - -Conclusion -^^^^^^^^^^ - -`An example `_ of the -format shown here is available. Refer to `How to Build API/Reference -Documentation -`_ -on how to use Sphinx_ to build the manual. - -.. _SciPy: http://www.scipy.org -.. _numpy-discussion list: http://www.scipy.org/Mailing_Lists -.. _Sphinx: http://sphinx.pocoo.org diff --git a/_sources/development/index.txt b/_sources/development/index.txt deleted file mode 100644 index 5775acb7..00000000 --- a/_sources/development/index.txt +++ /dev/null @@ -1,19 +0,0 @@ -.. _developer-docs: - -Documentation for Developers -============================ - -The information in the following pages are relevant for anyone interesting in -contributing to Astropy. In addition, the :doc:`../overview` is a useful guide -to the layout of the `astropy` package. - -.. toctree:: - :maxdepth: 1 - - vision - workflow/index - codeguide - docguide - testguide - building_packaging - scripts diff --git a/_sources/development/scripts.txt b/_sources/development/scripts.txt deleted file mode 100644 index 88301ee9..00000000 --- a/_sources/development/scripts.txt +++ /dev/null @@ -1,63 +0,0 @@ -============================ -Writing Command-Line Scripts -============================ - -Command-line scripts in Astropy should follow a consistent scheme to promote -readability and compatibility. - -The actual script should be in the ``/scripts`` directory of the Astropy -source distribution, and should do nothing aside from importing a ``main`` -function from astropy and execute it. This is partly necessary because the -"2to3" utility that converts python 2.x code to 3.x does not convert scripts. -These scripts should be executable, include ``#!/usr/bin/env python`` at the -top, and should *not* end in ``.py``. - -The ``main`` functions these scripts call should accept an optional single -argument that holds the ``sys.argv`` list, except for the script name -(e.g., ``argv[1:]``). This function can live in its own module, or be part of a -larger module that implements a class or function for astropy library use. The -``main`` function should do very little actual work - it should only parse the -arguments and pass those arguments on to some library function so that the -library function can be used programmatically when needed. -Command-line options can be parsed however desired, but the :mod:`argparse` -module is recommended when possible, due to its simpler and more flexible -interface relative to the older :mod:`optparse`. :mod:`argparse` is only -available in python >=2.7 and >=3.2, however, so it should be imported as -``from astropy.util.compat import argparse`` . - - -Example -------- - -Contents of ``/scripts/cmdlinescript`` :: - - #!/usr/bin/env python - # -*- coding: utf-8 -*- - """An astropy command-line script""" - - import astropy.somepackage.somemod - - astropy.somepackage.somemod.main() - -Contents of ``/astropy/somepackage/somemod.py`` :: - - def do_something(args, option=False): - for a in args: - if option: - ...do something... - else: - ...do something else... - - def main(args=None): - from astropy.utils.compat import argparse - - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('-o', '--option', dest='op',action='store_true', - help='Some option that turns something on.') - parser.add_argument('stuff', metavar='S', nargs='+', - help='Some input I should be able to get lots of.') - - res = parser.parse_args(args) - - do_something(res.stuff,res.op) - diff --git a/_sources/development/testguide.txt b/_sources/development/testguide.txt deleted file mode 100644 index 89c8770d..00000000 --- a/_sources/development/testguide.txt +++ /dev/null @@ -1,444 +0,0 @@ -.. _testing-guidelines: - -========================== -Testing Guidelines (Draft) -========================== - -.. warning:: - This document is currently in Draft form and is subject to change. Not all - described functionality may be implemented. - -This section describes the testing framework and format standards for tests in -Astropy core packages (this also serves as recommendations for affiliated -packages). - -Testing Framework -================= - -The testing framework used by Astropy is the `py.test `_ -framework. - -.. _running-tests: - -Running Tests -============= - -There are currently three different ways to invoke Astropy tests. Each method -invokes py.test to run the tests but offers different options when calling. - -In addition to running the Astropy tests, these methods can also be called so -that they check Python source code for -`PEP8 compliance `_. All of the PEP8 -testing options require the -`pytest-pep8 plugin `_, which must be -installed separately. - -setup.py test -------------- - -The safest way to run the astropy test suite is via the setup command ``test``. -This is invoked by running ``python setup.py test`` while in the astropy source -code directory. Run ``python setup.py test --help`` to see the options to the -test command. - -Turn on PEP8 checking by passing ``--pep8`` to the ``test`` command. This will -turn off regular testing and enable PEP8 testing. - -.. note:: - This method of running the tests defaults to the version of `py.test` that - is bundled with Astropy. To use the locally-installed version, you should - either change the `use_system_pytest` configuration option to "True" - (see :doc:`../../configs`) or the `py.test` method describe below. - -py.test -------- - -An alternative way to run tests from the command line is to switch to the source -code directory of astropy and simply type:: - - py.test - -``py.test`` will look for files that `look like tests -`_ -in the currect directory and all recursive directories then run all the code that -`looks like tests -`_ -within those files. - -.. note:: - To test any compiled C/Cython extensions, you must either have run - ``python setup.py test`` or ``python setup.py develop`` prior to running - the py.test command-line script. Otherwise, any tests that make use of - these extensions will not succeed. Similarly, in python 3, these tests - will not run correctly in the source code, because they need the ``2to3`` - tool to be run on them. - - -You may specify a specific test file or directory at the command line:: - - py.test test_file.py - -To run a specific test within a file use the ``-k`` option:: - - py.test test_file.py -k "test_function" - -You may also use the ``-k`` option to not run tests py putting a ``-`` in front -of the matching string:: - - py.test test_file.py -k "-test_function" - -py.test has a number of `command line usage options. -`_ - -Turn on PEP8 testing by adding the ``--pep8`` flag to the ``py.test`` call. By -default regular tests will also be run but these can be turned off by adding -``-k pep8``:: - - py.test some_dir --pep8 -k pep8 - -.. note:: - This method of running the tests uses the locally-installed version of - `py.test` rather than the bundled one, and hence will fail if the local - version it is not up-to-date enough (`py.test` 2.2 as of this writing). - -astropy.test() --------------- - -AstroPy includes a standalone version of py.test that allows to tests -to be run even if py.test is not installed. Tests can be run from within -AstroPy with:: - - import astropy - astropy.test() - -This will run all the default tests for AstroPy. - -Tests for a specific package can be run by specifying the package in the call -to the ``test()`` function:: - - astropy.test('io.fits') - -This method works only with package names that can be mapped to Astropy -directories. As an alternative you can test a specific directory or file -with the ``test_path`` option:: - - astropy.test(test_path='wcs/tests/test_wcs.py') - -The ``test_path`` must be specified either relative to the working directory -or absolutely. - -By default ``astropy.test()`` will skip tests which retrieve data from the -internet. To turn these tests on use the ``remote_data`` flag:: - - astropy.test('io.fits',remote_data=True) - -In addition, the ``test`` function supports any of the options that can be -passed to `pytest.main() `_, -and convenience options ``verbose=`` and ``pastebin=``. - -Enable PEP8 compliance testing with ``pep8=True`` in the call to -``astropy.test``. This will enable PEP8 checking and disable regular tests. - -.. note:: - This method of running the tests defaults to the version of `py.test` that - is bundled with Astropy. To use the locally-installed version, you should - either change the `use_system_pytest` configuration option to "True" - (see :doc:`../../configs`) or the `py.test` method describe above. - -Regression tests -================ - -Any time a bug is fixed, and wherever possible, one or more regression tests -should be added to ensure that the bug is not introduced in future. Regression -tests should include the ticket URL where the bug was reported. - -Where to put tests -================== - -Package-specific tests ----------------------- - -Each package should include a suite of unit tests, covering as many of the -public methods/functions as possible. These tests should be included inside -each sub-package, either in a `tests` directory, or in a test.py file, e.g:: - - astropy/io/fits/tests/ - -or:: - - astropy/io/fits/test.py - -``tests`` directories should contain an ``__init__.py`` file so that the tests -can be imported and so that they can use relative imports. - -Interoperability tests ----------------------- - -Tests involving two or more sub-packages should be included in:: - - astropy/tests/ - -and using:: - - astropy.test() - -then runs both these interoperability tests, and all the unit tests in the -sub-packages. This functionality is especially important for people who install -packages through bundles and package managers, where the original source code -for the tests is not immediately available. - - -Writing tests -============= - -``py.test`` has the following test discovery rules: - - * ``test_*.py`` or ``*_test.py`` files - * ``Test`` prefixed classes (without an ``__init__`` method) - * ``test_`` prefixed functions and methods - -Consult the `test discovery rules -`_ -for detailed information on how to name files and tests so that they are -automatically discovered by ``py.test``. - -Simple example --------------- - -The following example shows a simple function and a test to test this -function:: - - def func(x): - return x + 1 - - def test_answer(): - assert func(3) == 5 - -If we place this in a ``test.py`` file and then run:: - - py.test test.py - -The result is:: - - ============================= test session starts ============================== - python: platform darwin -- Python 2.7.2 -- pytest-1.1.1 - test object 1: /Users/tom/tmp/test.py - - test.py F - - =================================== FAILURES =================================== - _________________________________ test_answer __________________________________ - - def test_answer(): - > assert func(3) == 5 - E assert 4 == 5 - E + where 4 = func(3) - - test.py:5: AssertionError - =========================== 1 failed in 0.07 seconds =========================== - -Working with data files ------------------------ - -Tests that need to make use of a data file should use the -`~astropy.config.data.get_data_fileobj` or -`~astropy.config.data.get_data_filename` functions. These functions search -locally first, and then on the astropy data server or an arbitrary URL, and -return a file-like object or a local filename, respectively. They automatically -cache the data locally if remote data is obtained, and from then on the local -copy will be used transparently. - -They also support the use of an MD5 hash to get a specific version of a data -file. This hash can be obtained prior to submitting a file to the astropy -data server by using the `~astropy.config.data.compute_hash` function on a -local copy of the file. - -Tests that may retrieve remote data should be marked with the ``@remote_data`` -decorator. Tests marked with this decorator will be skipped by default by -``astropy.test()`` to prevent test runs from taking too long. These tests can -be run by ``astropy.test()`` by adding the ``remote_data=True`` flag. -Turn on the remote data tests at the command line with -``py.test --remote-data``. - -Examples -^^^^^^^^ -:: - - from ...config import get_data_filename - from ...tests.helper import remote_data - - def test_1(): - #if filename.fits is a local file in the source distribution - datafile = get_data_filename('filename.fits') - # do the test - - @remote_data - def test_2(): - #this is the hash for a particular version of a file stored on the - #astropy data server. - datafile = get_data_filename('hash/94935ac31d585f68041c08f87d1a19d4') - # do the test - -The ``get_remote_test_data`` will place the files in a temporary directory -indicated by the ``tempfile`` module, so that the test files will eventually -get removed by the system. In the long term, once test data files become too -large, we will need to design a mechanism for removing test data immediately. - -Tests that create files ------------------------ - -Tests may often be run from directories where users do not have write permissions -so tests which create files should always do so in temporary directories. This -can be done with the `py.test tmpdir function argument -`_ -or with Python's built-in `tempfile module -`_. - -Setting up/Tearing down tests ------------------------------ - -In some cases, it can be useful to run a series of tests requiring something -to be set up first. There are four ways to do this: - -Module-level setup/teardown -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If the ``setup_module`` and ``teardown_module`` functions are specified in a -file, they are called before and after all the tests in the file respectively. -These functions take one argument, which is the module itself, which makes it -very easy to set module-wide variables:: - - def setup_module(module): - module.NUM = 11 - - def add_num(x): - return x + NUM - - def test_42(): - added = add_num(42) - assert added == 53 - -We can use this for example to download a remote test data file and have all -the functions in the file access it:: - - import os - - def setup_module(module): - module.DATAFILE = get_remote_test_data('94935ac31d585f68041c08f87d1a19d4') - - def test(): - f = open(DATAFILE, 'rb') - # do the test - - def teardown_module(module): - os.remove(DATAFILE) - -Class-level -^^^^^^^^^^^ - -Tests can be organized into classes that have their own setup/teardown -functions. In the following :: - - def add_nums(x, y): - return x + y - - class TestAdd42(object): - - def setup_class(self): - self.NUM = 42 - - def test_1(self): - added = add_nums(11, self.NUM) - assert added == 53 - - def test_2(self): - added = add_nums(13, self.NUM) - assert added == 55 - - def teardown_class(self): - pass - -In the above example, the ``setup_class`` method is called first, then all the -tests in the class, and finally the ``teardown_class`` is called. - -Method-level -^^^^^^^^^^^^ - -There are cases where one might want setup and teardown methods to be run -before and after *each* test. For this, use the ``setup_method`` and -``teardown_method`` methods:: - - def add_nums(x, y): - return x + y - - class TestAdd42(object): - - def setup_method(self, method): - self.NUM = 42 - - def test_1(self): - added = add_nums(11, self.NUM) - assert added == 53 - - def test_2(self): - added = add_nums(13, self.NUM) - assert added == 55 - - def teardown_method(self, method): - pass - -Function-level -^^^^^^^^^^^^^^ - -Finally, one can use ``setup_function`` and ``teardown_function`` to define a -setup/teardown mechanism to be run before and after each function in a module. -These take one argument, which is the function being tested:: - - def setup_function(function): - pass - - def test_1(self): - # do test - - def test_2(self): - # do test - - def teardown_method(function): - pass - -Using py.test helper functions ------------------------------- - -If your tests need to use `py.test helper functions -`_, such as ``pytest.raises``, -import ``pytest`` into your test module like so:: - - from ...tests.helper import pytest - -You may need to adjust the relative import to work for the depth of your module. -``tests.helper`` imports ``pytest`` either from the user's system or ``extern.pytest`` -if the user does not have py.test installed. This is so that users need not -install py.test to run AstroPy's tests. - - -Using data in tests -=================== - -Tests can include very small datafiles, but any files significantly larger -than the source code should be placed on a remote server. The base URL for the -test files will be:: - - http://data.astropy.org/ - -and files will be accessed by their MD5 hash, for example:: - - http://data.astropy.org/94935ac31d585f68041c08f87d1a19d4 - -Tests then retrieve data via this URL. This implicitly allows versioning, -since different versions of data files will have different hashes. Old data -files should not be removed, so that tests can be run in any version of -AstroPy. - -The details of the server implementation have yet to be decided, but using -these static hash-based URLs ensures that even if we change the backend, the -URL will remain the same. diff --git a/_sources/development/workflow/development_workflow.txt b/_sources/development/workflow/development_workflow.txt deleted file mode 100644 index f5516c9d..00000000 --- a/_sources/development/workflow/development_workflow.txt +++ /dev/null @@ -1,30 +0,0 @@ -.. _development-workflow: - -#################### -Development workflow -#################### - -This document describes how to contribute to a git repository hosted on -GitHub. The example shown here is that of the core ``astropy`` repository, but -the workflow can work equally well for the internal development of an -affiliated package. - -Before following the instructions on this page, make sure you have correctly -installed and configured git: - -.. toctree:: - :maxdepth: 1 - - git_install - git_configure - -The following documents describe a beginner and advanced workflow for -contributing respectively: - -.. toctree:: - :maxdepth: 1 - - development_workflow_basic.rst - development_workflow_advanced.rst - -.. include:: links.inc diff --git a/_sources/development/workflow/development_workflow_advanced.txt b/_sources/development/workflow/development_workflow_advanced.txt deleted file mode 100644 index 5e57d4c9..00000000 --- a/_sources/development/workflow/development_workflow_advanced.txt +++ /dev/null @@ -1,534 +0,0 @@ -.. _advanced-workflow: - -=============================== -Development Workflow (Advanced) -=============================== - -In the present document, we refer to the Astropy ``master`` branch, as the -*trunk*. - -.. _forking: - -Creating a fork -=============== - -You need to do this only once for each package you want to contribute to. The -instructions here are very similar to the instructions at -http://help.github.com/fork-a-repo/ |emdash| please see that page for more -details. We're repeating some of it here just to give the specifics for the -Astropy_ project, and to suggest some default names. - -Set up and configure a GitHub account -------------------------------------- - -If you don't have a GitHub account, go to the GitHub page, and make one. - -You then need to configure your account to allow write access |emdash| see -the ``Generating SSH keys`` help on `github help`_. - -Create your own fork of a repository ------------------------------------- - -The following example shows how to fork the core ``astropy`` repository, but the same applies to other packages: - -#. Log into your GitHub account. - -#. Go to the Astropy_ GitHub home at `Astropy github`_. - -#. Click on the *fork* button: - - .. image:: forking_button.png - - Now, after a short pause and some 'Hardcore forking action', you - should find yourself at the home page for your own forked copy of Astropy_. - - - -Setting up the fork to work on ------------------------------- - -.. _linking-to-upstream: - -Overview -^^^^^^^^ - -This is done using:: - - git clone git@github.com:your-user-name/astropy.git - cd astropy - git remote add upstream git://github.com/astropy/astropy.git - -In detail -^^^^^^^^^ - -#. Clone your fork to the local computer:: - - git clone git@github.com:your-user-name/astropy.git - -#. Change directory to your new repo:: - - cd astropy - - Then type:: - - git branch -a - - to show you all branches. You'll get something like:: - - * master - remotes/origin/master - - This tells you that you are currently on the ``master`` branch, and - that you also have a ``remote`` connection to ``origin/master``. - What remote repository is ``remote/origin``? Try ``git remote -v`` to - see the URLs for the remote. They will point to your github fork. - - Now you want to connect to the `Astropy github`_ repository, so you can - merge in changes from the trunk:: - - cd astropy - git remote add upstream git://github.com/astropy/astropy.git - - ``upstream`` here is just the arbitrary name we're using to refer to the - main Astropy_ repository at `Astropy github`_. - - Note that we've used ``git://`` for the URL rather than ``git@``. The - ``git://`` URL is read only. This means we that we can't accidentally (or - deliberately) write to the upstream repo, and we are only going to use it - to merge into our own code. - - Just for your own satisfaction, show yourself that you now have a new - 'remote', with ``git remote -v show``, giving you something like:: - - upstream git://github.com/astropy/astropy.git (fetch) - upstream git://github.com/astropy/astropy.git (push) - origin git@github.com:your-user-name/astropy.git (fetch) - origin git@github.com:your-user-name/astropy.git (push) - - Your fork is now set up correctly, and you are ready to hack away. - -Workflow summary -================ - -This section gives a summary of the workflow once you have successfully forked -the repository, and details are given for each of these steps in the following -sections. - -* Don't use your ``master`` branch for anything. Consider deleting it. - -* When you are starting a new set of changes, fetch any changes from the - trunk, and start a new *feature branch* from that. - -* Make a new branch for each separable set of changes |emdash| "one task, one - branch" (`ipython git workflow`_). - -* Name your branch for the purpose of the changes - e.g. - ``bugfix-for-issue-14`` or ``refactor-database-code``. - -* If you can possibly avoid it, avoid merging trunk or any other branches into - your feature branch while you are working. - -* If you do find yourself merging from the trunk, consider :ref:`rebase-on-trunk` - -* Ask on the `Astropy mailing list`_ if you get stuck. - -* Ask for code review! - -This way of working helps to keep work well organized, with readable history. -This in turn makes it easier for project maintainers (that might be you) to -see what you've done, and why you did it. - -See `linux git workflow`_ and `ipython git workflow`_ for some explanation. - -Deleting your master branch -=========================== - -It may sound strange, but deleting your own ``master`` branch can help reduce -confusion about which branch you are on. See `deleting master on github`_ for -details. - -.. _update-mirror-trunk: - -Updating the mirror of trunk -============================ - -From time to time you should fetch the upstream (trunk) changes from github:: - - git fetch upstream - -This will pull down any commits you don't have, and set the remote branches to -point to the right commit. For example, 'trunk' is the branch referred to by -(remote/branchname) ``upstream/master`` - and if there have been commits since -you last checked, ``upstream/master`` will change after you do the fetch. - -.. _make-feature-branch: - -Making a new feature branch -=========================== - -When you are ready to make some changes to the code, you should start a new -branch. Branches that are for a collection of related edits are often called -'feature branches'. - -Making an new branch for each set of related changes will make it easier for -someone reviewing your branch to see what you are doing. - -Choose an informative name for the branch to remind yourself and the rest of -us what the changes in the branch are for. For example ``add-ability-to-fly``, -or ``buxfix-for-issue-42``. - -:: - - # Update the mirror of trunk - git fetch upstream - - # Make new feature branch starting at current trunk - git branch my-new-feature upstream/master - git checkout my-new-feature - -Generally, you will want to keep your feature branches on your public github_ -fork of Astropy_. To do this, you `git push`_ this new branch up to your -github repo. Generally (if you followed the instructions in these pages, and -by default), git will have a link to your GitHub repo, called ``origin``. You -push up to your own repo on GitHub with:: - - git push origin my-new-feature - -In git >= 1.7 you can ensure that the link is correctly set by using the -``--set-upstream`` option:: - - git push --set-upstream origin my-new-feature - -From now on git will know that ``my-new-feature`` is related to the -``my-new-feature`` branch in the GitHub repo. - -.. _edit-flow: - -The editing workflow -==================== - -Overview --------- - -:: - - git add my_new_file - git commit -am 'NF - some message' - git push - -In more detail --------------- - -#. Make some changes - -#. See which files have changed with ``git status`` (see `git status`_). - You'll see a listing like this one:: - - # On branch ny-new-feature - # Changed but not updated: - # (use "git add ..." to update what will be committed) - # (use "git checkout -- ..." to discard changes in working directory) - # - # modified: README - # - # Untracked files: - # (use "git add ..." to include in what will be committed) - # - # INSTALL - no changes added to commit (use "git add" and/or "git commit -a") - -#. Check what the actual changes are with ``git diff`` (`git diff`_). - -#. Add any new files to version control ``git add new_file_name`` (see - `git add`_). - -#. To commit all modified files into the local copy of your repo,, do - ``git commit -am 'A commit message'``. Note the ``-am`` options to - ``commit``. The ``m`` flag just signals that you're going to type a message - on the command line. The ``a`` flag |emdash| you can just take on faith - |emdash| or see `why the -a flag?`_ |emdash| and the helpful use-case - description in the `tangled working copy problem`_. The `git commit`_ - manual - page might also be useful. - -#. To push the changes up to your forked repo on github, do a ``git - push`` (see `git push`_). - -Asking for your changes to be reviewed or merged -================================================ - -When you are ready to ask for someone to review your code and consider a merge: - -#. Go to the URL of your forked repo, say - ``http://github.com/your-user-name/astropy``. - -#. Use the 'Switch Branches' dropdown menu near the top left of the page to - select the branch with your changes: - - .. image:: branch_dropdown.png - -#. Click on the 'Pull request' button: - - .. image:: pull_button.png - - Enter a title for the set of changes, and some explanation of what you've - done. Say if there is anything you'd like particular attention for - like a - complicated change or some code you are not happy with. - - If you don't think your request is ready to be merged, just say so in your - pull request message. This is still a good way of getting some preliminary - code review. - -Some other things you might want to do -====================================== - -Delete a branch on github -------------------------- - -:: - - # change to the master branch (if you still have one, otherwise change to - # another branch) - git checkout master - - # delete branch locally - git branch -D my-unwanted-branch - - # delete branch on github - git push origin :my-unwanted-branch - -(Note the colon ``:`` before ``test-branch``. See also: -http://github.com/guides/remove-a-remote-branch - -Several people sharing a single repository ------------------------------------------- - -If you want to work on some stuff with other people, where you are all -committing into the same repository, or even the same branch, then just -share it via github. - -First fork Astropy into your account, as from :ref:`forking`. - -Then, go to your forked repository GitHub page, say -``http://github.com/your-user-name/astropy`` - -Click on the 'Admin' button, and add anyone else to the repo as a -collaborator: - - .. image:: pull_button.png - -Now all those people can do:: - - git clone git@githhub.com:your-user-name/astropy.git - -Remember that links starting with ``git@`` use the ssh protocol and are -read-write; links starting with ``git://`` are read-only. - -Your collaborators can then commit directly into that repo with the -usual:: - - git commit -am 'ENH - much better code' - git push origin master # pushes directly into your repo - -Explore your repository ------------------------ - -To see a graphical representation of the repository branches and -commits:: - - gitk --all - -To see a linear list of commits for this branch:: - - git log - -You can also look at the `network graph visualizer`_ for your github -repo. - -Finally the :ref:`fancy-log` ``lg`` alias will give you a reasonable -text-based graph of the repository. - -.. _rebase-on-trunk: - -Rebasing on trunk ------------------ - -Let's say you thought of some work you'd like to do. You -:ref:`update-mirror-trunk` and :ref:`make-feature-branch` called -``cool-feature``. At this stage trunk is at some commit, let's call it E. Now -you make some new commits on your ``cool-feature`` branch, let's call them A, -B, C. Maybe your changes take a while, or you come back to them after a while. -In the meantime, trunk has progressed from commit E to commit (say) G:: - - A---B---C cool-feature - / - D---E---F---G trunk - -At this stage you consider merging trunk into your feature branch, and you -remember that this here page sternly advises you not to do that, because the -history will get messy. Most of the time you can just ask for a review, and -not worry that trunk has got a little ahead. But sometimes, the changes in -trunk might affect your changes, and you need to harmonize them. In this -situation you may prefer to do a rebase. - -Rebase takes your changes (A, B, C) and replays them as if they had been made -to the current state of ``trunk``. In other words, in this case, it takes the -changes represented by A, B, C and replays them on top of G. After the rebase, -your history will look like this:: - - A'--B'--C' cool-feature - / - D---E---F---G trunk - -See `rebase without tears`_ for more detail. - -To do a rebase on trunk:: - - # Update the mirror of trunk - git fetch upstream - - # Go to the feature branch - git checkout cool-feature - - # Make a backup in case you mess up - git branch tmp cool-feature - - # Rebase cool-feature onto trunk - git rebase --onto upstream/master upstream/master cool-feature - -In this situation, where you are already on branch ``cool-feature``, the last -command can be written more succinctly as:: - - git rebase upstream/master - -When all looks good you can delete your backup branch:: - - git branch -D tmp - -If it doesn't look good you may need to have a look at -:ref:`recovering-from-mess-up`. - -If you have made changes to files that have also changed in trunk, this may -generate merge conflicts that you need to resolve - see the `git rebase`_ man -page for some instructions at the end of the "Description" section. There is -some related help on merging in the git user manual - see `resolving a -merge`_. - -.. _recovering-from-mess-up: - -Recovering from mess-ups ------------------------- - -Sometimes, you mess up merges or rebases. Luckily, in git it is relatively -straightforward to recover from such mistakes. - -If you mess up during a rebase:: - - git rebase --abort - -If you notice you messed up after the rebase:: - - # Reset branch back to the saved point - git reset --hard tmp - -If you forgot to make a backup branch:: - - # Look at the reflog of the branch - git reflog show cool-feature - - 8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately - 278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d - 26aa21a cool-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj - ... - - # Reset the branch to where it was before the botched rebase - git reset --hard cool-feature@{2} - -.. _rewriting-commit-history: - -Rewriting commit history ------------------------- - -.. note:: - - Do this only for your own feature branches. - -There's an embarrassing typo in a commit you made? Or perhaps the you -made several false starts you would like the posterity not to see. - -This can be done via *interactive rebasing*. - -Suppose that the commit history looks like this:: - - git log --oneline - eadc391 Fix some remaining bugs - a815645 Modify it so that it works - 2dec1ac Fix a few bugs + disable - 13d7934 First implementation - 6ad92e5 * masked is now an instance of a new object, MaskedConstant - 29001ed Add pre-nep for a copule of structured_array_extensions. - ... - -and ``6ad92e5`` is the last commit in the ``cool-feature`` branch. Suppose we -want to make the following changes: - -* Rewrite the commit message for ``13d7934`` to something more sensible. -* Combine the commits ``2dec1ac``, ``a815645``, ``eadc391`` into a single one. - -We do as follows:: - - # make a backup of the current state - git branch tmp HEAD - # interactive rebase - git rebase -i 6ad92e5 - -This will open an editor with the following text in it:: - - pick 13d7934 First implementation - pick 2dec1ac Fix a few bugs + disable - pick a815645 Modify it so that it works - pick eadc391 Fix some remaining bugs - - # Rebase 6ad92e5..eadc391 onto 6ad92e5 - # - # Commands: - # p, pick = use commit - # r, reword = use commit, but edit the commit message - # e, edit = use commit, but stop for amending - # s, squash = use commit, but meld into previous commit - # f, fixup = like "squash", but discard this commit's log message - # - # If you remove a line here THAT COMMIT WILL BE LOST. - # However, if you remove everything, the rebase will be aborted. - # - -To achieve what we want, we will make the following changes to it:: - - r 13d7934 First implementation - pick 2dec1ac Fix a few bugs + disable - f a815645 Modify it so that it works - f eadc391 Fix some remaining bugs - -This means that (i) we want to edit the commit message for ``13d7934``, and -(ii) collapse the last three commits into one. Now we save and quit the -editor. - -Git will then immediately bring up an editor for editing the commit message. -After revising it, we get the output:: - - [detached HEAD 721fc64] FOO: First implementation - 2 files changed, 199 insertions(+), 66 deletions(-) - [detached HEAD 0f22701] Fix a few bugs + disable - 1 files changed, 79 insertions(+), 61 deletions(-) - Successfully rebased and updated refs/heads/my-feature-branch. - -and the history looks now like this:: - - 0f22701 Fix a few bugs + disable - 721fc64 ENH: Sophisticated feature - 6ad92e5 * masked is now an instance of a new object, MaskedConstant - -If it went wrong, recovery is again possible as explained :ref:`above -`. - -.. include:: links.inc diff --git a/_sources/development/workflow/development_workflow_basic.txt b/_sources/development/workflow/development_workflow_basic.txt deleted file mode 100644 index 65bfca64..00000000 --- a/_sources/development/workflow/development_workflow_basic.txt +++ /dev/null @@ -1,133 +0,0 @@ -.. _basic-workflow: - -=============================== -Development Workflow (Beginner) -=============================== - -You've discovered a bug or something else you want to change -in Astropy_ |emdash| excellent! - -You've worked out a way to fix it |emdash| even better! - -You want to tell us about it |emdash| best of all! - -The easiest way is to make a *patch* or set of patches. Here we explain how. -Making a patch is the simplest and quickest, but if you're going to be doing -anything more than simple quick things, please consider following -:ref:`advanced-workflow` instead. - -Making patches -============== - -Overview --------- - -If you haven't already configured git (:ref:`git-configure-impatient`):: - - git config --global user.name "Your Name" - git config --global user.email you@yourdomain.example.com - -Then, the workflow is the following: -:: - - # Get the repository if you don't have it - git clone git://github.com/astropy/astropy.git - - # Make a branch for your patching - cd astropy - git branch the-fix-im-thinking-of - git checkout the-fix-im-thinking-of - - # hack, hack, hack - - # Tell git about any new files you've made - git add somewhere/tests/test_my_bug.py - - # Commit work in progress as you go - git commit -am 'BF - added tests for Funny bug' - - # hack hack, hack - - # Commit work - git commit -am 'BF - added fix for Funny bug' - - # Make the patch files - git format-patch -M -C master - -Then, send the generated patch files to the `Astropy mailing list`_ |emdash| -where we will thank you warmly. - -In detail ---------- - -#. Tell git who you are so it can label the commits you've - made:: - - git config --global user.name "Your Name" - git config --global user.email you@yourdomain.example.com - - This is only necessary if you haven't already done this, and you haven't - followed :ref:`configure-git`. - -#. If you don't already have one, clone a copy of the - Astropy_ repository:: - - git clone git://github.com/astropy/astropy.git - cd astropy - -#. Make a 'feature branch'. This will be where you work on your bug fix. It's - nice and safe and leaves you with access to an unmodified copy of the code - in the main branch:: - - git branch the-fix-im-thinking-of - git checkout the-fix-im-thinking-of - -#. Do some edits, and commit them as you go:: - - # hack, hack, hack - - # Tell git about any new files you've made - git add somewhere/tests/test_my_bug.py - - # Commit work in progress as you go - git commit -am 'BF - added tests for Funny bug' - - # hack hack, hack - - # Commit work - git commit -am 'BF - added fix for Funny bug' - - Note the ``-am`` options to ``commit``. The ``m`` flag just - signals that you're going to type a message on the command - line. The ``a`` flag |emdash| you can just take on faith |emdash| - or see `why the -a flag?`_. - -#. When you have finished, check you have committed all your changes:: - - git status - -#. Finally, make your commits into patches. You want all the commits since you - branched from the ``master`` branch:: - - git format-patch -M -C master - - You will now have several files named for the commits:: - - 0001-BF-added-tests-for-Funny-bug.patch - 0002-BF-added-fix-for-Funny-bug.patch - - Send these files to the `Astropy mailing list`_. - -When you are done, to switch back to the main copy of the -code, just return to the ``master`` branch:: - - git checkout master - -Moving from patching to development -=================================== - -If you find you have done some patches, and you have one or more feature -branches, you will probably want to switch to a more advanced development -mode. You can do this with the repository you have. See :ref:`advanced-workflow` for more details. - -.. include:: links.inc diff --git a/_sources/development/workflow/git_configure.txt b/_sources/development/workflow/git_configure.txt deleted file mode 100644 index e258eef5..00000000 --- a/_sources/development/workflow/git_configure.txt +++ /dev/null @@ -1,168 +0,0 @@ -.. _configure-git: - -================ - Configuring git -================ - -.. _git-config-basic: - -Bare Minimum -============ - -The only absolutely necessary configuration step is identifying yourself and your contact info:: - - git config --global user.name "Your Name" - git config --global user.email you@yourdomain.example.com - -Once you've done this, you can actually ignore the rest of the document unless you want to customize the behavior of git. - -Overview -======== - -Your personal git configurations are saved in the ``.gitconfig`` file in -your home directory. - -Here is an example ``.gitconfig`` file:: - - [user] - name = Your Name - email = you@yourdomain.example.com - - [alias] - ci = commit -a - co = checkout - st = status - stat = status - br = branch - wdiff = diff --color-words - - [core] - editor = vim - - [merge] - log = true - -You can edit this file directly or you can use the ``git config --global`` -command:: - - git config --global user.name "Your Name" - git config --global user.email you@yourdomain.example.com - git config --global alias.ci "commit -a" - git config --global alias.co checkout - git config --global alias.st "status -a" - git config --global alias.stat "status -a" - git config --global alias.br branch - git config --global alias.wdiff "diff --color-words" - git config --global core.editor vim - git config --global merge.summary true - -To set up on another computer, you can copy your ``~/.gitconfig`` file, -or run the commands above. - -In detail -========= - -user.name and user.email ------------------------- - -It is good practice to tell git_ who you are, for labeling any changes -you make to the code. The simplest way to do this is from the command -line:: - - git config --global user.name "Your Name" - git config --global user.email you@yourdomain.example.com - -This will write the settings into your git configuration file, which -should now contain a user section with your name and email:: - - [user] - name = Your Name - email = you@yourdomain.example.com - -Of course you'll need to replace ``Your Name`` and ``you@yourdomain.example.com`` -with your actual name and email address. - -Aliases -------- - -You might well benefit from some aliases to common commands. - -For example, you might well want to be able to shorten ``git checkout`` -to ``git co``. Or you may want to alias ``git diff --color-words`` -(which gives a nicely formatted output of the diff) to ``git wdiff`` - -The following ``git config --global`` commands:: - - git config --global alias.ci "commit -a" - git config --global alias.co checkout - git config --global alias.st "status -a" - git config --global alias.stat "status -a" - git config --global alias.br branch - git config --global alias.wdiff "diff --color-words" - -will create an ``alias`` section in your ``.gitconfig`` file with contents -like this:: - - [alias] - ci = commit -a - co = checkout - st = status -a - stat = status -a - br = branch - wdiff = diff --color-words - -Editor ------- - -You may also want to make sure that your editor of choice is used :: - - git config --global core.editor vim - -Merging -------- - -To enforce summaries when doing merges (``~/.gitconfig`` file again):: - - [merge] - log = true - -Or from the command line:: - - git config --global merge.log true - -.. _fancy-log: - -Fancy log output ----------------- - -This is a very nice alias to get a fancy log output; it should go in the -``alias`` section of your ``.gitconfig`` file:: - - lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative - -You use the alias with:: - - git lg - -and it gives graph / text output something like this (but with color!):: - - * 6d8e1ee - (HEAD, origin/my-fancy-feature, my-fancy-feature) NF - a fancy file (45 minutes ago) [Matthew Brett] - * d304a73 - (origin/placeholder, placeholder) Merge pull request #48 from hhuuggoo/master (2 weeks ago) [Jonathan Terhorst] - |\ - | * 4aff2a8 - fixed bug 35, and added a test in test_bugfixes (2 weeks ago) [Hugo] - |/ - * a7ff2e5 - Added notes on discussion/proposal made during Data Array Summit. (2 weeks ago) [Corran Webster] - * 68f6752 - Initial implimentation of AxisIndexer - uses 'index_by' which needs to be changed to a call on an Axes object - this is all very sketchy right now. (2 weeks ago) [Corr - * 376adbd - Merge pull request #46 from terhorst/master (2 weeks ago) [Jonathan Terhorst] - |\ - | * b605216 - updated joshu example to current api (3 weeks ago) [Jonathan Terhorst] - | * 2e991e8 - add testing for outer ufunc (3 weeks ago) [Jonathan Terhorst] - | * 7beda5a - prevent axis from throwing an exception if testing equality with non-axis object (3 weeks ago) [Jonathan Terhorst] - | * 65af65e - convert unit testing code to assertions (3 weeks ago) [Jonathan Terhorst] - | * 956fbab - Merge remote-tracking branch 'upstream/master' (3 weeks ago) [Jonathan Terhorst] - | |\ - | |/ - -Thanks to Yury V. Zaytsev for posting it. - -.. include:: links.inc diff --git a/_sources/development/workflow/git_install.txt b/_sources/development/workflow/git_install.txt deleted file mode 100644 index 284d7a9d..00000000 --- a/_sources/development/workflow/git_install.txt +++ /dev/null @@ -1,41 +0,0 @@ -.. _install-git: - -=============== - Installing git -=============== - -The instructions here are adapted from http://book.git-scm.com/2_installing_git.html - -Debian/Ubuntu -------------- - -:: - - sudo apt-get install git-core - -Fedora ------- - -:: - - sudo yum install git-core - -MacOS X -------- - -There are several ways to install git on Mac. The easiest is to simply download the OS X installer (git-osx-installer_). If you have MacPorts installed, you can also do:: - - sudo port install git-core - -If you have Fink installed, you can do:: - - sudo apt-get install git - -In addition, you may want to use a GUI to manage your git repositories. A good example of a free Mac GUI is `GitX `_. Other (non-free) examples include `Tower `_ and `SourceTree `_. GitHub have also recently released `GitHub for Mac `_. - -Windows -------- - -Download and install msysGit_ - -.. include:: links.inc diff --git a/_sources/development/workflow/git_resources.txt b/_sources/development/workflow/git_resources.txt deleted file mode 100644 index 8e5cff7a..00000000 --- a/_sources/development/workflow/git_resources.txt +++ /dev/null @@ -1,59 +0,0 @@ -.. _git-resources: - -============= -Git resources -============= - -Tutorials and summaries -======================= - -* `github help`_ has an excellent series of how-to guides. -* `learn.github`_ has an excellent series of tutorials -* The `pro git book`_ is a good in-depth book on git. -* A `git cheat sheet`_ is a page giving summaries of common commands. -* The `git user manual`_ -* The `git tutorial`_ -* The `git community book`_ -* `git ready`_ |emdash| a nice series of tutorials -* `git casts`_ |emdash| video snippets giving git how-tos. -* `git magic`_ |emdash| extended introduction with intermediate detail -* The `git parable`_ is an easy read explaining the concepts behind git. -* `git foundation`_ expands on the `git parable`_. -* Fernando Perez' git page |emdash| `Fernando's git page`_ |emdash| many - links and tips -* A good but technical page on `git concepts`_ -* `git svn crash course`_: git for those of us used to subversion_ - -Advanced git workflow -===================== - -There are many ways of working with git; here are some posts on the -rules of thumb that other projects have come up with: - -* Linus Torvalds on `git management`_ -* Linus Torvalds on `linux git workflow`_ . Summary; use the git tools - to make the history of your edits as clean as possible; merge from - upstream edits as little as possible in branches where you are doing - active development. - -Manual pages online -=================== - -You can get these on your own machine with (e.g) ``git help push`` or -(same thing) ``git push --help``, but, for convenience, here are the -online manual pages for some common commands: - -* `git add`_ -* `git branch`_ -* `git checkout`_ -* `git clone`_ -* `git commit`_ -* `git config`_ -* `git diff`_ -* `git log`_ -* `git pull`_ -* `git push`_ -* `git remote`_ -* `git status`_ - -.. include:: links.inc diff --git a/_sources/development/workflow/index.txt b/_sources/development/workflow/index.txt deleted file mode 100644 index 076d6604..00000000 --- a/_sources/development/workflow/index.txt +++ /dev/null @@ -1,78 +0,0 @@ -.. _using-git: - -Contributing To/Developing Astropy or Affiliated Packages -========================================================= - -Summary -------- - -As described in :ref:`vision`, development of components intended for -inclusion in the core ``astropy`` package will initially be done by different -teams via *affiliated packages*. These affiliated packages will then be -submitted for inclusion in the ``astropy`` core package by creating a git fork -of the core repository, merging the new component into the fork, and -submitting the package as a pull request. The step of creating a fork and -merging the affiliated package into the fork can be done either by the team -contributing the affiliated package, or by the coordination committee if -requested. - -Once an affiliated package has been accepted and integrated as a component -into the core ``astropy`` package, subsequent improvements and bug fixes can -be made in the same way by forking the core repository and submitting a pull -request. - -The bottom line is that teams working on various components are free to choose -the version control system and workflow that they want, but ultimately the -changes need to be merged into a fork of the core repository and submitted via -a pull request to the core repository, either by the team or by the -coordination committee. - -.. _git-configure-impatient: - -For the Impatient ------------------ - -The only absolutely necessary configuration step is identifying yourself and your contact info:: - - git config --global user.name "Your Name" - git config --global user.email you@yourdomain.example.com - -More detailed information and instructions are below. - -After that, if you then just want to get the latest ``astropy`` source code, cd to a directory on your computer you want to put the source code, and do:: - - git clone git@github.com:astropy/astropy.git - -You will then have a new copy of the source code in the ``astropy`` directory. - -Later, if you want to update to the most recent version of the ``astropy`` code, just go do:: - - cd astropy - git pull - -If you find a bug and want to fix it, see :ref:`basic-workflow` or :ref:`advanced-workflow` depending on how comfortable you are with git. - -Git Documentation ------------------ - -The following sections cover the installation of the git software, the basic configuration, and links to resources to learn more about using git. However, you can also directly go to the `GitHub help pages `_ which offer a great introduction to git and GitHub. - -.. toctree:: - :maxdepth: 1 - - git_install - git_configure - git_resources - -Workflow --------- - -The following two sections describe the workflow for the ``astropy`` core -package, but teams working on affiliated packages that have chosen to use git -are encouraged to also follow these guidelines internally. - -.. toctree:: - :maxdepth: 1 - - development_workflow - maintainer_workflow diff --git a/_sources/development/workflow/maintainer_workflow.txt b/_sources/development/workflow/maintainer_workflow.txt deleted file mode 100644 index 8ae79723..00000000 --- a/_sources/development/workflow/maintainer_workflow.txt +++ /dev/null @@ -1,105 +0,0 @@ -.. _maintainer-workflow: - -################### -Maintainer workflow -################### - -This page is for maintainers |emdash| those of us who merge our own or other -peoples' changes into the upstream repository. - -Being as how you're a maintainer, you are completely on top of the basic stuff -in :ref:`development-workflow`. - -******************************************************* -Integrating changes via the web interface (recommended) -******************************************************* - -Whenever possible, merge pull requests automatically via the pull request manager on GitHub. Merging should only be done manually if there is a really good reason to do this! - -Make sure that pull requests do not contain a messy history with merges, etc. If this is the case, then follow the manual instructions, and make sure the fork is rebased to tidy the history before committing. - -**************************** -Integrating changes manually -**************************** - -First, check out the ``astropy`` repository. The instructions in :ref:`linking-to-upstream` add a remote that has read-only -access to the upstream repo. Being a maintainer, you've got read-write access. - -It's good to have your upstream remote have a scary name, to remind you that -it's a read-write remote:: - - git remote add upstream-rw git@github.com:astropy/astropy.git - git fetch upstream-rw - -Let's say you have some changes that need to go into trunk -(``upstream-rw/master``). - -The changes are in some branch that you are currently on. For example, you are -looking at someone's changes like this:: - - git remote add someone git://github.com/someone/astropy.git - git fetch someone - git branch cool-feature --track someone/cool-feature - git checkout cool-feature - -So now you are on the branch with the changes to be incorporated upstream. The -rest of this section assumes you are on this branch. - -A few commits -============= - -If there are only a few commits, consider rebasing to upstream:: - - # Fetch upstream changes - git fetch upstream-rw - - # Rebase - git rebase upstream-rw/master - -Remember that, if you do a rebase, and push that, you'll have to close any -github pull requests manually, because github will not be able to detect the -changes have already been merged. - -A long series of commits -======================== - -If there are a longer series of related commits, consider a merge instead:: - - git fetch upstream-rw - git merge --no-ff upstream-rw/master - -The merge will be detected by github, and should close any related pull -requests automatically. - -Note the ``--no-ff`` above. This forces git to make a merge commit, rather -than doing a fast-forward, so that these set of commits branch off trunk then -rejoin the main history with a merge, rather than appearing to have been made -directly on top of trunk. - -Check the history -================= - -Now, in either case, you should check that the history is sensible and you -have the right commits:: - - git log --oneline --graph - git log -p upstream-rw/master.. - -The first line above just shows the history in a compact way, with a text -representation of the history graph. The second line shows the log of commits -excluding those that can be reached from trunk (``upstream-rw/master``), and -including those that can be reached from current HEAD (implied with the ``..`` -at the end). So, it shows the commits unique to this branch compared to trunk. -The ``-p`` option shows the diff for these commits in patch form. - -Push to trunk -============= - -:: - - git push upstream-rw my-new-feature:master - -This pushes the ``my-new-feature`` branch in this repository to the ``master`` -branch in the ``upstream-rw`` repository. - -.. include:: links.inc diff --git a/_sources/index.txt b/_sources/index.txt index 0672d6b8..0542856d 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -1,31 +1,81 @@ -.. Astropy documentation master file, created by - sphinx-quickstart on Tue Jul 26 02:59:34 2011. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Astropy's Documentation! -=================================== - -The current Astropy documentation is limited, as not much code has yet been -developed. For more information, see the `github wiki -`_ page of the project. - -.. toctree:: - :maxdepth: 2 - - overview - install - configs - wcs/index - vo/index - tools - utils/index - development/index - -Indices and Tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` +.. title:: Welcome + +.. _`PyFITS`: http://www.stsci.edu/institute/software_hardware/pyfits +.. _`PyWCS`: https://trac.assembla.com/astrolib +.. _`vo`: https://trac.assembla.com/astrolib +.. _`asciitable`: http://cxc.harvard.edu/contrib/asciitable/ +.. _`astropy`: http://mail.scipy.org/mailman/listinfo/astropy +.. _`issue tracker`: http://github.com/astropy/astropy/issues +.. _`documentation`: http://astropy.readthedocs.org/en/latest/install.html +.. _`Numpy`: http://numpy.scipy.org +.. _`Python`: http://www.python.org + +.. raw:: html + +
        + +.. image:: logos/astropy_banner_96.png + +.. raw:: html + +
        + +What is Astropy? +---------------- + +The Astropy project is a common effort to develop a single core package for +Astronomy that brings together almost 100 developers from around the world. + +Development is actively ongoing, with major packages such as `PyFITS`_, +`PyWCS`_, `vo`_, and `asciitable`_ already merged in, and many more components +being worked on. In particular, we are developing imaging, photometric, and +spectroscopic functionality, as well as frameworks for cosmology, unit +handling, and coordinate transformations. A first stable release is +tentatively scheduled for early May. + +Stay updated by following `@astropy `_ on Twitter, or sign up to the `astropy`_ mailing list! + +If you are interested in finding out more about the Astropy project, you can read the :doc:`original vision ` for the package. + +Documentation +------------- + +The documentation for the latest development version of Astropy can be found +at `http://astropy.readthedocs.org `_. This +documentation is automatically updated any time a commit is made to the +Astropy repository. Once a stable version of Astropy is released, we will +provide links to the documentation for that version. + +Installing +---------- + +Detailed installation instructions are provided in the `documentation`_, but +we have included a simplified version here. + +Astropy requires `Python`_ 2.6, 2.7, 3.1, or 3.2, and `Numpy`_ 1.4 or later. +You can install the latest developer version of Astropy using:: + + git clone http://github.com/astropy/astropy.git + cd astropy + python setup.py install + +Once a stable version of Astropy is released, we will provide links to the tar file, and updated installation instructions! + +You can check that astropy is correctly installed by starting up ``python`` or ``ipython``, and importing ``astropy``:: + + >>> import astropy + +If you do not get any errors, the installation was successful! + +Getting help +------------ + +If you want to discuss issues with other Astropy users and with the +developers, you can sign up to the `astropy`_ mailing list! + +Reporting issues +---------------- + +If you have come across something that you believe is a bug, please open a +ticket in the Astropy `issue tracker`_, and we will look into it promptly! diff --git a/_sources/install.txt b/_sources/install.txt deleted file mode 100644 index e14d9e7a..00000000 --- a/_sources/install.txt +++ /dev/null @@ -1,111 +0,0 @@ -Installation -============ - -Requirements ------------- - -Astropy has the following strict requirements: - -- `Python `_ 2.6, 2.7, 3.1 or 3.2 - -- `Numpy `_ 1.4 or later - -Astropy also depends on other projects for optional features. - -- `xmllint `_: To validate VOTABLE XML files. - -TODO: Link to the planned dependency checker/installer tool. - -Installing Astropy ------------------- - -Using `pip` -``````````` - -TODO: Write once we’re up on PyPI. - -Binary installers -````````````````` - -TODO: Write about where to obtain binary packages (.dmg, .msi etc.) - -Building from source --------------------- - -Prerequisites -````````````` - -You will need a compiler suite and the development headers for Python -and Numpy in order to build Astropy. Using the package manager for -your platform will usually be the easiest route. - -The `instructions for building Numpy from source -`_ are also a good -resource for setting up your environment to build Python packages. - -Obtaining the source -```````````````````` - -Source packages -^^^^^^^^^^^^^^^ - -Source tarballs of past releases and the current development branch of -astropy can be downloaded from here: - - https://github.com/astropy/astropy/downloads - -Development repository -^^^^^^^^^^^^^^^^^^^^^^ - -The latest development version of Astropy can be cloned from github -using this command:: - - git clone git://github.com/astropy/astropy.git - -.. note:: - - If you wish to participate in the development of Astropy, see - :ref:`developer-docs`. This document covers only the basics - necessary to install Astropy. - -Building and Installing -``````````````````````` - -Astropy uses the Python `distutils framework -`_ for building and -installing. - -To build Astropy (from the root of the source tree):: - - python setup.py build - -To install Astropy (from the root of the source tree):: - - python setup.py install - -Building documentation -`````````````````````` - -Building the documentation requires some additional packages: - - - `Sphinx `_ (and its dependencies) 1.0 or later - - - `Graphviz `_ - -To build the Astropy documentation (from the root of the source tree):: - - python setup.py build_sphinx - -The documentation tree will be built in the `docs/_build/html` -directory. - -Testing Astropy -``````````````` - -The easiest way to test that your Astropy built correctly is to run -(from the root of the source tree):: - - python setup.py test - -There are also alternative methods of :ref:`running-tests`. - diff --git a/_sources/overview.txt b/_sources/overview.txt deleted file mode 100644 index 3ff9e1f4..00000000 --- a/_sources/overview.txt +++ /dev/null @@ -1,56 +0,0 @@ -Overview -======== - -Here we describe a broad overview of the astropy project and its associated -modules and packages. - - -`astropy` Package Layout ------------------------- - -Astropy contains the following base-level subpackages: - - -* :mod:`~astropy.config` - This subpackage contains configuration and setup utilities, including the - affiliated package install tools. -* :mod:`~astropy.utils` - This subpackage contains utilities of general use for multiple modules or - affiliated packages. -* :mod:`~astropy.version` - This subpackage contains the version number information for the package. - Note that the version is also available at the base level of the package as - :attr:`astropy.__version__`. -* :mod:`~astropy.extern` - This subpackage contains small python packages that are not unique to - astropy but are convinient to include as part of the astropy source code. -* :mod:`~astropy.tests` - This subpackage contains utilities to run the astropy test suite (the - simplest method is to just call :meth:`astropy.test`), tools for writing - tests, and general tests that are not associated with a particular package. -* :mod:`~astropy.wcs` - This subpackage contains a python wrapper around the - `wcslib `_ library for - managing FITS world coordinate systems (WCS). - -Affiliated Packages -------------------- - -Astropy also includes the concept of "affiliated packages." An affiliated -package is an astronomy-related python package that is not included as part of -the Astropy source code, but has officially requested to be included in the -Astropy community. Such a package may be a candidate for eventual inclusion in -the main `astropy` package. Astropy comes with a tool to install a affiliated -packages by name, and a single official index with a list and description of -each package. See the :mod:`~astropy.config` module documentation for details -regarding this install tool. - -Affiliated packages do not use the `astropy` namespace, but rather either use -their package name directly, or `awastropy.packagename` ("affiliated with -astropy"). These packages may later be merged into the `astropy` package, in -which case the original package may still be used, but it is recommended that -users switch to the `astropy.packagename` version as soon as possible. -Alternatively, some affiliated packages may not wish to ever be merged with the -`astropy` source code, but rather remain as separate packages that make use of -other astropy modules or affiliated packages. - diff --git a/_sources/team.txt b/_sources/team.txt new file mode 100644 index 00000000..084e4acd --- /dev/null +++ b/_sources/team.txt @@ -0,0 +1,50 @@ +The Astropy team +---------------- + +.. _`astropy-dev`: http://groups.google.com/group/astropy-dev +.. _`specutils`: https://github.com/astropy/specutils +.. _`pyidlastro`: https://github.com/astropy/pyidlastro +.. _`photutils`: https://github.com/astropy/photutils +.. _`kcorrect`: https://github.com/astropy/kcorrect + +Project Coordinators +^^^^^^^^^^^^^^^^^^^^ + +* Perry Greenfield, STScI +* `Thomas Robitaille `_, MPIA +* `Erik Tollerud `_, UC Irvine + +Core package maintainers +^^^^^^^^^^^^^^^^^^^^^^^^ + +In addition to the coordination committee, the following individuals maintain the core package: + +* `Tom Aldcroft `_, CfA +* Erik Bray, STScI +* Matt Davis, STScI +* `Michael Droettboom `_, STScI + +Affiliated package maintainers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* `Tom Aldcroft `_, CfA (`pyidlastro`_) +* Rene Breton, University of Southampton (`photutils`_) +* Wolfgang Kerzendorf, ANU (`specutils`_) +* Taro Sato (`kcorrect`_) + +Contributors +^^^^^^^^^^^^ + +* Demitri Muna, NYU +* `Adrian Price-Whelan `_, Columbia U +* `Steve Crawford `_, SALT +* `Adam Ginsburg `_, U Colorado +* Frederic Grollier +* Prasanth Nair +* `Neil Crighton `_, MPIA +* Christoph Deil, MPIK +* `Kyle Barbary `_, Lawrence Berkeley National Lab, + +... and thanks to everyone on the `astropy-dev`_ mailing list for contributing to many discussions and decisions! + +(If you have contribute to the Astropy project, and your name is missing, please send an email to the coordinators, or open a pull request `here `_!) diff --git a/_sources/tools.txt b/_sources/tools.txt deleted file mode 100644 index e1c540ff..00000000 --- a/_sources/tools.txt +++ /dev/null @@ -1,27 +0,0 @@ -============================= -`astropy.tools` documentation -============================= - -The `~astropy.tools` package holds general astronomy functions or algorithms -that are likely of use to users, but either not related to functionality in -an existing package or of general use across multiple packages. - -.. note:: - For functions and classes that are more developer-oriented, the correct - package is `astropy.utils`. `astropy.tools` is intended primarily for - functionality that is astronomy-specific and/or of use to users. - - -Reference/API -------------- -Below are the reference documentation for the tools sub-packages. All public -functions and classes in these packages will be imported into the -`astropy.tools` package, so the recommended usage is e.g. -``from astropy.tools import sigma_clip`` or ``import astropy.tools`` instead of -``from astropy.tools.misc import sigma_clip`` or similar. - -`astropy.tools.misc` -^^^^^^^^^^^^^^^^^^^^^^ - -.. automodule:: astropy.tools.misc - :members: \ No newline at end of file diff --git a/_sources/utils/api_collections.txt b/_sources/utils/api_collections.txt deleted file mode 100644 index 7b44d78f..00000000 --- a/_sources/utils/api_collections.txt +++ /dev/null @@ -1,8 +0,0 @@ -`astropy.utils.collections`: Specialized collection classes -=========================================================== - -.. automodule:: astropy.utils.collections - :members: - :undoc-members: - :show-inheritance: - :special-members: diff --git a/_sources/utils/api_console.txt b/_sources/utils/api_console.txt deleted file mode 100644 index 80ebcba2..00000000 --- a/_sources/utils/api_console.txt +++ /dev/null @@ -1,8 +0,0 @@ -`astropy.utils.console`: Utilities for console output -===================================================== - -.. automodule:: astropy.utils.console - :members: - :undoc-members: - :show-inheritance: - :special-members: diff --git a/_sources/utils/api_misc.txt b/_sources/utils/api_misc.txt deleted file mode 100644 index 054c57f3..00000000 --- a/_sources/utils/api_misc.txt +++ /dev/null @@ -1,8 +0,0 @@ -`astropy.utils.misc`: Miscellaneous/uncategorized Utilities -=========================================================== - -.. automodule:: astropy.utils.misc - :members: - :undoc-members: - :show-inheritance: - :special-members: diff --git a/_sources/utils/api_xml.txt b/_sources/utils/api_xml.txt deleted file mode 100644 index 8c186810..00000000 --- a/_sources/utils/api_xml.txt +++ /dev/null @@ -1,38 +0,0 @@ -`astropy.utils.xml`: Utilities related to XML -============================================= - -`astropy.utils.xml.check` -------------------------- - -.. automodule:: astropy.utils.xml.check - :members: - :undoc-members: - :show-inheritance: - :special-members: - -`astropy.utils.xml.iterparser` ------------------------------- - -.. automodule:: astropy.utils.xml.iterparser - :members: - :undoc-members: - :show-inheritance: - :special-members: - -`astropy.utils.xml.validate` ----------------------------- - -.. automodule:: astropy.utils.xml.validate - :members: - :undoc-members: - :show-inheritance: - :special-members: - -`astropy.utils.xml.writer` --------------------------- - -.. automodule:: astropy.utils.xml.writer - :members: - :undoc-members: - :show-inheritance: - :special-members: diff --git a/_sources/utils/index.txt b/_sources/utils/index.txt deleted file mode 100644 index 4c9ceb0e..00000000 --- a/_sources/utils/index.txt +++ /dev/null @@ -1,14 +0,0 @@ -============================= -`astropy.utils` documentation -============================= - -API documentation -================= - -.. toctree:: - :maxdepth: 2 - - api_collections - api_console - api_xml - api_misc diff --git a/_sources/development/vision.txt b/_sources/vision.txt similarity index 77% rename from _sources/development/vision.txt rename to _sources/vision.txt index 82f9bd84..0bd2dadc 100644 --- a/_sources/development/vision.txt +++ b/_sources/vision.txt @@ -1,20 +1,17 @@ -.. _vision: - -============================================ Vision for a Common Astronomy Python Package ============================================ -The following document summarizes a vision for a common Astronomy Python -package, and how we can best all work together to achieve this. In the -following document, this common package will be referred to as the core -package. This vision is not set in stone, and we are committed to adapting it -to whatever process and guidelines work in practice. +The following document summarizes the original 'manifesto' for the Astropy +project which was adopted in July 2011. + +Long-term Vision +---------------- -The ultimate goal that we seek is a package that would contain much of the core -functionality and some common tools required across Astronomy, but not +The ultimate goal that we seek is a package that would contain much of the +core functionality and some common tools required across Astronomy, but not *everything* Astronomers will ever need. The aim is primarily to avoid -duplication for common core tasks, and to provide a robust framework upon which -to build more complex tools. +duplication for common core tasks, and to provide a robust framework upon +which to build more complex tools. Such a common package should not preclude any other Astronomy package from existing, because there will always be more complex and/or specialized tools @@ -45,13 +42,13 @@ independent repositories, which will allow the teams the choice of tool and organization. Once an affiliated package has implemented the desired functionality, and satisfies quality criteria for coding style, documentation, and testing, it will be considered for inclusion in the core package, and -further development will be done directly in the core package either via direct -access to the repository, or via patches/pull requests (exactly how this will -be done will be decided later). +further development will be done directly in the core package either via +direct access to the repository, or via patches/pull requests (exactly how +this will be done will be decided later). To ensure uniformity across affiliated packages, and to facilitate integration with the core package, developers who wish to submit their affiliated packages -for inclusion in the core will need to follow the layout of a ‘template’ +for inclusion in the core will need to follow the layout of a *template* package that will be provided before development starts. Dependencies @@ -60,18 +57,19 @@ Dependencies Affiliated packages should be able to be imported with only the following dependencies: -* The Python Standard Library NumPy, SciPy, and Matplotlib Components already - * in the core Astronomy package +* The Python Standard Library +* NumPy, SciPy, and Matplotlib +* Components already in the core Astronomy package Other packages may be used, but must be imported as needed rather than during the initial import of the package. If a dependency is needed, but is an affiliated package, the dependent package will need to wait until the dependency is integrated into the core package -before being itself considered for inclusion. In the mean time, it can make use -of the other affiliated package in its current form, or other packages, so as -not to stall development. Thus, the first packages to be included in the core -will be those only requiring the standard library, NumPy, SciPy, and +before being itself considered for inclusion. In the mean time, it can make +use of the other affiliated package in its current form, or other packages, so +as not to stall development. Thus, the first packages to be included in the +core will be those only requiring the standard library, NumPy, SciPy, and Matplotlib. If the required dependency will never be part of a main package, then by @@ -82,8 +80,8 @@ by the community that this dependency is important enough to be required at a higher level. This system means that packages will be integrated into the core package in an -order depending on the dependency tree, and also ensures that the interfaces of -packages being integrated into the core package are consistent with those +order depending on the dependency tree, and also ensures that the interfaces +of packages being integrated into the core package are consistent with those already in the core package. Initially, no dependency on GUI toolkits will be allowed in the core package. @@ -106,5 +104,5 @@ Developers who already have existing packages will be encouraged to continue supporting them for the benefit of users until the core library is considered stable, contains this functionality, and is released to the community. Thereafter, developers should encourage users to transition to using the -functionality in the core package, and eventually phase out their own packages, -unless they provide added value over the core package. +functionality in the core package, and eventually phase out their own +packages, unless they provide added value over the core package. diff --git a/_sources/vo/api.txt b/_sources/vo/api.txt deleted file mode 100644 index 1efd735b..00000000 --- a/_sources/vo/api.txt +++ /dev/null @@ -1,30 +0,0 @@ -================= -API documentation -================= - -Public API ----------- - -.. toctree:: - :maxdepth: 2 - - api_table.rst - api_tree.rst - api_converters.rst - api_exceptions.rst - api_ucd.rst - api_unit.rst - api_util.rst - api_validator.rst - api_xmlutil.rst - -Private API ------------ - -These classes are not designed for public use. - -.. toctree:: - :maxdepth: 2 - - api_converters.rst - diff --git a/_sources/vo/api_converters.txt b/_sources/vo/api_converters.txt deleted file mode 100644 index e99baae3..00000000 --- a/_sources/vo/api_converters.txt +++ /dev/null @@ -1,13 +0,0 @@ -.. include:: references.txt - -`astropy.io.vo.converters`: Conversions between XML and Numpy datatypes -======================================================================= - -.. inheritance-diagram:: astropy.io.vo.converters - :parts: 1 - -.. automodule:: astropy.io.vo.converters - :members: - :undoc-members: - :show-inheritance: - diff --git a/_sources/vo/api_exceptions.txt b/_sources/vo/api_exceptions.txt deleted file mode 100644 index af725a71..00000000 --- a/_sources/vo/api_exceptions.txt +++ /dev/null @@ -1,39 +0,0 @@ -`astropy.io.vo.exceptions` -========================== - -.. contents:: - -.. automodule:: astropy.io.vo.exceptions - -Exception utilities -------------------- - -.. currentmodule:: astropy.io.vo.exceptions - -.. autofunction:: warn_or_raise - -.. autofunction:: vo_raise - -.. autofunction:: vo_reraise - -.. autofunction:: vo_warn - -.. autofunction:: parse_vowarning - -.. autoclass:: VOWarning - :show-inheritance: - -.. autoclass:: VOTableChangeWarning - :show-inheritance: - -.. autoclass:: VOTableSpecWarning - :show-inheritance: - -.. autoclass:: UnimplementedWarning - :show-inheritance: - -.. autoclass:: IOWarning - :show-inheritance: - -.. autoclass:: VOTableSpecError - :show-inheritance: diff --git a/_sources/vo/api_table.txt b/_sources/vo/api_table.txt deleted file mode 100644 index cf9b2dd8..00000000 --- a/_sources/vo/api_table.txt +++ /dev/null @@ -1,9 +0,0 @@ -.. include:: references.txt - -`astropy.io.vo.table`: Loading entire VOTable files -=================================================== - -.. automodule:: astropy.io.vo.table - :members: - :undoc-members: - :show-inheritance: diff --git a/_sources/vo/api_tree.txt b/_sources/vo/api_tree.txt deleted file mode 100644 index 11ee8aee..00000000 --- a/_sources/vo/api_tree.txt +++ /dev/null @@ -1,13 +0,0 @@ -.. include:: references.txt - -`astropy.io.vo.tree`: Accessing and modifying the individual parts of VOTable files -=================================================================================== - -.. inheritance-diagram:: astropy.io.vo.tree - :parts: 1 - -.. automodule:: astropy.io.vo.tree - :members: Element, SimpleElement, SimpleElementWithContent, VOTableFile, Resource, Table, Group, Info, Field, Param, Link, CooSys, FieldRef, ParamRef, Values - :undoc-members: - :show-inheritance: - diff --git a/_sources/vo/api_ucd.txt b/_sources/vo/api_ucd.txt deleted file mode 100644 index 142fc7a6..00000000 --- a/_sources/vo/api_ucd.txt +++ /dev/null @@ -1,10 +0,0 @@ -.. include:: references.txt - -`astropy.io.vo.ucd`: Functions to parse and verify unified content descriptors -============================================================================== - -.. automodule:: astropy.io.vo.ucd - :members: - :undoc-members: - :show-inheritance: - diff --git a/_sources/vo/api_unit.txt b/_sources/vo/api_unit.txt deleted file mode 100644 index 780e3e50..00000000 --- a/_sources/vo/api_unit.txt +++ /dev/null @@ -1,10 +0,0 @@ -.. include:: references.txt - -`astropy.io.vo.unit`: Verification of units as defined in the VOTable standard -============================================================================== - -.. automodule:: astropy.io.vo.unit - :members: - :undoc-members: - :show-inheritance: - diff --git a/_sources/vo/api_util.txt b/_sources/vo/api_util.txt deleted file mode 100644 index 8ae20f42..00000000 --- a/_sources/vo/api_util.txt +++ /dev/null @@ -1,10 +0,0 @@ -.. include:: references.txt - -`astropy.io.vo.util`: Low-level utilities used by the library -============================================================= - -.. automodule:: astropy.io.vo.util - :members: - :undoc-members: - :show-inheritance: - diff --git a/_sources/vo/api_validator.txt b/_sources/vo/api_validator.txt deleted file mode 100644 index b5a71980..00000000 --- a/_sources/vo/api_validator.txt +++ /dev/null @@ -1,11 +0,0 @@ -.. include:: references.txt - -`astropy.io.vo.validator`: Generates HTML validation reports -============================================================ - -.. automodule:: astropy.io.vo.validator - :members: - :undoc-members: - :show-inheritance: - -.. autofunction:: astropy.io.vo.validator.main.make_validation_report diff --git a/_sources/vo/api_xmlutil.txt b/_sources/vo/api_xmlutil.txt deleted file mode 100644 index 94d6de53..00000000 --- a/_sources/vo/api_xmlutil.txt +++ /dev/null @@ -1,9 +0,0 @@ -.. include:: references.txt - -`astropy.io.vo.xmlutil`: XML-related utilities used by the library -================================================================== - -.. automodule:: astropy.io.vo.xmlutil - :members: - :undoc-members: - :show-inheritance: diff --git a/_sources/vo/index.txt b/_sources/vo/index.txt deleted file mode 100644 index dc672bdd..00000000 --- a/_sources/vo/index.txt +++ /dev/null @@ -1,10 +0,0 @@ -astropy.io.vo Documentation -=========================== - -Contents: - -.. toctree:: - :maxdepth: 2 - - intro_table.rst - api.rst diff --git a/_sources/vo/intro_table.txt b/_sources/vo/intro_table.txt deleted file mode 100644 index cc4adcc3..00000000 --- a/_sources/vo/intro_table.txt +++ /dev/null @@ -1,282 +0,0 @@ -Introduction to ``astropy.io.vo.table`` -======================================= - -`astropy.io.vo.table` is a Python package to read and write VOTable -files into Numpy record arrays. - -Standard compliance -------------------- - -`astropy.io.vo.table` supports the `VOTable Format Definition Version -1.1 -`_ -and `Version 1.2 -`_. -Some flexibility is provided to support the 1.0 draft version and -other non-standard usage in the wild. To support these cases, set the -keyword argument ``pedantic`` to ``False`` when parsing. - -.. note:: - - Each warning and VOTABLE-specific exception emitted has a number and - is documented in more detail in :ref:`warnings` and - :ref:`exceptions`. - -Output always conforms to the 1.1 or 1.2 spec, depending on the input. - -Using `astropy.io.vo.table` ---------------------------- - -Reading a VOTable file -~~~~~~~~~~~~~~~~~~~~~~ - -To read in a VOTable file, pass a file path to -`astropy.io.vo.table.parse`:: - - from astropy.io.vo.table import parse - votable = parse("votable.xml") - -``votable`` is a `~astropy.io.vo.tree.VOTableFile` object, which can -be used to retrieve and manipulate the data and save it back out to -disk. - -VOTable files are made up of nested ``RESOURCE`` elements, each of -which may contain one or more ``TABLE`` elements. The ``TABLE`` -elements contain the arrays of data. - -To get at the ``TABLE`` elements, one can write a loop over the -resources in the ``VOTABLE`` file:: - - for resource in votable.resources: - for table in resource.tables: - # ... do something with the table ... - pass - -However, if the nested structure of the resources is not important, -one can use `~astropy.io.vo.tree.VOTable.iter_tables` to return a flat -list of all tables:: - - for table in votable.iter_tables(): - # ... do something with the table ... - pass - -Finally, if there is expected to be only one table in the file, it -might be simplest to just use -`~astropy.io.vo.tree.VOTable.get_first_table`:: - - table = votable.get_first_table() - -Even easier, there is a convenience method to parse a VOTable file and -return the first table all in one step:: - - from astropy.io.vo.table import parse_single_table - table = parse_single_table("votable.xml") - -From a `~astropy.io.vo.tree.Table` object, one can get the data itself -in the ``array`` member variable:: - - data = table.array - -This data is a Numpy record array. The columns get their names from -both the ``ID`` and ``name`` attributes of the ``FIELD`` elements in -the ``VOTABLE`` file. For example, suppose we had a ``FIELD`` -specified as follows: - -.. code-block:: xml - - - - representing the ICRS declination of the center of the image. - - - -This column of data can be extracted from the record array using:: - - >>> table.array['dec_targ'] - array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826, - 17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136, - 17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055, - 17.1553884541, 17.15539736932, 17.15539752176, - 17.25736014763, - # ... - 17.2765703], dtype=object) - -or equivalently:: - - >>> table.array['Dec'] - array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826, - 17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136, - 17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055, - 17.1553884541, 17.15539736932, 17.15539752176, - 17.25736014763, - # ... - 17.2765703], dtype=object) - -.. _pedantic-mode: - -Pedantic mode -````````````` - -Many VOTABLE files in the wild do not conform to the VOTABLE -specification. If reading one of these files causes exceptions, you -may turn off pedantic mode in `astropy.io.vo` by passing -``pedantic=False`` to the `~astropy.io.vo.table.parse` or -`~astropy.io.vo.table.parse_single_table` functions:: - - from astropy.io.vo.table import parse - votable = parse("votable.xml", pedantic=False) - -Note, however, that it is good practice to report these errors to the -author of the application that generated the VOTABLE file to bring the -file into compliance with the specification. - -Even with ``pedantic`` turned off, many warnings may still be omitted. -These warnings are all of the type -`~astropy.io.vo.exceptions.VOTableSpecWarning` and can be turned off -using the standard Python `warnings` module. - -Building a new table from scratch -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It is also possible to build a new table, define some field datatypes -and populate it with data:: - - from astropy.io.vo.tree import VOTableFile, Resource, Table, Field - - # Create a new VOTable file... - votable = VOTableFile() - - # ...with one resource... - resource = Resource() - votable.resources.append(resource) - - # ... with one table - table = Table(votable) - resource.tables.append(table) - - # Define some fields - table.fields.extend([ - Field(votable, ID="filename", datatype="char"), - Field(votable, ID="matrix", datatype="double", arraysize="2x2")]) - - # Now, use those field definitions to create the numpy record arrays, with - # the given number of rows - table.create_arrays(2) - - # Now table.array can be filled with data - table.array[0] = ('test1.xml', [[1, 0], [0, 1]]) - table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]]) - - # Now write the whole thing to a file. - # Note, we have to use the top-level votable file object - votable.to_xml("new_votable.xml") - -Missing values -~~~~~~~~~~~~~~ - -Any value in the table may be "missing". `astropy.io.vo.table` stores -a parallel array in each `~astropy.io.vo.tree.Table` instance called -`~astropy.io.vo.tree.Table.mask` to keep track of missing values. -This array is ``False`` anywhere the value is missing. - -.. note:: - In the future, the ``array`` and ``mask`` members will likely be - combined into a single masked record array. There are - implementation bugs in current versions of Numpy that prevent this - at the moment. - -Datatype mappings -~~~~~~~~~~~~~~~~~ - -The datatype specified by a ``FIELD`` element is mapped to a Numpy -type according to the following table: - - ================================ ======================================================================== - VOTABLE type Numpy type - ================================ ======================================================================== - boolean b1 - -------------------------------- ------------------------------------------------------------------------ - bit b1 - -------------------------------- ------------------------------------------------------------------------ - unsignedByte u1 - -------------------------------- ------------------------------------------------------------------------ - char (*variable length*) O - In Python 2.x, a `str` object; in 3.x, a `bytes` object. - -------------------------------- ------------------------------------------------------------------------ - char (*fixed length*) S - -------------------------------- ------------------------------------------------------------------------ - unicodeChar (*variable length*) O - In Python 2.x, a `unicode` object, in utf-16; in 3.x a `str` object - -------------------------------- ------------------------------------------------------------------------ - unicodeChar (*fixed length*) U - -------------------------------- ------------------------------------------------------------------------ - short i2 - -------------------------------- ------------------------------------------------------------------------ - int i4 - -------------------------------- ------------------------------------------------------------------------ - long i8 - -------------------------------- ------------------------------------------------------------------------ - float f4 - -------------------------------- ------------------------------------------------------------------------ - double f8 - -------------------------------- ------------------------------------------------------------------------ - floatComplex c8 - -------------------------------- ------------------------------------------------------------------------ - doubleComplex c16 - ================================ ======================================================================== - -If the field is a fixed size array, the data is stored as a Numpy -fixed-size array. - -If the field is a variable size array (that is ``arraysize`` contains -a '*'), the cell will contain a Python list of Numpy values. Each -value may be either an array or scalar depending on the ``arraysize`` -specifier. - -Examining field types -~~~~~~~~~~~~~~~~~~~~~ - -To look up more information about a field in a table, one can use the -`~astropy.io.vo.tree.Table.get_field_or_param_by_id` method, which -returns the `~astropy.io.vo.tree.Field` object with the given ID. For -example:: - - >>> field = table.get_field_or_param_by_id('Dec') - >>> field.datatype - 'char' - >>> field.unit - 'deg' - -.. note:: - Field descriptors should not be mutated -- they will have no effect - on the record arrays storing the data. This shortcoming will be - addressed in a future version of `astropy.io.vo`. - -Outputting a VOTable file -~~~~~~~~~~~~~~~~~~~~~~~~~ - -To save a VOTable file, simply call the -`~astropy.io.vo.tree.VOTableFile.to_xml` method. It accepts either a -string or unicode path, or a Python file-like object:: - - votable.to_xml('output.xml') - -There are currently two data storage formats supported by -`astropy.io.vo`. The ``TABLEDATA`` format is XML-based and stores -values as strings representing numbers. The ``BINARY`` format is more -compact, and stores numbers in base64-encoded binary. The storage -format can be set on a per-table basis using the -`~astropy.io.vo.tree.Table.format` attribute, or globally using the -`~astropy.io.vo.tree.VOTableFile.set_all_tables_format` method:: - - votable.get_first_table().format = 'binary' - votable.set_all_tables_format('binary') - votable.to_xml('binary.xml') - -Performance considerations --------------------------- - -File reads will be moderately faster if the ``TABLE`` element includes -an nrows_ attribute. If the number of rows is not specified, the -record array must be resized repeatedly during load. - -.. _nrows: http://www.ivoa.net/Documents/REC/VOTable/VOTable-20040811.html#ToC10 diff --git a/_sources/wcs/api.txt b/_sources/wcs/api.txt deleted file mode 100644 index 3aaa4ec5..00000000 --- a/_sources/wcs/api.txt +++ /dev/null @@ -1,23 +0,0 @@ -.. include:: references.txt - -API Documentation -================= - -:mod:`astropy.wcs` ------------------- - -.. automodule:: astropy.wcs.wcs - -Classes -------- - -.. toctree:: - :maxdepth: 2 - - api_wcs.rst - api_wcsprm.rst - api_distortion.rst - api_sip.rst - api_units.rst - relax.rst - diff --git a/_sources/wcs/api_distortion.txt b/_sources/wcs/api_distortion.txt deleted file mode 100644 index 2171e91d..00000000 --- a/_sources/wcs/api_distortion.txt +++ /dev/null @@ -1,10 +0,0 @@ -.. include:: references.txt - -`DistortionLookupTable` -``````````````````````` - -.. autoclass:: astropy.wcs.DistortionLookupTable - :members: - :inherited-members: - :undoc-members: - diff --git a/_sources/wcs/api_sip.txt b/_sources/wcs/api_sip.txt deleted file mode 100644 index 164708f4..00000000 --- a/_sources/wcs/api_sip.txt +++ /dev/null @@ -1,10 +0,0 @@ -.. include:: references.txt - -`Sip` -````` - -.. autoclass:: astropy.wcs.Sip - :members: - :inherited-members: - :undoc-members: - diff --git a/_sources/wcs/api_units.txt b/_sources/wcs/api_units.txt deleted file mode 100644 index 8007e295..00000000 --- a/_sources/wcs/api_units.txt +++ /dev/null @@ -1,299 +0,0 @@ -.. include:: references.txt - -`UnitConverter` -``````````````` - -.. autoclass:: astropy.wcs.UnitConverter - :members: - :inherited-members: - :undoc-members: - -.. _fits-unit: - -FITS unit specification -``````````````````````` - -Supported units ---------------- - -The following units are supported by the FITS standard: - -**SI base & supplementary units** - -====================== ============ ================= -Quantity Unit String Meaning -====================== ============ ================= -length m metre -mass kg kilogram -time s second of time -plane angle rad radian -solid angle sr steradian -temperature K kelvin -electric current A ampere -amount of substance mol mole -luminous intensity cd candela -====================== ============ ================= - -**IAU-recognized derived units** - -====================== ============ ================= ================== -Quantity Unit String Meaning Equivalence -====================== ============ ================= ================== -frequency Hz hertz s\ :sup:`-1` -energy J joule N m -power W watt J s\ :sup:`-1` -electric potential V volts J C\ :sup:`-1` -force N newton kg m s\ :sup:`-2` -pressure, stress Pa pascal N m\ :sup:`-2` -electric charge C coulomb A s -electric resistance ohm ohm (Ω) V A\ :sup:`-1` -electric conductance S siemens A V\ :sup:`-1` -electric capacitance F farad C V\ :sup:`-1` -magnetic flux Wb weber V s -magnetic flux density T tesla Wb m\ :sup:`-2` -inductance H henry Wb A\ :sup:`-1` -luminous flux lm lumen cd sr -illuminance lx lux lm m\ :sup:`-2` -====================== ============ ================= ================== - -**Additional units** - -====================== ============ ======================== ============================================ -Quantity Unit String Meaning Equivalence -====================== ============ ======================== ============================================ -mass u unified atomic mass unit 1.6605387 x 10\ :sup:`-27` kg -mass solMass solar mass 1.9891 x 10\ :sup:`30` kg -plane angle deg degree of arc 1.745533 x 10\ :sup:`-2` rad -plane angle arcsec second of arc 4.848137 x 10\ :sup:`-6` rad -plane angle arcmin minute of arc 2.90888 x 10\ :sup:`-4` rad -time min minute -time h hour -time d day 8.64 x 10\ :sup:`4` s -time yr year (Julian) 3.15576 x10\ :sup:`-7` s (365.25 d) -energy eV electron volt 1.602177 x 10\ :sup:`-19` J -energy erg erg 10\ :sup:`-7` J -energy Ry Rydberg 13.605692 eV -length angstrom angstrom 10\ :sup:`-10` m -length AU astronomical unit 1.49598 x 10\ :sup:`11` m -length lyr light year 9.460530 x 10\ :sup:`-15` m -length pc parsec 3.0857 x 10\ :sup:`-16` m -length solRad solar radius 6.9599 x 10\ :sup:`8` m -events count counts -events photon photons -flux density Jy jansky 10\ :sup:`-16` W m\ :sup:`-2` Hz\ :sup:`-1` -flux density mag (stellar) magnitude -flux density Crab 'crab' -flux density beam beam Jy/beam -flux density solLum solar luminosity -magnetic field G gauss 10\ :sup:`-4` T -area pixel (image/detector) pixel -area voxel 3-d analog of pixel -area barn barn 10\ :sup:`-28` m\ :sup:`2` -device chan (detector) channel -device byte (computer) byte -device bit (computer) bits -device adu A/D converter units -misc bin numerous applications -misc Sun wrt. sun -====================== ============ ======================== ============================================ - -Potentially unsafe translations of ``"D"``, ``"H"``, and ``"S"``, are -optional, using the *translate_units* parameter. - -.. _unit-aliases: - -Unit aliases ------------- - -When converting non-standard units to standard ones, a case-sensitive -match is required for the aliases listed below, in particular the only -recognized aliases with metric prefixes are ``"KM"``, ``"KHZ"``, -``"MHZ"``, and ``"GHZ"``. - -========== ============================================================= -Unit Recognized aliases -========== ============================================================= -Angstrom angstrom -arcmin arcmins, ARCMIN, ARCMINS -arcsec arcsecs, ARCSEC, ARCSECS -beam BEAM -byte Byte -count ct -d day, days, (D), DAY, DAYS -deg degree, degrees, DEG, DEGREE, DEGREES -GHz GHZ -h hr, (H), HR -Hz hz, HZ -kHz KHZ -Jy JY -K kelvin, kelvins, Kelvin, Kelvins, KELVIN, KELVINS -km KM -m metre, meter, metres, meters, M, METRE, METER, METRES, METERS -min MIN -MHz MHZ -Ohm ohm -Pa pascal, pascals, Pascal, Pascals, PASCAL, PASCALS -photon ph -pixel pixels, PIXEL, PIXELS, pix -rad radian, radians, RAD, RADIAN, RADIANS -s sec, second, seconds, (S), SEC, SECOND, SECONDS -V volt, volts, Volt, Volts, VOLT, VOLTS -yr year, years, YR, YEAR, YEARS -========== ============================================================= - -The aliases ``"angstrom"``, ``"ohm"``, and ``"Byte"`` for (Angstrom, -Ohm, and byte) are recognized by astropy.wcs/wcslib itself as an -unofficial extension of the standard, but they are converted to the -standard form here. - -Prefixes --------- - -The following metric prefixes are supported: - -======= ======= =================== -Prefix String Magnitude -======= ======= =================== -yocto y 10\ :sup:`-24` -zepto z 10\ :sup:`-21` -atto a 10\ :sup:`-18` -femto f 10\ :sup:`-15` -pico p 10\ :sup:`-12` -nano n 10\ :sup:`-9` -micro u 10\ :sup:`-6` -milli m 10\ :sup:`-3` -centi c 10\ :sup:`-2` -deci d 10\ :sup:`-1` -deka da 10\ :sup:`1` -hecto h 10\ :sup:`2` -kilo k 10\ :sup:`3` -Mega M 10\ :sup:`6` -Giga G 10\ :sup:`9` -Tera T 10\ :sup:`12` -Peta P 10\ :sup:`15` -Exa E 10\ :sup:`18` -Zetta Z 10\ :sup:`21` -Yotta Y 10\ :sup:`24` -======= ======= =================== - -Table 6 of WCS Paper I lists eleven units for which metric prefixes -are allowed. However, in this implementation only prefixes greater -than unity are allowed for ``"a"`` (annum), ``"yr"`` (year), ``"pc"`` -(parsec), ``"bit"``, and ``"byte"``, and only prefixes less than unity -are allowed for ``"mag"`` (stellar magnitude). - -Metric prefix ``"P"`` (peta) is specifically forbidden for ``"a"`` -(annum) to avoid confusion with ``"Pa"`` (Pascal, not peta-annum). -Note that metric prefixes are specifically disallowed for ``"h"`` -(hour) and ``"d"`` (day) so that ``"ph"`` (photons) cannot be -interpreted as pico-hours, nor ``"cd"`` (candela) as centi-days. - -Operators ---------- - -A compound unit is considered to be formed by a series of sub-strings -of component units & mathematical operations. Each of these -sub-strings must be separated by at least one space or a mathematical -operator (``*`` or ``/``). - -Multiplication -============== - -Multiplicative units can be specified either: - -- by simply using one or more preceding spaces, e.g. ``str1 str2`` - (The recommended method). - -- by the use of a single asterisk (``*``) with optional whitespace, - e.g. ``str1 * str2``. - -Division -======== - -Units which form the denominator of a compound expression can be -specified either: - -- by using a slash (``/``) with optional whitespace, e.g. ``str1 / - str2``. If such a syntax is used, it is recommended that no space - is included between the slash and the unit string. - -- by raising a multiplicative unit to a negative power (see below). - -It should be stressed that the slash character only effects the -sub-string it immediately precedes. Thus, unless brackets are used, -subsequent sub-strings which also form part of the denominator of the -compound expression must also be preceded by a slash. For example, -``str1 /str2 str3`` is equivalent to ``str1 str3 /str2`` whilst ``str1 -/str2 /str3`` is equivalent to ``str1 /(str2 * str3)``. - -Raising to Powers -================= - -A unit string raised to the power *y* is specified: - -- by using two asterisks (``**``) followed by the index enclosed - within round brackets and with no preceding or intervening spaces, - e.g. ``str1**(y)`` or ``str1**(-y)``. - -However, if *y* is positive, then the brackets need not be included, -but a following space is recommended if additional sub-strings follow. - -Use of brackets -=============== - -Any number of pairs of round brackets (``()``) may be used within the -string for a compound unit in order to prevent ambiguities. As -described within this section, a number of rules always/often require -their use. However, it is suggested that conservative use is made of -such pairs of brackets in order to minimize the total length of -compound strings. (It should be remembered that a maximum of 68 -characters are allowed in the card image of keywords.) - -Avoidance of underflows & overflows -=================================== - -The inclusion of numerical factors within the unit string should -generally be avoided (by the use of multiples and/or submultiples of -component basic units). - -However, occasionally it may be preferable to include such factors on -the grounds of user-friendliness and/or to minimize the risk of -computer under- or overflows. In such cases, the numerical factor can -simply be considered a basic unit string. - -The following additional guidelines are suggested: - -- the numerical factor should precede any unit strings - -- only powers of 10 are used as numerical factors - -Mathematical Operations & Functions -=================================== - -A number of mathematical operations are supported. It should be noted -that the (round) brackets are mandatory in all cases in which they are -included in the table. - -=============== ================================================== -String Meaning -=============== ================================================== -``str1*str2`` Multiplication -``str1 /str2`` Division -``str1**(y)`` Raised to the power *y* -``log(str1)`` Common Logarithm (to base 10) -``ln(str1)`` Natural Logarithm -``exp(str1)`` Exponential (exp\ :sup:`str1`\ ) -``sqrt(str1)`` Square root -``sin(str1)`` Sine -``cos(str1)`` Cosine -``tan(str1)`` Tangent -``asin(str1)`` Arc Sine -``acos(str1)`` Arc Cosine -``atan(str1)`` Arc Tangent -``sinh(str1)`` Hyperbolic Sine -``cosh(str1)`` Hyperbolic Cosine -``tanh(str1)`` Hyperbolic Tangent -=============== ================================================== - -Function types ``log()``, ``ln()`` and ``exp()`` may only occur at the -start of the units specification. diff --git a/_sources/wcs/api_wcs.txt b/_sources/wcs/api_wcs.txt deleted file mode 100644 index 5c77a0c0..00000000 --- a/_sources/wcs/api_wcs.txt +++ /dev/null @@ -1,14 +0,0 @@ -.. include:: references.txt - -`WCS` -````` - -.. autoclass:: astropy.wcs.WCS - :members: - :inherited-members: - :undoc-members: - -functions -````````` - -.. autofunction:: astropy.wcs.find_all_wcs diff --git a/_sources/wcs/api_wcsprm.txt b/_sources/wcs/api_wcsprm.txt deleted file mode 100644 index 24701620..00000000 --- a/_sources/wcs/api_wcsprm.txt +++ /dev/null @@ -1,26 +0,0 @@ -.. include:: references.txt - -`Wcsprm` -```````` - -.. autoclass:: astropy.wcs.Wcsprm - :members: - :inherited-members: - :undoc-members: - -`Tabprm` -```````` - -.. autoclass:: astropy.wcs._wcs.Tabprm - :members: - :inherited-members: - :undoc-members: - -.. `Wtbarr` -.. ```````` - -.. .. autoclass:: pywcs._pywcs.Wtbarr -.. :members: -.. :inherited-members: -.. :undoc-members: - diff --git a/_sources/wcs/examples.txt b/_sources/wcs/examples.txt deleted file mode 100644 index 7c430094..00000000 --- a/_sources/wcs/examples.txt +++ /dev/null @@ -1,22 +0,0 @@ -Example Usage -============= - -Loading WCS information from a FITS file ----------------------------------------- - -This example loads a FITS file (supplied on the commandline) and uses -the WCS cards in its primary header to transform. - -.. literalinclude:: examples/from_file.py - :language: python - -Building a WCS structure programmatically ------------------------------------------ - -This example, rather than starting from a FITS header, sets WCS values -programmatically, uses those settings to transform some points, and then -saves those settings to a new FITS header. - -.. literalinclude:: examples/programmatic.py - :language: python - diff --git a/_sources/wcs/history.txt b/_sources/wcs/history.txt deleted file mode 100644 index 0caa082d..00000000 --- a/_sources/wcs/history.txt +++ /dev/null @@ -1,90 +0,0 @@ -astropy.wcs History -=================== - -`astropy.wcs` began life as `pywcs`. Earlier version numbers refer to -that package. - -pywcs Version 1.11 ------------------- - -- Updated to wcslib version 4.8, which gives much more detailed error - messages. - -- Added functions get_pc() and get_cdelt(). These provide a way to - always get the canonical representation of the linear transformation - matrix, whether the header specified it in PC, CD or CROTA form. - -- Long-running process will now release the Python GIL to better - support Python multithreading. - -- The dimensions of the `~astropy.wcs.Wcsprm.cd` and - `~astropy.wcs.Wcsprm.pc` matrices were always returned as 2x2. They - now are sized according to naxis. - -- Supports Python 3.x - -- Builds on Microsoft Windows without severely patching wcslib. - -- Lots of new unit tests - -- `pywcs` will now run without `pyfits`, though the SIP and distortion - lookup table functionality is unavailable. - -- Setting `~astropy.wcs.Wcsprm.cunit` will now verify that the values - are valid unit strings. - -pywcs Version 1.10 ------------------- - -- Adds a `UnitConversion` class, which gives access to wcslib's unit - conversion functionality. Given two convertible unit strings, pywcs - can convert arrays of values from one to the other. - -- Now uses wcslib 4.7 - -- Changes to some wcs values would not always calculate secondary values. - -pywcs Version 1.9 ------------------ - -- Support binary image arrays and pixel list format WCS by presenting - a way to call wcslib's `wcsbth()` - -- Updated underlying wcslib to version 4.5, which fixes the following: - - - Fixed the interpretation of VELREF when translating - AIPS-convention spectral types. Such translation is now handled - by a new special- purpose function, spcaips(). The wcsprm - struct has been augmented with an entry for velref which is - filled by wcspih() and wcsbth(). Previously, selection by - VELREF of the radio or optical velocity convention for type VELO - was not properly handled. - -Bugs -```` - -- The `~astropy.wcs.Wcsprm.pc` member is now available with a default - raw `~astropy.wcs.Wcsprm` object. - -- Make properties that return arrays read-only, since modifying a - (mutable) array could result in secondary values not being - recomputed based on those changes. - -- `float` properties can now be set using `int` values - -pywcs Version 1.3a1 -------------------- - -Earlier versions of pywcs had two versions of every conversion method:: - - X(...) -- treats the origin of pixel coordinates at (0, 0) - X_fits(...) -- treats the origin of pixel coordinates at (1, 1) - -From version 1.3 onwards, there is only one method for each -conversion, with an 'origin' argument: - - - 0: places the origin at (0, 0), which is the C/Numpy convention. - - - 1: places the origin at (1, 1), which is the Fortran/FITS - convention. - diff --git a/_sources/wcs/index.txt b/_sources/wcs/index.txt deleted file mode 100644 index 5cc32c98..00000000 --- a/_sources/wcs/index.txt +++ /dev/null @@ -1,31 +0,0 @@ -.. astropy.wcs documentation master file, created by - sphinx-quickstart on Thu Sep 17 12:58:53 2009. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -========================= -astropy.wcs Documentation -========================= - -Python wrappers, SIP, Paper IV support (BSD License): - - `Michael Droettboom `_, Nadia Dencheva - - Space Telescope Science Institute - -wcslib (LGPL License): - - Mark Calabretta - - Australia Telescope National Facility, CSIRO (wcslib) - -.. automodule:: astropy.wcs - -Contents: - -.. toctree:: - :maxdepth: 2 - - examples.rst - api.rst - history.rst diff --git a/_sources/wcs/relax.txt b/_sources/wcs/relax.txt deleted file mode 100644 index a958ff90..00000000 --- a/_sources/wcs/relax.txt +++ /dev/null @@ -1,365 +0,0 @@ -.. include:: references.txt - -.. _relax: - -Relax constants -``````````````` - -.. _relaxread: - -Header-reading relaxation constants ------------------------------------ - -`~astropy.wcs.WCS`, `~astropy.wcs.Wcsprm` and -`~astropy.wcs.find_all_wcs` have a *relax* argument, which may be -either `True`, `False` or an `int`. - -- If `True`, all non-standard WCS extensions recognized by the parser - will be handled. - -- If `False` (default), none of the extensions (even those in the - errata) will be handled. Non-conformant keywords will be handled in - the same way as non-WCS keywords in the header, i.e. by simply - ignoring them. - -- If an `int`, is is a bit field to provide fine-grained control over - what non-standard WCS keywords to accept. The flag bits are subject - to change in future and should be set by using the constants - beginning with ``WCSHDR_`` in the `astropy.wcs` module. - - For example, to accept ``CD00i00j`` and ``PC00i00j`` use:: - - relax = astropy.wcs.WCSHDR_CD00i00j | astropy.wcs.WCSHDR_PC00i00j - - The parser always treats ``EPOCH`` as subordinate to ``EQUINOXa`` if - both are present, and ``VSOURCEa`` is always subordinate to - ``ZSOURCEa``. - - Likewise, ``VELREF`` is subordinate to the formalism of WCS Paper - III. - -The flag bits are: - -- `WCSHDR_none`: Don't accept any extensions (not even those in the - errata). Treat non-conformant keywords in the same way as non-WCS - keywords in the header, i.e. simply ignore them. (This is - equivalent to the default behavior or passing `False`) - -- `WCSHDR_all`: Accept all extensions recognized by the parser. (This - is equivalent to passing `True`). - -- `WCSHDR_CROTAia`: Accept ``CROTAia``, ``iCROTna``, ``TCROTna`` -- `WCSHDR_EPOCHa`: Accept ``EPOCHa``. -- `WCSHDR_VELREFa`: Accept ``VELREFa``. - - The constructor always recognizes the AIPS-convention - keywords, ``CROTAn``, ``EPOCH``, and ``VELREF`` for the - primary representation ``(a = ' ')`` but alternates are - non-standard. - - The constructor accepts ``EPOCHa`` and ``VELREFa`` only if - `WCSHDR_AUXIMG` is also enabled. - -- `WCSHDR_CD00i00j`: Accept ``CD00i00j``. -- `WCSHDR_PC00i00j`: Accept ``PC00i00j``. -- `WCSHDR_PROJPn`: Accept ``PROJPn`` - - These appeared in early drafts of WCS Paper I+II (before they - were split) and are equivalent to ``CDi_ja``, ``PCi_ja``, and - ``PVi_ma`` for the primary representation ``(a = ' ')``. - ``PROJPn`` is equivalent to ``PVi_ma`` with ``m`` = ``n`` <= - 9, and is associated exclusively with the latitude axis. - -- `WCSHDR_RADECSYS`: Accept ``RADECSYS``. This appeared in early - drafts of WCS Paper I+II and was subsequently replaced by - ``RADESYSa``. The construtor accepts ``RADECSYS`` only if - `WCSHDR_AUXIMG` is also enabled. - -- `WCSHDR_VSOURCE`: Accept ``VSOURCEa`` or ``VSOUna``. This appeared - in early drafts of WCS Paper III and was subsequently dropped in - favour of ``ZSOURCEa`` and ``ZSOUna``. The constructor accepts - ``VSOURCEa`` only if `WCSHDR_AUXIMG` is also enabled. - -- `WCSHDR_DOBSn`: Allow ``DOBSn``, the column-specific analogue of - ``DATE-OBS``. By an oversight this was never formally defined in - the standard. - -- `WCSHDR_LONGKEY`: Accept long forms of the alternate binary table - and pixel list WCS keywords, i.e. with "a" non- blank. - Specifically:: - - jCRPXna TCRPXna : jCRPXn jCRPna TCRPXn TCRPna CRPIXja - - TPCn_ka : - ijPCna - TPn_ka PCi_ja - - TCDn_ka : - ijCDna - TCn_ka CDi_ja - iCDLTna TCDLTna : iCDLTn iCDEna TCDLTn TCDEna CDELTia - iCUNIna TCUNIna : iCUNIn iCUNna TCUNIn TCUNna CUNITia - iCTYPna TCTYPna : iCTYPn iCTYna TCTYPn TCTYna CTYPEia - iCRVLna TCRVLna : iCRVLn iCRVna TCRVLn TCRVna CRVALia - iPVn_ma TPVn_ma : - iVn_ma - TVn_ma PVi_ma - iPSn_ma TPSn_ma : - iSn_ma - TSn_ma PSi_ma - - where the primary and standard alternate forms together with the - image-header equivalent are shown rightwards of the colon. - - The long form of these keywords could be described as quasi- - standard. ``TPCn_ka``, ``iPVn_ma``, and ``TPVn_ma`` appeared by - mistake in the examples in WCS Paper II and subsequently these and - also ``TCDn_ka``, ``iPSn_ma`` and ``TPSn_ma`` were legitimized by - the errata to the WCS papers. - - Strictly speaking, the other long forms are non-standard and in fact - have never appeared in any draft of the WCS papers nor in the - errata. However, as natural extensions of the primary form they are - unlikely to be written with any other intention. Thus it should be - safe to accept them provided, of course, that the resulting keyword - does not exceed the 8-character limit. - - If ``WCSHDR_CNAMn`` is enabled then also accept:: - - iCNAMna TCNAMna : --- iCNAna --- TCNAna CNAMEia - iCRDEna TCRDEna : --- iCRDna --- TCRDna CRDERia - iCSYEna TCSYEna : --- iCSYna --- TCSYna CSYERia - - Note that ``CNAMEia``, ``CRDERia``, ``CSYERia``, and their variants - are not used by `astropy.wcs` but are stored as auxiliary information. - -- `WCSHDR_CNAMn`: Accept ``iCNAMn``, ``iCRDEn``, ``iCSYEn``, - ``TCNAMn``, ``TCRDEn``, and ``TCSYEn``, i.e. with ``a`` blank. - While non-standard, these are the obvious analogues of ``iCTYPn``, - ``TCTYPn``, etc. - -- `WCSHDR_AUXIMG`: Allow the image-header form of an auxiliary WCS - keyword with representation-wide scope to provide a default value - for all images. This default may be overridden by the - column-specific form of the keyword. - - For example, a keyword like ``EQUINOXa`` would apply to all image - arrays in a binary table, or all pixel list columns with alternate - representation ``a`` unless overridden by ``EQUIna``. - - Specifically the keywords are:: - - LATPOLEa for LATPna - LONPOLEa for LONPna - RESTFREQ for RFRQna - RESTFRQa for RFRQna - RESTWAVa for RWAVna - - whose keyvalues are actually used by WCSLIB, and also keywords that - provide auxiliary information that is simply stored in the wcsprm - struct:: - - EPOCH - ... (No column-specific form.) - EPOCHa - ... Only if WCSHDR_EPOCHa is set. - EQUINOXa for EQUIna - RADESYSa for RADEna - RADECSYS for RADEna ... Only if WCSHDR_RADECSYS is set. - SPECSYSa for SPECna - SSYSOBSa for SOBSna - SSYSSRCa for SSRCna - VELOSYSa for VSYSna - VELANGLa for VANGna - VELREF - ... (No column-specific form.) - VELREFa - ... Only if WCSHDR_VELREFa is set. - VSOURCEa for VSOUna ... Only if WCSHDR_VSOURCE is set. - WCSNAMEa for WCSNna ... Or TWCSna (see below). - ZSOURCEa for ZSOUna - - DATE-AVG for DAVGn - DATE-OBS for DOBSn - MJD-AVG for MJDAn - MJD-OBS for MJDOBn - OBSGEO-X for OBSGXn - OBSGEO-Y for OBSGYn - OBSGEO-Z for OBSGZn - - where the image-header keywords on the left provide default values - for the column specific keywords on the right. - - Keywords in the last group, such as ``MJD-OBS``, apply to all - alternate representations, so ``MJD-OBS`` would provide a default - value for all images in the header. - - This auxiliary inheritance mechanism applies to binary table image - arrays and pixel lists alike. Most of these keywords have no - default value, the exceptions being ``LONPOLEa`` and ``LATPOLEa``, - and also ``RADESYSa`` and ``EQUINOXa`` which provide defaults for - each other. Thus the only potential difficulty in using - `WCSHDR_AUXIMG` is that of erroneously inheriting one of these four - keywords. - - Unlike `WCSHDR_ALLIMG`, the existence of one (or all) of these - auxiliary WCS image header keywords will not by itself cause a - `~astropy.wcs.Wcsprm` object to be created for alternate - representation ``a``. This is because they do not provide - sufficient information to create a non-trivial coordinate - representation when used in conjunction with the default values of - those keywords, such as ``CTYPEia``, that are parameterized by axis - number. - -- `WCSHDR_ALLIMG`: Allow the image-header form of *all* image header - WCS keywords to provide a default value for all image arrays in a - binary table (n.b. not pixel list). This default may be overridden - by the column-specific form of the keyword. - - For example, a keyword like ``CRPIXja`` would apply to all image - arrays in a binary table with alternate representation ``a`` - unless overridden by ``jCRPna``. - - Specifically the keywords are those listed above for `WCSHDR_AUXIMG` - plus:: - - WCSAXESa for WCAXna - - which defines the coordinate dimensionality, and the following - keywords which are parameterized by axis number:: - - CRPIXja for jCRPna - PCi_ja for ijPCna - CDi_ja for ijCDna - CDELTia for iCDEna - CROTAi for iCROTn - CROTAia - ... Only if WCSHDR_CROTAia is set. - CUNITia for iCUNna - CTYPEia for iCTYna - CRVALia for iCRVna - PVi_ma for iVn_ma - PSi_ma for iSn_ma - - CNAMEia for iCNAna - CRDERia for iCRDna - CSYERia for iCSYna - - where the image-header keywords on the left provide default values - for the column specific keywords on the right. - - This full inheritance mechanism only applies to binary table image - arrays, not pixel lists, because in the latter case there is no - well-defined association between coordinate axis number and column - number. - - Note that ``CNAMEia``, ``CRDERia``, ``CSYERia``, and their variants - are not used by pywcs but are stored in the `~astropy.wcs.Wcsprm` - object as auxiliary information. - - Note especially that at least one `~astropy.wcs.Wcsprm` object will - be returned for each ``a`` found in one of the image header keywords - listed above: - - - If the image header keywords for ``a`` **are not** inherited by - a binary table, then the struct will not be associated with any - particular table column number and it is up to the user to - provide an association. - - - If the image header keywords for ``a`` **are** inherited by a - binary table image array, then those keywords are considered to - be "exhausted" and do not result in a separate - `~astropy.wcs.Wcsprm` object. - -.. _relaxwrite: - -Header-writing relaxation constants ------------------------------------ - -`~astropy.wcs.WCS.to_header` and `~astropy.wcs.WCS.to_header_string` -has a *relax* argument which may be either `True`, `False` or an -`int`. - -- If `True`, write all recognized extensions. - -- If `False` (default), none of the extensions (even those in the - errata) will be written. - -- If an `int`, is is a bit field to provide fine-grained control over - what non-standard WCS keywords to accept. The flag bits are subject - to change in future and should be set by using the constants - beginning with ``WCSHDO_`` in the `astropy.wcs` module. - -The flag bits are: - -- `WCSHDO_none`: Don't use any extensions. - -- `WCSHDO_all`: Write all recognized extensions, equivalent to setting - each flag bit. - -- `WCSHDO_safe`: Write all extensions that are considered to be safe - and recommended. - -- `WCSHDO_DOBSn`: Write ``DOBSn``, the column-specific analogue of - ``DATE-OBS`` for use in binary tables and pixel lists. WCS Paper - III introduced ``DATE-AVG`` and ``DAVGn`` but by an oversight - ``DOBSn`` (the obvious analogy) was never formally defined by the - standard. The alternative to using ``DOBSn`` is to write - ``DATE-OBS`` which applies to the whole table. This usage is - considered to be safe and is recommended. - -- `WCSHDO_TPCn_ka`: WCS Paper I defined - - - ``TPn_ka`` and ``TCn_ka`` for pixel lists - - but WCS Paper II uses ``TPCn_ka`` in one example and subsequently - the errata for the WCS papers legitimized the use of - - - ``TPCn_ka`` and ``TCDn_ka`` for pixel lists - - provided that the keyword does not exceed eight characters. This - usage is considered to be safe and is recommended because of the - non-mnemonic terseness of the shorter forms. - -- `WCSHDO_PVn_ma`: WCS Paper I defined - - - ``iVn_ma`` and ``iSn_ma`` for bintables and - - ``TVn_ma`` and ``TSn_ma`` for pixel lists - - but WCS Paper II uses ``iPVn_ma`` and ``TPVn_ma`` in the examples - and subsequently the errata for the WCS papers legitimized the use - of - - - ``iPVn_ma`` and ``iPSn_ma`` for bintables and - - ``TPVn_ma`` and ``TPSn_ma`` for pixel lists - - provided that the keyword does not exceed eight characters. This - usage is considered to be safe and is recommended because of the - non-mnemonic terseness of the shorter forms. - -- `WCSHDO_CRPXna`: For historical reasons WCS Paper I defined - - - ``jCRPXn``, ``iCDLTn``, ``iCUNIn``, ``iCTYPn``, and ``iCRVLn`` for - bintables and - - ``TCRPXn``, ``TCDLTn``, ``TCUNIn``, ``TCTYPn``, and ``TCRVLn`` for - pixel lists - - for use without an alternate version specifier. However, because - of the eight-character keyword constraint, in order to accommodate - column numbers greater than 99 WCS Paper I also defined - - - ``jCRPna``, ``iCDEna``, ``iCUNna``, ``iCTYna`` and ``iCRVna`` for - bintables and - - ``TCRPna``, ``TCDEna``, ``TCUNna``, ``TCTYna`` and ``TCRVna`` for - pixel lists - - for use with an alternate version specifier (the ``a``). Like the - ``PC``, ``CD``, ``PV``, and ``PS`` keywords there is an obvious - tendency to confuse these two forms for column numbers up to 99. - It is very unlikely that any parser would reject keywords in the - first set with a non-blank alternate version specifier so this - usage is considered to be safe and is recommended. - -- `WCSHDO_CNAMna`: WCS Papers I and III defined - - - ``iCNAna``, ``iCRDna``, and ``iCSYna`` for bintables and - - ``TCNAna``, ``TCRDna``, and ``TCSYna`` for pixel lists - - By analogy with the above, the long forms would be - - - ``iCNAMna``, ``iCRDEna``, and ``iCSYEna`` for bintables and - - ``TCNAMna``, ``TCRDEna``, and ``TCSYEna`` for pixel lists - - Note that these keywords provide auxiliary information only, none - of them are needed to compute world coordinates. This usage is - potentially unsafe and is not recommended at this time. - -- `WCSHDO_WCSNna`: Write ``WCSNna`` instead of ``TWCSna`` for pixel - lists. While the constructor treats ``WCSNna`` and ``TWCSna`` as - equivalent, other parsers may not. Consequently, this usage is - potentially unsafe and is not recommended at this time. diff --git a/_static/astropy.ico b/_static/astropy.ico new file mode 100644 index 0000000000000000000000000000000000000000..37484b2b58c3239106e061ac996c7b6e2fb333e2 GIT binary patch literal 1150 zcmZuvYiN#P7{0$YW;OYYwpKGDGdZmsRuYo%LwsayOc-+-%VBdGWo*k~$YI!$GeueX zCx_KX`C$(62Vp|aMI*-8eP6EUeHQ!S{<@#%K3vyzKhN`iA|d|5Vd2_Kmc)uAiAV;W zC02Z$+yAYX`g)2cN@8nqhZOygov#24vzIC)+zRQg4XU|08o8-zbhkr#Xd``Uppo7-H(kS$u1`7+RJ(E8(DKVLc@eR_6>-!{$n@Tc zvGi^8bdCHy#}F%!48xi|!CVZQK}KHCuR!4e zawZx!P}f;Pg#3xtBvTdHRc5V}9=y_!THyPSUpthG4PTmpAHM*Zq8L_UaM&3;&0H?I z`n>Bx&slkjGjbJ|?)%&+Jbnv|E%&+PDAIVopFC^fF=Cm^eA^~@ikhh5dkc_S%r_`d zzL{DzFR-sCE9%Pus? z4)kuv64~jWBB<>}l2jv44&tI5!fWm=9cu83`)N6Vak39_0d5DRX^cp;i%1zOWihOV V+B^XKTgn(ZkJ4Wd(?qP1_XpBnfAIhS literal 0 HcmV?d00001 diff --git a/_static/astropy_word_26.png b/_static/astropy_word_26.png new file mode 100644 index 0000000000000000000000000000000000000000..a3b77f1ec50ff44c0c3f34ac0989f65c9e776751 GIT binary patch literal 5320 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 Y5RN2v*$yoC5<|H6S^xe2ga3X12YH=4vj6}9 diff --git a/_static/astropylogo.png b/_static/astropylogo.png deleted file mode 100644 index 708de1938767f9b6082035adb6cd8143860168c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79223 zcmXt6x>ocDR%_x;L1@A0kcY}Ww*z%8vO>PF;o{(l#clKhUA zGbfM-3O}RAFhC8SV}tyG&ijdl9{^yj`M-;T8U09&{3WfwmaYcv94#jRNj?Q%v9jjsbUgJ(fSx$Vc4zZrxl&e3YS8<@5FXJVdH)Ng# zh-f7Eo0yf}-+0l>?EQ#x0mSsV&p>RB8|HwjbB^`2FpqukjjgC~(ZAep^rY+|X(8(G znX-*j!rJ|*sGYtWn29Jfqb403Ej0*T22UfHc5cU+--+S* zVQF`R!3W3cj55+>c7vTGeNOyofe6N->c$w+&&l{s*q30+A7>H6+ zD-D54U%sdL20;nulPf`UCsOnFup*e@Xu8)7@7H<2KAOb+nQs|_c_v?2pYHbp8FYl+ z#rPq4R7LkhndaFPIWuuTQV!*l66tn8IiEr5YJw9UG1V$jC3Exkx?Fo3Wpu0zC63mi zq(oZC;G9?Y=HtkNhec=eESMW6hER2o8WdMq34%e8jp|@HKBSO{f+9f>zEM92HSR}P z6tN&^F?18Ve-a)QRYabHipoJ=QSg_ZOw=1NG~P{VOnD7vpiKus8{xpE%yv=r)nDr| zeroloS}ayqfC(EgA-#A8E+Nc6X*Y+>$R7;$8Qy+zbH)MRhz zQqI*8jF={dC|g;%&)w~pL*IVY1~QNF@?NMFj7aHVy(%cPan(>b%(Gy6_Jv1nfDM=RO$Y!01HyHL z*D-$hh>sDqoMC^*5QQO{!U<4jjd$oIhVkMA(9gqGK=d&u1dWR)-=u!z@h&RE2%;na&o|TQ0`h!g0%hox%43p6OMlEc^665w{~_~i={xJxMHDk zQ9X>D;dB77C#)zkBmPfkk&XanpM2Zyo7K2rhw9aV!lime$}^MLrbwk+he5^Cl%|P| zuWYg&6Cb&unmRH2mhPS?0iXs%9r(`Es#Fvg4GqNKD12b{6j6ZQ>wCpiba_y27rYWD zI`rOTk?!GpAbyhkdPEiEr%Eok$rd>BKQhX6u`-2BwC(WkKW;NTClzJg-I+pDYPjG)g%j2c@ z(LX`q^$*~f<1}azw3&bd%M+0xqBV*Ej(YuYBhIy)wnV@CU=gmP^K~9k-miZ|u z0RVG5J6Rk^a&Hk~G1gRX@qke7q3k2O*r#%^uX35Xw3niKj=Y3ZPT?xi!2{}3RHK(M~@Yb z8tck_OgiY=d@sYvG#OyCbc}+Q6rkNaBOU}7aU}RX1|@=u(U$ZUSybHG7KUhiLM5A4 zsg#eC^uPm2i`#&;kgletruO!yz}-bDT$}0Zfy}>W;LqS!407yctF9JK5rWvjM3D1v z+zoLa>Rb?Y#%goA<~oLo8t}1M=9zZ3vljXPE3@h==+W6FMCDW;eTut9V69PcE!%jR z7@vLfu{1K8Zm_=E)e>LPWGZ|I{mw)lr7e-0%y5tZJ0FXVLUzb?bDw&PPGq}yZHaT^c3`Lrmgvybjj%~DiT zv;js(@V&@BnD_J3*8&lVpwNY^cb;bx<@%*mJ#xp3_g&=>FmF6q^WW@tjSLNZSRRhz z&wv4)b5(&&o(R-CG@q@}^aJALi7K7e?U&Gag9Bxe83+qbsmZo!pu?}^=AY?VUb z=fn3$MpdqqaG!*dz~?@G96P=;`9~4rr8J4U6YC*&;r@7eQdK2$j3uILH-GVCYpXNr zp`1Cmf*S|4FYs#5^2s8GpvKq~QHYQ9+QRTjOF?Rqf)?->=4l1v<`ZSHl?ch7)K|MC zZr8 zPBvHAWs0EK!c|e!naTy8s`K8~aYO7~H`~e%^ZQzfubqGXvhs@DZ;5c94zfI|Z$Xb2 z3xVO5o9d%&HSK|0v%akyJIXH|+58HL8|boC3c#xbp$8KLpWf?`>Md;DtPt|IS!gqO zwN*+Mu3kXJe~WHWVEhk83dhHEv^W5sHD!ZWiIg*wNL-TfO@XK}Fc0jr(Bb0KQnV4_ zqZeu{oV7R0=P7;4~S;O-h#-jyvV)dX|oi% znPTThtm69DM8h9Jup!12&xY4 z>lMZF`S13&>AFWp%3WD? zUtC?BcVEO^EUXibENxoIC7=U@c)o-_uQTtsITtU8lqk>}SoN8Ze#N~W@&X019v0xW zX<3%8zZcIvh;laBxpdx1E3A>yeP%_BrDfy=AXi`T`&@$$&oq?JHFKtDdd|fICN{wD z62sr;IEDNoZ-FPEl>LdBJ{N40>0mI4wZuYzkp|d9Uiw(beE>i4HPjZHmsm$&b3DK& zfTo|XHZ}csvuf-5i4FH!o{!DgWf-^NJC{S+IRggwT z9@JAW+C*SyXOCD?BpF!3!ljp2FgMradUUQY(|nZ1K@QUIci&E;fP`bTZ+{h`CSs_f z2?Vern@QDFrRSMN)8gSp=E6PC;#Y()(Rw4+px}*BuBZd8#5M0Cio&sQT{eq$6Py%I z{$ud8JLxiiH2jxeQP_7Y;@`38s!Hu}-h1iH0XN?vc$!>oabSFiiOIKDg0I&)WyQe! zPnnkv39{i|9tJ60%uCUxH0ekr4j`n#h4inDM5&o#GETzhrN_atxv0v@dV+w`BjDE7 zJyVl9^T`rJ`CQb|(d{^U>W@L3yiS;VDFY@ZM@Fa1P;PQZ^4QRi%?`G7aS>69hRO^D z*Xuz((Wm)rSF3@E@+v>r70N;t+N7X?EU{Bhev8mAaq$Wa{7Xrm!leHKR(!MVv zF|@)_%v%=C#CB_K+}tM1d9L|?&D_#KnXH!ZqaE86hS!ArY9tWI@DpY*D2;Q`F&!V7 zCYI}a{O#B|K!-f<;VDiDow`>mi4Xtxh3glpBvGOmHMW-6c}yqH6x2vC(w>l;C<8<{ z$qdyudzw|5B=x00AJ=em)tcmz)^z7sDUMt0I;sINAE>Vn&<%Uu)l^kuo@7B0A_9;hlz-s%vGwB((M89pxjiuD$#^H^IOezSy`ifx$>Yrm%r zP}RCi33lHTEl0axD*a`MtL1fUU)_I2*Qz(CjE1^nyoFJ{h~B)S{WMZqlkk z{#k!?H8~#~y_zRo4J_>q9*t2XLE?)==W04Pep!W9fCLPOM44nHxf-H=X9m`VK%0p9`j z$a^u+U~j4BjFdrwOAoOvi{s7MKbcZ8U)Bz5JCA#xjs9qh?R`4s-5b+0rmmJ_A~K4E zQfi2RJ5HPTfw}k1j-mGlXK0w-ZBAa|UvJ-eG%0io8N5@O5mE?8VGk{`m|$2s3}W_c z_6F4}WjzExTuz<%Xwp)^TNN05VB~sj=j#nxdgX{I5R4T*cGyNQ#AxbtVm`Or!NQ*r zA+G*f;u^UVG0iJWhrPWO!UMBgU^MAU8Tn+zqRj?j*3_B(gLP@Yh z2rk-yj~eJ;k;TtFTJPcKmjP|I#0q58q1}{NLr8Kg^eX2&6QfG}azUmEAQaSc^QGEt zJ(&kj7$3(sTnE4si-qb%pMH1*T!~T0mdUX|pvOUmCMEpS_uvj|AH zaC}~x5+7Fq3-$X97M%|bsW+{B^XsynqMPcZ2N~W30+?cCWMx4yU8IS+_DkPE@Ra7` zMASRm%1TDU{h9m>LA}XwlGMV_buwI%4Pzexono2w2# zAeS!muZRhxtHy>!OMT$IRGhVh_HM9}<%9e+b8M5Vd&ZTKHV<>=pX#O%F)^Dib>S6E z@1aCLt-izxhJNuDptADMS!9m!DFo+&{SWs;k;no>Z{?p-f=_uCM6Ii)VcMyb)sR$!{?*)Y#&&| zcF{^2~O&C?o>jr1Ng9<3!*nKV{sL z9frr0pQ(zJ3x$CY|CE?z2pdGTs?gC1Z8EL_q{?ETtorT0b%URGANNfK=Y@h$bw+QniYU<2lkfNHabL=IS= zeEvGdX!1DT=M%AT`tM(BjYRQm^78?aRKqU@KPTC1NWFi*yXfwjT>Sg2OK1?C^83^l zeGUHJ%MJAt*Y<(_BI+a~wE_TK0jZMtO1=-iqa}xXX4C1e)__*vBjFL>z(4UB$^A)2 ze=*mhD@F3l@JR6c0f?cDT+)n3bEO$|#(Q$R90wX`ItD_uo+<~EcpAh>XtiY^8B*aSse~elErJX?r&Bv^DtSkJ)-o&>ZTDPv(27!WnaL~ z7Ld$63c~YE&xsE;w23M^HKf+{vVAk#@WprMU1wdTHD*=oZj!7PRdgEKGtx?Mopi|K z5(d}@(i!NHqZ^n31%>gwvUnu(0u(ecFWAokA$DG5d4*g&v+Gj#5!xRM?-2I9GQ!-W z8bt__%9a~i z}qaeVp%n3sz5Ag2q_eF%p-`R&9;WGJ7xe~Lk*tligIS16^)j!^? ziGb`{+qt==B}MaG5IswB=Ym`d}j{3y5-E#eFcd3E<@ zRc^Y_qqd_@U)W?;{}n+sQBSh&Xjc?}Ek)0Q2j6amLd*@BA;DyzMFSB^>J3X}5J0+= z(3OFoxqHrOBVPKnSraz+F-9D(res)J>lA#}8r?kSOiZSlvE0LMvAkK@n%)|@yw{N# zpvDGH_@I!!Jf$|YcMO~@6rvCo>whyExB_HwzgNQAGYKwlWI)}X;Iijt=gRC+OT>&@*2{lcu-gH8J5WPWOMw_9ymA<10(#3M#L|4fspJd0)j@SMc zG`B0Fu~RG70e45n??TKuXf2h>U)*a(z%5tqtR95n?8Y-=4K)Oh}w=I7!c7po@8ih zvfAcamXUkRohhSvqX*-M232_qsN+7N@2#VtZYb7NL4qZ*gJ7whJJD;Q!kOAJ9n#}U zGju8;IRc#+q)X#Js%X;Q4l+*3G>TX%kA`032P|82BV9ZZ6Co&jte+TafC(AyJO3p- zLy;FLfkQzxY~P#can8$6H)Hq3kgDGpWWQUM_uhc}3rG%r?dkEA7K!?u5DA2bp6r!^ zOO72RS!-)+Nq_%BsAI-|XRO_Iq{e?pmt^9AVAP|@1VsvWH(5g@a~buN{}BKuhv+?f z+eF4do9$yC8VOqb?Rrog)^Bk3d6Vc+v1dMdf;Jiq>Y1G7)qe9cwA2_j2&N))K(wRW z_0G=ZsSn^!Bi!|jutBXl1?$WbR#>qY-yK+f4F}6&{5#-{?4XXpZxa8hC1_EFkS;nB zbxRBqF$QX^6zU9kuwbHszKBPq;q`HWx?@+ zSM{^u)0>veXSSXVbiXveQI^zini>76q#QiOypVa}z%7(7{21zoZ;GKXUG3t>WWqkS zE&Nv_ejRU)-}s@(B#Jt*{KzaPySSsn9V^dIt%lQD!a9Bj-O|MU&Xe<=l@#FV#hpY8 zacd^30{`>;BJ}iI8+xBSkGxAexZ0&3=DgG=_WLlfJAr_JhHAS~Q>w-e01RXkHrZFN zj%A~Kl$rGA43&Mab6)+-h~YtCq-mt`GUJxzd(`h2y}Hg5fHOcbz($q!hx?ORp!|vU zgBHyxjoEOs>oKw_?~?YZ6M6;5(A zb|xGwp1CRgaY_ZzIRIU55{-d(i?xaeK|z9({`mir^B7F8vw5g+62InS*7Yo7B+7LH zA10~p{p=gws+N8`;^)+QR+F*PrKlh7U=~XM=*8BjA6XwxRsTG5T(sPL6g=W?yAM}6 zf)||(BSL5N1t-w^i2&i9gC2^$noauKN12kYY+7Bc+ywdK)UK_<TVXMCgNKK5kLf9w;a zE~{4`AT(rj$OwnYXJ|XX2-DLbN@2xlu;bSTr3#IhGIq&P`aU|doqtKPM$@tU{(fK=AsbN!fYGNb^79@>-Y-lXwUm1|HWpXfSTb^ z<-|x2z7z`SG8MP&QexB3s_(xuT%VhM7!*a?)We9>+8U#bBc?|M8}xdDVPbX*7T7!{ zE8^nGYp#y)^Qah4tuh6T*0Uq*CNNQ4lL_4rvlR9n~d?~?t&*%N86$PS4ro$5XS_xkvofxQ!Lo4aq&^E9}fDUEPqw z!1V}70b;afwh$2F1+JTfczZ8nm|(%AXU!6Kv<3WhUIz=A7NZr2LZ#Xj%p#=}sRL7P zAzvki%kPw|Ex#3e`YxpmNw1j;d^AY9U;6rn4>mf-<$uxNq70qV`h(Uc2UZ?VBS-zL+AAt>`@FW=oJ8z`&z0PT#IkU%7 zM2ij;G-+!^|2SM|^^$yz6?m2EXo1AleuN9nHTd^;=kDcgEto*(!i?H7nLMwOd8k^X8c zwrYI^ZWnHR-;UV=75pzeNty=Dnxbiubr?}(w6sKhsfGp7om*3OJ z$kkbk?OyKnyJMHyE0H#q*H!j+2cp&+%w8zADAHROwdnFoOXOy~JjW=kFuOM7Fha0d?`n*8 z={N}@kN$rzz)<&T_f@a>`Fw)Pzi(&T?Ou|sAzb6L3_5`2Z-PbW!dH&WB}+t~SW@c+Ld3wl;Aq3}mEO2!_ogx32@X!q z8q=x+KOS@3k4aHzkv=ONAJ;|JJYaH1^+b%GKnCco=YRb3XC*QHb1%ZK;p|fez<=6w zUA8)&wzh+M!P`jmcHt+UEeE2UqAfu| zV#xm^<1enQ`&vyiK)C3q@0Rp2UB{dt?cDhHWG2A?J3FI=!pNOuuTSQbB|Agw!Ov11 zAjdn;ylcia= zkmRt_k|r=@VzTP_aRq|2>#U}BZZ0iV`Dl4HRb{G4fJp=O`o?vrOiKNP>l`U;vg;}~ z>R>sJCGsMIbk@IgHWD}gn1Kvr$Ov2QAp|LP8$i&|)=KP==ao#mQS)AAu+hj7N!$;C zy>7gZd;{!}&nB`GJ3PbObxllwFB=Sn$$XmO`s(iQR-#y-jY`qTX0y-YT@4G_A$P^; zBp$n(+4{k1AJmw!CLi*5sWibJnPP}CirIPd{Anfwg_?Ho>w(pNM+el*;-a#W5@zH% zU301#od2C*UHuw;hT(NcV;w5Z$0YmppFAf6?X4W2!!|gAhXRkXWHAS7#K~ z$@ZTXtFuKH@uAAeZfaDuP~WC)5UE_{!b1D&uU|*mMd6l%GW_CsWoohuflu{*Byciydb`nlt%zsKBnlb?mIw25GmRqCY+%=;)oZD4sP1X8Ml;HPlg3{1o12wfNf{uZu^q0>He4Q~zKf zB>s9$o=A+~M;PEk@B+JS)W9wG?&Fs#%6`94$CoF>qT`;_N(O+m=NAh#c__iMYS734 z)o!Wx7#1>n9ATM(taV+eo`9%k?J{3?@f7YyK@%szCZ@$TXT|ooe_&84hE4}qv3c6} z>KQF9Ek3SZl+4Q0xJ=R<)Ui$AXUI3>NsLO&ZnqqAk2#;EJLZ946Vk^EK}()33rCB` zUB~mSe(mk;-)s}y+8W2`xZ{8GG3csRyKhd&dW4neFL>{LD=)mw;Q7MKrentu_8U#m zE{OG<|p?*UJQXV@x)I z7LOB1 z7(4p#;%{#I3&h09v#9;tUt{8}-wu|S?GZr<_UVMO!?Z1;?fBo{AGJv48X09kp;Y~+-sgHF$_Rwa~n*1 zX1(hF`CVQ%e}tZXlc(0P5htgu1spT?yPQu!;4w2ZGY-^`P=waTe-y=aI0e~Uo%Ej% zN_8mbspyqH%X{T%x{rX_KR(!^Bw7o{LATG8ha^jluUGLt2d}K}8L)?J?A_)@3ePRf zmFL|2ueKsw#<}g;Zz=zMKEcJ~h=~J~kwCPc6H0u@G2}-;#3)#7Xk1>lK+pAVtxL?y z=tLhGH*6EdZgguhO+!gN3&|#(Mgmev>QO}P&NLt#QKJu!t?!2ovI1Pnd6Nb!sl&t+ zkZJpR?0%~)7ZP``0Xzf_1(7$nE>a_wL|oIAhU6bdH;u2>SLTOCcs?}LAEbi|A^*)z zJwUW@UX3h$qI)rWIYSCb{NB;aG(%$31RgKCvelu(oDCI-4{M&nj7$7tpe3_G$?I+r ze!RgSSXiv7dtZ*jv{OOegU3O~-XTZhdvW#X?!#o2^M@*za}JhwGE&OTF5Zh}+Az}G zwkBC8I#c82GAsK5IyQ*Ad<4>3N^cNAwYC@HI5vwJb#dQ+6Kd zcF5-TqOIoskmO4rMt{byK91OFBq(j&T3xubDMCzr=f`6$3u*v~f!`Wf>Hj4}tQ4ao zklfERy5B`2+pZkzz-Il9t;JBqh@*3CZFs++^5Lr|R9w#Q6dfOv8%9*aJ713v$C|*I z&DOuv_-|_keho9C*PMlymYT63o{*~AYAdQ}!~X;_uz!ZDYzcFjP@dyjKGQs9jN>Ez zbppW@=+I>8`Qil+@^*H@+}vE)+KE*QPh`*Kw)n%Ngw)TA=eXGIy}QQ|Zx`hs6uf1o za`9yP%~qkgS}BzDrHx%52Xr7tbXIqhxURm0kvfSzqfvE2Hvk?evQI81a|7I*s&vpB zb@}~^;%z>W&F2Ao@vaR@azT-+i_=THlh4F`akwe-!Kq+%Y|IFDYj;TwM6Y!be}K}Y2hlLmFwLTy)A*GO^)3s;)86a5AXH- zt1`VPJvcJBogGaJ0QL|pNf)!T3V_LglBSwX1>76vC2Hg88k_ya?$vvw;NSapKjtwV zyD47Q53)Vyl!=Q9QG1?y}*Yeyy8uLXlv zJLw^meL(TdvfG_(_>;9*w4~8d#8Mbn#yHeFZFTEEt%ZWcQ%jk=?&<^@gh|k@4F}rW$Pe2H(x%*T1IJSjLul_J`nc;-jr>6;8wh!p(_e3Wwi3rEf zO~Ho&R<2+4Vos)Cp=2!4!-SJ`6$yoRAP0h_0>De~ZARNsZ1e2ba+eAy;RtMyjZB^d!Bu8 zveNw|Yxn=yO!Rt15{G6xE=QIwBd*qLuJ-KCr4qblW>jm$)d|uUsaF$M8}UqnDpxJ^ z4oHgcd)^j7HmL9J1MO4RfW4Ce>!u zp0u?$Zlq1ef!y8mU3_^I!)O)#5Xve(JAX^ijPAPAEo*JnyOKH70IqX`SUKjS^0ml9 z1XUQ7>U45G3N1NQ&um)$MAiLaernU0jhBQP$`62H(J*ATS>m_hzmqDk;{CaIH+a6; z(~b4%HMN0F)_7XT6#}HGFva&)24Fu`|)T&_eSmI zX$ER{`q6%UsD4bYCj9@bIb6^y*;ygdwP{A zXX)R6C1xGlRWcm2Q;Ro>{(b(y76)qU8fw58iGb-K!_TFJ*L!*>0CGg$Xgk`vXp0;~ zzf&q!q4h^z=JWDc*Z=ON&>tOZ@u}=GsqEgr8m-mBRv&8^Y6;V+mFpF>dGE>K7zc zPnKcaC`88ACf zCBgOPw%68htMe8=@0Bqt);{w7f-rIjrYxxcnl;1*KokR^r}oJ_RhtS!_1W{X{lD*T z)=J=Tt$fy{hPO@gePc2EliyxK+479LiXX88?0q*kU2G#vO86{hY{HZ+u}!a`c*Opf z^%b(^L|Qju;9g6Sa>N(E(T6ucEiEl=%~Y{+4C5`c53pJC*Jv82K1hkEdy$p4$h}$> zEY<;rDrdqzDiH2lYf6 z<8rFC*;%C`1DVP*HU~44zo{zcD_wqqUUHpHotJ$qT!*(~1ey2Sls)FiOSh*11`t8!6f>+CyX!0ZLLQuZaV5xvZD+gQ-BWm5Fk`T z2Fdr;V4$VG#vMZaZWufS=1LhrNo`{Gl{4?qFTe)Qu91y7^7xQH1=?%~9{N|cg5kQ1 zqqFD8@&8u4*w#UHem!9bl#ZFaH=b;p=ZHaqw1u4;g_3qX2-3QI!4Y9nZxe;C6X;D` zkqk=zwjFF7Q4F?&W}LJtkl=9!01xbqLd>(kuzx>3(pF>ewkJ~#k`FP-+q2g;|2ir4 zfRF1{gKBI#{Wln4UoBfI+fTw{+6>Z7@R)OKBlp++abCWA%?M4qR+urdNo@*gs zVETNfC@K*FQ9K-E3R;p?ICL|`cc(Wtnia_=n4zFH(~2y>9^j6dC!T&fnfgU(s$_7#IE$7=RH5WOQ ze}A8*t;P?JC5snZTl`AOk!Sj|o1s&wf#{in zwO03Q85)?PQVqv_{{$A9)i>Y*BU+kT1NKu8EXfgY>z}n4KU5DGuBlg>l}Xu|Z!OW!Trstz5S1wyn-;`#XfZrzld+ZhS+qUCVIcAWWsnPp( zhq_sfZRq(>kszN(*LKuro%88mR+FFLp z1cg%OQqeeJV9(J}pv|=Kb{V=1{Samjgs7LH-=oXK`uIp;r1qMpA#WxbvIc`QUX}&> zxVvu_hHZ!Z%0 z@F6#&U7au#+&%J|XvaQzuB9WIaR0a6r?H^dHa3F~-5>I*yJ3BpV+QpW0*78@%(*Lu zg$>d&2_G~Ii6k4WW|r4v4q=-PL%TI)Xy`k~8^4+bcsAD5_xe9Pa%nRRailaa=b^Jk zYj{}+K@M6ZgZ|ZCZqT0-x|NJtL=-hU+%TaVcuJkupH1IOgUPM z+?bEis>${AQGt<4ytWl9Vks*k#UL1JIl>!nH(K%uq*O|cNnKnm3I58gkyaz1b5Ci* z68Y|VjFB6508Fvx?w)a&a)QTmQc_3DBj{qsQ&<2WTUxS3qK$qRa7(Si)d|`uos&DQA)UTRszCda7bGta zZ#+x##o^(J_tb!a+K9Y(a=p-X+%0pYAe1K4K5aJrB`3*x4`Y+_och%gxZVJ**x4-CwDOo<4Tp-Q8Vx=}9Rz(|ytK8feHU}T09P+Mu=+m& zpkJVHE&6QnFG;-VC}VeaNyQ=wMC{m_T@hnuq?4mp)~WwHPxzIRpU>XC6lIY_j%y(RG1+{)@{pafe=WhGmRW=J9ZJ00LldqVRm zd1XdW0F07?fB$>}eQ}y(EZ~8ivb3WQv8k_o&rv#CT9ZM?&>+g5I$$$h$_PS!cdUCd zeeHHje;N3`g-x5)iBL0{_a`oY;hsnU!GYFJxSSb}z~JED5#d|zc4y16^a4iV7(l5s z6)vaY=VS#Ln}sDLQ(^f>haAr||B=G}Z79xOu$XJkb`8-fng^mkr(X7rCf!VoE=#2d zb8;4_pB%~;L#LBjYRbixYuKp$P|c=}2QlJjig=JFufJ@xCJ!Kn!5);M<;IuCX81DQ zGgHV=bkOueMMWJhFHPDx^)bP`x$J$h^?1&gw5OaYl)?i1jFeg+Zb#W@{O)?tg#7XQ zdl&Gfpwr^93(hAg`T+r*Tnonwe)vWA+Cwbq%#>9_jlWNh^@LLv_kPuo`Pzm#4Mvjs zy@3%s3ffr7VR}c1J|OmE>g7iF`GNS=X}LT=<+8cmN?%;O7R!EPuipEX2^>Y*f6kmb zUcDH6xcgXmVSb)GA@0(afM|)tCW5m?O1jgF0mWNNV!kVjA4=Y`+o$~3>p};9pTncB z?JoWCJE1LWmTjWI{>8&74{ozMBUFRvS)ASZwM1`@{t%1CIZuSth90O$|3_<57c~0a!*IQ^j{vHz8iPzW| z{X14I&lHx={xG_uc(~1{{m#d!!={t|Ysq7$rlW(eR*+%R_@T+;i;k~Ah^Bkh1K1C9 zD^p1z$Z7J4>&r$O`$6GV12?`NA!)0~@ZI@SPQc|t`Qq+*^8KjLUBdXoEJ`VwQ*|it6I6n__`YEt%8~q5&09)AhsGTlB%dn*wN>T!X=aW}$#xr}~K92U3$-}GV zfQmt?oKl)z&o@Hz905Yt`e>C8+#jdR9*^as3AU3>8Tn0F%XCE&NyXB-u|lFl?pq zwy&>HHk0*Tmw?*4J%pFf+*9QFC$@Sliw&>$fXR=J4~Jp`EW6QB9Yc{GW}cxTTp4?o z3a}6B)J3U*s8dS3u)FeAd>F~6T`O@Qi-!^8F3BGr=a^+>Qh)%Hq{DFs$IRDXz8Ba9 zjABKfLNq3Ks_G9|;mprsB1WHSX2B@$+8YK?Ev?$RdfMKB@&|D)2DP%~1&mRq1S$QB zI&D!ok?P(hiCb5`@LG&~vFZy}$NkYZ#(_%?&OKPHo&ncoz62D0?>@=DI_hW9udbI=aQ`>|78vnkj{}7Az*Wq|<(ue|3-vnF--=KI8FmePLU!R11a9#b+%x&`W zFu48pcccIEb<0(J_;R>`nk8xX7g^yA4GrWFg^$BfJs&kITzFl>kOCl2G)n64KdEG# z=#Ru&1gJ~~YW!#Ij9SMm1tJl=4uf01yv91<>qy$wGp>Iut5x<_V@KaS z^Sm#RmGN_V;Uuz?HqZrnOeS)7rhUTNLUNsLR%drjQwuvbfa!FJ35T)4&p@J!piR`uA(J*!t5+IxI)`IaU=G)>XLkEn$mPx#dU9NZ%jaJ=JZ$m{-Tco$o1!g$rjE*8 z8(DfF9Pe{~)X&|MIWD7ZSZ{pIb%_GCE437|F*x4x)|!d9Phqpx@!G#7yjw<-*i6wiQG_f zI40%k&7Pk>c~p1CGuMknMfV*{d`rhgGf>}!-mHquaD1&_&p@9no?!p9CYOH3`Ya+c z?GhOw^DZ*=K9x<#?=@nz1xmY=v)ik5!ft~NMt}O5YS%P0fg(v94q-%_7QfeQx41?Y zTEBP-5DNpaN{<~5B9_oG5E#g4+*pHO`(5U>yC)R2EJZhL@I&9QIj$G)6xUOX48eCa z-lYgvrGpqX#_T1$OZYJRA7c4zG}6mfxq;yQdL>!_(!qOUFHYisBD!g^?76bX4NHOD z`oK3#FmB|&(rCTt5Dxh6)B_y%NtQ4^S=h#&1r9|36%(k6MTCrT}hB~Ur~FTCQbH#s_=LDwtR+0u#2nn^`)Jn zlm45}5PyCypU#FCSBj+i@?%-Z_1=AfYvCX#3HzO{$&s_1s!mViknbW5Ks^5Rr#Gq@<+a z*oa>n*##2LOM32%XlLQfo9Em^Qsvzh@7ZoJXrxse!JY^wNgO0s8_+Pq(CHW{lvdWA zk>@DTco`p{gVY`B?)HT!cKwz?;E`3x%MS@p`Jo7H;iQ=d16(5Kt+^j>LDMuU6RP^} z>$m-0t-SSp&BEdYKm)inZPwk{6$2Uv(}NN(HW~Nl=H`+l zaq@#srTbS6gC-<1}Ou`DaXkZY|Qln>GjAhhRQ zKTf=GfP@x};(h(x`I@ZE<13}#G zaxk7dr)uOCb3eZIfpE|5;CsC;{?)%HR=G&&3ewt6ZF&zNj1Ro$zuVz+HvjIkc~KgK zTJ4#<5<%1`q@J0bA7^=b^<_$FyWLz_S#eK(c6RpCr7PWTy8^VicngSTf|)%4k?TJ5 z%%A_CEQnQ^xwyOZ@CRPo+BHgE_|j+G&f%O#QIro83s9jY;#7+QBD`?>-F)#b8Z^JR zMGa0K*fs z))f|R9~VXCaZhOxMvWw?gb-oqI~hm6$Rq%>hmO`O5&%F37h3c4!!#+i%-64U^AXwc zo@smDZ_W1CE&~9XQS2V#C>?ps6Grb4DQjcW+91AWJkjQC=iYbi(2ssS7c|Nl`964XjbMPq9;w#nd0QXLWXm`-B1w- z164T$%OC`zD9W+|K?@0G1axn`cY5t?zVv*v8>tNB;|dWxymWHr=$m%Fw{YK){@UgF zx%thF_3!`i_kZCFUvRv@t81$_=D%TF$M~8N?ZOyB$m=Y&?s>;+U#c}`ynHrYy$D5N zMPUKZ2(Y-*J$MW^=h1alw6#_%ZBeZcnP%F%c-h!@NBiiT(XQq9tHXSKsbcJ~WdOjQ zBaZ}oj=uiYFdQb?IH!~}?s$_wci@Kq#_9 z$8K3&U(bp@hPL*+1GSD8W2~*I`>J*82|~yiF-AH3H4KBnVC0PF%Bo^vD?a?-wX=A* zo}By6#$Y6+nwy&&r|Gf7hpKQM-sFBJ-!Ev$_48SpSYs|;yck7MSr(&Y1QEXB@jVUZ zxlJ{xMvcMDpMB{4h+H2dvyCh1iN{s%YS!Pdva&`4qkU$R%~g=}ij{K)K;E30I{U=v z{PWWTZ>CXSMETr3kF{>Se^)Gar?YRccKcF$Wo0FfL(-h*t?wdet)2V^z@&ToL-GEb zE@fTigYz%ABy9rp5+sdjEgqVG;C=9hd&!#qOHXXR^!Md(v&svtORXwf<>ltZvcD3{ zAG+E75UeE^Uz&u%cq#< zMNyQbNtR`lQYFQW_az~&zH>KHmmpr;oc=!74!g78DT}Pph#iT+-FTjl%Tf?R^1LJj zagH}mKYL)`U3H|aQ^|T#Q{6bglmlyx5?WSP3D%g|DIyLx+?O;)BQ&9uTVTh%)o0GG zNGa3QlHz2tdDe-oFlEi7Zx0s^?(msjYauvr&u+9A?GA3I;EAG0DlvQfJ(%D4)YjvE zv3y2rE2Y-jXrYQJMgQ;r-qy|(0fRysGEX%U;eO^|1 zB`OF(bl~`OF;T9aZy@{84}JLeKKHqqZrtmS4j<|y!%@F?MQ1}i)$h4Mxf8a6*?sBS zMPm$QTw3G4hSMXv%FaOyj4@Oe2X8ra>fCw83HO*XT4-4*)tAD(K_~`BLV<8KusyNxw&br9S(=BLwEDmO%b}m`R7Gdcpl}PD5Y|(wt6cUFD)Yo5rTvw zQI*y5D|+uS%x+piHg36Zyne-HfQ%6fU{MIhd9&T>^?C$BQI-IJJ$v^OLato70t*N+ zqy&+(m)4~Ml?4a^h!6w@K?^aQmdw`mtV<4t!z7A=cH18eMgV|zyJ?K^7w?$GfqYVm=) zZhF*fl`fyDrE0FDxO{b;5=JQ<4l_|z001S0>R-hRhi@9fI}6Q){VLtu2E084t1K_v z0p^nyrQ`izLnbFn~aP`72LcxNzl-Z+hs-r(b9uedEq$K`^&JXwAxOIB`!T zGz>#Wka1Y6BmWUX1UAEQy51Z5A#)58r2wUhhBwBZSff++*Xky6Eot|C9t43qG#%I} zlAc?XT2{XAcRHQr%am4in4I4${51~ zzZ805&s?61s;Z(W3OvdP1+OV_Cg|X8_t%3j>ya0A8CO-ZECnIVS||sr<>uvb^K#i= z+qZAu```b5#@OQGqO~^9^D-|QQGE1{Bkg9(YLjQ#Os8As#V)G{=rH!U&-~CUDv^vw z*Kq}Fx>jD6${0qO@9nZEtu?Dpf3e)S=-P5_%CY0Glp7a^XP-$fofw{Z=2i5USC^#M zUDaT%MqTP+gR>9-Vl8CM3xep-p+jL9Ze2NNcVycKv-_jC;RL&)QjB`_IJWvsNYivU z96E+g9LLRO6C=W;wn|B}ZGDCjvH%(Y>bhy#Uf=Qfjj_JZDWxkbYmo4{``&r2D`oA< zQ(uy0;RU`lTI5CG@pikZl%|9zrI(f#`y1r&=03|*3! z6$JoboMwCW%qtD9m9vG-~Y(I=bk?k1VNG{4?q0y($dnIGiTi4m~UP! zHm_J!O?Oi}cfNTCV6Ip_3###TtSGH5B{T^AEX&d~otf!6yZ?Cc5cZ-Scs9eUXBae% zMiT;*7r6zdc5-t9ZpUoOvrKG1UW_mW)&O7$Mici-1B99wa@JL69a^38(#ea4!z2v- z`8)0>?WJoG4pjbdeVC4bh1S@R;;JmNEXNRvO3uu5)>hZL4G*=J@J#^Q?fb#H%*w&K zs{`8YcI_GBdjCqPyvX1AwzsS;Uu762gH$WkY&3wel~Ao)?}4xB$kod|+JB6-<`7}P zTB`&h7*mU&oA`n#Wu5j+o)wj-q!cb})Rvsi!^A2T_`a0lp*K8u=h0(l&z_N$ICk`C z>hA;WIBi{`s>npUBFIQRsmK z2LJ$9uU@Siq1UZHue}iMy<;a5!j+ee$lU=lH3`mEqL5N>&ZHDh6k&`ZVVkvfqBLM# zrW;qr<4h?T1U`VE&Td^$sH#d-756-+#Kjn6$~Z!hAwV#K04M;JLCPYE;dM=+y3i?0 z;dxvsWsE&`>?q!MpMlq2zdZN+saIYUqwHJX{6^sURhci%&CGP#`FI?J{%Dvm3i2$c z+~eInyC86Wv~}hgm&0w-l&Z<;mgnxU#zGGI!$1F%|NNCNf3Xsk5TYn$yVD?@12-dH zxTivbhCjDIK5(pY=s550!G1$(SY%^p4Ws^tKm7gU@i81#l(TZD+wqUJ=_Z%Zk~d>>&< zFrkFTx9o&LiVIKXnZb-zRYeFnfByW{t5==FE6Wl>jQrT2-M4eTn_N9Z2n+%bAt1N&v0C^BA*9kTc7nD+r;f3{)MAwoYBg&Omp84o|J}}>%0l+|QLISN( z|LsrwM61ylr+MVj(DyI|TjyT1H)&^2V?(W_!%mLrCQ5V8os+hkVs!7l_x||Deq{gr z!iPWn{Rlt|AV$dJBu!J1Y`osSHYU8i(7fgT#RuPa==*+R>8&5-2k*9F2Vp9ebi|f0 z4C6Td#3w#c^Zs2ue&WQ5d+)thYn|m8#@Oj1c50$V@zG;<{^U>oH;j8iNC4ny`0wwt=G%rm$7Yf2>{q!QqPH{5gE zZHLOTzyu-$oP%ze?sChJa3|}5$R_D{+C1L@eC}_@F`byk7=yZVGnkN4AZC2al)J@2cq@#QsHD*Rhx;|LBeCo`V)l~~P zK!MOEioASWw1b&Sj)SG|g%*S;_gZt8N0o|aDfh4%kCUMg6=U?mh4XIna?Zx3Zgjg! zDXS$g=FM+7{+ZwT-~QkK_{Y(Xa)|80(<{qY)1e+o*B@E{xaTP?87A?8V>{#a!wWBHZCb6)cs$00 z)S87_+Tk#!ns0?d-`iYU9}I@vlaxvegzx)BevNc9-JNt)%Q%ia&l`_(%!6q0(DWDB zI`=$dEQ%sVnalYI0aDw%tfVr^TBS{12{%V4z4X$qOC(%4NP;G#{QvmzDo2e@N>ObH91(J>7>sym;h( zH;QI!Ys<0u%d+%6E{j}>k}>8nyt=;e?|$$1cawdCM<0C@LU8KTDbHiGvol#%)D1IZ zjOTfA6pzQ_FMjEZPkilftkI)kpEI&c-&_b$mRj4g6vlu?qlFMr%3ws51P*9)NV7AE zgoN$z^W1XfM!l339)hrEnveXC@0HAZraqwy?=>Erk_{P0m02YsbkBfuO z9^Kg3_~8%#%Bf#`<#&Gb3*7pVN8tbzTj1S~s(ZZ;9$xt7BX5`qIT%$C0UOSMbR#nc zp)=p)Z}{NOyszDtCiBAE-k9+yf9`9P(pIbG9CE8XwZPtf_?BbGj(z?wK7ano+9(-& z!7lL4-~HX+Sqrq*LMQ-|Mk7j+F(uU5$d8f{1QSXu!YJe<84P^B3(w=8d+s^;@=Nb} z?7dGv{q$CEGs_CkV*sFLvukbN5euhfM(8GBS$(aqZBR;-GDZX91B@qVWer-nj)S8@ zLcB{e2~yVY_uX=oQo4j?dR;o~xvmzBF$e?j!4G`jzy8<%{rlc~pS1!aqYWUKPp3Gw zj0j&dt+cInGun3){QrN&`;MN!aODHvf9%xrz!>1S#l~uJ=$7DL{l*7B|CO`9_Q(J6 z3x7U)&n;ihDljusz3tJrraf@z$RW=8V10G-J6|+6p{##bSGfPK#{Q#DL+uhEpCP=B zu>lAO!NZ~)ywN;>#G@B{adJf(fPA-7G>AEwz%e<~VDu zi#!){m&a?hc5OK)FuIOoBs4vL zw5H95VTcf5ojquW^7g;ng(%n2o)^C}`t~zl2ss&UcUGdO11F!Ie9;Ok#4yp_f!r2$qJ>pt#!8uRU%v#Vq^2p6vdH=;P;y3zdULqR)kN@n$`S|pu zv*G3@xNzyr>UwcGPjZ#+Inubadhw4x_n$9cTBQhGx^QlOVQzVORZ0c4$d*rKTg%K3 zu@}MJxC=Ytrn$|B6Oo}*lroGE#KdXn{2=swKiGfQPDRP7C!;7L1PdV%0<*I-**F(c zOop~V$ZmrdG+e5L2+v>Bm{5|wA&tgMP=6y^CiilQXToh>KxL;s!+?8=bsJ@=<` zWclS&D?r%eckX%RG6=(&N{k7$X<0EJP{JdB@1VCXtMS}Sb7N}+062JX|JvG`LpR3b zyxr~6)*Osxd3$MBWaI`|$>!zk)Duq3&zM)1C1ZqBR+gpGDvsiGoZh-4OKAD4pDBte z41H$`P*oBF=xlUc5$UixLI@(bDoX?ahTy;lclyk$U;V$_@Mooz^WY?eG@J3Z83wox zaa?@!59|zjT>1K+%*Jdm=#9tYC<@%GHx|(C28>gGI~E*oEb%)Y*$J^4tX+KkKQ$T+ z&iUr%rWg3NB|$COseyV|Ph&`c0iY^n5X4H7JTEvWMIkt2&eOUmq-4 zFbmf1-d_^A_N6bJyu4oEm}zGGgmt`bo{5Iv+Spu;qsR~O)*#`O1cAS?vE_LagSjB^ zlTlKPwrsjlET2>B7ltbrO_gDSF$=)!h@cST)ss)USwR32?)lc3yeKh(t#+drkK-r| z4($YVXBVH7QZ<{6ZOSdN7C3ipsV1l=3X%)yzbjWG~{rKLq{ zO;r_f91R8|3p61}DKkCD5C9M^-b(y2||cq zN5gTW+1(~nN_ie<+*9*+PRF+4%a6-3Cdgo>=I7`0v4xOVV%&%gM9f%YfHA;A1dB>Q z3?U{iF(3p30JJE=J$LL<1$&L3{;{8W_Lb~IANwbgg*?DXzsDhxL|3px6jZVx7)V)a zWjLi^Vj@MI{B3*ohh{Y3%umNDv`XhASZwvrzc9M^qRd9j4>8{fz=IGLmrhbbtg#V| zv+<}IF{>*CO`esV=G-vJ+jrc*BTo5(Ydsik5yAjKt>j&I-jOClpEH6Xqqr<92voN_ z3#={jQfb@1{S7;(1lAgc(4gN}qT0K(w7Id_X*R4jR$Fb2Yo|LWON5};S=@z*oUDE8 z?;n5Z<(B}17+PIwSYnBh=ZCTqMkz`thSsOpqhxvYYJ10qQ+D;0Vz6HOS1GAl&1RY; zj4}j~R?6cZ1W;>h4X_r#8+M0l>$i#Z-jtfmtxMF}GmUjs!}W61Yqa`&xr(A;+{+m*3qJAG|x-f0s9RurBecs`7k784N;CYu)K| zIPh=B>^}S2WE04YVT?Rn|VN#^K(afxayP^V0b^`#wxbQ$w{PFclP3{^&O!9Gbc!3SAp{XZhYuf?Qoi!aE8qO)H?u4c!!V9Q z=eGv7rGJxfGuWl45O(*p<3Oa@55E7Apa0|!_xe2=`lCTF9remQafmwQp%*l`9~!h1 zG^?vzX2WUum($KW`kzzDy1iOEc%dm1qSUS?Rhv#(@3%4~Ah}lMQy=tB!SXb#(<`)a*y+GizwE}VY4rKpc_Rgcu;GEd zGtq(BuFPe(!ODD;7ipeVHLJs2*H4R?LbHnX^Si!)=)hfJ5F|;WD&ei(`R@P#AOJ~3 zK~#A>j&F`hVNx$;XAR|io-oE*14=39bUYp>X~H@Gt>5~sGiT2H=#T!W5GEUJ-L#NQ zdeev_p-2kVXf)T?wg3Rm$7Z+o1~=P>1YmV_l`%FPCD)nH?9}n1 z6B;2xXl7<6jzdC7nx?M$el5&Q2r1Ui?VKrTx zUvaDLJ#V?=zFYVFqj$aS&;P^!-e7WRmP8)*{lInHYnarnQCD_N&x3*xrdM`vg|oP; zSVIXFMGXY-*4Aciv`~NAoJB_w>CdZU$65F*Yg#*|>@c`S~?ah|SktWip%DDwTC zdXo9t`8w!Qf<}WOqpT{#{M$7qpHYud*1RcywAj2{3^%7cif%P;ZEa;)=9b_C4?N(0o<6J5 zYj3_b<-cxbAcQd9cNF4lwUH{uVz>qX(Aw;c;k}0!fA+_I=+>q7r+)fJ2AirZrO~oZ zo@&!TXL&g7jxe$Q@2|>ixa&LU9KQG1(Idx>97Tw<8lCIH`L$$uyP1ZlCzWy|o4(5Okb4{xsLj^;I?!6= z1;@lFvBQ^d-FiQv?Aj1Qj47pgo`*rWzOgf5a|a3%d#&K;@uQvgTsh7O3o!KoViW6Hk;^K>QELa% z>hSEd*FmJNx)_hgZo0rU-RD(Kls7EBos!y7Law1wcVI#=#)KfoJd7zJj8O(593_KxyJ>-5TiY5AhgBu$%#CH~ zqccy#sVAtV;FKvLg^-aS&$PP~6D@@<^BvQ*X7_>jvhH5MLTv#cj5O!k#~+Q3y(RF2 zJkNd4ciy{o3W#@WRU3%6&v9&w$+A4lCf4O{rPj4(eS9;<@=MR|#Ak(Y=B~Gn5^?(M zl`JVJAYK>|?$sd;A>=dKy}1Lz`0`8DaD6)Cudg5o+yY>XJ@Ld7(}o4^_{PX;YmGJ< zW7O?-`lHlXZGp+Mf-x+mbPKntWc%>_!TiBjbvV|}>U5Ch5&#_G@UeG2Hte5nclFcH zJOLno=DB5zF(TJ;qk2?%Q4|nhr8H-r1%^_ZWd$LS^1z=zv>SvCsqbeS7cj-zPU_R? zGSiJ?3HRSwZ(`P%fl+A2r5I}|k|^|zmP!iFD1xxa@eeu{FMm$_6rYJ^%>7OGMz+MtbnJGx&atH~&%*oHw+l_kb#VPRftUF0RBB#ata zmIDBTAk6cEa}NMmRf1szwPc-}0y;cycS23fD9uwIdPy=w&{kE+J#MVQgw7m3&iCHf zjZ=&^M$dhz5{w0N0t~8BKobcVD59XY7Qi$edw%eyH^1e=`3ndWYXL?G0w9FojNmBn zD5ZW7q~jtTXWS!E6y|wpE%1G=wbI%^2zhgE_P%#sch-yXu-dq20Gyefd*#%HvzN~8 zzvb{(zxG5X=#$T1ICXi5{YX@~>rc9Q8A_=v%gVB{c4APSWjR8SQp7pe#E+J4+nvl7 zb;M}Po%K~E9I<(EaWRUbJkQIrl2SDf-;1Y)BJya4cjhPV{?Ci|S${IGf)#yC($Qx7RvF=WuBKdH=7_4Fh-R5kyTI=hZ5CUT~ z=RD5~mn^wi-cGJQY0>3F?8P){-*o%Od&Yy!@#bcu(NbFGS!RvF7>lZU^aDSb#s_cM z9M)B_@$?s=g_hbXA0dNU3=&y{I0Kc0lsm#vSriv9UaW(+Qo;>WE6WlS1oA>aXnmho zLLv+uNXa>I_J7<9TKkW5?|J8I-xh1mAd!xH>)ANb7@WJZ`HiQZfBxj<$Dca&+{;^D ztC@}SMjX^K*~zpKr5U4?Fc;*cl$&mV#an>t_d!gpHH=aO0b;(_o(ty>#>I}sqxJ-2o0skyn?x4rFctE;Ok zD=Ur6spU z5kkf0W#ol7ZG}VV&)pKu?vrIDRYfq0THVI{zUaX5BHDMu6-EAm`vZLC&WHJh<97IFkUk7s!`Gt=(( z2O0p*sgx2DfA-#YVji%t1$T6~GqQrZs>&Q1HM(+UeCZ|M^W%1Fb!~NK?-H&=nx;ij zxvb9^KnU`EpHXi#8qMAJPRxDGxP_Sb@pttux3R;qEysgX-yUyXacQdy2DiNLr@?ps zY1cpE!Rp%ce}!a1X$JyU>0HVLK!6AcS<4!jml8rK%Yreag$R9YA@UaQXx;ht*ZC{N zaDD6PFDNAe0LPCXKY#u_T0GV~csFz)(|5&bvKClvtOezmUVUm~V`DHFA&i3{NYnJ- z!GluD<>lpvAAb0$r=FTv;A(BH?cVWVd~;Wz*MFr~PxVeb4uORb0?P#$TV<$W0T8$E zgG>AN|NS>EwQsxQ?3pv%^IW3k1{lY2JU`z&b?ST^`w(F4QGDNh_pNWN6-8k!fCz+P zSeAltf99^Y6EEDAzXLIWgcC0!e#3~;4z{$mqhuJz{;)StQUUpZp8wz#)XV zdUXXt&{#T5nsWdl@ZGZPAOsLWgk@DMzxa)^EE|njD($Az4Tr;4t5p<5Q5236TEj^o zABf>P@*?6z-`nFV`>VYZkEfST5R6@1IIuSwr&uZ)cM$jC^16BDN&=f)itRBsWr+}y zLb!VREpK__nKP$~LTarrvUYZMW_fuPA=vG9v%GL4QF$0eJ5mF0vhO#tjmvxY?@iMr z@EA~{l8z8?4H5zqC7Xf}wr;!sds~aw*LtgGJs{oA18#7^rE|m8lO9G8BKX~qk!9LT z&V8qU;%n7l&033)!4x43jX}U528D;VIO+)j5CDt;h*_3q2$MX^2tj29jJ2}ABFZsu z&7+$~YpdkevtPDlT9!fx(QGy_MoKBtTJYKn|B$DlMWHv(7e!@^CX}UVy0o+;rF4!i zNs_o>c#in(>t~%BSruDX1}{A^Jo}8ylN$Fy2=zBM@(TM=cbso# zg{Iy-^k?&OP-dlL8zGFHI;SWK0D#t_*XvP2A;gdX;Bit^Dh&Ai{QT9`m9kVpz{*n0 z&(G$0o~9W9fMA9YDyyJDzEcz+bbygv8NC%Bl#%Kq=wIy$ESNkGYW+4w+I)<$39GS`$KRg@#jPyQb*E z!U6zbZEbDh-_H1AXUS9}RY+-Oy@ig65o>e}3TY4nL?9**0;7Zxr4gmf24c8g4cAqk zfGIyuE8CP4h(TEtMh|Y;2Y%omwcq#tTV8zf$Y1~MQ(yeM)5MPe^56aLcYgJ&UnsNG z08S9{d@6Mrgps#!Skne?%~CIbgaK<+k*Xq5<3YK4+KR$?DiTHK~Ij$VMY& zfQ5j1gb)S{F0;bter7e%!Uu|I@Zf`YzI^(^Rw7u`s$}A%@k*IitC3~dWI&zN0Dy-c zdWceb;=~CzM8Q2`}X4^3!^CDtQe==Zuj!?nin)G zshSuL%gk#8l~$$_ad%-n7-L8{E?x9;W7vwKgb?_?KR>s)va+I-!UV=~JQ(y5f|OFv z4@aYsQpWR`TXW6{O>fW5t@#{I`R11CXmpJU;l`;5EOe^pgGSJ8m0|Dd)hxs_u&5AL zhYugFs_N3EORoHK{KYiSu4`^haB^4`0ssh_5#h33j0+FsbDZuyQmyvD<_P2_7-e>0 zVR3Ek3a9YyJKuQW;+g(%3t<(;k=DAZacRTSrZvOKydR+m zL2iH&rF3JnH#tRaT-E&*$mT z$lMx}CSw8t$37IEM1{vaT`64(3WWtk9cAhhcnD?%0+LjePI$cDk)6T|)HTKZq#m&tXYg92VD5ilQ zCTWT&4n1V75`c`f{qi@SSsRU+N4LF1!OYBzvs!j$9#Tric$%jB_wVoZdTzL)*80GK z1Jgrl>c+B^QX^ojG+II}I7O6l3z#xQqmubd6cr)FNMTiJq&a@)!9iL=1RKqUkP;$P zRu%WWvMiX7jRFurrE`sqLTFqvtc&%UC@c4LqM0WkD#GN+OIf z1WxbLIgb;L)e$A@`002AjzpKYuP4JP?&<)$;%*%_i(P(5@9z{`ARn{7Jth<7#EUSLM zzr4I$QxDx_Rxq*Zo6HAty)`%D1wztV&zw1%rb(6+jYd>eRZ&!N92G@T6cqrrECuIm zW~K`v@H}rcN)duCZ*c->M>c>EA~aDXy2){27`pdT+oVj7s>K*fZ9LB6C~zZzi&7|K z0YpX%Myas~0$`QJ5HXI*q8JwweWM$DH96L{1-Nw^x$fS%wSf>aS|fyi_^C}p)Lwo`sM5=v1Nt!67plCmn}s9Bbx*=Y9%L+2AxkD_)1;0J?Y zRS8OoF~((|RV67U^%1!Z%qpjxH^!tX2>rMe86kjiT$Ys-y5CQY@k5+-RQlNd;lq2? z>Xi)6HLqA&jSGxGmZeHbj7d!|pc7+mZ7o2MU_=n45MqZB-hko|`c)}pB|SeFC28O@ z-@{i|Mp4*I(xlVs8Vj>DWt?G*F+rZkF~*+9%d%vQ-EzyJm6f$H3^-?Vb8{|;BuP?L zQcBTox9ZpLMkczhH>I=^lWBAA$aVsAH&b@n{;DoRMO9j>tv1Rir7cDzj2fMGJ1>*l zZ$DCIMUj<_W>agcgc@fR;mob?&g)v4c?bN73$T0K?nJj{-&Zz$4i`So+z}&2qBcx79b0d zF!CgVXdf!zkFMnyTaM1T)|U@;1kkO4Jnx)|x| zIG3}#z33#vuEwl=)H&x9)3@!@+7eg)$MsrwG;EC z(Bqs7q1^CFt#uSdE`@jhX38>Zk|9J<)a&(J+cV1y#<8IZt;A+asTV2lSE z+j!_sx!aEIkm__-yF9f+oUyvo?T$O9ZPSTy85ccj zcc(Lb)1G(#vClp4>In>0sfu&zRO#r|z2|C|<5!mveT|ni z76EjM%v;;-b*=GIITy$~e)6Y&=l$?JRG$;)2$vZBahi39sY+r0OLpe)O}-ELfhob&bd^;lv@dcgj|Znf36 zvW|{kNs^^$9&632Uf_U(2QAf7Y{R<{5Fj4uh%05}C^;F08ds3ZDmPdejm6+S8jT30 zS}D%?b7#*;)wHt41PEhfC5srpol=^nA|9vF&N)XgA%r3nD8*QI1!>nu;Y#%ds?CQ# z^hn)8x3?aGj1Isn$B?}vz{XgBr4w&l{ghG&Xg{HNxkfQD#zazCl5nM3&T-u|X-bW; zOEDy^F~&mhIHKC?bwlu@(MU>ZjAe|)d~0=~R}fPCE6<-j|HUu;W!=sxr5J^#X&K{- za>2bjGp7$emwxt42fNu+!G7DYZ73>J%WJRW6P zT2&Rscr+T;b#08<+S>ZcSDtpxt~B*x&K(WDg%G`74->jrEMl%X7z|?LJKlvGY~~_+ zsI4UcV8#exAs`<-Co~bPZOr=mdRZ>&x*ClJRaKrn`@9Q|vgLh@#D*A&R%zmD;$TG$ zzCPAS>0mI3HH;8KwQaxK)k;x|)4|K>Npx!>=f zJNJCsw)1&ODTyMKRn=r!iV!l!b~;5gx6|4p1Z}HA0OyudFUGo7*F@MgR~yhbz+B%91dK z@OY=9b7SZ@>3@zk6%*T2t4yO?AhmwBFazlmCf+piZqli&3K|$O;O~==xEL!OKfdylzWAJ z5|~k7V!z?iDzHJYWmRcy5n2^CDl3UuRhsNggX% zfg8rZB0HFKZnVzw+&Q9;|`5M}rB80ODM< zQpMp?V;!YTDxK_Mx%&r;LI@%ubyFsZz?gsy~YE=LO6=EB9mn^>~*H)+zFhLqLrEwW{tJhF;2BM01hL@nE*i6n#e(hfQ=5I zuyFyWy?JGI<$FmtG|DQey&Md?*RE~Et+{O)&bYHKhGgd)1hfYR(Im-a+fa-W!M(GI z;BDJxiBMABbaEJEg}9!S?cx4#`q-IjvMp{Z64jroiKc-hh(o3--{}_8)$616#bPc5 zLnw5+9gLB+hI5uA>B`A!RUiTYVOSeS83GjQMu~(H3dTB%1)xI@Klt2x-t#^W3n45< zK4=<1b-Tss)2Fw$w;=eU$lJEIR<+7u!h{f<;^2&ujj_gsU_pCu0l;~{gg6HnllUZZ z#u;U@Z6O2%o>59Lww6%BWowJ1`?LSk|MKuBKE}MuC|Dqjv9@Wvb9tU~#_Os=fM&Du z*=L^zAg$CSVOS|;9K;TF%uVB?{bD*g0C?xeqw(&1B9-d)yRB+3U%X5xWLYPsx7OH| z-F?)Ki9777`?3d9`MBZ2KK1#SbH~6LS>-Y4T5A`Jl3)@udMPDFI8D>4sxpxj{a%*m z)194!P+2ueBL3F5eOtnFt>u!XfROVRAsCNG*1W(xHHPzEuh;E%qqSM=yTrmv2$70p zHl3y-5u7_~*VfjivngkM#g|@zDe>$E{jM>lX(eYYIu;OuDWyIPcdOZf4*Z?By#DE@ zpWfi|j@yT?0Pg*@yZ~i@kdzS7)K$O%QM|o5>voH_ZH);S!(!0@cqwfRjr)c(mydMQ zxPEWASX3d9Jj;|cf@c^ZWAv~5%U|2wnSJt;A5Vm;Dg^+?kK8nw?JA|~s%;x-tX*F_ zV6CB)F)m^Z)_SRM#28DG#8|W6B{AN(5CUg>uNpDN7;BevU0IRV^#Vb7`Q5kwhY!5} zHLrg8`~KZ;KJ?I^U)fqj+$xsQbzMhUqL}6?rOL7-40&aisbqu?Y=~3$H(IL4|JB}9 zZCzyfkt2s@vsqa-oqka@I!m)iDPNUWOH>l$l^{{PjxnXsO080v{h5t(HcivG1tWx( z3*B0bi4Y=gNyZw^cu^D~gu1EbWr-=(tt8&R>h8OpwO{zc7ZE1&`CMyltqCCj1Z!h| z5=XFoB{5G3$+9fgw()^kUGyYLY~36=aOlT>^uK@bp$EKo#@eDNs-{M8T}^bAyhjQ% zKp2gN_uO+2A;fzZAqYfRk|L_rx4-H&kA3dRJMM;m_A}o%Xuq;PR0&1KcUzNePj(3p zEES8nN)y^Nt+g;1bhOrKD!%nwzxBd}b5Z7Hf4qo~2c!A-ec$)*?o4O%a&3HIJ}lU- z>GBrgSxhctY8yg0c<|uux8J_IySoY#gc2Nc^T^h5undYfBowI~s=Nw}c!VB!h_d%6D&$BGc^q$yUl(>yk z88Im#n8c-zG4{qDIeu(w^IES{1f?JRvyWkdA9?hV>0-ecjj}C5h{0e;39YJ{5*m+f zh33S#7@O?zPejZmW@*Bqs;VA;{BiIBV{Dv5aZA~2hpb{`3@Y7D9-VC3wmpC0qLgaT z?;k#V_`=3nt`%YZPkjEVBRT$-K0c5={k{M9cfbC~+9MC0yKvQ!{K&MLQ{e+39P;tF z*R~BpVQp>ATAO9r$&)9aeDawX_+LEeSJf?}^umSn-baMINfOaCHQ`|~nJ~ukg6BCw z0NdM(*WCBIG%q%l+v;G zXOwyuUVGo`&Yyd()9pU?*c026nlrGTtnkzbAeLo0olavZwv=B>1p^2X$#5|`M*Zv; z!fdO9kWO`rj!}{TN`!FU8D~8p9Kbop8IMsXgb+Ca&M$FPtt~*Hlwyp$_k3@tZ@&a) z{KLRT1xvrFSgOnlznvIGgYP_G7f7w1SqPwKuiZEUNY%wPI5rd#~DR zwgg4&JwlC8d+$v}QBix>s=fDff1l&{<=_03Xi&*~PbqouL;?K@SJFiwE!l z`{-sy#9yEN1-Bhm#e`3_@g5encE~4PVw)3;ny|=ap$el{gu%EDoJU_??lR)(-$gh} zG<#WFUpEot-2U5FA>winN|cqQ5GGg~Ul~c^c2#3TI?j>F@@A=xh6Wyj;f! z%JDSqk}g)?n5KVkV~7t1dO~;k!zc*;i~NZ)XQgx*Q!y)Dx6%t*GiFX)AREjDjkFyW zah`kgCLK)ohBZuMa!bHU^N>sWE55Rxc2e0q5TVE#uRkr-0FAkMa4w`AMS-vV=vGM^GQ^<%`(P0s`kHpj{oWwsXpIowL{rDN4+zc9DeHDKfh`I5en!2*4AVuJZU|~Ooq{1vkjP3r2Y~~lq z-(CT5V2gb`B5ET;Lw;t7kIGl6RGlNKS>^Yq)Xao_^aFoH$P+U@X;yRYzIcTK=;&OR zQa|3i9G?!=W{8q!a6qV_egP&V{J&FSGI!^VqFL^W31(p_B!uP$_$%V$kk}m2r->mAryQm0?^r3ILvXfS_9Y9iGl2#tx7FXhUAP6Kr%-*Fl3-25;ndGr;pP=Qg5!#q*- z`0ichbXh6;AqFmwmMln!pqkQltNNr7+Y5$`VW2&n z)BhqPrW2-dTEdjtt1O2*DaU~_oWaIEurU48|BMA>Q}Bo!aI}#SK>O|jgG4jj(W~v_ z0w{>l@LnDLg5#NGN`oSF(V<05uf8I-uYYRsccX1t`Lt?@@VeyTd*_Fgj_Z-2a~7Ht zYT;r(ep3MO4vpzSa{m``u#XuNcR&Bi(%x;5Untm5kZret`aGUn`~e5toYjt@mhNOM z3{(9t@#y=Z+C%r)!zlxiBoOd`8p!Mmhl;)D(8zLam&|MBswL_4<3@f^lH2RsVrIpi zDmvyrSeZ8$gh{oGB%%)i z!1rMI_@63p7ioxgHYM_)WphgMzr7e?UJmU+?O+7!6U5dwk`;)*Bea_mjwYc^KZ8KGS08=_Z4E!OY_Zg6i17y z#WjY`EgM$cEgSPqC$^d@#gl#}KI(1X5xiJ*=W6!`vPx8PX*={7@CZ5^P(_R~ogRT1p<@rHs9` zhb;(8g$YzY#?3OpyiqlH183@L*>;E^MxUsFSK6L-aWG8^B+YtE)V{CMiq86BgIh-R zqxa{Cs4~f6ug_-u{oTVQ-kA7R;Zv9O!)picWS+m}J-9XEj;JCjFkQj;7O=jF?z7;2 zIBCdkrwR$YT3i=QC_c0|@72%!J@Jw0wWufO^)86VRTcyWF#y!|L~vi~CnB`$+X*vx&lk~X z);#nlxtZLhoH6nn1G2JOKHTTnGQBDP_8m~DrvNyM$V#mv354UubNaAGMytA=iBw!Lnula_BJ<2}a_f3Z4Oa#a_T}~>}oq7NSkuKDOw(9eMlDoB27UG7^+D~)`$aYyX2zpZW32!B8=V?z>gtlLY%Aw-rbnqd?ws59 z&nkm1^Y9|q#$8(F@MqJee6qEopt2kJD`C088TD9)S!$8I^{gY!PLQyTKb{4XAO1H| zU2HL_?3h;a1RlPl4#Ib0wlW5A*Wxy}RcH>wqCv0?#P3wv^@6ppvC?s_%1pRGT-aT4 zB+XTC-uqD9H(@;JFi(Zb^<;;jOR2{i} zlvd=o&rnb`6`2BZoh!dcy1wm&`*W9sQuV6o7R>t*zm>V=+vnk(I8c9fvC8$8&H(%l z`W2M|u+tAEj`twg%*nYnM$yV7be39a;>r}vb;;6LM_e$|Cu8cN(tk>>kRA4B{H zsy)5;NqqRkL7dvz$q6T{NGHqbK-n~KwTI^JyH}vQ`(}ytSo_YRU!~EU?GC%X_IesW z``8mSX>6+e2pNGj!tABrugnv*;%{1g^PRJ1a5r@1@_P_EF*WTGQI}tT7(z)*EF-yK zT#AFKPRwiFtYZoFmq6Mk(><>Idn%9z=bIJCF+y{5L<5W}_WhPW%O^RBEimGe^6ans z#CsMZzz|$=|3fT(6J6q&CMoFR^|-WCdn@}^B`3LqI6f3d7hYkadFXv;!h=` zKEwBlx+bignK8X6B9-47v8rK^3eq;cFg5AH1X;)il86Sjv|!9R%>F5-=xZHXe{TDE zi~}!_iWo*)|8wnt(LhT_HJwQsjF*=j#aND_B;@{P3=enwP&dK{Br!HPIXOiJPcT*v zU%xuI^piZs(A?fhUgPwOAPGq)>R*HGJ`#YJ%yOFqR^CITf6em9wJdOf^zFkS;FTiV z`uh5Ol>%Poba_21ifv3;lni^Cm4V~r{x`$w$^YD@=Nw-tNH=9ETZv}HB6hOEHKEz| zRFaj!qyTQBNk_(}?XCA_D`eY2_df%6!#)upHUwB-E7F5{%zn+yX7WTu({qft{nlJiB6nL=EabzF%tuOzrm%pR6)`+fQS<(mFbW!`rwRZ{3 z8Dn|_>Hi9doc#~ANyZ59+v(kwOWsWzh?l+VXcTqsWLwLJXET?1HrWMo$=a}?58R2`beQB6&44*Q>G^zJJXup@LOfJ=XQ-jCcJ z5x`eBGG>r2V>@~`@!NADiZN~Uzaz>i&sRx?^e_bD*9ms^hKrkk8Kr)GIUAk5{~kSI z4~{T@_anLMT_@x5s&Ct3I05-i^WKFY&__ziX8Rq?6`5yFtL_^8!muN0ap_VguFon1 zMstPqe{$Fs5{#VdOx7z6GZM#p+N1EK=q{U`V#a016%#(NDT0$GKH35q`t&cPe|!2J zF6VI)XH0uRA{dp2W%n|j(?y9@(wII_c>mEkTd3z78^WBQ#z|i1&6FdwXvDla{pOU? ztk{s5W=}vd4sCTtU!pUPfAXK_aqq;WL5ys)I9!^3Doyud&A(8d_cMLo=O*o6$!Ppl zB=EItSHKr72X)R7%;2J_;^9H!%KUWhF`768%*^{!n4F$07xmS+T4Cr&!b3ExC>}-y z@0?`~16ULGFZ=#bc;m#rAQDkEm`ok|m|u9LEcqee@6R-K|J${Tw);BF%xISC!Rs!w zx^C7_pRg3_qtaa;TlsWkyumoZxT&gvlDNEd80H7qg5j?{DX3e6rgORn2yBi0~jqT2|djgyYXk5(_6e69+~FSRGJj9;vDAs{$&w|7Wo{M{~U+50nfq4 zDvI8I4$}kzo%m3A_wU(fggVg)m!&g<2<7go9jZA6{q}RpUeS)Z(}m@VAX$TfI9<8U zbeJkL(qV4tt`iS4{mlRGWR4e?4T^|byjCm=P3~D0kuw2%-3W3MFI` z69Ff=*%0xU&%({*G1FP~tWxPu`t|8$iU+$Q@5--t(Qyd74dUFs*40craI_m{_pgPV`}RLLz&^7I{WDa#%&ML|0SLq z8v118NHKmxlb_IY=T8{{ML|Tl5CRJ?*t}ze;aZ^v=+GioTn0tjuKrFcr8QTGWwj1! zS;A(1!|LS}LqK%B__{EL5L^2Ov<8WCNo?eKe11o|MleE7r?@S(}_99taJh1sR>Cg^123>$?e3smKrHD6PlGI-1IjfsV zVIp+G>psJ*U)$=oq!w!VuCsdEYYwpDZcJ%M$G3 zV8kswg>!p?j%9T_o_^3!&wf#kghHn>lMcP)XaRH2*KM{G{nN}fREIw{P9B-drl}<` zo)=9Bpmv$7g?ReM?P%%u;(3VkCUY*o=0J>q+P28ni0>C+p0sU+xECP3o&%10Mu}u_cs;KHGf9`>%zyN%q`Zbd@i)WF92t?lKHk@-%I(Le z{6U8_50H>(+Fc9YY1pO@yYM88K?X1r&+Gx8tgm%NgZyax5Z0tO-*^9>Zckn;`W+yZ zQxJRy57Q5Sxg{T(in9ZEI`eR>$4r&@C8*=TT~Kqj7n=@5&3a+WSFQgTE&B)SMn?q{ z0fG6i>WUMU+L&=UUZqw4J_lazD1T97g}2b(WDC8t{7NzEuI7@ zjLBNhB71;#d-ZX-1J`P_d)1Q0%Htx1FjM+Z)hT?}gHfiVB>ho_YyrlGN!ow^xruw| zV2!`+e#xX_PpX-ULOC8_ciVQ#*u74WQF;{oXpBuY$w_a%{qD&e@$x^<7N2ZowyZPW zLqq38fhiaR7{S*y*jirUq@D>znEwsPE*uuK`ndRR(B9$hM~Y7L8{DAV!Ot@u%%4gr zfh6QFF8!fIFk3ka>v)J6Hw%wqm#0 z)TjSj(^o*`pYZ4C?W%aSD6aau4Ia+xE3e&wX2*_=dcBv8C+iNos|SIH z?*U5BBrp;h*)?%LNHh)PTk)@-^NJEg8Oj;df*UZJ(pe{&t}5?me&Y31;2m^n#3C>V zW(hO+rFYu~3jC`tI_2?Qd%_b2{{d7nw}a#JK9Irbtk8Ue>&iB6V$nIKPULSMKClMV z{@Z#+#@}Oo=J1P3-xAnU=yXMnyBO)b=+;-F&=f%l7KHFR!I_>9pua)zrT;+5u}SFb zF!=FiDu@Xfl@bNrZx|jHLnoLAM4uVxSyX#s-f`UJDII}c6AVc4$p$A+1by17HEpyv*@97fj&+RLd0N^ zd1`sgKua_QdC1B+fr z8y`YeVPG=?w#luH1*FnatZGkFn=zQj=#u3UOayO5UEmtkl5mD9w^8eI7OAv=qa{j5 zt8abGPcltqwIa*YN2f&P5L2J}c@XzWMa76yrBIftWpVM`Han`k3eHQ@3Za)a4(*bn zni`e^Q_C}~3fRgxpSw5f@yT&Gvf+Npc{(_)kB~6ZV_527y=iOLdM*8qZLLic=5sK~ z7-QkZo&5Hzu$_v$g%CG(4n46lBFQWa^3Oo7REv(IYi#=31E!1EP+LRrh823zsrKq+ z`;urVB>eO>gIAVzlN(SsDd@%s+zpP%fWHb5fxj}^CvhI1W|#yV^lgsut@4eh=@JmR zoNmQmIZ(n$p>UNiFIE%94$mob~zTMFXx=w39xwN%m3Yt!^PC^K;dh@bu|1aaC= z03<}>P^N|&SPq<7g*J=;Xog|SKXj4XaJ8pmRM1bMgBWC)ZP4LZ(DB~#Z@uiL-Vg+e z4nZR>oV@W93ns{{tMjP8(RNM-ES1gs4^Uh&D^jXT)^Lge89;05{%ODi)KQ9wDA@L( z3^%ekezhsdhD0XFX3yV5wRp3L#f-xY(F#f~uVXIm*S{v#Tyd(s=Egcl5-qs>m&2P} zWP96v_ZY-6oapVt?yJczU=lo!w@qd1+g8 zvpQd)#$Uv0;4*3;oL4O&j8|7@3OLPIw+n4&*+jv4PQ@)BU%Sc#L#@0USO(vBPnPL< z``rm{ax!;<`=Ht~#L~-IB2gzit4P<5_-B?8eNLBA4;8)fIN;?fJOkd;wZV&31w01q%24;A_)m!rcZ#* zNX3Uk>Bgus8+9jmgKu~41R0oU{c(CpC4ne+-Ql5+#iheEm!A)o{xsHBxxOAd)|U%N zqVrdA(qH2BqO@nY9T9mCw!)9|8Ol3~&rmylIA;mEv<$l447$2<4CA*{QW5WyW>aJ( z2}$yN`|_Dg!sy?V!I9QH#}_QUcP63i^-}cpR^?Wi4O(Z-Sw-yJCXI*Z4S^RU2cKrh zvp?|-onX?kMpaRxU3F)&#`JLDHzb8^6;;W+PyN1As_oIgHjdtZ*8jbHSZy3DCe!Pz z74YTG&<`O_4KVJHsSHU~K%Is-AXnd)-v)HGz6b6A@?-HiqxNRu=HwG6>Hkn=-rUZr z)B*npGEUgpo|Ji@zi1|Z`6wB0C*tfhI?C;{{joZlw-$wc2rTp+pIc^XkzIZ2w^6c8 z91`ikO$s5BxRhaZrB2W)HBNB1NEd1Rw)vjuYlC@!Z9`JfFYtj*^SEoXeU=8-K#W`7*;p!;a)A<$TI& zA@m%_1@dwG#dHTmX&lTB{;`%KFLA6ZwO!;UK6GX)^-^{0#dI7w2U)LOjU;Zbt2+Bm zR^DD$;?w=zun>n@=qugIlR_+2!u)h|jWgN44r?i!zTCW)4U))k1FaH1V^$CU5TgK= z#>$kJ0(Xaf6Cmv|Imi|wyzhB9;y<`79+S8oc$jNgoUW0-)Esn8xb2|1yp+7sJLpmg zZrICLp?HeLi$1@Qu23H(ZLX~Qj(wW)w=r|GUs7Z4C-9IjuBOGYK zG%AHJ3sz)WI~x+7R#gPl6Ge_tbFR+1y)v!gBFDl6V$HYub8jca1e;cq*y zPExo{+cP(}11XPpB>Eh`2m3eni~J=?69t8Ja(|WC(y;zcOE_~!!1j9PPi@r zD*XbWK`508sFFv^u5VSQW|jTLXyM8;_NR`bMits&riRYx5y5^t$~hUvZ3t|AORW`_ z7CoNQM@&$0+A&t9uy9DHh|2OX`gEpdGuLTWcdGwK{=?634$j>S@uLt?C04n+%(dkV zUA}Q+Hm&mi_UUmOo9ZZP&i~h8MENybP-9hN7F`EkRkj_})m%9MHG;}&qb@GxMXr>7 z$cs@-Jnz++_uag=|H*5m>61RM29{_93(2fXxVGu{G#!C#>{wb_V zs{8MOLXCn!pj|uO<9KyZZ_#~8sEt{jpU_4C%Isg_lVC+r0A*<0{?o6?37K0uP)}}EpB8P_RKec z@cZB~{m6;Hdk{-pj_|KBw|Be|_hyL051^NdQM|caxo7tf9#FViCE!B2Hy>cI0_^cD=xm1e;}gCFo(U&-gve<1-{TGJ@h)ZAYwrLXot_pvXS+5Q^J} z0w?}(!|x%07`|!S#YXy)MpPJPx@*nGQJral8M?_Vg6emOnS~ME;NVK}nun1YP#=6q zE?mebb)M%5)yppG3R*F}JvF?B;&$!gJ(gO2xFzpU;Z^<=1tK?)|AC8zPB1z&`tlq^ z6d5oKf;@i}fv+)4L7K@TU8tDgnl00W6c}aO7$24Y^5F}D_cQOtjS1t38}g~uOP<=K zMy%%l(*kI**wT}jU{Hc@cBA_*bNN@#c=)xN;WVpkP*STi9!?!2oZt%%BpV!S1sQ_h z4Fg)U9^p3sD=mZ9!q!TP(p7G-!;t*g4_3+DEsJLz_u~fv8iJ?4kF*V^>)%R^?+JQl z9ft+~n!SNQH|c0g2#dSLfE=IBWk>qPgx5^Ln%}AgpkeT%A=PVqIb4Q=mto(S zzv3VNol}pAd--YXM&jE=)LvHKM$Ay7kS-sv3HB=~mOu!0|*l zPgqj|7xHXn`Lo$85UX|mpM^ASvyiIgHeNg7EghXl!h{h4jtES;YY4B1>+0pnnCX)) zOOo2EFj_~L^jm2(9zzm|ID@`0W1V0aUH1=9nC+uKIL~?$rNlb!=4ftz4Yb?1=$^_0 zh~=zz*DFK;wUS%%?}+;;Xn8P@<`0je=E>nU$;_aUWKYd?x=(C|XbLIez*{I?qrp!R zWTtz`N0mls!D7o@QEeDR3OcJx60)YEIQhLNlBgc(kp2c&xyd`0gs-AJzP;CPXYXcm zs!a{jDqPbmEK>wTTE!o~S^-IidiQR9V-^@a<=AgOVW0`@#cLLv*}0%E8P|{o+IufA zZ>S}vIqA+(hAg>OG{ka~ePlw`VBt0)1L0t3n;;N_M>h1cjBF*nN4I-g@u*{7tM7ah5DX$xjw%|*n z!!`P*@Vd?8ND0h}>%00#d9#KcXtOK?DEILrIfsZ+KiT6*E05=7IEgj^BjBc{5#Be8 zj!t{@opl0AyQC~}KSzw;)fCyT@@P9m7uy0AWS#v#S4%j)K`iB_4{@Y9AUD?0ai#XP zx91qDmKzR^zlbd^(c*jUCIfDNC(5l_Qio23taaJcdhMbb0{6SPS@}kZg5z7$8Sg9{ ziz?n}B}VO&n|-}f1!M6vn`?4Sy;*9RvhCYYmH2 zV!R|vU&@9KBy^orPCxhDjigk1w#>K)w|Z<>yYo<<6(Ziz?=q5td3uDo%SgTjOnN`4 z?uZhJ9|r$_$4}x=Va0AED{qmXu>WhJixo1oi19j)9bKdAB`$yqA z)?mw@=l%W4w%QRy=YOW(!cCOOC@a)TIhE_G5H8X-9VzoZ0}Cl!PCQD)-8wUcwkFdk z!hWj8tF5gp$s7Kqv%d%8C-d4=hKZQ^B3>UfJ_F(hkea=>pqOpV{Wf*co%2qPt1qSU zd$Ca6MCl}3t9#db9Sp2Rjl~*1_Ma8Y!Ic>?ooYe&AgJJ;CtzUdu4*jsIvPmCjj@R4 z#qBTcywUkead1C;O-es*s01YMw#8`q?#oo>#`kcaR@jY^ow2c4kEx_S8S%&Z1PG(bjA{TEg^CObPtmnfocHjHQ$n*be zFuqunzxSV1fNOwynr!T}G1+|CUXw!}-K=83Oz)F;yW5%4dRS@i7*>Q^hI*Ohf5R}pV+VysBx!ZDB)J>9Ro%fs`X~}ZZ7OIpO?w~ti+NKue z_eN`m2)(JGv`jB@G)yX@pY;LY!;`f}wEYYX@9a^9^9yMY3pv*_WBz~n<9R&*Y*oGE ziMTqze@gp@XMJw@WjgZdMF|*wVu9E=bI8US#qtI_{%0k36}XDq^l7D4w}1A3QfVM{wFGI=HdCEh_PebN<#Qm`$L2_sUX*zBg< z3=sCbMoc(5;948V+rEVYChfdBMVaH#rQ1tkY^P?S7{9E#%7y{pm@m}G^ zdVNYZ84Z^-15t7&!U=)Cuzk+;(OuIZD@H=nh@AG?&OcsavJ1a;7XJNn5F@Xx#sx@w zg$~E!z_lb}tmfsF5uJh#xFsbD{99EF>Y4qt7aDYVuy~Taq^3Q==4*O8k%H7+ay|G; z+UC3k2fA~&VlRYNSZH0WR)offppC?#TH9IR5Us0gi~hksYhdknH$FStOe7k7P6qG` zbP0H455+cFt){b(5SUUc$V`P^_$dhBHuwJh%iQ0{8dVQtwOl+mUOJ=dxUN{bZa7dS zjb9&f(2Q?OqlWWJgA9^oNS<#BgqgwLgEc_u%yiFx7a$z$@e7EJ7V^H-y!iW^-0J5k zQrA?lm=Vl@V$H)C$fd++9^Bag*7wz1_2wBuf!q)D{T{G9g9|605U55Lr|5zho3>6jehW1mlB2QQND#0NN%njT^#X~R z_LP@?G0UC^?pf)Hd^A!jD*`(SdI-ABq4~5t38gz&F*L!5{VrG*m$lW*x~y(;H0S7QOf)ub<_X|L+h(7OJ;mu@ z(aN=qAf4e+om}^!mj14z%+E~1o0dWuYz6nK)>U4u;7D4v&(MR)W6~hf$z-gIsy!t2 z?S|6y<5#${*bLeLisOwoCTAm>@JIh zNIM$hT(W9WOMlU>MsO+q)inMI1+eTFzdccPWT{2j!$sk^1=J~v1>ux}Muw`|t6$HS z6%YanlOLE_LzK`5J3)uZmt=(+sGDHm(9YTVvyAGveq}0ZZ8S=-xtUJouX~ zAf)SJR`6ZN=|O1jB^`mFz>W|KtY$JOUq5x`v}9DBTp0QdQ|9SOrNza<2KkOE9!`HK00>=G=K zTqo~2RKuz7+mP}6a^cOeUt8a%1ssbL@q%SskU!P$d*eDzvJP&4Mc#kYaK#~}ciI>y zWa9euC0>>#Lf@^oO~P%CIT4^21s8<t7daY+J19yedor+Q-in6~A2f;ml*l`)e|DYXvCr z;xB81hh(kb{6D=I6WH->uv!4Yt zvIg~SCVKV@dtMf28p)pEKv82A7OV7XZHB;uqe|y6N|40$#{eARUY8)BlFw4cJ( z{mtO6|71;)>fD{gO*qImfX!k-oVfqds!sLGXH63Jlmzo{H906rcVEo09y?caMmGp{ zlV`fizkFh&aT@c6%gkC_S!=Cr0%kAE2A4NZux0~k4cnnm?rkQ{_SQE~oiC{x7JW~W zIQ0HT`yhDrl#q(eOILs8=J96b()wCqwM8f@gHa-nOUD7s6Vs$8*gfT2b8 zzLjPJ6IKTaQ>sd3Hl*DoBOR`zLrNCn)xU&F(}m6T?bj??{m?Gq9dBQ>tw8IM#60k_ z0Hv1lq>K_9k~%KZaqii*{bEaC!$W@xGycuB`SDkdog@pWA3#V%N%IM^xd%Z-O z+A(KGz0cmlL7)&4!As(!QD$~qXOkXeTxofCIAIykX~(lQ?fG^quHM@VUUhJb*HJ4r zgDQQ_!B(`j@o!H0_qRVH(=c0!ELhVuN_fIS99UHuhB(lYOd!RTV znzz0P9y_4?2-gHU8J5H$BBR6e`=e}%?+B%YkB*M0>0O_8Q}Wl@n0@(RsHK_1+>@t- z9>JRV86?|p;#?%vcoq8RUiO=>2d@~N`&PMwEJd@D33~dDK9YjI^?qgfz=6W9AIV-) zH)%}}%L|7x&g9y@_!S}Ys8$X9MesWoE0zMDGVD!$1y48GIOAAx=gLzlYnfNu4^0c}q>wcrfhfc) zvg&WwP^EO^D0h}o$7Q41@4LmHSlEBA>ooXQv~ApboH_DC}YE}HRj z?D_f5My7iubtNKQg&EGv9p5LSp3r--3<7tE)=T+ipE-v+%D&>C4_JcOJm$d>(i@;yA zBOrDWFm*BK%TPtG+LBFha=%#CS@GEpGXv9+qj=v$b(gZm2riPvLb~;#@-qw5uQFdy zOE6?k(Ye_Zv{~AZM9NQo+4j-Ie+qi`s{31)0RvpNCVhG~#?a5V*vB>EjUg@^rZ6b@ zctcu=#xw<^4<=^9O3?y~WW#UTT1!U`B+i95jX=$amHT%?gbb;2D}5y9*eF3Qy8|*M z9tPYLD_gkjoR_!JzEQ_gboXU@!ADdOkDQkmCyl5v4xU)`cA&)Ystqf0-LW7BiST`) z06&_IXVBW6o)5U_BiKZ0-I-KYWb`3rxqmiFa@`RHzWX`WR*1MqUC+=^zUQ2!Uc;+wWKN1!lV;|2NJ2 ze71a^9q6{+wk~@p>XDqw<5$>H2INo4HJf>4hyE*ziV6+x^`Xs7`|u+7Ii0{u!X#Z! z?Hfv_vB}ZVy*Z~AD@R8WaEW`r$oImuu}XaF6)hXKf?#R`!}gPUz4oK*Mb%0vIvhDS z``1rH7)N`+BvGJKBvCbnf`dB+aQz(kAI<1)*>`74W9uFFnmVy<0K61kTul;T`kg=m`!cS*yMyk5^n}Ls&E}4hJV6KT7cX8>J*=AE9?{(AP0HDZvK0`% zQAHxO9#ihd5^jG!)S&+JB<|w~lO9~oYN7pV)Y<*9qjOwcJe(Nh@NxkCxoAbwSK0sd z)H;K8Mh$5=uUDr9oE95H0sh>eFDPe8Cj13al?qY$p7Je8%Z@GAeRp$A%pPh9q`A~q z3Qr2`UjXsrxLEe-=gEdn5s;rzKJz0e_h$xHzmIp^cr)QpA)L+dbyWZP;PLwk! zBmQ9y!Jta$ZuhUxJ0A8b?MFb!`6u%u69l^{as&)rOjfqVh?zO72Q_kY9R zS9rvHduIFlvV@0+?e?9Yb!eT8#{~j9Dbv^>;~1O2Dbp&LQCYpTjbb@VsPWZ|3xE+L>r! z*Yy=a(EZg|+@|HSRJwJIg%kW3n;N!T(kqWAEb{%oy@8LjA#w~Ik;s_63p|i89Srn3 zOigJ>|6A|XQQu+3dpw%?wORkGt7;tP%7h1M$hVr@-RS15+5K?;(tUc*Y2t2Sta6Z?NOVT?b1l-4 zTHa?iT;Vv&zdY}jZh8kK&&QXNwD{#-{W3HZ!+>yIJ8~Kv=Z3V^nG*pGn!bHYn{kKW z#84$2{MN4Uf~!hb>v2J=)yZ_vuV?$7fNZ_Ln{Z7ygKA(=fZU^GlDoOlb!>KA6GwzMpBB$b=jy!Ukf~+0!P(p8I%zj3&}0q zlOliXm*w(9Y`{M>o0kqo|H?jp1bwfBn%EDe@eksy>;T>(pz>e9p!Jm;Ira7Rzh}VM zwx=}iz?c7KYTiLU8Wa`oyRF~%Nr&YvrPX3!9K2YHl*wFb)gH43n?dVw- zW9*u;*vXf?DQdBAZv|j5#gteFCzF1JFbMn@0+XcG9JYX)_yzd-A1w=9{g%5~?>pa6 z4%O4#ZxNnxp14fV2}w!kkkedtbgSlcG^{{mjy|#UF#L(5#7chvEWwBK|18c{&DKl* zdi&P>lJ6h`eN&d$RE-gZzlR|Bahaw^2)wO%gpPClW7v;Xw(INX_cEd@ zuWm{}wXM}|uHMtw58oKP@@be%*Bz^Lum0^}9X4SIEksEwBvhD0PS!Rb;nwN1qu7Zp ztpMy2UP{)5v%B&*_z0JBp>oC_OKt5mN4R*a0CAew$@2g9?P*otOh|Y%FOHeYaC^$^ zsN5W8k4wv!Y{REp$Xb-kvdH7f6Jyt003Yx_YPVd+-k?j#hdUM^;reX;gqslW{TJ8g z%zAVh#)Oy8gCR-@g-Zv1cKHx#oZ`?7u%xYsW2h0ownp&eqcfuNj@3K1#h1qPCgtDVD z4gS?5?GyQ?QCru+uGiPKMXUu>I&_x)NMplkw2BwoDgdL zrV{${PTjkL`ZC~lF0%L}{~hR~Il9RqIPdqf>Os30+AQ?$+(EM?OpPmZ@lQv85b}FM z2y?Vfiy%~{<8~Iu#W`<*rQOZP+||R!nu_?}T$4$HG#;d&X6C0d_YKP3Ip7#QO&Ci! z_}P6&(#PM;t8DM77U9?DEk7fWFWWck3UCM}3AE3w)nDjk{eI=P==tLQHJf7#>a!EU z0bc)+36FV>M%yKJ7%-H(@^9xGEXO)2bpzo$J~Q_Ic(;lyU$T#~_0GD`OI~#CraHM) z{)kddD6~!I@K-`UN2WGtDKRBQfLytFJ|~Re(Od(PqVWeSQGR%WxM3!_HhcllP-F|o z0zjTVrJX}%qQQx)tMZQ_L z2@JhSk9m;>A%F9^H-?r(CO2p-J~XjcPhGu7-29!s?%vbsC5;T9gz@dh{bF&hBJ&7Yj<;?%6Ik3rD8aZ29B7ix)yTtTXhC1!*~w-Pk3;Ej z<3dTg`+9ZQY2~9Q6on-oF*Mkp6cCi|1SYzPmaaW?Lc3 z+w!c)zV@xk+N0Auk;Rz_zmLSNDrw|&GHh%kvt>JeD~Zh&Jv@cKVyr!rS#%fzw*b}7 zPDybAXW1_0`vysK@9CMP|6E^kb8>$2R8Y5)2U&z|Wp7cu|3(+q{Vf~|3qXKohCj}) z3|bqCd5Vx>voc@UhpfU~&4YE5BkxQsVyMr_5kFEe4Qx@cu9%u<*loL*t=sfu*5_LK z`0rfkR^0zj3qTju4I-ue_>}htAU0;Uovme$(hjSt-_h}2h}~^OTTpcU;lTo{y0h)r z&pum&;BVDpDdfz4szUYB8rFeKUg`-eQqGtFMHVcV@k{MJ?LVE6q?^$Vepa;BrWIb1I`QyUix$k#wL3&?ATYZ zdDRuR3Y`~e>|!P({qCX6Dl8fnSz*qxcjP&qYCLcGK=Ptrij5QqyzR76a3M4nrlh6^ zbI|$B9oF-~!myOIvGep{BKOxf_t{=DZ2bCL1Wc{Jz-}*bK&UU$QN&uq5E9WyZ>6f* z`Zw8AcU{YX#}K4%!-&;ClJDif2N=K@2?z+}?4`ejdfD?y1g*5X(W3o~*uUUQ{gL{J z)%&q>WvAT9Tl>0Q)a+s5{B%-1^Q~V+sW2#*qzK5)gIa>yv^Wp+GWq(Y!WNJJHWan1rxPEM|#Enbr3;bU|7cyKtlCriOhpy`-F)|N@=^i4zbD#uT94I z)`X-ulzSFO@cs>b*rEyAdQTIAtEtrF5Dqa&9%VkM<_w1b+~tCZ_HK?SY+AMNe_Pv+ z`Yj7IC1clyKDw#4^1<6A>?Q>ght|9BXif{okk6TZ6Zk!$LsUdpDI1s zoqx3XT%Aw-Ab*v~*7Vu$S<7$+#WnvpOKJE@?$U0|zzgXx&6g2*Lin9w5-t%m!ao04 z)^$dHa`P`#byrvgo`kauNN+pkH<}u-MXidD)z!<1NozoXRLSRI<&K7?bBZN%$BgxOIV=j=z``73I^D2UteEV)~kmo`8aC8 zG$Zk&fw_tx&KuQs@&9N#??*P@zl(<|u|t&@C5obA?@=RG?NwCNs=bPup+=2TyTqtj z6s=ji_Kuc{9eeM+ijP{){r%y|pODbR zW)qBw)4U&c+)9D=P{$}evdu4(3a*VTn1XoiNpjQXKF**!%Gx?Q++^_WGdZG;gGE9( zN$3~g7I7Q1nUp2vO=4X}{)I*o6q@+Ld%5>vg&@~OnQL#OC!KcA|4bGeS*A#&|3s;| zp`oEkiUNe)5gHDQ=EfunZf%aEaAOE&#`|(_`;L(2&Vh6OETh_wN}At{O}}t9o8&Fv z((q&*Jjec=9Jqe(**L6YK}{rkm(Av4!$|$NX_qpmGKZ;Iy{1&6#f*qIJW*eq{G#s* z`mMNep4pf(0vrwotuYaRm}TEWLFIL1_W;L-NUr#e%mYMuMSR;yid*aIBe}rSL2-YN z7u>e(xo&Q50htTH@j2g{P6*ty)*9QRC$umrKj-c)eMX4ax;!Pg72?#Jrx-~~SDBc9 z0V#cUxpt$QDtFJEV)q^hJ&t)vaBR*6<4zf+ZutYTq~qooxwq(VDVv!iajXj!;^rXe zftJ=Dk*5VWGb{Zs{GSiKPPVv7S*?^fUkanFE4PWQ=WVCmxb($(uo5W2qPt+0Dzj#1 z{|i;qWBj~ry#wrLp&T5E)eCd*SUhlN)0^xFx0b;DNDBpsL^^`C_Gybo?Z6J!uGr;uo)z$1LwC2Xm_mRe`sCj|xzB?Xhl>>#jSe?^|F!d$Ak?f2vxe*-@$^emj{3V(M#{k3(_lTr$I+o&ZMc1=g#LdR3-xV< zy^*eOju|Myb|A?e&m>9x0~VhoLLB=66aoi|m8F^>x7W|6OVcv$(NW#3HVzCf12`iN z3^t-VnG6r~YGDp(YQ|Ig4|sjF2d;fm#UwjI2!I4vPMc_DM&&bcxg*1amoWg9I-UIQ zl=38(Fw=RZ(Dp%Fzd+P`MRTI@V1C>V7nuyNvHJI~f&kl5+c{w455481P9Wi@<@3ZX z_-c`e@K_zYalaF|5D~gNpd1@3c9-3^vSz2Ij-ry<@v}}lEtfv}%%f)Ocy7fbD@{vF z{)zgwFi7eC*>tS*onR-9Q~(7f5|j9S{IZ@x`TeVikFiRyZ`Mx7NP(*T>FaiR{|isZ z1)pn~o0|o77EgI*la+`P$arw>9zhPlx{e~ywpX`$>>`uX>oGMRN=gj-nW}j?Pr7j0 z+$Zb?hXeSd(y(L>UIUH|CAE})S1If6Px<(Q>-v96l6 zZPcG0tr3IVjnoRM*gep?i#c5@z~Bdg+j7UIGG=R0%l^ z>QVKstSbDAdU&9hyVnbvhK6lt%Jg`JjRQAvxcj zqvhSji-n7zyKQ?&=nT}kd~~MIHq}-Z5|})Ec(Hkk;&ggD@%(qfR#CD^$no?kogiq@ zZz(hOzMDleg_xU}f7FGA|(->f)=v-(KFYUXd_K7g(Yz+xH5_pM( z;5gbV>9jrt`MCNxC;ywAO2j+L1LFii3`#5ui&0AwQ~~xfGYcm;Ga}jBW)^0qDa7?= zrQ#o?aLS9!r*>A8hFqJvz5xK+pKrT%+er&=B#~5gtn@$qa5adJa<@eeJg_lFP%G(M$Sn2mh-pHZ$37&eG;GWXxvQ!{+PU0AUK8s$43E2@eMaKCDvnb=7FneJ@+@ z-j`!1v{qbSAJcTFIpz4K$%5JV!mB7AdcERu3=dW)uSBGssJ*pNN_cWihpF6jonBLtq z-yJR9bZYZB#^`oiDuI!Wg>(Jez*p(j}!ie|d)CNxP$8e6;EVo#;+?#9r zf8DjNNRFPaA47#DJ0wc6pe@77ou>0gt%r7C1<+6Sk8vYb&|24SXdTWnU922}d$-IJ zEa~h-d!L5LbsDw?a=(4op+`fFc!%}G5-M1hcS5h=KXOmTQ(}<267kPqE5GxQ&e+PS zHLvV6eG=B|d(DV`hk;oUEx{+inYeg%xX#<|<;bRGy*P6~Nl-gRc6KCjEyw!Qo`w*t&Mz{3NqYVtPbnQL)+G~4suY-2%f%^0W`VEt*LZ8cF-V zUpTkc){|thK|HWyBD@1970n0#jsVoQeek)x0tED<*+48C8?n@O_CKMl6KK#F#GsQT z;-m9v5TFq7d*ehFogMCh(E$}7{5<1N(&wL^{WdI(%?V!?M7ZrNXOjIa_PPu6Eh_88 zI~_HLgq&_-w>vDZ^N0%BGFY%pNC>TqW4=I(6xqa&Uv5d{%*c{yWFd^dD<9RyW4cGWj}Vb zzklo^Mv9-o{*kVntXmgsK5>7_0H|UGqNA-qqr`&Tqh3hp4ft~5g#2f}@(RhDKfaTG zfdkW@IsbcmzBN+N7yroA%w(|cUPOKH);|R25`DNz4#qnmbG<(#Q5%~Jd`QxWm%*uT*}K`T$d|pZ4x;mDE<~N zRQ^|U=s9PN&@Mk$WF0=Ma><*BS}W#3@|ciU*xNg9j%V#0IW6o|U2TN~Ao-{|8lC0 zplUc_2X(5vrU0v}S)`szt<%nvFMldOqRgg&7a9OynIf(K>;GA>dElG*X7{eB<`Zi< zr_OX5Wnxg%c2TC77@w%?#F@R{P~|NN<6AdGm<3-RAqYzL;eQES7qL^BPxY=Bnms=j zo23KJ_ki|V&MXk<`n>`%Y#d=3o9)e-M|!jD7P!}79(YxnBYC;k-w*VWx5*q`j0K8+ z4Q`M;iQ(_h)>khCvjVp;`|SHOV1}39Gt6@yo`#YN@A1-}wY;&(>S)4&skfp=Wd`tV zUk%(>VgLFfhW0V!;$+&-2gUcsBBru+b-6$2;P>}>5Q2a;1mw?nEMjOsAP&vH7trI<|CdGp1BF+bs@B7-UVfbo26 zx+h@b@bxTMVaVzDP{&!3+XK5l!gyGnCkefEg=LZRfD2z5B~tdMUq*v2mAx3LuTl7C9o- zxnUi6!bm1jEuO*(=WQmkutc8Ec6s-44B}h-Ce~D;`gKhyR$DKj#CZsHE(LZlvOF)0 zqd}a{jECuJVsmrX0M%RlND)--jTAYLT>P7H>?iX%C49In&G;-!;BjL;j#RHER;V- z7G)K9Gm68UpVt>xUs>I=-aDIA4Zd3bRTp?<#3LtBL6t3dj zK~C21_*y@&y+#`*j|16fFIH66oSHI z`yRA^SyjH4R`L`V%bs0Vc)VtkyYzJM%NrqCCJN4EH5%prX#xKxyyFC!$p~+2czJm* z#d>QL?vhF0*U;0sGH|q(HK;NS#(Cn9l_^^(nSsAg8kpj7?+?oxf=}4*7L=JeJ7*Wp z>#q*mi9iC`sX#@NUWcUk^F^Al~l zg5pd@+qCI^QEd+Qy;vpqEul{2OLm{98oC67~FY@%v-ULE{;{wE_)+Xamdj5>fEo zg`D>4x$~l5IO%&(cs-rc$oAMS6ath6$G`rg9ESJ2>+4eu8)CLR-7J92l{vUG^zJgC zhE_lY>VvEUDNrk+Du-YdrT-#hpjG{kLFN_vg;4?yy2BufITz#X8-P zn+xPaW<5ScNnuWyIlsLtG8|NndBizYt|67?o!ss2g1A;gsgue zo{!SV!`Sb}hJx(Y|C#a+U9tq7=rH^JH|vq)a1SIOF0@&}W#x6~sq( zAY~Lwy#!I2g5LY&iS=(hD{^e&WK}QC4cG)c_hY$2My@U{`q2>(r~#!pKukTo3=(Qp zjktEwR((5$WRVLBQ|-zqI*wR6=$Xs7*~OS)T%D*0SXuuxOXIw!4=?O%rZ3una{bm_ zvyOC_RzT|lZha8Q0^I#^I8EiiO74PsUYfpaK$yNDHLV?$7y5qbW5qW#!!>x-+UZwM zoHd3tHspXy1RQuxycm)@UAehvJ-NGy;pgRNuBpgAI0`tt%X=*)=egsR)U$eQlth5} zw*78yAOMGSi~d$uk>Ml(C27s10a#)B2U2$vt{LG80IIM2f*JnGe3DnCIjlB5L=l`9 z9<j8nn3Vbd9w4Uv*sXQFVtu`^q@>RvCQDSk zu0<;e3W6x>ne-R-=0Uok_wjT~Y-9EAr#Rs$W%G?Q3w9x$S0#oqXi=i2r7xOeFWo1I zC;o9xuk(3;-iJXP)*+$l^k5H&lC7xL=r>ml>kv;E+3&&ux~A54?XT+K<#q|@{gst` zNY}+UwsG4lgPoXzD#VD}D%OL73HUz*9I)NXmO}GQ>V>~@yK;s;2=Wb759lsz`^!xa z1=Ff;-%8Uyhy`BwD_n^PO^m0TU$-O?#1BzdDb|u5OR36Y^=P|WwE>O4cRBv=Hy$X& z6U#NrNGciLQit}G7pCQQJZL#J)RDcc#TB_STD!I{ZidFx$F2Ac?_PN?aDgj(AFX^6 z26#RLw)-pB5XIdxJS!6^*h7lepF@@%+_1BCudJ;D~2QvLIZ@ zrQAr}gtQv&%rG+WPXrcZd1yW248LqR5Uz=|3H;X!m9~FofZ=osuByd>UsKA1HX(!% zJXb&w0Xf9+4D6iG9{ya7m*#sVp(9X{8LeCW^QXi#{iJs`yV|Ts$9wTtidv`@&HXH4 zyGc%%3wbIb*8@oZOL>!yl(HQu4S(-3T}0y&r0LkkS*&~vzVwQppMMB=U%6<5aq5)+ zT4jbB_}xeaGl%Le{Epw!D1k<05`3Q&CihE$vUkt?5$=fRCRlpXB(A6eck^-36kx#| z1TIIdUfcQTXu{5*dtq;e^^IMV2#}vAS)`%o{ztuy`ZH-K^Cpd^a0M{vtB3%`KUic_ z-Xt{^Pv_k$Gqcv)f4lsze!>dl^L3qPT?Gz2#tUSIQgFA4^THI}u~j7{|H6WxLfFjQ z%jw*py{bdKXkbj#{Jnl^?+m%$4uq?`7SmfDsUP%2weo zfkH4q-Bxv7V`E*NWVTjlh?G4H(d)8scpka16m_w~-gO zlN#N2PF@+2y>`dhZB2Ms>xN%C)C zP%%7}ATj6bsFyAe5d-7%^#qDDX$}Sa#qXOcxTr84n6WJov`D_3r3Qg&_0$Jouv1hv z`!Wuf4tX_MhvSRyzA-v9Yor7vs?U3kX{mp|e3w)7-50MGhY!ju`T&XLl-55fqM9`G z&2~$>Fkq>4XXKhdPI|Ytwwk5dnoY{$nvdrBJ(_}p?}0+HM<7k+IoQnzoJxQpj5Jy1 ze4=);`dnLf-gHs!zl8@U1MisaVo|;Hl)6?*&t4`#2!>$<^ww5Nl4(GxU2pHSi_xSZ zRH)r-&3B45+%ZeUwIHGg+I~CLsXA-DOKm-e+Lk^4&m!<{Z`)&bi3>bxWA$?hEvRqk ztwlV6e9C(v(>&-URqW#X+UMp|x2fqY7@wPi^;?BkPNUpiS9{>!DmNX@IKgqeFLg{` ze>>FrSp_OOstGC+SjUzLlZHj)mvzB>D6ld5+{ry3^;PJ-Cq_0de>q30n3|5Uf3)x= zm-R`=`o6+-tkAgF_X}AXcaVBrZrEy0OCX~5xSUBvV!+?fjI<)33y;E5vr{(V2cJj; zm^P*O{@fml;3Ys3J=X%#Nrnh%S)p7 z9E%SZ(OW^N`^9@_C(|vjV;QW$j}agFgD*>2{_7yBhM&Gkkd5>mRl04w_SdrS0??Xf zlgt7;zanmX7F$ELH5>u>Oc+=6iMcv>X0C-GWp30SHRAOk< z+`toD@#-ec8F_M8t&_y5;c=jl7)XCgMDlbioQeewM_Lw>x51CQ)V2(c8ux}>b$Tj^^>NjTna6YoYJdYQDYJ{Goo6_n?QS0+v#jz{V^5kZVdX6-XDf-0u#3+yl6bS}p*suOawUJWu~t zV&6UNP25*ckTAv)%tZJ2a1+D|mMJxG=6i&Hb)kL!V8DV8;TZcKVjcJJVPk;a^ybpSnGAck;F4#s!+U@T4Gf8?A9H#E*tdMG_ z5fh`X1}YPjB4Ojd(GfVK0Xy^3%~9sIHe?(wwx&yBfMm4HkRYaJ8m={F_7QF$D&Qa) z2}atp+$}t?xS26##Nr{$uKy$H@s)%ibn+F!tPBEwez_P~Mj^VQ?)Mo{sz&**KCme8 zE9(oM-YQH;;~BghGXO8&HR5KFpe$eR+189K>F-ET87@gbnoAEi@d}1`RyE0D$lnlt zw@cRtL71dIl6<>%#4P6~cjl=xK*(6om98Qf0sa$hS37)_t#i#tlgA|w#plQ@NwT-3AeQMhCK}K<%yq1_3c|hjlAn7AGE9~-_R}bTJ9E| z>w7ygTwFC5+n7xPuF=Vt`FoLTQd^9y<9PEmCd-lY|10#)#(4vPu5g;u*9Xlf`CPR) zGy!x~B#yhg6}ZvYf$d_eE?efNKYNir!y#2Z&saYX@9 z!4hf+JQhnB$WX1Ow-ILEpg?#|kNwAKVq(&Gb{O*ClGdGW z!D|)(J3*Y45W>nw-WjD|loGGc5uq$#0xc|fs9RT8LpXh#a6Ppvd-5sa-A;0Dj;39h z!rfk@r&?Am?**rdv6=Uh`|R6bd@c^t1*g`lky|_MCmGTQ|0Y>32OH+@x)=Sg zXCJNn$USPd=(TOH5hifIn{uN2H1li#0y0m0AZ4G#P9OJS^*0%76vRmX?E)V!KQA92 zctl?_RxJA{=`L~d?YmrwfxyQXn`qDTr)HS>^>^Q^&0VrTAsBg0I_$>Ioh^cw#=m=t z8neSd4-i$N6&0Bh(NsndeQsO5)JYaor0FAGJ|<~jpO(g(6`+yAQ9T`P=j{BhyNa=C z9dn~^eTD9`oUM1vU?}JoV2Yy!RP&rp@i})F6l#0pwv*t>E!R~_v{l=C(xOm;xE5!U zidJ6F0?-i^yG<2zs@;Guu?kMg;touj%!htKemVA928uSOd|aKkraUpxf*G5QG|{Bm z#MZHOE#7Y$Jf8toNYL=H?b>x$X!s1Y@P!@?ZU)em06|r|&;Gyp6W2*g+Y ztwLwgw!xF7OE0PU>1m)`H(hY%tss(Na5F+siYy<9J>On?=H?#tANqJTG$#n>N^=*Q zD}3R3Gt8{u7p(hFvgpMOG?F+1j9g;+G2_&EAHfcO3^ebZ{My<1Y*0+43mJLybi%b} zF@QXA_+w2u5y81Tk8jFs#ocv`hT>*O(o@UY3R|-ictR38V)%oj3u~4!FD9J2s4zPJ zc4hZLo4LO)f*2TEGb>W#HIYi?G2AD!Bw zP`0wUir|!_?qzpx*Iv~RBVzH?&hxHpp5%$T<=o0;`ONk?9_z5D3-@Ix(^6S#A96fq`pa|=P}8l80^Cn-$ied z*eBEt5ZwYv`ojI!zVi_VlOK414y04_2MF*VXdTwbFoKvo^hZVJMBPMRj(^Kaxm;!C z({Ig+EddMj{0r~ja0bf-5mQy+9!Ie%;TS;Kbxn>lu;+q#>I^n`wRTd>kzje!@aZ~> zbJ2W$+QW9jqwCC}p+J)3l%I7QCB)G>O{x`gZx7~B9GXnM1lHec(G0Igo$T@6rmM5o z3c<<1UBf2oCVDinofdaT?YD&%{|#5|y5$b4g9e3%Wa(91hFQ?cgAq39r{z0MJ8Op* zYMPSH<&d{SL~6!{qM14=`luXhrTY2?yPD}brbXb|3nO4AJ`arb)CMbq>#=4{wKr4N z2_$*Y0>_NOO;0Q;L&<|l+8%%vF(`ujt7BKct?P4tkL#S$Q=dt7c8#k73MCe8gd8)( z{zo8@pwm~2txC#w%ru_AEUD&t_HU|o@Em~19tr1O{sAJIjmLg1z^AqKQD4>2A}W=> z{Ql-Rj}n+wVo~FbLwm+|3yljhDXioN$V>Y)BV)+ptcF)n<~ibqV@{vgKNgc;t+qcf z+YdVU8byWZcz;lKh?50ebRd;(uIRvz9|d2>N*33#<*yGT99%WIMRpSIwkTuM<<7b! zDJcS|l(|+{=DO{H5us-95tJNire7A z4Vlc(Oj}19Wqo3hyrE(2eQc9JOVQ;m@VJH!YZL$`h?Vz{XnmJ5V*D8qp^t2!5F$L8 zd+(%pS-k+Gp6lHNxy~5-02`|xgg|{;W>=CZC-9u!S~ICf-SO_c3+6I=o+f(~GxY3g zPUmJ^$FY1UM_PkB0_0RaCUb}NZ9DCGptFWDr|C8God+h{ZAO^R`d@$JpzP|&T@&Xf z#yZBwep$aP5`n$53Pgd+^vzcStbVk(uNcq5*Vdo#UGbJ>ts%MK49lcVy#;G9sk37w z!KMA*WKa}LX;`W_?$}ysmnj5f#TE|IcH-c+;^B$p*4~Wh7qm>5B!JYUtOw2B`l_|%IjlD((tcfgDWBs^;2J^D+*kl+h)zX{Ue-c~KJf*yS5zDFqm0RNuo zmr$&os#%acB#dPxV&??w{t=*n_Y8l_n7F~oqga2w5gch)tQYfN`ED?KR=}xa*0i3= zSTEKGSz-T}SxBB2*M?%Hvkb%6<}l zjWm479``r~BvON5R}&m_{z=(|Gbs)iqt$1?kBXfDHK9ymi^qVrc&9+?ZhU!YT?e@; zoBHp|)6I;cRQ)xS&+$qV`mx&U@Goe5)?X-6Rxth(0!{)(`wRFkUdXVNGhk1^+hPhy zhggFMvFoS}=_ddiydTQ=q3n$xQ|~6$+#Ofs`0q~dyl5m9XvkR-KS1R!=XgeDlzx5s zU0wfowF{d`S64MJC7z66IYhAS86vTvvPnwVQ?K z@o(3_+1+!Mhc>#8dajE)H zHw88ZdqBDXC31LBf3Px}1d8|6S~>Ng%2t0*6fGEvuQQ8%x&>anVt85F;EOTjC@oon z?|C)JM>%?Ir^fdb(6F%x=}#Ea98Z@q!70$GXsFgmqk;X)Dj&aIX4x?{138n$E-KD& zD^0<_znJF^;Y!lOrq;2dTK7s{0JgDgZKCJ$mXahr%0G{ID~M>w5m7HndQE20UC`5o z{e7svW>|=!;e$TCBz8;B+v>D=6i`?&v6(xRRQ7EL&`3&3VhvJ%mV8gNJ^itW7gxtG z5DpXhm|Rk^Dl)!s1V-h@HT>yQ!xWC-@>2>8#tRF-DPm}xqS7YHqypboWvbq-7vG*n z%AKTbriG>H8fZfh%6c6PB+uFF8yW46m-d2|UL9m>hn7!(Q5cEBSfF1}tKi$`49~D+ z^7(yU-i_9S_@pUcZJ4rXZ4P7qcQU^gyE()9_37^w4v>*lOm9+Q%k z>hdYV9KsFzU!?qZGG>v%;bpjyyd9+vw{eX%eYvIE6`^Z5u_taU{`J>zo9|?N(G=bun-XH6KRSA8+(-v>ws_67(E`Yi=5hx=NNqE&9EhKc$9>BvhFA4aQa# z7IM4{dmUR|RtD$eW3cWBg4i9OeqydL_@%f@hDi7PKvj(qNXQRS8!%U0_Z&?oaJ9&` z(`Z;494gxh%3Vhi$9^+P)i0`Bg9~8TJxGWuxME=76Pe<0T3ftZxV&!YTl$yAHwz>j zSrGrj?||Fxc4cJOgjuV|Hc2VVAavRbX{njOEGhf>pnj-@cTxbjlod?0UbN)Hee7zU z{FaZ@qi^&&Ne`N6+_-H%u_E#wJ*eBXx0-8y7r6JV9w(hZoEJ|0D9Q30z1_rz*xzS?T&Z{TY`;gk8<$N`=35Am0`F>bpA?~w-k`O#iCd<>~jO(ELehcip?@7fpkM zg8+|@`uT~n-XFH8)8O@3rzk$Olyi1{Pjh0DEcb$svn%Q8ah%GF3F1EY%?;omqD-#+ zX<3vD=buUMU+rOx=)}s&;k+<=GAJAc zyT-o{&9{SosF^0SCVRq~7;#SiU1a=t|JnO^`a`$SA;uN#m}2Y2xWl8qJczopC=?D` zOA!L54_n9V*}3Vtg?Vq>!(JDm&yN$b+wx)-+Lq4E+x}ZE7p3i0!}x8*cB^>o?!4X| zpH9}|Za;YBcGcu7`**AO?(ai>x$D-&)4`coxw{^*LO8`3j4VzOX>GNC!_QiGbCw)H z`!w+pTK|8gPTiDpEzQlOtD@FqE*u5?HenIj-dHyEP#9PuMsY!7#XR*Ib2B}AyK&Wa zJeQ|>xApm0P-=e0|Fx%#|H=xkmNw1Iv1Hp!1!l zlQRyk<)^>8-}PIs5L;!P&d;0u7nbGu!@zr`hjP$^Q4||3?1#3Tl*$mg>3M-+|6(>(4cKA!j!;S8ho6VCcsKqP?U-u zt<4M)#QS_NSAfiFkZ*kd5oLj7>OouEJc}Gwl7HZ& zYYZ5@yqo#e(l*3{R_EK#4i>8kgUolb3TUXJxjd20sNUA|L!I2V_0bx-u|(yp;JfCa zU#v7e?|w+2YgX3nb>@BEZvS;|r!qOEOt_{#T$(>)Q}*Z$Py*i%vr3RDL>ok3lOJk< zGGQcqe0*V1qsXpjXX4B0Tr`Yq%fAS(|5Q{0y{V&2* z!>%$oDrmDIXwX>p=owd(Zp)Q{+^HEwp0?aPecTFMDLvl4Kw<;T8@Qd)dt)ZXbE`ir)e zE2S>6PEZA`%zd!-Ea4pu2eLHcwhLGR%D-Dg5haL3=bH%LOJUrcJ3kjIeDS$|{r-+QZS4Mdaw=LYVIh;g12FB?;%wlVouJ4g3$CeyvEv&6@xjgoCfnCUxKQG-L zjbi9yPTxgwugC}rrE8Zi>jOueF*4?Ezc|Pk^_t2I3V+M+r|ACM1=hnvow0O51UF&l z2bg6?%ij67`Wgv}#E~L}i)^{`M{@ruE?$%`dP|_r7iMV}ua^>n)+g_5Qk=&h$sKP+ zdNdv#x8HQwIQxEYkbn1$AwedlCXGFQkz#!$%kZhqA6i3>@S|_euem?hrb=^v1LI3+ zQhXj$)#lrf?4=cEvHL`dcuzk-B%Oj9#8pu~t)|u-c@2B8SDlFUsm0+XWGR372JV{G z7yA08r zMz1(ouixHaTeIUO=)@W4AO1YmyJ=pwP)4g!(dX4eF&N`m)uxw63fV0#7CwZu-mZI8owY5j2VVXQT zlGb=>NbUl>77^?d6B2v66N$g_u;IlwZ}IWShrPogs|2(z0!1`-%eqevnak5yAUt^|d*X%K9MB2AYrpZGzlAN;GPwrtPqtYj{{&sM28;3RI*vfC zp_HrapW{_6ZmFM0<+hC03Q?Yl^xtdOoQ!zLu1!6Sc9eLrKzL(WZFSpC*}}8EHdG1d zAQ1JqalB1KGstd%NRB4yKGow|m+-zG{{|iL`Kt$c(~)X~Xmwt9Qt_`;I zaA?yDWIk8)VIZ;QHyv|FORINcnS(l$NZ)uAwd@p~1~=77)+rZ>f+axBoAeeh)VNt# z`I5FVuM>RGcz5d@eEpepgYmAn;oYG0!ZGlmziRcL2x$NDLm+c79MZj$#=}) zA|VPh7d0)mgJn=`_O?=z4bAzF&i-)0m_VU<_dc|(THFo{qc^&qK4MqDrZLi>~x47Zcd&tq+mx`vy*mMFa5^p@+%@RrzHk;o8^x z7I#C%xj{}wqB2Y9`$oH_+PSj+Yg1=uajXD(k zhr0(uo>+bw2$WBO5?uJzE-+RjT;8Q6QrWJy~|8+*_-0cnJKJz`F-mLr~ zFv@JJ0FtIZMVrQYWDsCin?|tzM94qVJ)f0PwT`O>&%eEP==smV*T*$b{8vr&h`DrZ z)J2=ii;SV7lTR0cw|%!mcdI~C3@4gr_g&Ue^{~uy=-DZk8YvCHTL9vF z;gFx<@|;zDrSl1G?m0_UHYS8sm;fCx38KD%b6muPdAK9DX?x8^DsbmF@8-zmX@gwA zwvdZ#?Qgm#RE`;Mv7OmHFZ0k>334Za?Z=tz^^FT5Mng zJMKo`bk`>~<1!xaB}s^3!Win&S|*}lRwo5=ClA~2a&+1*dGB^Sb>8hQ-u#+uKMc$r z(VE*O(`Me^-=i&^%(*+V2-^BsoHLGdglv7Og%2o3QYe_oLCGXGJ(zTg@1MM}vT`VM zX88QIQ5na^;PYC03%lX4zY{KKtPz8f%D|zrXl>^i|1$e6z30sJFPYqhh2LxAyqbR6 z{hXWLdj1WaifIQt%eYHcz@|yz<|`|C2KxcE+3g1Z?P+D;SYu_=;jQt)XyAX-b@@V= zof4X4wf8^L^r_VoIdRtCV-=&8GKq9v@*hZx7XZuwJ&#G(7y18kXda6%zb3jGyomJnf>%rW2Ec*E+q9^ z$|y4;q7#F8^4y9Fk<88!&MX(?;0e@w5cG~CcU#0&9$=hVi>(89dBt51W8*H=7A$6& zHd})vc_3ZhW)|&1ar%F_fGzuyo?#kq**!xV`KPWvA=2VHw348IdlNhgsykh%q3pJ+ z_^sU5jR|`e|K0h%c_Nm1^VvDFFkN-)Sgj;Y$Imu`Cq2mK&0+1^Xx8z#TPesU{!q+j?*Wv`!UvONvi495{A-gvVWoo5B?~)`<{uH27T4k|Zkbx!8Yw z;XD8k6|6LA(>_Edz&B7fW&il)t`37Y+S}aD)M=i)d9ml@dg}FD&`oo&drC5Evr)ff z@=&AP#^54=^nYOjfb$kB2<$9H7!;n}V#M14PJC;{Q>lDfK|PhUdTQY@g#dNcPC z9%qm24d<=T?`NmYdp8*Mvl&k&K`QHZE(o>Qz`cp2Un~Zy$&BKbik*o1-MLNKS9-T+ z>1%$>@x*-haoF!?IQOW#Z0R`Z&PBHSxSFYJaNCR6WIg3YkK(Q3kXQ+h@cU^&|@aaNmN@vSx>vPnJNoiHTmU7HqqR@R! z316+BT`Zr}98e~ru!8JevcEr0@C>jC>iU=%O3g&nl5FEGD2lOM)5&eTukv~!;2V57 z(dK25>;HQJxCiDpAblML(iz} z=OemhzLb^@T?AZWu{5mXhrXEz6_gBff&v`MOfU25x%rorM0VmANM*g+=r68wGs&J- zFMm?}?)xJx98K3{w@#og{P)P!g6{6ML88&eDoLHEY2OsC!zQ~ zO-=Dh>_($64~e^ZB0r36yVMHL%ugHj>tY~XSXB5?+xauW8TqNw9g^oBh|mnWW9A4e zB`_^QKzoHaMy*HqP3RaG_eTN(&RSv0rdw(XFl32;^=XHt{_7|)$D zE0$diU4fFP^1=L+@YWb;mFTT=K>yf37$-k=S7)4nmeUg5GfTszPs$!;Ozf7TAC$p` zq9pGylM7M{Q}5MkWj>9og6v6JOZ)ltK#M|rv@RK9CL9>Nu>Vlm3J)o1hAE8n8}J5ID!aWKz}QMGL7?@N3x%Yf9Q)+xli-l~noL!$@&4Q3)XovXgpdgXkC^XLAfo6)Iqq4V03u(Y8YAfz&k{baA25-pS8)iiS2eNDCe4pO?zi&V8~^R>ysKl*FcCi)qd=c!~PR?z*y`j%spQn$zKUnN-W$o`C)DdPu4DI$XXZ zZCWZ?-y~HKbI^8mFlLV}D=(igoEYU>{`3~(w)JbGOTvu`5vCv>Ewl%**5CC+Q@&i{lyh*Q}?!jwWoh7SKU1oZ2ZsF>){9uaj)u^c)7 zy9uIE!9fpOPmP?l!1cJgS*lZb>frwcB`@00t*yyq0t1hBF#voB+O=lT1O))ad+1}3 z_ee@Pn-pLH;{8KMT0Tc+J<2eM&YC=vn<5~OH0Ez6?Ic7TM5%BTWZAO z0WQiP_>ONsed^RBkA0SgXmDt0T9u6yy-r>h&Bn$SLg+QGx&QLzD;_z7+^{#?9ZxY~ zdERMeqbv=y723Fn$69N?4+WG(A*IBG#BqG(`R92M^m;w;wSoKw8d7^D_^H#k@9wOY z)zlf(NxR6phaP&M(+z+3y?+K(+L_ZgJ^AF5QkibITb8ADc4cL-xv}d#isO`0T$W`J zuqa9ZN`U7MiM16SY!3~D$);(Xx85Oycp7)BW*SCTYIo18kDHM_bol76{pxQXI(e#? z%<_f)Es=$s@B9D8cFzIk3eWCNs_WE5kjX})V$nC zd%-AYkeBzSky?YyBGe@CqqTGVs;UB>5JCt=N-3ql7l!0{Ue}_H2<_e~r4)H>jB(lt zt-VK47zri4_Xr2QL4UHljgX7dl!p-|L0zduIqEL-Pu+S(A@qqyA1Q=oSr8{lu{jwG z7r+u^Wo701_3Q9>ZEb@j#Q`hEI}9O$P-iJVa`TzbfBGpvzN)fJvn&V#sJl4lO3J}- zh!EP{*#V4GDa8nFg9ux_a#fom2ryzOi<9l`?Wdo9x)Bq2uUhM(l2SRSuNh;UppA{) zey=|sPrdh2?iobL{kFP|D^To%Kn#?$a24SBGESVO1jl*SshTOqIM2~-x83&8J#SFP zT4xZ(*4pp*wr_j%@y|@B(ptQ4*u&uWhgi~D-uEj-xFN(6SUiAdE2VDR^H$LW{w$|d6mhL}uh$)or#uV@qiLEK;~i5@ z(wG71wVq6pG>eBFl2_clyO6lh=UG8*qAnsUi@3`~M zvuDr#@gKeC_)2!^+3j0zIr9&n`Yh6DVK5kv$6*vzWqIoS`Ae5B!IewWv}u~Us=_GB zvJ9L+=1~RO%X^$7YgL-0N*K<=Suxq(o@!%yy`GSIcXt$JnRh--;<~CRBi49~F=#Ll zLZXNZ*&sw9OwMmJT5GL$2%{*D!zi-OS!b=YT5F}8*2Y>tE2oTMOnhDY(eBpkU;oB# zZ}@A!{_daux&Qu~zxD19f9S8)*S4dWI!Az5+EVRXpVW4)IuB$lO8&m)tW;&fZ?*blbt%VTI+b{@uz+kVLQQlS; z^8$PbW6)rRY6Onp%F0R$azR}PuhUwKFtT>9;%WgPr8Ll4=Skg=A3pk_4;(pq(9AwjCX^OA*J-r4F&^B>1;ZU zlf=(0E?|ZTLXL6d9I}?AY0o2LUCntkot0T{@XNpQt2fABt=oQ3fSI|yp!(k?)LlLx-MVwidX#O zKYjvZ%&fH-dCsW!R$2tzDEz1}Z-Bk`1HvrreVD7mZp>BZyPp^Msd>Ba zwuXZsn9WLrP@2Xb5r|>!)-3!QC1jRmaGv(;s*LIP`%NR^aw6pRsFpAg$LxUcJyd>i znoK5>Fbv=R_P3unapISL>6fO{DR@n{rDV6;-QC@7*IDNHA2);^wU!4ILEv-d@RD}^ z($(wTh2FHPtujfH2aK21sNG&*jKxW)gk+2rwMaT0t+g{Y&-13Lq!69FGb?6En%;i< z?H4XwC}y)D4B-le42`FXAkvA{um9qYM^W(g-||BZ%A?QCEq9X>oBkFzWb z!|?j*D#94HOyROYen-x?(VcdqB#GD^cb=P0W*G5GNQANTwy6b3e}Ct9{p;=R?f1U- z_bK*eS>1HgDPyb<(iod(IY^Iox`}rfe!`Ze0^K(zL@Q;jRZ2}J6D1`fB+Ih0l*oIG zT~$}sI`7?V*2GaK%vdq4f-nR93~ODMrb0+eDU7@U){5ge%d(a<+D5_lA6plT7RhTB zk>ux%-cqwEDIf?MOjmd9rE6xJ~^yOVWBx^wYj1t!+D{g-QTA zj6lo(`cpshmaqKkbLa1|2+@GCD6OjoSp|qaOq_wH0Lp3eLf`XJi6AfwzfwvGa}j7$ zZoc_uLdfOIm)l|B%F4>l&Q2RRTjUk2++kOX5VE$mrnMdn2B5*$ZqUYYj4>{X!dgoy z2Jwihs=W7M7!pF9L)tXnqa+D9=S5LDi@V*yV3=QDUH9ILMlKJQ>$*0|DyuNZP};(q z1%EB)oWp@=CimX`w$a31eE$7eH`BYOAB%~PUc9XaB{JybGe)G8NgB;&b(Tfek)~;& zjK&xrJ$m%Qg$v%f{=!0wv*IM~qGo!mk9H=g@(5>(oa1u31#n&%@-U1krQTy9gb)He z_r4&zHV7DFtgc1B-|h8!moHzz7*Wa&6mV^dIY4>ZOQ|Rz1RGtEMCbIUR?gkxEA)&C})GQE7ddq}XWs;u#}Ci1QG#2BZMXSV@U6M&1t>7lEhJG);RbskR|cXi;lJ zkYlN642>gYs+&)p!WcD811@96Sg6Fon&be{fe@1Ak&yEHf8bpgpSdudO@wH)u}KmD zO@ICzALvWwc|DX;tt}x06OXaS7<=atc8u}Qf9~@;J2S?EC`zO>Qc3T86ox3^N;RAy zuf1rBn8(&rV<^V<#m15t<0y(-Q;T^o-!S3RN*A>nEDk2qq7e2q*15PL0cu;jXLFS6$%3{U_NPt!Ct)=E_yqY<*!8f!Ji4q*%B zM4G14*$iR7FkBpuc9arNeC`Qr?c(C1)_OD=!SO1~vcK3@l6z9W>Sc$T&Fs>%&#=gn zFgIGfz%hIOo_9JOs5B7rS(YJej~zR00?ecrGx6n9a(Ch0endKWeS#9CJ=F zCQ=$8*R+F^_Wymc#_s%8vsUl7&%}Gn8S8d?MjNf2_dW_EO0krJbLxHMv>^^BVL+J{ zrmB@e%(Ry8aEQyLr}HmSlrm!+1S}7+?T=zAyUH4@1(zQz=&FwS4(Xq1bj_V97hfz zf}FM1Xq|UEi^Ji@#s(bUTW`H}V`F39%dIVl;bg$^MF=e|EtO>nb#rSp);hUBV1NhG zdcm|>D6r=M)1wwtZ^c0&h=NWZ)CPOtf52OL<@WJ5O{0z4ceSzBqJBS3lDMj8&IWND z2_ZUpu9eV2$DHPAGA%03`N@+f0fdI{Jef?ES13kVNb(`4OL)4oxp8%MGwo+m`2%Yw zZNmU>5Lg6tEiYYq=Kb$~zmmGs?Vdk>9yCjY5Y`w7_U%N9E_Kt!xJo-r*g}>bI&^q@ zGTE&fWZkuE*ETlR<2YfAZEx?4$Kx;zy}tpbv{M9YZ5(H1S$8_U*{o!YcRIbgZeWtq z=IC}e<;BRwe687n`>j@!wKmDZG)t{9Le$RNG~x)^BxZ+l*Ue(%1MSI731d*m18SKk z=nJmta2~W{5_rvfu%gr0yQZp<(~PnxjsYpe2m=}lWzf#fPHSl1!c34)p&?+5Wm$Ii z?Ah(@ZD?*Fj@EU3;>3x%u3^LlFf!O`w>$apP2ecBU;f49A?W=1vp@X3Z~47H_;@KBl5~vHVH%6l1U|D=eUa`vXt!rtM83gbaP8W)cIE`t+pAyw>Z@0; zf+^j+W$e7RNxLclM-z}8NZ)W1V4@2xR4c!YF$Sx(wgBCS*~!^k@7md##Bt~5n{Ek% zWHO!^W79MwJd};-_c~1_mU`V^|K(r)_{aW!vNL-6>QyLAlO(x*{d&LO2Ry4D*Fj8m zZSFmf-~F2p-SuTR|N1XJJZlyO)d$91^W#t{B^Yw{dU;(-&WX|%40Yggp;ZG=x1eLcR01 z+MK31aX0vl(`C7pGTn(veU_*chKq~VIZTL2-Vth#tCLwS5+g$n!}#%kXT!JTpZlI)R@0Cs9SaVaI>ZLRS#tS$@&$*W%VWf-F%2&<~;bh|)7 zcyYluFXQ$FEl~k+1z)fr2+}mo^L$oJFh)Vh(ll0Dc<-fZ0O5Bp{J`&@BnfcO+Rc(y zhwT8dt(D_xS?*yNf|Ydp{pY9cdj-DH*4lorzp${-G|kHL%6s1P9_QVaD_3Bvu&(PY z%YdW|O*$}oU~;JT5vZ~d{oWu+5-BxfEXxu~G3T_=&2TsnsvM2CtTBs=StsRr!sMiv zCalvFP1(q5hUl88pFi9`^7kM6!wVOlEUW4J-uK79_dnjP^z8V_B}5vF{L=DpXEH+= z(SXNUIw@<$3D7qulL_?5Z+XjGf-p43NXLAZkFkDwcl!r_>TiGNkL^T?S3mHkrKP3q z?d`U(W{iQG&is>{|NF^gA)#$E`cl;IqPxfJG@y+gb+f?qWRRPKK>_v`o7iG z&B1VCGMN&BrBsa3`L)9rJ5C<>z?cDWz7}f*C-+V#E{aBJl_b$?U;6;1cyn`;>~F#! zINXr?=8qj5h<3~A#m;kWNe9OlvuHAA#$ihuElk$K*7z5Q6}339)>94-yjeqA;H zUjGS6LC*Qo(h{I5U_}jW3Z*`d1J0=T#yPvay|uQsNeH5hA270n51b5`&dtke&Ufqc zr?aKWK~8|4H%XF~?{h#B5tdrOI8=TVpyWeFIZ zROhgd8-f!xp=-SoIBTEbK{MK6^{>SI?;IL@Kd*Abi z|M$=T&f%Mf|N7hS`2HXKowUO#56e>;$v%gb4o!IaE7*X?$VLB?2kWe3t|6t&8C zC`pn$&k;hqySs2vfUnRN;95I`P!LAOm^|+yf|E3bb^8CM50r-Or){Wsb0|spXuK1I z%vyBstMB>1Uwyb~khS(te*d{N>c!p7zx&ir3{PDA*8lCzU2^V!{PwKd8)_9t!NNP= z{taP}J42O5weZl&h(_jlUhFq>aU5YnV2=?>@SW{#n8zOJWeAaemmWJD3Y=8RpxQ91 z;rz9$VQ|S?I`)A_0JEq2mcc~ckW!fWOVlI z*#{nY08|x|ly`e+9Eb4kIj5K)gi#O@gb|^L5JV|nUS2+R>eO&JgwPnrG2piV2!~;a z5#pR@S(arP!U$m$=UJR*&>TR24WJ!NHG(hlK?rrb-B$GvPEr_#Nz5=pj3SIsx07Ln zFhY5n0UrmTY3TP`*B>y+oAZBVNs_c0K=29YK7fI@$8LFf8DcH`fbgB$Uz{Z=MhN~o zTo`c5Fhc!q56Ud~zYs#5PN(1RL+FL-HVnf!j-kq=DM!XU000!7Nkl^NR$FXk05Jk(!(1UL{cWmV-Lp(rekfUP@ zE2oa1BPc~EK6TfCwD%a3#rBB&{6Psm|CBiAg9I^(X^8sl_z(^M zzu)T~%@c$c({QB|47x13`nu(h=lMM<0nl$#3|H{&eZ+$z!}sfB*_(hg;@b(m*rxN_wA)yZT!T3Q(% zKYHYuOBbBi2zig3b5=_kg;5lSqtWggUiW$_#P;@lTYP)(mzI_wz$e(*!9t2z zy)8A7ueke6VB0wAoB+4Ms2rrr~?BkJ!d=AJPOL#zy_{PcHn@3fTl#>Vw9!km-5lV~G&K$0j0 z#MF6r_3BlCS9{%FSyyo!gN`PpbZ2`zP7)ym^H>ma>hP_um{yU#dg038Pdr!fMS3wOR)OJ9qBv+S)ooju32&zT=MD*VorLXF^EMDd)^N3x02m zQ7F3FcXk8Fv?d5ck9^(KVaPnz9%<*bl)AMh0H_%VIGpq6o_h|+!tmf=8zzbpBUB!B zq%z8w&f=058XN3w6Z%7Sv&#b?5Eh60$qP?Lfj5?U>xo0udx|i@*dcGdBM3vPfosDU z3wU6R;T$AWETzPIhrA;gNzr)A!w6M%?Yz#?nBhc9&q!dbW;8$u8)FgLTLewhlm$WE z)NvAGj0vWqF+sqsX^>Zx3FnlR*eiy#j$=|zX4E6>Q51%Ra;o6tc`I5(J)|`Adfg>1YuzmfRl!776wImKm|j_I_nW37ExN{(V(fK zvfgF^s@DGE`_TXM?{E6K-@h1T`F?M~Fh&>??~zo}TGdMY6GD_Sj8TlSwayqv2uy($ z6p`LL&VyE~u2oiHjMa6clmsTM_ud%SG&QvIaU6Q@n?_pe`u$#~)0s^6!p!{I*SsfR z7=~GvR8^&oa}H%$oM&B_uEHn}NRV}1Ljw*e1`Z88Q-v%c)HGs-dK zxs21kwE>MXp|XH4*9}5Q5R5q|j53U|@y>bYyr=labgFIbjWG!OFAz2mqLdJ(zv98W zzxu1+{Lzm-th87h4y@bTONNRC>Q49#0pnz8jKVPFL13+|s%kQw5<)^AaK^^tahB&oNzpX)g-$S+1B>hGuK~?$Ft3(M~g~8SjqDa92+1+_brb-3w;oIMp37C!l8hv z-S`M9&4XDJ81vqbrz0^X1hmv$UDry1?rLa^YNZg9BoRVJQD}_eoWWLuF~*oZQbp4= zgzRn6Ltuj+24v}!QiH()7_kt7tEx`Z7#Q6`sN=_v)^*FEhJf*fyJLVJF-A(6PB%fw z)wOEs23!lEr~twul%bG|q3dj!i-w@QlUG%7@=Hm4<4V~9T zS+$5dJhT>99}b7J*^Cgv7@15aX%_G9j4^gaQKxCFwH88J>pGpBQaT=w>#Esf5qJ-B z*LyNU#`JoQQnn-z3Jk3;b%XxRwSq5 zpaf2eQYy=mPN!>(Hb#eG0EWPX;5^T(s*dBRX(TwR?jxNZV+4c%_&3mh&2M$V3QJ1@ z2dYLKN3&U}wTYtO&2N4)LTG(`eKsqlR4qm7z?#_7(h_V&ce|Y+;IDY)-C34RCL_iI zfViPbZuN0sNCSvkyJt-Z!QNK0a&eIBVtVdGbaW6LTOMqz?XK-^B7$;ylX2M7>50WR zzw>p!=h^DDtIt@Ym6BF#W2`oiemp@pOoLy*)!xl9CT$`9Vs2qu|3K`Yw}Xd6>727}Z%>Bc+tZG7x(+ot zHMqH&{{MAdON<@Yajm-d_V4xkaE9|CM^q$=`dPA_NQyv3i5SD%Xp=<{K=8&{XAubA zWFsJpth@=b4xpVSWD^8Vg2ax47>eTrh!u;HOw*P|qDV@d8P5B5_wDw;>$)oJyZ~k2uqN=NI81 zile9lQ)8^PF$U+XF;*&4G9jW6BE!jTYm|~~4%=~fh3LqUR?u#;2i);fheR@QVJPE>}ytfDtPSAB=4O@loP}}7ZQ;|W({Up zfq*{vZs5*9Qc)Cx!9WPfl-A&#_u(5?UVi_>5B~cn@BHecPr2`W>7~oo+FQ47$4FaS zn=#OdHWwM|;vP#$#Vu)i;&$7~;vP5&>*Ky0k)1T}WYo++$9k*wFxmBX8clm{lLRH6D)vAfs56lg*7`M)jM2{l@O)=YINwpZxsVVcp2#V3>_&yPJC#&;QYP z-uV6VkKFm}*AMR>{bP(idL~jNQYwK$suU>prIq(?g@98+%Jq|mJVr9c4$DbZ+dLbX zRvX)Nd|oN#WHRB?p|0!IszMaTw0Wk+!{USYukUV-o_^|yzyF6HC?&Hjy>a8l#~**Z zxw#R7*IM%_3jhhnTwIe#iZlZvl_l1>rfE=$vu8G>5LI1uAlH|ic~6F0oo1DBo33Ht z`UJ%~(M!A)!0HAc-WvVktNC}o``cH4c0-t_51X4xDV3-+%dNGm#cF?l|LS}14fY;$ zN;;%~B#W(`b~Y6;w!WBbjAPwMT_T+yZYOQ4o2CVXix(fcc=6HseCoX=5}hBg_hE1E z{BpVC+}f{!*mwtkI4JwXPrgFuJfE-qN99~7OU|mkZH*A?DBRjQ+cf%tO!W@xlTs)p z`F%~2#I&v~%O{_Faz3B)Ntqd14Q~{hdG99jd?m-hZtGoH(7ZI7F6Z>AVlsL28$e z@3dEbb3^W&`Kpe`FJF0fHvfEDRj$}_LsjD!dZ`gbSr*ngA;6gS?%hS6t3+kSIQHHY z0-226kzV%-t#v*rs#Pt@JQeNq^Y?%B@BjAh zesgH@7)`YZx%-YWmf|aMyfjg-W~262c<*2Tb2h)-c(}P(Ur`9rdk?e*L$KU6 z#!o9hn+I7{2TFw3U;nf5c>MF9{bH0Q?P789!f#m1yY)N(SmWzT3lz@A5PVlM0>G_X zw@wtF=zSmpr4j%PAre81WSu=T-Zg$^>H)}wHwB4G3f0wHU3Oq#nX7pA`{S@9qWOF- zrC^+oh!0@k_ynL3dZX%p?x}cQQnu(i%0m3v*m~+a1O$f}gbp5L@C4va8Cv|g~ z?oW%#N^lM-F~&`XgOqZ+Y`|0n+UEE$jfGj+Goy{=vW}6mJjeA#gh&AqvOLZ56p#p_ zkm#e!^Fp9%wFc`XIjb#tzjStEG{M#?B#%yeryEzMDGBer^Uf)i4Tq!AXoyIwRTaE@ z;f3da`OE7lR9Xyg-?_!24v%|G^tx19K^`(Sq2f)RH+0*ba^)Db_{R^XU&%LG0O&0CdT?KE0NS7 zAIT_cIEW^yC{(IfDg5GY`oA|uOWNGoImc=6#9NwT41=<`bm1Xqjn-DjROWfnwkFMB zfB%!)w+>TPu*I9!ZMTcLv+xo^5XDo}o)a6{do#B_aYiK&gKTY^%2DfTiGv8Ov!1m+ zr}nRO{%l=p?w6AHgF&Zus-61uH~w|!6SGFTf}y8?O9&ib5E1~$*iCAgn4Qg>ud@F}w3ujxh>>U5@LwJHt`Am{$VDSDt!$KA#&GF6?bQ_uMnLm$lPP za6t&z*xFWELOvn^VH5%Z1QD~iz4tBz|Fy4u{oJ{8yd$yO+{1T?uaOVw4!im2lTVKi z4uB$21cahU1)^>n>zw!Ay4Ic$Q~1E!JAWZBxa((Ai5MeA3IbKR)|oJN?8;GYt7No=d;y!3#t|M8K|)Aqv6ZgU`}JO1Znc z+poHkB%v7k7uCJDP16d2gF(^iW>wYSc;)5SzV+HW@BGK@i^Hj> zkR_RIZITHo6@mzXy@@?H-A6}vr_;z{=qQA>I)&j2W-S?G9^Ovt%4=(+LYby2%`QE0X*4bw z*zPZu<@jqF-Rq5@(|A#IAV?(wh-8`+A-2wYDHMS6J_<=h9^sz(dnc1)LEd;93< zSZh5j^Iv`R$q#?@O$JvyJ zN7bEaZMVWTgfJMS!CQhb9+yPH`EYjo%*96^na>yF@kmM$V#xD?nIc3~t(I-8xg1hT zNvQx306Psk3$6HPt@U61Ea5;Y6^{djkWwmE5A(O} k_NoAYOdwGT5xlqm2Waa3dH;B5rT_o{07*qoM6N<$f@ad(Q2+n{ diff --git a/_static/basic.css b/_static/basic.css index f0379f35..43e8bafa 100644 --- a/_static/basic.css +++ b/_static/basic.css @@ -79,11 +79,11 @@ div.sphinxsidebar input { font-size: 1em; } -div.sphinxsidebar input[type="text"] { +div.sphinxsidebar #searchbox input[type="text"] { width: 170px; } -div.sphinxsidebar input[type="submit"] { +div.sphinxsidebar #searchbox input[type="submit"] { width: 30px; } diff --git a/_static/bootstrap-dropdown.js b/_static/bootstrap-dropdown.js new file mode 100644 index 00000000..fda6da59 --- /dev/null +++ b/_static/bootstrap-dropdown.js @@ -0,0 +1,55 @@ +/* ============================================================ + * bootstrap-dropdown.js v1.4.0 + * http://twitter.github.com/bootstrap/javascript.html#dropdown + * ============================================================ + * Copyright 2011 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function( $ ){ + + "use strict" + + /* DROPDOWN PLUGIN DEFINITION + * ========================== */ + + $.fn.dropdown = function ( selector ) { + return this.each(function () { + $(this).delegate(selector || d, 'click', function (e) { + var li = $(this).parent('li') + , isActive = li.hasClass('open') + + clearMenus() + !isActive && li.toggleClass('open') + return false + }) + }) + } + + /* APPLY TO STANDARD DROPDOWN ELEMENTS + * =================================== */ + + var d = 'a.menu, .dropdown-toggle' + + function clearMenus() { + $(d).parent('li').removeClass('open') + } + + $(function () { + $('html').bind("click", clearMenus) + $('body').dropdown( '[data-dropdown] a.menu, [data-dropdown] .dropdown-toggle' ) + }) + +}( window.jQuery || window.ender ); diff --git a/_static/bootstrap-scrollspy.js b/_static/bootstrap-scrollspy.js new file mode 100644 index 00000000..efbc4329 --- /dev/null +++ b/_static/bootstrap-scrollspy.js @@ -0,0 +1,107 @@ +/* ============================================================= + * bootstrap-scrollspy.js v1.4.0 + * http://twitter.github.com/bootstrap/javascript.html#scrollspy + * ============================================================= + * Copyright 2011 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================== */ + + +!function ( $ ) { + + "use strict" + + var $window = $(window) + + function ScrollSpy( topbar, selector ) { + var processScroll = $.proxy(this.processScroll, this) + this.$topbar = $(topbar) + this.selector = selector || 'li > a' + this.refresh() + this.$topbar.delegate(this.selector, 'click', processScroll) + $window.scroll(processScroll) + this.processScroll() + } + + ScrollSpy.prototype = { + + refresh: function () { + this.targets = this.$topbar.find(this.selector).map(function () { + var href = $(this).attr('href') + return /^#\w/.test(href) && $(href).length ? href : null + }) + + this.offsets = $.map(this.targets, function (id) { + return $(id).offset().top + }) + } + + , processScroll: function () { + var scrollTop = $window.scrollTop() + 10 + , offsets = this.offsets + , targets = this.targets + , activeTarget = this.activeTarget + , i + + for (i = offsets.length; i--;) { + activeTarget != targets[i] + && scrollTop >= offsets[i] + && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) + && this.activateButton( targets[i] ) + } + } + + , activateButton: function (target) { + this.activeTarget = target + + this.$topbar + .find(this.selector).parent('.active') + .removeClass('active') + + this.$topbar + .find(this.selector + '[href="' + target + '"]') + .parent('li') + .addClass('active') + } + + } + + /* SCROLLSPY PLUGIN DEFINITION + * =========================== */ + + $.fn.scrollSpy = function( options ) { + var scrollspy = this.data('scrollspy') + + if (!scrollspy) { + return this.each(function () { + $(this).data('scrollspy', new ScrollSpy( this, options )) + }) + } + + if ( options === true ) { + return scrollspy + } + + if ( typeof options == 'string' ) { + scrollspy[options]() + } + + return this + } + + $(document).ready(function () { + $('body').scrollSpy('[data-scrollspy] li > a') + }) + +}( window.jQuery || window.ender ); \ No newline at end of file diff --git a/_static/bootstrap-sphinx.css b/_static/bootstrap-sphinx.css new file mode 100644 index 00000000..89b93c13 --- /dev/null +++ b/_static/bootstrap-sphinx.css @@ -0,0 +1,19 @@ +/* +* bootstrap-sphinx.css +* ~~~~~~~~~~~~~~~~~~~~ +* +* Sphinx stylesheet -- Twitter Bootstrap theme. +*/ + +body { + padding-top: 42px; +} + +div.documentwrapper { + float: left; + width: 100%; +} +.topbar h3 a, .topbar .brand { + background: transparent url("astropy_word_26.png") no-repeat 22px 4px; + padding-left: 62px; +} \ No newline at end of file diff --git a/_static/bootstrap.css b/_static/bootstrap.css new file mode 100644 index 00000000..aaa9b2a8 --- /dev/null +++ b/_static/bootstrap.css @@ -0,0 +1,2496 @@ +/* The following few lines were added by T. Robitaille for Astropy website */ + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: hidden; +} + +.logo_banner { + padding-top: 20px; + padding-bottom: 10px; +} + +.brand { + width: 72px; + height: 32px; +} + +/*! + * Bootstrap v1.4.0 + * + * Copyright 2011 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + * Date: Sun Nov 20 21:42:29 PST 2011 + */ +/* Reset.less + * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). + * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ +html, body { + margin: 0; + padding: 0; + text-align: justify; +} +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +cite, +code, +del, +dfn, +em, +img, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +dd, +dl, +dt, +li, +ol, +ul, +fieldset, +form, +label, +legend, +button, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td { + margin: 0; + padding: 0; + border: 0; + font-weight: normal; + font-style: normal; + font-size: 100%; + line-height: 1; + font-family: inherit; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +ol, ul { + list-style: none; +} +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} +html { + overflow-y: scroll; + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +a:focus { + outline: thin dotted; +} +a:hover, a:active { + outline: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} +audio, canvas, video { + display: inline-block; + *display: inline; + *zoom: 1; +} +audio:not([controls]) { + display: none; +} +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; + -ms-interpolation-mode: bicubic; +} +button, +input, +select, +textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} +button, input { + line-height: normal; + *overflow: visible; +} +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} +input[type="search"] { + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +textarea { + overflow: auto; + vertical-align: top; +} +/* Variables.less + * Variables to customize the look and feel of Bootstrap + * ----------------------------------------------------- */ +/* Mixins.less + * Snippets of reusable CSS to develop faster and keep code readable + * ----------------------------------------------------------------- */ +/* + * Scaffolding + * Basic and global styles for generating a grid system, structural layout, and page templates + * ------------------------------------------------------------------------------------------- */ +body { + background-color: #ffffff; + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 18px; + color: #404040; +} +.container { + width: 740px; + margin-left: auto; + margin-right: auto; + zoom: 1; +} +.container:before, .container:after { + display: table; + content: ""; + zoom: 1; +} +.container:after { + clear: both; +} +.container-fluid { + position: relative; + min-width: 740px; + padding-left: 20px; + padding-right: 20px; + zoom: 1; +} +.container-fluid:before, .container-fluid:after { + display: table; + content: ""; + zoom: 1; +} +.container-fluid:after { + clear: both; +} +.container-fluid > .sidebar { + position: absolute; + top: 0; + left: 20px; + width: 220px; +} +.container-fluid > .content { + margin-left: 240px; +} +a { + color: #0069d6; + text-decoration: none; + line-height: inherit; + font-weight: inherit; +} +a:hover { + color: #00438a; + text-decoration: underline; +} +.pull-right { + float: right; + width: 280px; + text-align: right; +} +.pull-left { + float: left; + width: 280px; + text-align: left; +} +.hide { + display: none; +} +.show { + display: block; +} +.row { + zoom: 1; + margin-left: -20px; +} +.row:before, .row:after { + display: table; + content: ""; + zoom: 1; +} +.row:after { + clear: both; +} +.row > [class*="span"] { + display: inline; + float: left; + margin-left: 20px; +} +.span1 { + width: 40px; +} +.span2 { + width: 100px; +} +.span3 { + width: 160px; +} +.span4 { + width: 220px; +} +.span5 { + width: 280px; +} +.span6 { + width: 340px; +} +.span7 { + width: 400px; +} +.span8 { + width: 460px; +} +.span9 { + width: 520px; +} +.span10 { + width: 580px; +} +.span11 { + width: 640px; +} +.span12 { + width: 700px; +} +.span13 { + width: 760px; +} +.span14 { + width: 820px; +} +.span15 { + width: 880px; +} +.span16 { + width: 740px; +} +.span17 { + width: 1000px; +} +.span18 { + width: 1060px; +} +.span19 { + width: 1120px; +} +.span20 { + width: 1180px; +} +.span21 { + width: 1240px; +} +.span22 { + width: 1300px; +} +.span23 { + width: 1360px; +} +.span24 { + width: 1420px; +} +.row > .offset1 { + margin-left: 80px; +} +.row > .offset2 { + margin-left: 140px; +} +.row > .offset3 { + margin-left: 200px; +} +.row > .offset4 { + margin-left: 260px; +} +.row > .offset5 { + margin-left: 320px; +} +.row > .offset6 { + margin-left: 380px; +} +.row > .offset7 { + margin-left: 440px; +} +.row > .offset8 { + margin-left: 500px; +} +.row > .offset9 { + margin-left: 560px; +} +.row > .offset10 { + margin-left: 620px; +} +.row > .offset11 { + margin-left: 680px; +} +.row > .offset12 { + margin-left: 740px; +} +.span-one-third { + width: 300px; +} +.span-two-thirds { + width: 620px; +} +.row > .offset-one-third { + margin-left: 340px; +} +.row > .offset-two-thirds { + margin-left: 660px; +} +/* Typography.less + * Headings, body text, lists, code, and more for a versatile and durable typography system + * ---------------------------------------------------------------------------------------- */ +p { + font-size: 13px; + font-weight: normal; + line-height: 18px; + margin-bottom: 9px; +} +p small { + font-size: 11px; + color: #bfbfbf; +} +h1, +h2, +h3, +h4, +h5, +h6 { +/* font-weight: bold;*/ + color: #404040; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + color: #bfbfbf; +} +h1 { + margin-top: 14px; + margin-bottom: 10px; + font-size: 22px; + line-height: 33px; +} +h1 small { + font-size: 18px; +} +h2 { + font-size: 18px; + line-height: 27px; + margin-bottom: 10px; +} +h2 small { + font-size: 14px; +} +h3, +h4, +h5, +h6 { + line-height: 36px; +} +h3 { + font-size: 18px; +} +h3 small { + font-size: 14px; +} +h4 { + font-size: 16px; +} +h4 small { + font-size: 12px; +} +h5 { + font-size: 14px; +} +h6 { + font-size: 13px; + color: #bfbfbf; + text-transform: uppercase; +} +ul, ol { + margin: 0 0 18px 25px; +} +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} +ul { + list-style: disc; +} +ol { + list-style: decimal; +} +li { + line-height: 18px; + color: #808080; +} +ul.unstyled { + list-style: none; + margin-left: 0; +} +dl { + margin-bottom: 18px; +} +dl dt, dl dd { + line-height: 18px; +} +dl dt { + font-weight: bold; +} +dl dd { + margin-left: 9px; +} +hr { + margin: 20px 0 19px; + border: 0; + border-bottom: 1px solid #eee; +} +strong { + font-style: inherit; + font-weight: bold; +} +em { + font-style: italic; + font-weight: inherit; + line-height: inherit; +} +.muted { + color: #bfbfbf; +} +blockquote { + margin-bottom: 18px; + border-left: 5px solid #eee; + padding-left: 15px; +} +blockquote p { + font-size: 14px; + font-weight: 300; + line-height: 18px; + margin-bottom: 0; +} +blockquote small { + display: block; + font-size: 12px; + font-weight: 300; + line-height: 18px; + color: #bfbfbf; +} +blockquote small:before { + content: '\2014 \00A0'; +} +address { + display: block; + line-height: 18px; + margin-bottom: 18px; +} +code, pre { + padding: 0 3px 2px; + font-family: Monaco, Andale Mono, Courier New, monospace; + font-size: 12px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +code { + background-color: #fee9cc; + color: rgba(0, 0, 0, 0.75); + padding: 1px 3px; +} +pre { + background-color: #f5f5f5; + display: block; + padding: 8.5px; + margin: 0 0 18px; + line-height: 18px; + font-size: 12px; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} +/* Forms.less + * Base styles for various input types, form layouts, and states + * ------------------------------------------------------------- */ +form { + margin-bottom: 18px; +} +fieldset { + margin-bottom: 18px; + padding-top: 18px; +} +fieldset legend { + display: block; + padding-left: 150px; + font-size: 19.5px; + line-height: 1; + color: #404040; + *padding: 0 0 5px 145px; + /* IE6-7 */ + + *line-height: 1.5; + /* IE6-7 */ + +} +form .clearfix { + margin-bottom: 18px; + zoom: 1; +} +form .clearfix:before, form .clearfix:after { + display: table; + content: ""; + zoom: 1; +} +form .clearfix:after { + clear: both; +} +label, +input, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: normal; +} +label { + padding-top: 6px; + font-size: 13px; + line-height: 18px; + float: left; + width: 130px; + text-align: right; + color: #404040; +} +form .input { + margin-left: 150px; +} +input[type=checkbox], input[type=radio] { + cursor: pointer; +} +input, +textarea, +select, +.uneditable-input { + display: inline-block; + width: 210px; + height: 18px; + padding: 4px; + font-size: 13px; + line-height: 18px; + color: #808080; + border: 1px solid #ccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +select { + padding: initial; +} +input[type=checkbox], input[type=radio] { + width: auto; + height: auto; + padding: 0; + margin: 3px 0; + *margin-top: 0; + /* IE6-7 */ + + line-height: normal; + border: none; +} +input[type=file] { + background-color: #ffffff; + padding: initial; + border: initial; + line-height: initial; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +input[type=button], input[type=reset], input[type=submit] { + width: auto; + height: auto; +} +select, input[type=file] { + height: 27px; + *height: auto; + line-height: 27px; + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + +} +select[multiple] { + height: inherit; + background-color: #ffffff; +} +textarea { + height: auto; +} +.uneditable-input { + background-color: #ffffff; + display: block; + border-color: #eee; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + cursor: not-allowed; +} +:-moz-placeholder { + color: #bfbfbf; +} +::-webkit-input-placeholder { + color: #bfbfbf; +} +input, textarea { + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -ms-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); +} +input:focus, textarea:focus { + outline: 0; + border-color: rgba(82, 168, 236, 0.8); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); +} +input[type=file]:focus, input[type=checkbox]:focus, select:focus { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + outline: 1px dotted #666; +} +form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline { + color: #b94a48; +} +form .clearfix.error input, form .clearfix.error textarea { + color: #b94a48; + border-color: #ee5f5b; +} +form .clearfix.error input:focus, form .clearfix.error textarea:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} +form .clearfix.error .input-prepend .add-on, form .clearfix.error .input-append .add-on { + color: #b94a48; + background-color: #fce6e6; + border-color: #b94a48; +} +form .clearfix.warning > label, form .clearfix.warning .help-block, form .clearfix.warning .help-inline { + color: #c09853; +} +form .clearfix.warning input, form .clearfix.warning textarea { + color: #c09853; + border-color: #ccae64; +} +form .clearfix.warning input:focus, form .clearfix.warning textarea:focus { + border-color: #be9a3f; + -webkit-box-shadow: 0 0 6px #e5d6b1; + -moz-box-shadow: 0 0 6px #e5d6b1; + box-shadow: 0 0 6px #e5d6b1; +} +form .clearfix.warning .input-prepend .add-on, form .clearfix.warning .input-append .add-on { + color: #c09853; + background-color: #d2b877; + border-color: #c09853; +} +form .clearfix.success > label, form .clearfix.success .help-block, form .clearfix.success .help-inline { + color: #468847; +} +form .clearfix.success input, form .clearfix.success textarea { + color: #468847; + border-color: #57a957; +} +form .clearfix.success input:focus, form .clearfix.success textarea:focus { + border-color: #458845; + -webkit-box-shadow: 0 0 6px #9acc9a; + -moz-box-shadow: 0 0 6px #9acc9a; + box-shadow: 0 0 6px #9acc9a; +} +form .clearfix.success .input-prepend .add-on, form .clearfix.success .input-append .add-on { + color: #468847; + background-color: #bcddbc; + border-color: #468847; +} +.input-mini, +input.mini, +textarea.mini, +select.mini { + width: 60px; +} +.input-small, +input.small, +textarea.small, +select.small { + width: 90px; +} +.input-medium, +input.medium, +textarea.medium, +select.medium { + width: 150px; +} +.input-large, +input.large, +textarea.large, +select.large { + width: 210px; +} +.input-xlarge, +input.xlarge, +textarea.xlarge, +select.xlarge { + width: 270px; +} +.input-xxlarge, +input.xxlarge, +textarea.xxlarge, +select.xxlarge { + width: 530px; +} +textarea.xxlarge { + overflow-y: auto; +} +input.span1, textarea.span1 { + display: inline-block; + float: none; + width: 30px; + margin-left: 0; +} +input.span2, textarea.span2 { + display: inline-block; + float: none; + width: 90px; + margin-left: 0; +} +input.span3, textarea.span3 { + display: inline-block; + float: none; + width: 150px; + margin-left: 0; +} +input.span4, textarea.span4 { + display: inline-block; + float: none; + width: 210px; + margin-left: 0; +} +input.span5, textarea.span5 { + display: inline-block; + float: none; + width: 270px; + margin-left: 0; +} +input.span6, textarea.span6 { + display: inline-block; + float: none; + width: 330px; + margin-left: 0; +} +input.span7, textarea.span7 { + display: inline-block; + float: none; + width: 390px; + margin-left: 0; +} +input.span8, textarea.span8 { + display: inline-block; + float: none; + width: 450px; + margin-left: 0; +} +input.span9, textarea.span9 { + display: inline-block; + float: none; + width: 510px; + margin-left: 0; +} +input.span10, textarea.span10 { + display: inline-block; + float: none; + width: 570px; + margin-left: 0; +} +input.span11, textarea.span11 { + display: inline-block; + float: none; + width: 630px; + margin-left: 0; +} +input.span12, textarea.span12 { + display: inline-block; + float: none; + width: 690px; + margin-left: 0; +} +input.span13, textarea.span13 { + display: inline-block; + float: none; + width: 750px; + margin-left: 0; +} +input.span14, textarea.span14 { + display: inline-block; + float: none; + width: 810px; + margin-left: 0; +} +input.span15, textarea.span15 { + display: inline-block; + float: none; + width: 870px; + margin-left: 0; +} +input.span16, textarea.span16 { + display: inline-block; + float: none; + width: 930px; + margin-left: 0; +} +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + background-color: #f5f5f5; + border-color: #ddd; + cursor: not-allowed; +} +.actions { + background: #f5f5f5; + margin-top: 18px; + margin-bottom: 18px; + padding: 17px 20px 18px 150px; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; +} +.actions .secondary-action { + float: right; +} +.actions .secondary-action a { + line-height: 30px; +} +.actions .secondary-action a:hover { + text-decoration: underline; +} +.help-inline, .help-block { + font-size: 13px; + line-height: 18px; + color: #bfbfbf; +} +.help-inline { + padding-left: 5px; + *position: relative; + /* IE6-7 */ + + *top: -5px; + /* IE6-7 */ + +} +.help-block { + display: block; + max-width: 600px; +} +.inline-inputs { + color: #808080; +} +.inline-inputs span { + padding: 0 2px 0 1px; +} +.input-prepend input, .input-append input { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.input-prepend .add-on, .input-append .add-on { + position: relative; + background: #f5f5f5; + border: 1px solid #ccc; + z-index: 2; + float: left; + display: block; + width: auto; + min-width: 16px; + height: 18px; + padding: 4px 4px 4px 5px; + margin-right: -1px; + font-weight: normal; + line-height: 18px; + color: #bfbfbf; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-prepend .active, .input-append .active { + background: #a9dba9; + border-color: #46a546; +} +.input-prepend .add-on { + *margin-top: 1px; + /* IE6-7 */ + +} +.input-append input { + float: left; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-append .add-on { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; + margin-right: 0; + margin-left: -1px; +} +.inputs-list { + margin: 0 0 5px; + width: 100%; +} +.inputs-list li { + display: block; + padding: 0; + width: 100%; +} +.inputs-list label { + display: block; + float: none; + width: auto; + padding: 0; + margin-left: 20px; + line-height: 18px; + text-align: left; + white-space: normal; +} +.inputs-list label strong { + color: #808080; +} +.inputs-list label small { + font-size: 11px; + font-weight: normal; +} +.inputs-list .inputs-list { + margin-left: 25px; + margin-bottom: 10px; + padding-top: 0; +} +.inputs-list:first-child { + padding-top: 6px; +} +.inputs-list li + li { + padding-top: 2px; +} +.inputs-list input[type=radio], .inputs-list input[type=checkbox] { + margin-bottom: 0; + margin-left: -20px; + float: left; +} +.form-stacked { + padding-left: 20px; +} +.form-stacked fieldset { + padding-top: 9px; +} +.form-stacked legend { + padding-left: 0; +} +.form-stacked label { + display: block; + float: none; + width: auto; + font-weight: bold; + text-align: left; + line-height: 20px; + padding-top: 0; +} +.form-stacked .clearfix { + margin-bottom: 9px; +} +.form-stacked .clearfix div.input { + margin-left: 0; +} +.form-stacked .inputs-list { + margin-bottom: 0; +} +.form-stacked .inputs-list li { + padding-top: 0; +} +.form-stacked .inputs-list li label { + font-weight: normal; + padding-top: 0; +} +.form-stacked div.clearfix.error { + padding-top: 10px; + padding-bottom: 10px; + padding-left: 10px; + margin-top: 0; + margin-left: -10px; +} +.form-stacked .actions { + margin-left: -20px; + padding-left: 20px; +} +/* + * Tables.less + * Tables for, you guessed it, tabular data + * ---------------------------------------- */ +table { + width: 100%; + margin-bottom: 18px; + padding: 0; + font-size: 13px; + border-collapse: collapse; +} +table th, table td { + padding: 10px 10px 9px; + line-height: 18px; + text-align: left; +} +table th { + padding-top: 9px; + font-weight: bold; + vertical-align: middle; +} +table td { + vertical-align: top; + border-top: 1px solid #ddd; +} +table tbody th { + border-top: 1px solid #ddd; + vertical-align: top; +} +.condensed-table th, .condensed-table td { + padding: 5px 5px 4px; +} +.bordered-table { + border: 1px solid #ddd; + border-collapse: separate; + *border-collapse: collapse; + /* IE7, collapse table to remove spacing */ + + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.bordered-table th + th, .bordered-table td + td, .bordered-table th + td { + border-left: 1px solid #ddd; +} +.bordered-table thead tr:first-child th:first-child, .bordered-table tbody tr:first-child td:first-child { + -webkit-border-radius: 4px 0 0 0; + -moz-border-radius: 4px 0 0 0; + border-radius: 4px 0 0 0; +} +.bordered-table thead tr:first-child th:last-child, .bordered-table tbody tr:first-child td:last-child { + -webkit-border-radius: 0 4px 0 0; + -moz-border-radius: 0 4px 0 0; + border-radius: 0 4px 0 0; +} +.bordered-table tbody tr:last-child td:first-child { + -webkit-border-radius: 0 0 0 4px; + -moz-border-radius: 0 0 0 4px; + border-radius: 0 0 0 4px; +} +.bordered-table tbody tr:last-child td:last-child { + -webkit-border-radius: 0 0 4px 0; + -moz-border-radius: 0 0 4px 0; + border-radius: 0 0 4px 0; +} +table .span1 { + width: 20px; +} +table .span2 { + width: 60px; +} +table .span3 { + width: 100px; +} +table .span4 { + width: 140px; +} +table .span5 { + width: 180px; +} +table .span6 { + width: 220px; +} +table .span7 { + width: 260px; +} +table .span8 { + width: 300px; +} +table .span9 { + width: 340px; +} +table .span10 { + width: 380px; +} +table .span11 { + width: 420px; +} +table .span12 { + width: 460px; +} +table .span13 { + width: 500px; +} +table .span14 { + width: 540px; +} +table .span15 { + width: 580px; +} +table .span16 { + width: 620px; +} +.zebra-striped tbody tr:nth-child(odd) td, .zebra-striped tbody tr:nth-child(odd) th { + background-color: #f9f9f9; +} +.zebra-striped tbody tr:hover td, .zebra-striped tbody tr:hover th { + background-color: #f5f5f5; +} +table .header { + cursor: pointer; +} +table .header:after { + content: ""; + float: right; + margin-top: 7px; + border-width: 0 4px 4px; + border-style: solid; + border-color: #000 transparent; + visibility: hidden; +} +table .headerSortUp, table .headerSortDown { + background-color: rgba(141, 192, 219, 0.25); + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); +} +table .header:hover:after { + visibility: visible; +} +table .headerSortDown:after, table .headerSortDown:hover:after { + visibility: visible; + filter: alpha(opacity=60); + -khtml-opacity: 0.6; + -moz-opacity: 0.6; + opacity: 0.6; +} +table .headerSortUp:after { + border-bottom: none; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #000; + visibility: visible; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + filter: alpha(opacity=60); + -khtml-opacity: 0.6; + -moz-opacity: 0.6; + opacity: 0.6; +} +table .blue { + color: #049cdb; + border-bottom-color: #049cdb; +} +table .headerSortUp.blue, table .headerSortDown.blue { + background-color: #ade6fe; +} +table .green { + color: #46a546; + border-bottom-color: #46a546; +} +table .headerSortUp.green, table .headerSortDown.green { + background-color: #cdeacd; +} +table .red { + color: #9d261d; + border-bottom-color: #9d261d; +} +table .headerSortUp.red, table .headerSortDown.red { + background-color: #f4c8c5; +} +table .yellow { + color: #ffc40d; + border-bottom-color: #ffc40d; +} +table .headerSortUp.yellow, table .headerSortDown.yellow { + background-color: #fff6d9; +} +table .orange { + color: #f89406; + border-bottom-color: #f89406; +} +table .headerSortUp.orange, table .headerSortDown.orange { + background-color: #fee9cc; +} +table .purple { + color: #7a43b6; + border-bottom-color: #7a43b6; +} +table .headerSortUp.purple, table .headerSortDown.purple { + background-color: #e2d5f0; +} +/* Patterns.less + * Repeatable UI elements outside the base styles provided from the scaffolding + * ---------------------------------------------------------------------------- */ +.topbar { + height: 40px; + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 10000; + overflow: visible; +} +.topbar a { + color: #bfbfbf; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.topbar h3 a:hover, .topbar .brand:hover, .topbar ul .active > a { + background-color: #333; + background-color: rgba(255, 255, 255, 0.05); + color: #ffffff; + text-decoration: none; +} +.topbar h3 { + position: relative; +} +.topbar h3 a, .topbar .brand { + float: left; + display: block; + padding: 8px 0px 0px; + margin-left: -20px; + color: #ffffff; + font-size: 20px; + font-weight: 200; + line-height: 1; +} +.topbar p { + margin: 0; + line-height: 40px; +} +.topbar p a:hover { + background-color: transparent; + color: #ffffff; +} +.topbar form { + float: left; + margin: 5px 0 0 0; + position: relative; + filter: alpha(opacity=100); + -khtml-opacity: 1; + -moz-opacity: 1; + opacity: 1; +} +.topbar form.pull-right { + float: right; +} +.topbar input { + background-color: #444; + background-color: rgba(255, 255, 255, 0.3); + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: normal; + font-weight: 13px; + line-height: 1; + padding: 4px 9px; + color: #ffffff; + color: rgba(255, 255, 255, 0.75); + border: 1px solid #111; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + -webkit-transition: none; + -moz-transition: none; + -ms-transition: none; + -o-transition: none; + transition: none; +} +.topbar input:-moz-placeholder { + color: #e6e6e6; +} +.topbar input::-webkit-input-placeholder { + color: #e6e6e6; +} +.topbar input:hover { + background-color: #bfbfbf; + background-color: rgba(255, 255, 255, 0.5); + color: #ffffff; +} +.topbar input:focus, .topbar input.focused { + outline: 0; + background-color: #ffffff; + color: #404040; + text-shadow: 0 1px 0 #ffffff; + border: 0; + padding: 5px 10px; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} +.topbar-inner, .topbar .fill { + background-color: #222; + background-color: #222222; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); + background-image: -moz-linear-gradient(top, #333333, #222222); + background-image: -ms-linear-gradient(top, #333333, #222222); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); + background-image: -webkit-linear-gradient(top, #333333, #222222); + background-image: -o-linear-gradient(top, #333333, #222222); + background-image: linear-gradient(top, #333333, #222222); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); +} +.topbar div > ul, .nav { + display: block; + float: left; + margin: 0 10px 0 0; + position: relative; + left: 0; +} +.topbar div > ul > li, .nav > li { + display: block; + float: left; +} +.topbar div > ul a, .nav a { + display: block; + float: none; + padding: 10px 10px 11px; + line-height: 19px; + text-decoration: none; +} +.topbar div > ul a:hover, .nav a:hover { + color: #ffffff; + text-decoration: none; +} +.topbar div > ul .active > a, .nav .active > a { + background-color: #222; + background-color: rgba(0, 0, 0, 0.5); +} +.topbar div > ul.secondary-nav, .nav.secondary-nav { + float: right; + margin-left: 10px; + margin-right: 0px; +} +.topbar div > ul.secondary-nav .menu-dropdown, +.nav.secondary-nav .menu-dropdown, +.topbar div > ul.secondary-nav .dropdown-menu, +.nav.secondary-nav .dropdown-menu { + right: 0; + border: 0; +} +.topbar div > ul a.menu:hover, +.nav a.menu:hover, +.topbar div > ul li.open .menu, +.nav li.open .menu, +.topbar div > ul .dropdown-toggle:hover, +.nav .dropdown-toggle:hover, +.topbar div > ul .dropdown.open .dropdown-toggle, +.nav .dropdown.open .dropdown-toggle { + background: #444; + background: rgba(255, 255, 255, 0.05); +} +.topbar div > ul .menu-dropdown, +.nav .menu-dropdown, +.topbar div > ul .dropdown-menu, +.nav .dropdown-menu { + background-color: #333; +} +.topbar div > ul .menu-dropdown a.menu, +.nav .menu-dropdown a.menu, +.topbar div > ul .dropdown-menu a.menu, +.nav .dropdown-menu a.menu, +.topbar div > ul .menu-dropdown .dropdown-toggle, +.nav .menu-dropdown .dropdown-toggle, +.topbar div > ul .dropdown-menu .dropdown-toggle, +.nav .dropdown-menu .dropdown-toggle { + color: #ffffff; +} +.topbar div > ul .menu-dropdown a.menu.open, +.nav .menu-dropdown a.menu.open, +.topbar div > ul .dropdown-menu a.menu.open, +.nav .dropdown-menu a.menu.open, +.topbar div > ul .menu-dropdown .dropdown-toggle.open, +.nav .menu-dropdown .dropdown-toggle.open, +.topbar div > ul .dropdown-menu .dropdown-toggle.open, +.nav .dropdown-menu .dropdown-toggle.open { + background: #444; + background: rgba(255, 255, 255, 0.05); +} +.topbar div > ul .menu-dropdown li a, +.nav .menu-dropdown li a, +.topbar div > ul .dropdown-menu li a, +.nav .dropdown-menu li a { + color: #999; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); +} +.topbar div > ul .menu-dropdown li a:hover, +.nav .menu-dropdown li a:hover, +.topbar div > ul .dropdown-menu li a:hover, +.nav .dropdown-menu li a:hover { + background-color: #191919; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919)); + background-image: -moz-linear-gradient(top, #292929, #191919); + background-image: -ms-linear-gradient(top, #292929, #191919); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919)); + background-image: -webkit-linear-gradient(top, #292929, #191919); + background-image: -o-linear-gradient(top, #292929, #191919); + background-image: linear-gradient(top, #292929, #191919); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0); + color: #ffffff; +} +.topbar div > ul .menu-dropdown .active a, +.nav .menu-dropdown .active a, +.topbar div > ul .dropdown-menu .active a, +.nav .dropdown-menu .active a { + color: #ffffff; +} +.topbar div > ul .menu-dropdown .divider, +.nav .menu-dropdown .divider, +.topbar div > ul .dropdown-menu .divider, +.nav .dropdown-menu .divider { + background-color: #222; + border-color: #444; +} +.topbar ul .menu-dropdown li a, .topbar ul .dropdown-menu li a { + padding: 4px 15px; +} +li.menu, .dropdown { + position: relative; +} +a.menu:after, .dropdown-toggle:after { + width: 0; + height: 0; + display: inline-block; + content: "↓"; + text-indent: -99999px; + vertical-align: top; + margin-top: 8px; + margin-left: 4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ffffff; + filter: alpha(opacity=50); + -khtml-opacity: 0.5; + -moz-opacity: 0.5; + opacity: 0.5; +} +.menu-dropdown, .dropdown-menu { + background-color: #ffffff; + float: left; + display: none; + position: absolute; + top: 40px; + z-index: 900; + min-width: 160px; + max-width: 220px; + _width: 160px; + margin-left: 0; + margin-right: 0; + padding: 6px 0; + zoom: 1; + border-color: #999; + border-color: rgba(0, 0, 0, 0.2); + border-style: solid; + border-width: 0 1px 1px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.menu-dropdown li, .dropdown-menu li { + float: none; + display: block; + background-color: none; +} +.menu-dropdown .divider, .dropdown-menu .divider { + height: 1px; + margin: 5px 0; + overflow: hidden; + background-color: #eee; + border-bottom: 1px solid #ffffff; +} +.topbar .dropdown-menu a, .dropdown-menu a { + display: block; + padding: 4px 15px; + clear: both; + font-weight: normal; + line-height: 18px; + color: #808080; + text-shadow: 0 1px 0 #ffffff; +} +.topbar .dropdown-menu a:hover, +.dropdown-menu a:hover, +.topbar .dropdown-menu a.hover, +.dropdown-menu a.hover { + background-color: #dddddd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd)); + background-image: -moz-linear-gradient(top, #eeeeee, #dddddd); + background-image: -ms-linear-gradient(top, #eeeeee, #dddddd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)); + background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd); + background-image: -o-linear-gradient(top, #eeeeee, #dddddd); + background-image: linear-gradient(top, #eeeeee, #dddddd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0); + color: #404040; + text-decoration: none; + -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); +} +.open .menu, +.dropdown.open .menu, +.open .dropdown-toggle, +.dropdown.open .dropdown-toggle { + color: #ffffff; + background: #ccc; + background: rgba(0, 0, 0, 0.3); +} +.open .menu-dropdown, +.dropdown.open .menu-dropdown, +.open .dropdown-menu, +.dropdown.open .dropdown-menu { + display: block; +} +.tabs, .pills { + margin: 0 0 18px; + padding: 0; + list-style: none; + zoom: 1; +} +.tabs:before, +.pills:before, +.tabs:after, +.pills:after { + display: table; + content: ""; + zoom: 1; +} +.tabs:after, .pills:after { + clear: both; +} +.tabs > li, .pills > li { + float: left; +} +.tabs > li > a, .pills > li > a { + display: block; +} +.tabs { + border-color: #ddd; + border-style: solid; + border-width: 0 0 1px; +} +.tabs > li { + position: relative; + margin-bottom: -1px; +} +.tabs > li > a { + padding: 0 15px; + margin-right: 2px; + line-height: 34px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.tabs > li > a:hover { + text-decoration: none; + background-color: #eee; + border-color: #eee #eee #ddd; +} +.tabs .active > a, .tabs .active > a:hover { + color: #808080; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} +.tabs .menu-dropdown, .tabs .dropdown-menu { + top: 35px; + border-width: 1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} +.tabs a.menu:after, .tabs .dropdown-toggle:after { + border-top-color: #999; + margin-top: 15px; + margin-left: 5px; +} +.tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle { + border-color: #999; +} +.tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after { + border-top-color: #555; +} +.pills a { + margin: 5px 3px 5px 0; + padding: 0 15px; + line-height: 30px; + text-shadow: 0 1px 1px #ffffff; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} +.pills a:hover { + color: #ffffff; + text-decoration: none; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + background-color: #00438a; +} +.pills .active a { + color: #ffffff; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + background-color: #0069d6; +} +.pills-vertical > li { + float: none; +} +.tab-content > .tab-pane, +.pill-content > .pill-pane, +.tab-content > div, +.pill-content > div { + display: none; +} +.tab-content > .active, .pill-content > .active { + display: block; +} +.breadcrumb { + padding: 7px 14px; + margin: 0 0 18px; + background-color: #f5f5f5; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5)); + background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5)); + background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); + background-image: linear-gradient(top, #ffffff, #f5f5f5); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); + border: 1px solid #ddd; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} +.breadcrumb li { + display: inline; + text-shadow: 0 1px 0 #ffffff; +} +.breadcrumb .divider { + padding: 0 5px; + color: #bfbfbf; +} +.breadcrumb .active a { + color: #404040; +} +.hero-unit { + background-color: #f5f5f5; + margin-bottom: 30px; + padding: 60px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; +} +.hero-unit p { + font-size: 18px; + font-weight: 200; + line-height: 27px; +} +footer { + margin-top: 17px; + padding-top: 17px; + border-top: 1px solid #eee; +} +.page-header { + margin-bottom: 17px; + border-bottom: 1px solid #ddd; + -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} +.page-header h1 { + margin-bottom: 8px; +} +.btn.danger, +.alert-message.danger, +.btn.danger:hover, +.alert-message.danger:hover, +.btn.error, +.alert-message.error, +.btn.error:hover, +.alert-message.error:hover, +.btn.success, +.alert-message.success, +.btn.success:hover, +.alert-message.success:hover, +.btn.info, +.alert-message.info, +.btn.info:hover, +.alert-message.info:hover { + color: #ffffff; +} +.btn .close, .alert-message .close { + font-family: Arial, sans-serif; + line-height: 18px; +} +.btn.danger, +.alert-message.danger, +.btn.error, +.alert-message.error { + background-color: #c43c35; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(top, #ee5f5b, #c43c35); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #c43c35 #c43c35 #882a25; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.success, .alert-message.success { + background-color: #57a957; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957)); + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -ms-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(top, #62c462, #57a957); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #57a957 #57a957 #3d773d; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.info, .alert-message.info { + background-color: #339bb9; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9)); + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(top, #5bc0de, #339bb9); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #339bb9 #339bb9 #22697d; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn { + cursor: pointer; + display: inline-block; + background-color: #e6e6e6; + background-repeat: no-repeat; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); + background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + padding: 5px 14px 6px; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + color: #333; + font-size: 13px; + line-height: normal; + border: 1px solid #ccc; + border-bottom-color: #bbb; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -webkit-transition: 0.1s linear all; + -moz-transition: 0.1s linear all; + -ms-transition: 0.1s linear all; + -o-transition: 0.1s linear all; + transition: 0.1s linear all; +} +.btn:hover { + background-position: 0 -15px; + color: #333; + text-decoration: none; +} +.btn:focus { + outline: 1px dotted #666; +} +.btn.primary { + color: #ffffff; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.active, .btn:active { + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); +} +.btn.disabled { + cursor: default; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=65); + -khtml-opacity: 0.65; + -moz-opacity: 0.65; + opacity: 0.65; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn[disabled] { + cursor: default; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=65); + -khtml-opacity: 0.65; + -moz-opacity: 0.65; + opacity: 0.65; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn.large { + font-size: 15px; + line-height: normal; + padding: 9px 14px 9px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.btn.small { + padding: 7px 9px 7px; + font-size: 11px; +} +:root .alert-message, :root .btn { + border-radius: 0 \0; +} +button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { + padding: 0; + border: 0; +} +.close { + float: right; + color: #000000; + font-size: 20px; + font-weight: bold; + line-height: 13.5px; + text-shadow: 0 1px 0 #ffffff; + filter: alpha(opacity=25); + -khtml-opacity: 0.25; + -moz-opacity: 0.25; + opacity: 0.25; +} +.close:hover { + color: #000000; + text-decoration: none; + filter: alpha(opacity=40); + -khtml-opacity: 0.4; + -moz-opacity: 0.4; + opacity: 0.4; +} +.alert-message { + position: relative; + padding: 7px 15px; + margin-bottom: 18px; + color: #404040; + background-color: #eedc94; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94)); + background-image: -moz-linear-gradient(top, #fceec1, #eedc94); + background-image: -ms-linear-gradient(top, #fceec1, #eedc94); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94)); + background-image: -webkit-linear-gradient(top, #fceec1, #eedc94); + background-image: -o-linear-gradient(top, #fceec1, #eedc94); + background-image: linear-gradient(top, #fceec1, #eedc94); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #eedc94 #eedc94 #e4c652; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + border-width: 1px; + border-style: solid; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); +} +.alert-message .close { + margin-top: 1px; + *margin-top: 0; +} +.alert-message a { + font-weight: bold; + color: #404040; +} +.alert-message.danger p a, +.alert-message.error p a, +.alert-message.success p a, +.alert-message.info p a { + color: #ffffff; +} +.alert-message h5 { + line-height: 18px; +} +.alert-message p { + margin-bottom: 0; +} +.alert-message div { + margin-top: 5px; + margin-bottom: 2px; + line-height: 28px; +} +.alert-message .btn { + -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); +} +.alert-message.block-message { + background-image: none; + background-color: #fdf5d9; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + padding: 14px; + border-color: #fceec1; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.alert-message.block-message ul, .alert-message.block-message p { + margin-right: 30px; +} +.alert-message.block-message ul { + margin-bottom: 0; +} +.alert-message.block-message li { + color: #404040; +} +.alert-message.block-message .alert-actions { + margin-top: 5px; +} +.alert-message.block-message.error, .alert-message.block-message.success, .alert-message.block-message.info { + color: #404040; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} +.alert-message.block-message.error { + background-color: #fddfde; + border-color: #fbc7c6; +} +.alert-message.block-message.success { + background-color: #d1eed1; + border-color: #bfe7bf; +} +.alert-message.block-message.info { + background-color: #ddf4fb; + border-color: #c6edf9; +} +.alert-message.block-message.danger p a, +.alert-message.block-message.error p a, +.alert-message.block-message.success p a, +.alert-message.block-message.info p a { + color: #404040; +} +.pagination { + height: 36px; + margin: 18px 0; +} +.pagination ul { + float: left; + margin: 0; + border: 1px solid #ddd; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} +.pagination li { + display: inline; +} +.pagination a { + float: left; + padding: 0 14px; + line-height: 34px; + border-right: 1px solid; + border-right-color: #ddd; + border-right-color: rgba(0, 0, 0, 0.15); + *border-right-color: #ddd; + /* IE6-7 */ + + text-decoration: none; +} +.pagination a:hover, .pagination .active a { + background-color: #c7eefe; +} +.pagination .disabled a, .pagination .disabled a:hover { + background-color: transparent; + color: #bfbfbf; +} +.pagination .next a { + border: 0; +} +.well { + background-color: #f5f5f5; + margin-bottom: 20px; + padding: 19px; + min-height: 20px; + border: 1px solid #eee; + border: 1px solid rgba(0, 0, 0, 0.05); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.modal-backdrop { + background-color: #000000; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop, .modal-backdrop.fade.in { + filter: alpha(opacity=80); + -khtml-opacity: 0.8; + -moz-opacity: 0.8; + opacity: 0.8; +} +.modal { + position: fixed; + top: 50%; + left: 50%; + z-index: 11000; + width: 560px; + margin: -250px 0 0 -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + /* IE6-7 */ + + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.modal .close { + margin-top: 7px; +} +.modal.fade { + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -ms-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; + top: -25%; +} +.modal.fade.in { + top: 50%; +} +.modal-header { + border-bottom: 1px solid #eee; + padding: 5px 15px; +} +.modal-body { + padding: 15px; +} +.modal-body form { + margin-bottom: 0; +} +.modal-footer { + background-color: #f5f5f5; + padding: 14px 15px 15px; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + zoom: 1; + margin-bottom: 0; +} +.modal-footer:before, .modal-footer:after { + display: table; + content: ""; + zoom: 1; +} +.modal-footer:after { + clear: both; +} +.modal-footer .btn { + float: right; + margin-left: 5px; +} +.modal .popover, .modal .twipsy { + z-index: 12000; +} +.twipsy { + display: block; + position: absolute; + visibility: visible; + padding: 5px; + font-size: 11px; + z-index: 1000; + filter: alpha(opacity=80); + -khtml-opacity: 0.8; + -moz-opacity: 0.8; + opacity: 0.8; +} +.twipsy.fade.in { + filter: alpha(opacity=80); + -khtml-opacity: 0.8; + -moz-opacity: 0.8; + opacity: 0.8; +} +.twipsy.above .twipsy-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #000000; +} +.twipsy.left .twipsy-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} +.twipsy.below .twipsy-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; +} +.twipsy.right .twipsy-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid #000000; +} +.twipsy-inner { + padding: 3px 8px; + background-color: #000000; + color: white; + text-align: center; + max-width: 200px; + text-decoration: none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.twipsy-arrow { + position: absolute; + width: 0; + height: 0; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1000; + padding: 5px; + display: none; +} +.popover.above .arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #000000; +} +.popover.right .arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid #000000; +} +.popover.below .arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; +} +.popover.left .arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} +.popover .arrow { + position: absolute; + width: 0; + height: 0; +} +.popover .inner { + background: #000000; + background: rgba(0, 0, 0, 0.8); + padding: 3px; + overflow: hidden; + width: 280px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); +} +.popover .title { + background-color: #f5f5f5; + padding: 9px 15px; + line-height: 1; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; + border-bottom: 1px solid #eee; +} +.popover .content { + background-color: #ffffff; + padding: 14px; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.popover .content p, .popover .content ul, .popover .content ol { + margin-bottom: 0; +} +.fade { + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -ms-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; + opacity: 0; +} +.fade.in { + opacity: 1; +} +.label { + padding: 1px 3px 2px; + font-size: 9.75px; + font-weight: bold; + color: #ffffff; + text-transform: uppercase; + white-space: nowrap; + background-color: #bfbfbf; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.label.important { + background-color: #c43c35; +} +.label.warning { + background-color: #f89406; +} +.label.success { + background-color: #46a546; +} +.label.notice { + background-color: #62cffc; +} +.media-grid { + margin-left: -20px; + margin-bottom: 0; + zoom: 1; +} +.media-grid:before, .media-grid:after { + display: table; + content: ""; + zoom: 1; +} +.media-grid:after { + clear: both; +} +.media-grid li { + display: inline; +} +.media-grid a { + float: left; + padding: 4px; + margin: 0 0 18px 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); +} +.media-grid a img { + display: block; +} +.media-grid a:hover { + border-color: #0069d6; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} diff --git a/_static/default.css b/_static/default.css deleted file mode 100644 index 21f3f509..00000000 --- a/_static/default.css +++ /dev/null @@ -1,256 +0,0 @@ -/* - * default.css_t - * ~~~~~~~~~~~~~ - * - * Sphinx stylesheet -- default theme. - * - * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: sans-serif; - font-size: 100%; - background-color: #11303d; - color: #000; - margin: 0; - padding: 0; -} - -div.document { - background-color: #1c4e63; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 230px; -} - -div.body { - background-color: #ffffff; - color: #000000; - padding: 0 20px 30px 20px; -} - -div.footer { - color: #ffffff; - width: 100%; - padding: 9px 0 9px 0; - text-align: center; - font-size: 75%; -} - -div.footer a { - color: #ffffff; - text-decoration: underline; -} - -div.related { - background-color: #133f52; - line-height: 30px; - color: #ffffff; -} - -div.related a { - color: #ffffff; -} - -div.sphinxsidebar { -} - -div.sphinxsidebar h3 { - font-family: 'Trebuchet MS', sans-serif; - color: #ffffff; - font-size: 1.4em; - font-weight: normal; - margin: 0; - padding: 0; -} - -div.sphinxsidebar h3 a { - color: #ffffff; -} - -div.sphinxsidebar h4 { - font-family: 'Trebuchet MS', sans-serif; - color: #ffffff; - font-size: 1.3em; - font-weight: normal; - margin: 5px 0 0 0; - padding: 0; -} - -div.sphinxsidebar p { - color: #ffffff; -} - -div.sphinxsidebar p.topless { - margin: 5px 10px 10px 10px; -} - -div.sphinxsidebar ul { - margin: 10px; - padding: 0; - color: #ffffff; -} - -div.sphinxsidebar a { - color: #98dbcc; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - - - -/* -- hyperlink styles ------------------------------------------------------ */ - -a { - color: #355f7c; - text-decoration: none; -} - -a:visited { - color: #355f7c; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - - - -/* -- body styles ----------------------------------------------------------- */ - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: 'Trebuchet MS', sans-serif; - background-color: #f2f2f2; - font-weight: normal; - color: #20435c; - border-bottom: 1px solid #ccc; - margin: 20px -20px 10px -20px; - padding: 3px 0 3px 10px; -} - -div.body h1 { margin-top: 0; font-size: 200%; } -div.body h2 { font-size: 160%; } -div.body h3 { font-size: 140%; } -div.body h4 { font-size: 120%; } -div.body h5 { font-size: 110%; } -div.body h6 { font-size: 100%; } - -a.headerlink { - color: #c60f0f; - font-size: 0.8em; - padding: 0 4px 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - background-color: #c60f0f; - color: white; -} - -div.body p, div.body dd, div.body li { - text-align: justify; - line-height: 130%; -} - -div.admonition p.admonition-title + p { - display: inline; -} - -div.admonition p { - margin-bottom: 5px; -} - -div.admonition pre { - margin-bottom: 5px; -} - -div.admonition ul, div.admonition ol { - margin-bottom: 5px; -} - -div.note { - background-color: #eee; - border: 1px solid #ccc; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.topic { - background-color: #eee; -} - -div.warning { - background-color: #ffe4e4; - border: 1px solid #f66; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre { - padding: 5px; - background-color: #eeffcc; - color: #333333; - line-height: 120%; - border: 1px solid #ac9; - border-left: none; - border-right: none; -} - -tt { - background-color: #ecf0f3; - padding: 0 1px 0 1px; - font-size: 0.95em; -} - -th { - background-color: #ede; -} - -.warning tt { - background: #efc2c2; -} - -.note tt { - background: #d6d6d6; -} - -.viewcode-back { - font-family: sans-serif; -} - -div.viewcode-block:target { - background-color: #f4debf; - border-top: 1px solid #ac9; - border-bottom: 1px solid #ac9; -} \ No newline at end of file diff --git a/_static/fork_me_on_github.png b/_static/fork_me_on_github.png new file mode 100644 index 0000000000000000000000000000000000000000..7dc1afca60b9d40dcd402703f5b29717583150d7 GIT binary patch literal 9267 zcmV-3B+T21P)W|DAso zWLbuAhad?0P4z6Qw@vD8Q`6({&6JG1uUWIVLSVE9{5>Z^-Vo_oyKTHb-)r^vq-+8) z>jr?yL73=jXmh>j`|K}TVURrKQnA*nDY=82`X)wPdx_zurW3H zi5Ta-AWw}DV7(90)Ns^*btUl3`ElQL$4Kc(fi~55a>Bcz?A_>MK?L0+mm$YK09PE zjAc>JoUxX{{K+hkjO&g%`2TI~?R8U)zXDnEgPE8exB?jDs{k5A04)7A#1u+HX8{t@ zAu+qy{?osNXFgh_11p9DYiZ42II$kq1gb0MH5Ytkb3w-EV;s9co*o6?x&I;}e(0K; zyQ_IEm@Hr-x=;3w!g!yj<1;V#9{tZw-4uGcDO_Hr(pErS`u2RM8=h)8Kj`*dc#oPu zb4J-U5$cO!FbMcS8tn#QV=>qqw>l2*j@KB=${A~End(YxWi~JtH7T#S;7g@haW1R< z9=fgf^`0UeFtPlu20X{5f|$M;~BL_uB-O?Gp}T6$2)VN9U**UJLR$NaT> z5m;wh+T2s8>J{V zn8L@l*z;WIc}G8%@9bNIErzc;G!reM9`-fn7!Y%|lRtqmD&8OZ*%TM=%V7Q%#aPXq zJ#KHuYXq<&m{fPe)w&v@CDg;d#_t7rvN5Kp*}#56==(*oQx!9|kWIxfjB)Y4q)ZhNW9=f0)!H|C$ak?B zOey(b&b^s_yV2BB!0aUO>kW`4sb_X+k7*E)$j($o2WgrEl1g?E@t(xR`w}x%xwD5lWHtKx*Ld)kA{muV<%Y!4h4(~dzrmZ@{dVnD^XAu{@!9@7WHGn!~l$4XyS~u z)S$xmGk=*223A>dkt^1|69VK5^m$$fnTX|R07?Uqq%Ia&_~uxKv`b0 ze0ZBY7EqTYGZ!wapW|24W|DFsF?X~5xlfAR-LRBQ#k^i=ii+b zE4-4cfn_KP3>7d4EP9rd$CK}@g4q0WxOAi%%;c)9WSPjah(XrU1U&t0bT?$(sEGI8 zj`q*|QsSm?DVQo6jMdyde8`XKDRC)a&b)5!G?qEs`(OYRf@nqxvJ;-;KT-vm57kj% zr9D_jU!#F7AP2>L$j?G|!^j1qu}UDR_#@84du&|1FD0lV0oKl^15csnefrFc1cAQOAlR}oyMf0Fml{-&0*f-%=@&o__`rmj1oJTzgzoNS zm8B$Apd)Y!R6q@%ISxIq9)y{RA!zwdC5$xG!_Zp?6^4V*NO@Qv*vte-gY6*1CP8AB zoio-_2=zHWXYt~_Fx#b6=?sIv>m887B>Ks~xDF&{x93+)-d`(#nkFVMHr)=ruN{O= z!d7OJBGO~XIfh(8EIFGs!7c{Kp z&c3aDiRg@+N3_cZ21AC@0Ok4jYB=$~Z-%k64UoOF3T#^{LOkq#b(bg^J?&vWSMgbp zOT|RL)FQAIl{=1nDwf9zmy)R>WvtiG^PZjHqN&NqSiK*FI7l^-&hGk5x#f`eK z0AWx}^m~YV-j^0s5drH_@v$u>PM5Xdb_k62g0JHh^0fqJnLnBFNyXn@MM2d2+gimW z29(E>$|~TxFCGPRLMpuw|Kt#O{-qKE-3`R`0#I9zyo4`nLUR901AY2h1sflLTTU_mB`AlkC1A4{GXKwzzV#uAtM2QJ!= zg&M1W+U*}`1#|X|U@iSP-G#}FdtFo^isnmX%$QldU-;<*6i}`IRt@KVT?_s1)>EcJ z_R@V?QqWoIQ^6TvG}kQWC;_%K+5^(L|036u42cCdI*+XLVhV9NerP1XYU()W_O>0P zUna&11r<;N11$V%%(zUUz)B{1YMAIL+yUYbEFmm~JHmlK)l&eO^UA?*O{IXEMo+w7 zjTJIJFIL2d{7(L9#q*w=4~d&@a2)<0rgiIX5SQx*M+B_S9`{VwJ77vJ0Bdmth;b=8 zumlxYq87^&gUfr#1Br#@ka6p7*!)Nxf-^38KKfj-v#*!zFf&DATV9KWe3W4R1 zNreqxI0gdIO~#A|*#IsKKuhhvCwLElEz9mayiWaCORlM+rLkWByy;72#rA!cyjwsf z+k3C)_27mhzqIc)v90;mom-pvGX8?LW_Gyhx(H;~5@2%s*% zc@QoisiscS7$&Ph%fW&$PEsKu9fb4}0JSN|dJ^v|0#uO#YfFiP>GcwPe; z(}E3V%BSrH1HqkP3^947Pbh$D`EfOzfAt{!DlLhrl(}rgR1Umx5PE-F4Y8`%J;oH& zXzcDV9I(Kes3iLNCSkm%)$`Evqpp|N0kFiCav_mutj5+3x3}>>2rK#YL_a|Y>MLEi zBg2@K6_=C>#eb{#tJtp5N9&+21R{=;r@-GX;-{ zVI@|ehg9Mi9-kXnsbC@|SEjMTMk3xv)|_}3S2E%kE8g!x@!rx(n}X0P9jrQL&68%n zH0HtO9fINGwUC%;r*4Fa=HrTP64inV)r_KR0v(}VE%%)TCzCx2Fh|-9VNdB|6A0#5 z+7#sQ8Wis<8dQ-2tEG3s?H_0XbIw+XDf70fxaK_0Y4GutVTi;Y0fW)qAx2R`S{WbNUo@%z|yLA zv^qk)GDn`LOrJId=>{RCfH31$$KeO8YX(@W0#wlembdc_5R-Dj;@CyA3BX_qb;d$- zH|){PqV|==5|ilsiUO$a-_%kupYy;0nzD>+HKTg%1I#9X1y)#J*6?`|&m(_;>mi{|UUIMx2B>mwD8*^8^cwf;jg=^++C@ykY(T_!Ag|CzC{kZb2sHQ3) z1yhqzD<%C|4S2_fXdae@=&Bo@RN{pne18uu`?}{}FH?Yh@c0HL=&TBUJx*w7020>K zfVYWo7m!5>drkDV)9i-T=x$hbOcfP(LtCfY+x#2y837{R9n7D)v8|B8UPH%fVfgKX zv}i&D6sF8zmP4W%(itM)(geFN5KLv3q<(*`?iysrl0 zw(r&f<~KA~o72^xx*H^#=y#kvCV(xc#EBWCs|{GI*8D}o6uzM)`sHk+u|gl#7(!?v zg;wdT#R<_*HSB4inW7qNopD!FAeQVspeOoGbu~cG4=QQ-mu3bv&%E9P%U}XST1DEj z6;n7ptS9=d7E`#YnJPNsz0K`ydWk^HrZxqM*O|)bc}JInkFXnh-Ea7s0;uL6SJUE& zE&J-|{qw)Bh1MVKp*zO-ZM)}e2Pwh)4RR%H3WDQT(A|)hy{g3fngCVAo_9Jxzyqet z>%eNin>Gb8dfl~LEEM4KkO%sIS4($;n8b$+g@;xFZC2BjMRE@5Gb+swuvy3CAjlUR z0g`iRQ;;KjlUIeiVNIC7sF*^mE6h!HS@Un9yF!}X!1N1c3srrAV9E^MzU>*AR^+t* zTQy}c6z`aW)$xxvQxCnx(4&EEu4WQKJ0;Ibn-N6X%}>ZE1t8Zo)^&=eCa+{uxMr9t zVpE8W)ji_&U2Fn#){PK@b%pUM%72m}6Tz$&oN9~K4iX?Ca9X}wi8Gs_=Y{<+bIGGK zl8*^Ivpy`p6k3@x%OuiR;RTR7-vrqb2e$kzPVC*Vk{N5wF;&Ej^{Dt*nPZd7LWhla zga5*NLB}OiNWrcowYv;fJbMoAf$6S>SvgkheY0R-EknM$UQ%xm^Fm5K2;{oZERJ`c z=y>qw()#L#Sh%5}iGJz;ft6?q*EFai0oI%7ZYXi?vuwHzq>*l* znGR@*7+^_k`ymx%Y@6+Xn)jalzya8Jca?rkgGAi-Jy)&wZm=-HYz(oJ^jH^`t6$0?1&~^V+l;J1`D$@G#RoRG(b&| zongxl_dx$^2O*8z$HLZWf3R-@o9w6cY>>lbIOw~=z7NR{F+pN_-imWKta(sHEZ(sx z$Y2MUbGAXu=KDd6O9}!@2yFyn5<;0KftWlBD59}Wf4h=~bw)ZH==6z;Yk1qrDsAw(Sl{^wZjKv-wyOgxMViyfh~ZlJg)j zugtzuLOSaPR1pKKv&W4C#!VZFAg1J_G*&nlxHPA!)}u7-mfes}*0!2sv{<$E$bQKC zcnxIjRCHGQ$7&#+2z|Cqq*k9Og>#nb=251xLb?6-ROHd7AfFVM9aw8#s7GDAW2_K6 zz>M|MSvqVtzW}o{L_ZYfS7kg{2WfW&MLH(TYR&aGBf<>&pB^%M>v8Ky3=5RY6OJ z-VNGqfqdzXFCU{jLUe}q{Ipu}Z$W5l?S#?_h$Xv7%#rtCu@0aNSfu#`d98}Q)7G^i#0D;0glr~1~uh2dY zAcu~Qo7K{Yi5ucsj!mUi&}bHM(wFC7_kf>hEqW2;3X0HKO3dN;uWtyN!7!cuLV=Y^ zdyoohQ;@yaI99l>g?co_`(4jS-*0MZRbqv*L`TaBsxv8M2sqO*Ib4g!RKi9GC`_Yi zCObqN)D&QViIcwuez8A9%=?+FQaMb=KlEL}#U_xkDM&{CH5c!ksjh)3#C$BPV<#2u z{?0e3h}WjivnDaXq|az2U7Npsnd+%#vO^p>b6o$+7Y!MsxUpG>0+OPKO4pWms zUxoY<<{0WA6;$zltuz*As%SHoHb4N)A9;(YHU*KHT^$>Y7MS~qWT%IKLbImA$dc5VL4p?&G%@75Cn@)Rx%uh zP9KNfpYMmBpHwTLGR)!$7^YL`z`|Hz$E(CbOJK_^bX*Hl$U$`tfz{eOe#qC~2trae zn9=O8<`qJ-JLzp=$_B{J4xORcio0O<0k{zXMeZk)T^}+L=3Ffp{PWY}0D zPNvvc48p`EIzS*=?gq|OOJNFe*f_=tar#%ueRP_A5UjzSp;-mRr5E=@;}aXGwmSRo z)o}530;ruqK%K0uq|;ULv4ld!EaD6u%p}E?ytfXd+;XLqjO}YG8)Ajy{UG<8AYv{9 zY(+OYpN~?a9|zSE0jsgi>wLKC58?V5WGXs{nKg~d{YI~=M+GlAb^_a z_t2qD+JU-D8!4Abc7(}9z^Cs!3O)ifpJBwD5m?}xQU(YRU?t|1M8(~}&EHbH8#bl8 zEY5ogrHsN1hIA%}Legf~7@T~_|FQU=m3GDa=7ryL7GC7OhAP*3`_Ub z(ZoOW!h613NqfI*BYcf5yG3J92b@z)V}+x1fWU(<_!jMM;GkM!U}3DV%vre4oU>g? z^uwkghLLY+>$sSfMgNU@_vIYpP`w@3cxMqYSKMXDFDhy5EXzY^#^o6L^Z#O3r(1h8@ywsGz{u z;!*&Gjcsu`_8y>tXqkYc_^V1#8V_SA2OxZtTVyHh^A5@RU~}H?e0~v4K{!(_H)G}4 zTv)Iwj}Iur##M+)OrV(!<6t-Bq?>j_>ks!p?xzk=4TUD}y??5t@44mgjw#r<=z%1n zyYM-jW{>7CR&5>0HVk2N--Ak9qz!jzcEiK~Z3?mw#^Rt_3F6(JOB4Mtj^{i37C8@x zR6++>bEtwVwX%k`+(yt~uKSRufxae%=&f5-U}^da)0yM6d4*=C8d@++u7}VhLD6JY zG?o@C{Mpo1X)JF3R)8sN>g;u6LtA7BZC)WjXeG2sHHBJw^7uOkVZ7-$w31z(_q?K& zViJjldgy@ueiZlPWVeW!qdqA#Hpqr^LW)>{348};=l}uOPy~sE+Z;ze6?0XwLe5kx z$rNTMx~xvZSeTmJbApKY(V+G*q$jfi9{p38hgJ5ZGOG}^RqNsXaOvH8xQVb<91-dr z-&GhZ)*Li{vxYVqy42{uh&2HOobQ9JB8hn4dj(U-nQ8?wR!jfXp}@sv5K{}loOcUh zDM4o}(U6A~GG*143fFy20Ti0N_YYLk;Q`yfp*)5;S(8L#v4s>`slCQv0X9Ymh7l-q zfIufiq|X1c^6sA37I z@HN4CfK|*?-{rRBhJ;neoGdF)L)D&JZ$H7yX0^9lvRBq-Rk zK2`&TyAROb?k5Rr;Z@}BQeuZRqxApY3ClfV^6W zRJ@PFM4!jAw|;Ej?>y8LdeuLW8O~HI)D)hh+=O94&c73F(Y=HqaK`*cb!{3bg&b1I)u7>TY0LMzV#e0CU_< z*r+xIxeOCMEp3nd8a~TGwMu~X79BQTOfyKa5<1ZFDoChr7+}eU4AOvA5$~AYP)I~M zYAXa3Ci!8dPvIwOXv%We_bNedJ5E7m7DH2H<^&UaJH|%mN@HE&R9{OwH-D?e-9U$p zx4FHie?i5&kX{lDsc4Q%b{;f>Vuom??gl!WFk2Pxok#c6a8Qgb6>{%aQkDZ)tjeYu z3v-*nu(#2Vb-4rNxD<%Xa5y>Zoc$KBY%D0xQ}tt%WoQ4jKrzUo}f<7tcYp1{fLoLw$YmBj)d&Uk0`p(ck2^K64WzABU2^B0D7RpX@J;s@8 ztuj_-tjk<<7cIHMxl&+n+AUr7fS7dySc)t4rXcb>Yy*pY zPUf0woiWy?jV|nsC68Z(K+nlJ8D}BvbVYr|LACaQwWT0~igz5@iy<8}iIJMU`Ch}# z-+B=5=LZkrfN?CfGG&xrQFzZs6IUbLIa93@#(G=xyxVuu)E5bxg3L_J4zVnf!8lW` zL&n;HjMX=#bo9$815@FhG*v~OgNd%hVDml3nQA>UR(7HigeKx$!dkv4yBauCtw+Y{ z9e4W&TIjHGbJ-_AP}^}w%hkX^wN8Q6bdz_=cceMH;IV% zT_Af$A<+H4GRG!DR|99Nb#DqM4h1eYfsm97CUlZU!PUT-iZhlX-ZNwL0RlK|90v$2 zR=9Jf;*6y*R=-yrAg~oIbbvtOqI4A(>Ks@hz-nykbo-irL-X84W`Mv#cZA&haZ@;3 zyyvGW0|dNd;6L|A8Y^6gaOX_L8EY0}wR8_33Ur?!5K976=9UG!8aPvN#tO?=@2CR= z%#NK(Z}r{}LH12v(VYOCsW@ZJ#aMT!0|X=@-o=b9V6xu>f;l#kA zOa3h&jSmpU`rwMXiZc~wtSd8C_lVoy-w39x>%m<17a+u?%&V(7s5r2$4p?3Nhv>vF z(F|f*@w~1EZvMC_T$m}$PEb>mM?mU1Nt=Rjq0Wzp7^|g!`cPn?6~qliVA^yW?Pkk` zIzJ+1EbAW>cf+IRqC54bAlMs{GZjA;%~&6C!}kbdJsr5z24c=Ou#|orgxDl5)cFw^ zux@w5zqEO}>in%Qlg|hcbLikgoga%fg=S`%-miu)7iFb>!9u5hjY8nUpE#)av0z|n zbN$Tf{yw;bfr9u6vgEErfOW@)pN#l|ndli4Y;kDKjxb5QYP!N4+} zwSnBw`WVz?6w3+!b#Nq0PkRddzs9@43aE!O$HK=4fF( z*E#1~FdwiqAccSmkF$@%HzEcVKh`#Bg#i`|BsM2cd#!Bd|8M-5Pu)OhlRZ#f4Kf2N z2|`JbgNh%E0+wuGFP5o*gNh#u1(wXR63mvUz%>;=7NfDk-RDfjk3};U7?{fV90wIY zA_7-f2IHXON7O;avlRFd^@D?oAJJFyJa)$q&Q$#1pyCGy6+igFLB)@icl@^i0|1Ge V)~XPt9$f$c002ovPDHLkV1fgJi?9Fy literal 0 HcmV?d00001 diff --git a/_static/sidebar.js b/_static/sidebar.js deleted file mode 100644 index a45e1926..00000000 --- a/_static/sidebar.js +++ /dev/null @@ -1,151 +0,0 @@ -/* - * sidebar.js - * ~~~~~~~~~~ - * - * This script makes the Sphinx sidebar collapsible. - * - * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds - * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton - * used to collapse and expand the sidebar. - * - * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden - * and the width of the sidebar and the margin-left of the document - * are decreased. When the sidebar is expanded the opposite happens. - * This script saves a per-browser/per-session cookie used to - * remember the position of the sidebar among the pages. - * Once the browser is closed the cookie is deleted and the position - * reset to the default (expanded). - * - * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -$(function() { - // global elements used by the functions. - // the 'sidebarbutton' element is defined as global after its - // creation, in the add_sidebar_button function - var bodywrapper = $('.bodywrapper'); - var sidebar = $('.sphinxsidebar'); - var sidebarwrapper = $('.sphinxsidebarwrapper'); - - // for some reason, the document has no sidebar; do not run into errors - if (!sidebar.length) return; - - // original margin-left of the bodywrapper and width of the sidebar - // with the sidebar expanded - var bw_margin_expanded = bodywrapper.css('margin-left'); - var ssb_width_expanded = sidebar.width(); - - // margin-left of the bodywrapper and width of the sidebar - // with the sidebar collapsed - var bw_margin_collapsed = '.8em'; - var ssb_width_collapsed = '.8em'; - - // colors used by the current theme - var dark_color = $('.related').css('background-color'); - var light_color = $('.document').css('background-color'); - - function sidebar_is_collapsed() { - return sidebarwrapper.is(':not(:visible)'); - } - - function toggle_sidebar() { - if (sidebar_is_collapsed()) - expand_sidebar(); - else - collapse_sidebar(); - } - - function collapse_sidebar() { - sidebarwrapper.hide(); - sidebar.css('width', ssb_width_collapsed); - bodywrapper.css('margin-left', bw_margin_collapsed); - sidebarbutton.css({ - 'margin-left': '0', - 'height': bodywrapper.height() - }); - sidebarbutton.find('span').text('»'); - sidebarbutton.attr('title', _('Expand sidebar')); - document.cookie = 'sidebar=collapsed'; - } - - function expand_sidebar() { - bodywrapper.css('margin-left', bw_margin_expanded); - sidebar.css('width', ssb_width_expanded); - sidebarwrapper.show(); - sidebarbutton.css({ - 'margin-left': ssb_width_expanded-12, - 'height': bodywrapper.height() - }); - sidebarbutton.find('span').text('«'); - sidebarbutton.attr('title', _('Collapse sidebar')); - document.cookie = 'sidebar=expanded'; - } - - function add_sidebar_button() { - sidebarwrapper.css({ - 'float': 'left', - 'margin-right': '0', - 'width': ssb_width_expanded - 28 - }); - // create the button - sidebar.append( - '
        «
        ' - ); - var sidebarbutton = $('#sidebarbutton'); - light_color = sidebarbutton.css('background-color'); - // find the height of the viewport to center the '<<' in the page - var viewport_height; - if (window.innerHeight) - viewport_height = window.innerHeight; - else - viewport_height = $(window).height(); - sidebarbutton.find('span').css({ - 'display': 'block', - 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 - }); - - sidebarbutton.click(toggle_sidebar); - sidebarbutton.attr('title', _('Collapse sidebar')); - sidebarbutton.css({ - 'color': '#FFFFFF', - 'border-left': '1px solid ' + dark_color, - 'font-size': '1.2em', - 'cursor': 'pointer', - 'height': bodywrapper.height(), - 'padding-top': '1px', - 'margin-left': ssb_width_expanded - 12 - }); - - sidebarbutton.hover( - function () { - $(this).css('background-color', dark_color); - }, - function () { - $(this).css('background-color', light_color); - } - ); - } - - function set_position_from_cookie() { - if (!document.cookie) - return; - var items = document.cookie.split(';'); - for(var k=0; k001BWNkl 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 - - - - - - - Configuration system Documentation — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Configuration system Documentation

        -

        The astropy configuration system is designed to give users control of various -parameters used in astropy or affiliated packages without delving into the -source code to make those changes.

        -
        -

        For Users

        -

        To see the configuration options, look for your astropy configuration file. -You can find it by doing:

        -
        from astropy.config import get_config_dir
        -
        -print get_config_dir()
        -
        -
        -

        And you should see the location of your configuration directory. The standard -scheme generally puts your configuration directory in $HOME/.astropy/config, -but if you’ve set the environment variable XDG_CONFIG_HOME and the -$XDG_CONFIG_HOME/astropy directory exists, it will instead be there.

        -

        Once you’ve found the configuration file, open it with your favorite editor. -It should have all of the sections you might want, with descriptions and the -type of the value that is accepted. Feel free to edit this as you wish, and -any of these changes will be reflected when you next start Astropy. Or, if you -want to see your changes immediately in your current Astropy session, just do:

        -
        from astropy.config import reload_config()
        -
        -reload_config()
        -
        -
        -

        Warning

        -

        The above is not true yet, because the setup doesn’t automatically -populate the configuration files. Hopefully it will be true soon, though. -The astropy.config.configs._generate_all_config_items() function will -already do this, basically, but there has to be some thought about how to -make driver scripts that actually do this for each user, and coordinate -when they get run so that everything is already built.

        -
        -
        -
        -

        For Developers

        -

        The Reference guide below describes the full interface - this is a summary of -typical practices. The most common way to use the configuration system is as -follows:

        -
        """ This is the docstring at the beginning of a module
        -"""
        -from astropy.config import ConfigurationItem
        -
        -SOME_OPTION = ConfigurationItem('some_opt',1,'A description.')
        -ANOTHER_OPTION = ConfigurationItem('anno_opt','a string val',
        -                        'A longer description of what this does.')
        -
        -... implementation ...
        -def some_func():
        -    #to get the value of these options, I might do:
        -    something = SOME_OPTION()+2
        -    return ANOTHER_OPTION()+' Also, I added text.'
        -
        -
        -

        It is highly recommended that any configuration items be placed at the top of a -module like this, as they can then be easily found when viewing the source code -and the automated tools to generate the default configuration files can also -locate these items.

        -
        -
        -

        Reference/API

        -

        Below are the reference documentation for the three main config sub-packages: -astropy.config.paths, astropy.config.configs, and astropy.config.data. -Note that all the public classes and functions in these sub-packages are -imported into astropy.config, so the recommended usage is simply -from astropy.config import foo.

        -
        -

        astropy.config.paths

        -

        This module contains functions to determine where configuration and -data/cache files used by Astropy should be placed.

        -
        -
        -astropy.config.paths.get_config_dir(create=True)[source]
        -

        Determines the Astropy configuration directory name and creates the -directory if it doesn’t exist.

        -

        This directory is typically $HOME/.astropy/config, but if the -XDG_CONFIG_HOME environment variable is set and the -$XDG_CONFIG_HOME/astropy directory exists, it will be that directory. -If neither exists, the former will be created and symlinked to the latter.

        - --- - - - -
        Returns :

        configdir : str

        -
        -

        The absolute path to the configuration directory.

        -
        -
        -
        - -
        -
        -astropy.config.paths.get_cache_dir()[source]
        -

        Determines the Astropy cache directory name and creates the directory if it -doesn’t exist.

        -

        This directory is typically $HOME/.astropy/cache, but if the -XDG_CACHE_HOME environment variable is set and the -$XDG_CACHE_HOME/astropy directory exists, it will be that directory. -If neither exists, the former will be created and symlinked to the latter.

        - --- - - - -
        Returns :

        cachedir : str

        -
        -

        The absolute path to the cache directory.

        -
        -
        -
        - -
        -
        -

        astropy.config.configs

        -

        This module contains classes and functions to standardize access to -configuration files for Astropy and affiliated packages.

        -
        -

        Note

        -

        The configuration system makes use of the ‘configobj’ package, which stores -configuration in a text format like that used in the standard library -ConfigParser. More information and documentation for configobj can be -found at http://www.voidspace.org.uk/python/configobj.html.

        -
        -
        -
        -class astropy.config.configs.ConfigurationItem(name, defaultvalue='', description=None, cfgtype=None, module=None)[source]
        -

        A setting and associated value stored in the astropy configuration -files.

        -

        These objects are typically defined at the top of astropy subpackages -or affiliated packages, and store values or option settings that can be -modified by the user to

        - --- - - - - - -
        Parameters :

        name : str

        -
        -

        The (case-sensitive) name of this parameter, as shown in the -configuration file.

        -
        -

        defaultvalue :

        -
        -

        The default value for this item. If this is a list of strings, this item -will be interpreted as an ‘options’ value - this item must be one of -those values, and the first in the list will be taken as the default -value.

        -
        -

        description : str or None

        -
        -

        A description of this item (will be shown as a comment in the -configuration file)

        -
        -

        cfgtype : str or None

        -
        -

        A type specifier like those used as the values of a particular key in -a configspec file of configobj. If None, the type will be inferred -from the default value.

        -
        -

        module : str or None

        -
        -

        The full module name that this item is associated with. The first -element (e.g. ‘astropy’ if this is ‘astropy.config.configs’) will be -used to determine the name of the configuration file, while the -remaining items determine the section. If None, the package will be -inferred from the package within whiich this object’s initializer is -called.

        -
        -
        Raises :

        RuntimeError :

        -
        -

        If module is None, but the module this item is created from cannot -be determined.

        -
        -
        -

        Examples

        -

        The following example will create an item ‘cfgoption = 42’ in the -‘[configs]’ section of astropy.cfg (located in the directory that -astropy.config.paths.get_config_dir returns), or if the option is already -set, it will take the value from the configuration file:

        -
        from astropy.config import ConfigurationItem
        -
        -CFG_OPTION = ConfigurationItem('cfgoption',42,module='astropy.configs')
        -
        -
        -

        If called as CFG_OPTION(), this will return the value 42, or some -other integer if the astropy.cfg file specifies a different value.

        -

        If this were in the astropy/configs/__init__.py file, the module -option would not be necessary, as it would automatically detect the correct -module.

        -
        -
        -reload()[source]
        -

        Reloads the value of this ConfigurationItem from the relevant -configuration file.

        - --- - - - -
        Returns :

        val :

        -
        -

        The new value loaded from the configuration file.

        -
        -
        -
        - -
        -
        -save(value=None)[source]
        -

        Writes a value for this ConfigurationItem to the relevant -configuration file.

        -

        This also writes updated versions of the comments that give the -description and type information.

        -
        -

        Note

        -

        This only saves the value of this particular ConfigurationItem. -To save all configuration settings for this package at once, see -save_config.

        -
        - --- - - - - - -
        Parameters :

        value :

        -
        -

        Save this value to the configuration file. If None, the current -value of this ConfigurationItem will be saved.

        -
        -
        Raises :

        TypeError :

        -
        -

        If the provided value is not valid for this ConfigurationItem.

        -
        -
        -
        - -
        -
        -set(value)[source]
        -

        Sets the current value of this ConfigurationItem.

        -

        This also updates the comments that give the description and type -information.

        -
        -

        Note

        -

        This does not save the value of this ConfigurationItem to the -configuration file. To do that, use ConfigurationItem.save or -save_config.

        -
        - --- - - - - - -
        Parameters :

        value :

        -
        -

        The value this item should be set to.

        -
        -
        Raises :

        TypeError :

        -
        -

        If the provided value is not valid for this ConfigurationItem.

        -
        -
        -
        - -
        - -
        -
        -exception astropy.config.configs.InvalidConfigurationItemWarning[source]
        -

        A Warning that is issued when the configuration value specified in the -astropy configuration file does not match the type expected for that -configuration value.

        -
        - -
        -
        -astropy.config.configs.get_config(packageormod=None, reload=False)[source]
        -

        Gets the configuration object or section associated with a particular -package or module.

        - --- - - - - - - - -
        Parameters :

        packageormod : str or None

        -
        -

        The package for which to retrieve the configuration object. If a string, -it must be a valid package name, or if None, the package from which this -function is called will be used.

        -
        -
        Returns :

        cfgobj : configobj.ConfigObj or configobj.Section

        -
        -

        If the requested package is a base package, this will be the -configobj.ConfigObj for that package, or if it is a subpackage or -module, it will return the relevant configobj.Section object.

        -
        -
        Raises :

        RuntimeError :

        -
        -

        If package is None, but the package this item is created from cannot -be determined.

        -
        -
        -
        - -
        -
        -astropy.config.configs.save_config(packageormod=None)[source]
        -

        Saves all configuration settings to the configuration file for the -root package of the requested package/module.

        -

        This overwrites any configuration items that have been changed in -ConfigurationItem objects that are based on the configuration file -determined by the root package of packageormod (e.g. ‘astropy.cfg’ for -the ‘astropy.config.configs’ module).

        -
        -

        Note

        -

        To save only a single item, use the ConfigurationItem.save method - -this will save all options in the current session that may have been -changed.

        -
        - --- - - - -
        Parameters :

        packageormod : str or None

        -
        -

        The package or module name - see get_config for details.

        -
        -
        -
        - -
        -
        -astropy.config.configs.reload_config(packageormod=None)[source]
        -

        Reloads configuration settings from a configuration file for the root -package of the requested package/module.

        -

        This overwrites any changes that may have been made in ConfigurationItem -objects. This applies for any items that are based on this file, which is -determined by the root package of packageormod (e.g. ‘astropy.cfg’ for -the ‘astropy.config.configs’ module).

        - --- - - - -
        Parameters :

        packageormod : str or None

        -
        -

        The package or module name - see get_config for details.

        -
        -
        -
        - -
        -
        -

        astropy.config.data

        -

        This module contains helper functions for accessing, downloading, and -caching data files.

        -
        -
        -astropy.config.data.get_data_fileobj(dataname, cache=True)[source]
        -

        Retrieves a data file from the standard locations and provides the file as -a file-like object.

        - --- - - - - - - - -
        Parameters :

        dataname : str

        -
        -

        Name/location of the desired data file. One of the following:

        -
        -
          -
        • The name of a data file included in the source -distribution. The path is relative to the module -calling this function. For example, if calling from -astropy.pkname, use 'data/file.dat' to get the -file in astropy/pkgname/data/file.dat. Double-dots -can be used to go up a level. In the same example, use -'../data/file.dat' to get astropy/data/file.dat.
        • -
        • If a matching local file does not exist, the Astropy -data server will be queried for the file.
        • -
        • A hash like that produced by compute_hash can be -requested, prefixed by ‘hash/’ -e.g. ‘hash/395dd6493cc584df1e78b474fb150840’. The hash -will first be searched for locally, and if not found, -the Astropy data server will be queried.
        • -
        • A URL to some other file.
        • -
        -
        -
        -

        cache : bool

        -
        -

        If True, the file will be downloaded and saved locally or the -already-cached local copy will be accessed. If False, the file-like -object will directly access the resource (e.g. if a remote URL is -accessed, an object like that from urllib2.urlopen is returned).

        -
        -
        Returns :

        fileobj : file-like

        -
        -

        An object with the contents of the data file available via read(). -Can be used as part of a with statement, automatically closing -itself after the with block.

        -
        -
        Raises :

        urllib2.URLError :

        -
        -

        If a remote file cannot be found.

        -
        -

        IOError :

        -
        -

        If problems occur writing or reading a local file.

        -
        -
        -
        -

        See also

        -
        -
        get_data_contents
        -
        returns the contents of a file or url as a bytes object
        -
        get_data_filename
        -
        returns a local name for a file containing the data
        -
        -
        -

        Examples

        -

        This will retrieve a data file and its contents for the astropy.wcs -tests:

        -
        from astropy.config import get_data_fileobj
        -
        -with get_data_fileobj('data/3d_cd.hdr') as fobj:
        -    fcontents = fobj.read()
        -
        -
        -

        This downloads a data file and its contents from a specified URL, and does -not cache it remotely:

        -
        from astropy.config import get_data_fileobj
        -
        -vegaurl = 'ftp://ftp.stsci.edu/cdbs/grid/k93models/standards/vega.fits'
        -with get_data_fileobj(vegaurl,False) as fobj:
        -    fcontents = fobj.read()
        -
        -
        -
        - -
        -
        -astropy.config.data.get_data_filename(dataname)[source]
        -

        Retrieves a data file from the standard locations and provides the local -name of the file.

        -

        This function is similar to get_data_fileobj but returns the file name -instead of a readable file-like object. This means that this function must -always cache remote files locally, unlike get_data_fileobj.

        - --- - - - - - - - -
        Parameters :

        dataname : str

        -
        -

        Name/location of the desired data file. One of the following:

        -
        -
          -
        • The name of a data file included in the source -distribution. The path is relative to the module -calling this function. For example, if calling from -astropy.pkname, use 'data/file.dat' to get the -file in astropy/pkgname/data/file.dat. Double-dots -can be used to go up a level. In the same example, use -'../data/file.dat' to get astropy/data/file.dat.
        • -
        • If a matching local file does not exist, the Astropy -data server will be queried for the file.
        • -
        • A hash like that produced by compute_hash can be -requested, prefixed by ‘hash/’ -e.g. ‘hash/395dd6493cc584df1e78b474fb150840’. The hash -will first be searched for locally, and if not found, -the Astropy data server will be queried.
        • -
        • A URL to some other file.
        • -
        -
        -
        -
        Returns :

        filename : str

        -
        -

        A file path on the local file system corresponding to the data -requested in dataname.

        -
        -
        Raises :

        urllib2.URLError :

        -
        -

        If a remote file cannot be found.

        -
        -

        IOError :

        -
        -

        If problems occur writing or reading a local file.

        -
        -
        -
        -

        See also

        -
        -
        get_data_contents
        -
        returns the contents of a file or url as a bytes object
        -
        get_data_fileobj
        -
        returns a file-like object with the data
        -
        -
        -

        Examples

        -

        This will retrieve the contents of the data file for the astropy.wcs -tests:

        -
        from astropy.config import get_data_filename
        -
        -fn = get_data_filename('data/3d_cd.hdr')
        -with open(fn) as f:
        -    fcontents = f.read()
        -
        -
        -

        This retrieves a data file by hash either locally or from the astropy data -server:

        -
        from astropy.config import get_data_filename
        -
        -fn = get_data_filename('hash/da34a7b07ef153eede67387bf950bb32')
        -with open(fn) as f:
        -    fcontents = f.read()
        -
        -
        -
        - -
        -
        -astropy.config.data.get_data_contents(dataname, cache=True)[source]
        -

        Retrieves a data file from the standard locations and returns its -contents as a bytes object.

        - --- - - - - - - - -
        Parameters :

        dataname : str

        -
        -

        Name/location of the desired data file. One of the following:

        -
        -
          -
        • The name of a data file included in the source -distribution. The path is relative to the module -calling this function. For example, if calling from -astropy.pkname, use 'data/file.dat' to get the -file in astropy/pkgname/data/file.dat. Double-dots -can be used to go up a level. In the same example, use -'../data/file.dat' to get astropy/data/file.dat.
        • -
        • If a matching local file does not exist, the Astropy -data server will be queried for the file.
        • -
        • A hash like that produced by compute_hash can be -requested, prefixed by ‘hash/’ -e.g. ‘hash/395dd6493cc584df1e78b474fb150840’. The hash -will first be searched for locally, and if not found, -the Astropy data server will be queried.
        • -
        • A URL to some other file.
        • -
        -
        -
        -

        cache : bool

        -
        -

        If True, the file will be downloaded and saved locally or the -already-cached local copy will be accessed. If False, the file-like -object will directly access the resource (e.g. if a remote URL is -accessed, an object like that from urllib2.urlopen is returned).

        -
        -
        Returns :

        contents : bytes

        -
        -

        The complete contents of the file as a bytes object.

        -
        -
        Raises :

        urllib2.URLError :

        -
        -

        If a remote file cannot be found.

        -
        -

        IOError :

        -
        -

        If problems occur writing or reading a local file.

        -
        -
        -
        -

        See also

        -
        -
        get_data_fileobj
        -
        returns a file-like object with the data
        -
        get_data_filename
        -
        returns a local name for a file containing the data
        -
        -
        -
        - -
        -
        -astropy.config.data.get_data_fileobjs(datadir, pattern='*')[source]
        -

        Returns readable file objects for all of the data files in a given -directory that match a given glob pattern.

        - --- - - - - - -
        Parameters :

        datadir : str

        -
        -

        Name/location of the desired data files. One of the following:

        -
        -
          -
        • The name of a directory included in the source -distribution. The path is relative to the module -calling this function. For example, if calling from -astropy.pkname, use 'data' to get the -files in astropy/pkgname/data
        • -
        • Remote URLs are not currently supported
        • -
        -
        -
        -

        pattern : str, optional

        -
        -

        A UNIX-style filename glob pattern to match files. See the -glob module in the standard library for more information. -By default, matches all files.

        -
        -
        Returns :

        fileobjs : iterator of file objects

        -
        -

        File objects for each of the files on the local filesystem in -datadir matching pattern.

        -
        -
        -

        Examples

        -

        This will retrieve the contents of the data file for the astropy.wcs -tests:

        -
        from astropy.config import get_data_filenames
        -
        -for fd in get_data_filename('maps', '*.hdr'):
        -    fcontents = fd.read()
        -
        -
        -
        - -
        -
        -astropy.config.data.get_data_filenames(datadir, pattern='*')[source]
        -

        Returns the path of all of the data files in a given directory -that match a given glob pattern.

        - --- - - - - - -
        Parameters :

        datadir : str

        -
        -

        Name/location of the desired data files. One of the following:

        -
        -
          -
        • The name of a directory included in the source -distribution. The path is relative to the module -calling this function. For example, if calling from -astropy.pkname, use 'data' to get the -files in astropy/pkgname/data.
        • -
        • Remote URLs are not currently supported.
        • -
        -
        -
        -

        pattern : str, optional

        -
        -

        A UNIX-style filename glob pattern to match files. See the -glob module in the standard library for more information. -By default, matches all files.

        -
        -
        Returns :

        filenames : iterator of str

        -
        -

        Paths on the local filesystem in datadir matching pattern.

        -
        -
        -

        Examples

        -

        This will retrieve the contents of the data file for the astropy.wcs -tests:

        -
        from astropy.config import get_data_filenames
        -
        -for fn in get_data_filename('maps', '*.hdr'):
        -    with open(fn) as f:
        -        fcontents = f.read()
        -
        -
        -
        - -
        -
        -astropy.config.data.compute_hash(localfn)[source]
        -

        Computes the MD5 hash for a file.

        -

        The hash for a data file is used for looking up data files in a unique -fashion. This is of particular use for tests; a test may require a -particular version of a particular file, in which case it can be accessed -via hash to get the appropriate version.

        -

        Typically, if you wish to write a test that requires a particular data -file, you will want to submit that file to the astropy data servers, and -use e.g. get_data_filename('hash/a725fa6ba642587436612c2df0451956'), -but with the hash for your file in place of the hash in the example.

        - --- - - - - - -
        Parameters :

        localfn : str

        -
        -

        The path to the file for which the hash should be generated.

        -
        -
        Returns :

        md5hash : str

        -
        -

        The hex digest of the MD5 hash for the contents of the localfn file.

        -
        -
        -
        - -
        -
        -astropy.config.data.clear_data_cache(hashorurl=None)[source]
        -

        Clears the data file cache by deleting the local file(s).

        - --- - - - - - -
        Parameters :

        hashorurl : str or None

        -
        -

        If None, the whole cache is cleared. Otherwise, either specifies a hash -for the cached file that is supposed to be deleted, or a URL that has -previously been downloaded to the cache.

        -
        -
        Raises :

        OSEerror :

        -
        -

        If the requested filename is not present in the data directory.

        -
        -
        -
        - -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Installation

        -

        Next topic

        -

        astropy.wcs Documentation

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/contributing.html b/contributing.html new file mode 100644 index 00000000..3127a809 --- /dev/null +++ b/contributing.html @@ -0,0 +1,189 @@ + + + + + + + + + + + Contributing to Astropy — Astropy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        + +
        +

        Contributing to Astropy

        +

        There are many different ways you can contribute to the Astropy project!

        +
        +

        Report issues

        +

        Even if you don’t have time to contribute code or documentation, please make +sure you report any issues with the package, the documentation, or this +website, to the Astropy issue tracker!

        +
        +
        +

        Contribute code

        +

        If you are interested in contributing fixes, code or documentation to Astropy +(whether the core package or affiliated packages), you can join the +astropy-dev mailing list, and head over to the documentation pages on +contributing to Astropy. You can either send us a patch, or (preferably) +work on a fork of Astropy and submit the changes via a pull request.

        +
        +
        +

        Develop an affiliated package

        +

        Whether you have an idea for a new Astronomy package, or already have a +package that you want to integrate with the Astropy project, you can develop +an affiliated package! After joining the astropy-dev list and notifying +other developers of your intent to develop an affiliated package, you can head +over here for instructions on +getting started! We can even create a repository for your affiliated package +in the astropy organization on GitHub!

        +
        +
        + + +
        +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +
        +
        + + \ No newline at end of file diff --git a/development/building_packaging.html b/development/building_packaging.html deleted file mode 100644 index 505b96c9..00000000 --- a/development/building_packaging.html +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - - - - - Building, Cython/C Extensions, and Distribution — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Building, Cython/C Extensions, and Distribution

        -

        The build process currently uses the -Distribute package to build and -install the astropy core (and any affiliated packages that use the template). -The user doesn’t necessarily need to have distribute installed, as it will -automatically bootstrap itself using the distribute_setup.py file in the -source distribution if it isn’t installed for the user.

        -
        -

        Customizing setup/build for subpackages

        -

        As is typical, there is a single setup.py file that’s used for the whole -astropy package. To customize setup parameters for a given sub-package, a -setup_package.py file can be defined inside a package, and if it is present, -the setup process will look for the following functions to customize the build -process:

        -
          -
        • -
          get_package_data()
          -

          This function, if defined, should return a dictionary mapping the name of -the subpackage(s) that need package data to a list of data file paths -(possibly including wildcards) relative to the path of the package’s source -code. e.g. if the source distribution has a needed data file -astropy/wcs/tests/data/3d_cd.hdr, this function should return -{'astropy.wcs.tests:'['data/3d_cd.hdr']}. See the package_data -option of the distutils.core.setup() function.

          -

          It is recommended that all such data be in a directory named “data” inside -the package within which it is supposed to be used, and package data should -be accessed via the astropy.config.data.get_data_filename and -astropy.config.data.get_data_fileobj functions.

          -
          -
          -
        • -
        • -
          get_extensions()
          -

          This provides information for building C or Cython extensions. If defined, -it should return a list of distutils.core.Extension objects controlling -the Cython/C build process (see below for more detail).

          -
          -
          -
        • -
        • -
          get_legacy_alias()
          -

          This function allows for the creation of shims that allow a -subpackage to be imported under another name. For example, -astropy.io.fits used to be available under the namespace -pyfits. For backward compatibility, it is helpful to have it -still importable under the old name. Under most circumstances, -this function should call astropy.setup_helpers.add_legacy_alias -to generate a legacy module and then return what it returns.

          -
          -
          -
        • -
        -

        The astropy.setup_helpers modules includes a update_package_files() -function which automatically searches the given source path for -setup_package.py modules and calls each of the above functions, if they -exist. This makes it easy for affiliated packages to use this machinery in -their own setup.py.

        -
        -
        -

        C or Cython Extensions

        -

        Astropy supports using C extensions for wrapping C libraries and Cython for -speeding up computationally-intensive calculations. Both Cython and C extension -building can be customized using the get_extensions() function of the -setup_package.py file. If defined, this function must return a list of -distutils.core.Extension objects. The creation process is left to the -subpackage designer, and can be customized however is relevant for the -extensions in the subpackage.

        -

        While C extensions must always be defined through the get_extensions() -mechanism, Cython files (ending in .pyx) are automatically located and -loaded in separate extensions if they are not in get_extensions(). For -Cython extensions located in this way, headers for numpy C functions are -included in the build, but no other external headers are included. .pyx -files present in the extensions returned by get_extensions() are not -included in the list of extensions automatically generated extensions. Note -that this allows disabling a Cython file by providing an extension that -includes the Cython file, but giving it the special name ‘cython_skip’. Any -extension with this package name will not be built by setup.py.

        -
        -

        Note

        -

        If an Extension object is provided for Cython -source files using the get_extensions() mechanism, it is very -important that the .pyx files be given as the source, rather than the -.c files generated by Cython.

        -
        -
        -

        Installing C header files

        -

        If your C extension needs to be linked from other third-party C code, -you probably want to install its header files along side the Python module.

        -
        -
          -
        1. Create an include directory inside of your package for -all of the header files.

          -
        2. -
        3. Use the get_package_data() hook in setup_package.py to -install those header files. For example, the astropy.wcs -package has this:

          -
          def get_package_data():
          -    return {'astropy.wcs': ['include/*.h']}
          -
          -
          -
        4. -
        -
        -
        -
        -
        -

        Release

        -

        There have been no releases of the core package yet, so this isn’t fully -defined. Some important items that are expected to be involved:

        -
          -
        • The release process should be done by automated script.
        • -
        • Documentation is currently hosted at http://readthedocs.org/docs/astropy, -and tested at https://jenkins.shiningpanda.com/astropy/job/astropy-doc/, -automatically updated with every commit to github master.
        • -
        • c files generated by Cython should never be stored in source, but instead -generated during the release process. The setup script will always use these -generated c files for release versions (instead of the .pyx Cython file).
        • -
        -

        There is a central setup.py. It defines which Python packages to -install. Each package does not have its own standalone setup.py.

        -

        Each package that needs to build C extensions has a module -setup_package.py that contains a function get_extensions() which -returns a list of distutils.core.Extension objects defining any -extensions to be built.

        -

        There are a set of helper functions for commonly occurring things when -building C extensions (e.g. finding the Numpy headers and library) in -astropy.setup_helpers.

        -
        -
        -

        Future directions

        -

        We plan to switch to a newer packaging scheme when it’s more stable, the -upcoming standard library packaging module, derived from the -distutils2 -project. Until it’s working right, however, we will be using distribute and -distutils.

        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Testing Guidelines (Draft)

        -

        Next topic

        -

        Writing Command-Line Scripts

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/codeguide.html b/development/codeguide.html deleted file mode 100644 index f520a46f..00000000 --- a/development/codeguide.html +++ /dev/null @@ -1,546 +0,0 @@ - - - - - - - - - - Coding Guidelines (Draft) — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Coding Guidelines (Draft)

        -
        -

        Warning

        -

        This document is currently in Draft form and is subject to change.

        -
        -

        This section describes requirements and guidelines that affiliated packages -will have to follow before being considered for integration as a module in the -core package.

        -
        -

        Interface and Dependencies

        -
          -
        • The package should meet the interface requirements set out by the -coordination committee.
        • -
        • Packages implementing many classes/functions not relevant to the component -requested will not be accepted - the package should only include the -required functionality and relevant extensions.
        • -
        • Packages must be compatible with Python 2.6, 2.7, and 3.x (for 3.x -compatibility, the 2to3 tool -will be used).
        • -
        • The package should be importable with no dependencies other than components -already in the Astropy core, the Python Standard Library (v2.6), NumPy, SciPy, -and Matplotlib (versions for these packages will be specified in the -Astropy setup.py file and on PyPI).
        • -
        • The package should be importable from the source tree at build time. -This means that, for example, if the package relies on C extensions -that have yet to be built, the Python code is still importable, even -if none of its functionality will work.
        • -
        • Additional dependencies are allowed for sub-modules or in function calls, -but they must be noted in the package documentation and should only affect -the relevant component.
        • -
        • General utilities necessary for but not specific to the package should be -placed in the packagename.utils module. These utilities will be moved -to the astropy.utils module when the package is integrated into the -core package. If a utility is already present in astropy.utils, the -package should always use that utility instead of re-implementing it in -packagename.utils.
        • -
        -
        -
        -

        Documentation and Testing

        -
          -
        • Docstrings must be present for all public classes/methods/functions, and -must follow the form outlined in the Documentation Guidelines (Draft) document.
        • -
        • Unit tests are encouraged for all public methods and functions, and should -adhere to the standards set in the Testing Guidelines (Draft) document.
        • -
        -
        -
        -

        Data and Configuration

        -
          -
        • Packages can include data in a directory named data inside a subpackage -source directory as long as it is less than about 100 kb. These data should -always be accessed via the astropy.config.get_data_fileobj() or -astropy.config.get_data_filename() functions. If the data exceeds this -size, it should be hosted outside the source code repository, either at a -third-party location on the internet or the astropy data server. In either -case, it should always be downloaded using the -astropy.config.get_data_fileobj() or -astropy.config.get_data_filename() functions. If a specific version of -a data file is needed, the hash mechanism described in Configuration system Documentation should -be used.
        • -
        • All persistent configuration should use the -astropy.config.ConfigurationItem mechanism. Such configuration items -should be placed at the top of the module or package that makes use of them, -and supply a description sufficient for users to understand what the setting -changes.
        • -
        -
        -
        -

        Coding Style/Conventions

        -
          -
        • The code will follow the standard PEP8 Style Guide for Python Code. In particular, this includes -using only 4 spaces for indentation, and never tabs.
        • -
        • One exception is to be made from the PEP8 style: new style relative imports -of the form from . import modname are allowed and required for Astropy, -as opposed to absolute (as PEP8 suggets) or the simpler import modname -syntax. This is primarily due to improved relative import support since PEP8 -was developed, and to simplify the process of moving modules.
        • -
        -
        -

        Note

        -

        There are multiple options for testing PEP8 compliance of code, -see Testing Guidelines (Draft) for more information.

        -

        See Emacs setup for following coding guidelines for some configuration options for -Emacs that helps in ensuring conformance to PEP8.

        -
        -
          -
        • Astropy source code should contain a comment at the beginning of the file (or -imppediately after the #!/usr/bin env python command, if relevant) -pointing to the license for the Astropy source code. This line should say:

          -
          # Licensed under a 3-clause BSD style license - see LICENSE.rst
          -
          -
          -
        • -
        • The import numpy as np, import matplotlib as mpl, and import -matplotlib.pyplot as plt naming conventions should be used wherever -relevant. from packagename import * should never be used, except as a -tool to flatten the namespace of a module. An example of the allowed usage -is given in Acceptable use of from module import *.

          -
        • -
        • Classes should either use direct variable access, or python’s property -mechanism for setting object instance variables. get_value/set_value -style methods should be used only when getting and setting the values -requires a computationally-expensive operation. Properties vs. get_/set_ -below illustrates this guideline.

          -
        • -
        • All new classes should be new-style classes inheriting from object -(in Python 3 this is a non-issue as all classes are new-style by default). -The one exception to this rule is older classes in third-party libraries such -the Python standard library or numpy.

          -
        • -
        • Classes should use the builtin super() function when making calls to -methods in their super-class(es) unless there are specific reasons not to. -super() should be used consistently in all subclasses since it does not -work otherwise. super() vs. Direct Calling illustrates why this is -important.

          -
        • -
        • Multiple inheritance should be avoided in general without good reason. -Mulitple inheritance is complicated to implement well, which is why many -object-oriented languages, like Java, do not allow it at all. Python does -enable multiple inheritance through use of the -C3 Linearization -algorithm, which provides a consistent method resolution ordering. -Non-trivial multiple-inheritance schemes should not be attempted without -good justification, or without understanding how C3 is used to determine -method resolution order. However, trivial multiple inheritance using -orthogonal base classes, known as the ‘mixin’ pattern, may be used.

          -
        • -
        • __init__.py files for modules should not contain any significant -implementation code. __init__.py can contain docstrings and code for -organizing the module layout, however (e.g. from submodule import * -in accord with the guideline above). If a module is small enough that -it fits in one file, it should simple be a single file, rather than a -directory with an __init__.py file.

          -
        • -
        • When try...except blocks are used to catch exceptions, the as syntax -should always be used, because this is available in all supported versions of -python and is less ambiguous syntax (see try...except block “as” syntax).

          -
        • -
        • Affiliated packages are required to follow the layout and documentation form -of the template package included in the core package source distribution.

          -
        • -
        • Command-line scripts should follow the form outlined in the Writing Command-Line Scripts -document.

          -
        • -
        -
        -
        -

        Including C Code

        -
          -
        • C extensions are only allowed when they provide a significant performance -enhancement over pure python, or a robust C library already exists to -provided the needed functionality. When C extensions are used, the Python -interface must meet the aforementioned python interface guidelines.
        • -
        • The use of Cython is strongly recommended for C extensions, as per the -example in the template package. Cython extensions should store .pyx -files in the source code repository, but they should be compiled to .c -files that are updated in the repository when important changes are made to -the .pyx file.
        • -
        • If a C extension has a dependency on an external C library, the source code -for the library should be bundled with the Astropy core, provided the -license for the C library is compatible with the Astropy license. -Additionally, the package must be compatible with using a system-installed -library in place of the library included in Astropy.
        • -
        • In cases where C extensions are needed but Cython cannot be used, the PEP 7 -Style Guide for C Code is -recommended.
        • -
        • C extensions (Cython or otherwise) should provide the necessary information -for building the extension via the mechanisms described in -C or Cython Extensions.
        • -
        -
        -
        -

        Requirements Specific to Affiliated Packages

        -
          -
        • Affiliated packages must be registered on the Python Package Index, with proper metadata for downloading and -installing the source package.
        • -
        • The astropy root package name should not be used by affiliated -packages - it is reserved for use by the core package. Recommended naming -conventions for an affiliated package are either simply packagename -or awastropy.packagename (“affiliated with Astropy”).
        • -
        -
        -
        -

        Examples

        -

        This section shows a few examples (not all of which are correct!) to -illustrate points from the guidelines. These will be moved into the template -project once it has been written.

        -
        -

        Properties vs. get_/set_

        -

        This example shows a sample class illustrating the guideline regarding the use -of properties as opposed to getter/setter methods.

        -

        Let’s assuming you’ve defined a Star class and create an instance -like this:

        -
        >>> s = Star(B=5.48, V=4.83)
        -
        -
        -

        You should always use attribute syntax like this:

        -
        >>> s.color = 0.4
        ->>> print s.color
        -0.4
        -
        -
        -

        Rather than like this:

        -
        >>> s.set_color(0.4)  #Bad form!
        ->>> print s.get_color()  #Bad form!
        -0.4
        -
        -
        -

        Using python properties, attribute syntax can still do anything possible with -a get/set method. For lengthy or complex calculations, however, use a method:

        -
        >>> print s.compute_color(5800, age=5e9)
        -0.4
        -
        -
        -
        -
        -

        super() vs. Direct Calling

        -

        This example shows why the use of super() leads to a more consistent -method resolution order than manually calling methods of the super classes in a -multiple inheritance case:

        -
        # This is dangerous and bug-prone!
        -
        -class A(object):
        -    def method(self):
        -        print 'Doing A'
        -
        -
        -class B(A):
        -    def method(self):
        -        print 'Doing B'
        -        A.method(self)
        -
        -
        -class C(A):
        -    def method(self):
        -        print 'Doing C'
        -        A.method(self)
        -
        -class D(C, B):
        -    def method(self):
        -        print 'Doing D'
        -        C.method(self)
        -        B.method(self)
        -
        -
        -

        if you then do:

        -
        >>> b = B()
        ->>> b.method()
        -
        -
        -

        you will see:

        -
        Doing B
        -Doing A
        -
        -

        which is what you expect, and similarly for C. However, if you do:

        -
        >>> d = D()
        ->>> d.method()
        -
        -
        -

        you might expect to see the methods called in the order D, B, C, A but instead -you see:

        -
        Doing D
        -Doing C
        -Doing A
        -Doing B
        -Doing A
        -
        -

        because both B.method() and C.method() call A.method() unaware of -the fact that they’re being called as part of a chain in a hierarchy. When -C.method() is called it is unaware that it’s being called from a subclass -that inherts from both B and C, and that B.method() should be -called next. By calling super() the entire method resolution order for -D is precomputed, enabling each superclass to cooperatively determine which -class should be handed control in the next super() call:

        -
        # This is safer
        -
        -class A(object):
        -    def method(self):
        -        print 'Doing A'
        -
        -class B(A):
        -    def method(self):
        -        print 'Doing B'
        -        super(B, self).method()
        -
        -
        -class C(A):
        -    def method(self):
        -        print 'Doing C'
        -        super(C, self).method()
        -
        -class D(C, B):
        -    def method(self):
        -        print 'Doing D'
        -        super(D, self).method()
        -
        -
        -
        >>> d = D()
        ->>> d.method()
        -Doing D
        -Doing C
        -Doing B
        -Doing A
        -
        -
        -

        As you can see, each superclass’s method is entered only once. For this to -work it is very important that each method in a class that calls its -superclass’s version of that method use super() instead of calling the -method directly. In the most common case of single-inheritance, using -super() is functionally equivalent to calling the superclass’s method -directly. But as soon as a class is used in a multiple-inheritance -hierarchy it must use super() in order to cooperate with other classes in -the hierarchy.

        - -
        -
        -

        Acceptable use of from module import *

        -

        from module import * is discouraged in a module that contains -implementation code, as it impedes clarity and often imports unused variables. -It can, however, be used for a package that is laid out in the following -manner:

        -
        packagename
        -packagename/__init__.py
        -packagename/submodule1.py
        -packagename/submodule2.py
        -
        -
        -

        In this case, packagename/__init__.py may be:

        -
        """
        -A docstring describing the package goes here
        -"""
        -from submodule1 import *
        -from submodule2 import *
        -
        -
        -

        This allows functions or classes in the submodules to be used directly as -packagename.foo rather than packagename.submodule1.foo. If this is -used, it is strongly recommended that the submodules make use of the __all__ -variable to specify which modules should be imported. Thus, submodule2.py -might read:

        -
        from numpy import array,linspace
        -
        -__all__ = ('foo','AClass')
        -
        -def foo(bar):
        -    #the function would be defined here
        -    pass
        -
        -class AClass(object):
        -    #the class is defined here
        -    pass
        -
        -
        -

        This ensures that from submodule import * only imports foo() and -AClass, but not numpy.array or numpy.linspace().

        -
        -
        -

        try...except block “as” syntax

        -

        Catching of exceptions should always use this syntax:

        -
        try:
        -    ... some code that might produce a variety of exceptions ...
        -except ImportError as e:
        -    if 'somemodule' in e.args[0]"
        -        #for whatever reason, failed import of somemodule is ok
        -        pass
        -    else:
        -        raise
        -except ValueError, TypeError as e:
        -    msg = 'Hit an input problem, which is ok,'
        -    msg2 = 'but we're printing it here just so you know:'
        -    print msg, msg2, e
        -
        -

        This avoids the old style syntax of except ImportError, e or -except (ValueError,TypeError), e, which is dangerous because it’s easy to -instead accidentally do something like except ValueError,TypeError, which -won’t catch TypeError.

        -
        -
        -
        -

        Additional Resources

        -

        Further tips and hints relating to the coding guidelines are included below.

        - -
        -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/development/codeguide_emacs.html b/development/codeguide_emacs.html deleted file mode 100644 index 76aa72f8..00000000 --- a/development/codeguide_emacs.html +++ /dev/null @@ -1,321 +0,0 @@ - - - - - - - - - - Emacs setup for following coding guidelines — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Emacs setup for following coding guidelines

        -

        The Astropy coding guidelines are listed in Coding Guidelines (Draft). This -document will describe some configuration options for Emacs, that will -help in ensuring that Python code satisfies the guidelines. Emacs can -be configured in several different ways. So instead of providing a drop -in configuration file, only the individual configurations are presented -below.

        -

        For this setup we will need flymake, pyflakes and the pep8 Python -script, in addition to python-mode.

        -

        Flymake comes with Emacs 23. The rest can be obtained from their -websites, or can be installed using easy_install or pip.

        -
        -

        Global settings

        -
        -

        No tabs

        -

        This setting will cause all tabs to be replaced with spaces. The number -of spaces to use is set in the Basic settings section below.

        -
        ;; Don't use TABS for indentations.
        -(setq-default indent-tabs-mode nil)
        -
        -
        -
        -
        -

        Maximum number of characters in a line

        -

        Emacs will automatically insert a new line after “fill-column” number -of columns. PEP8 specifies a maximum of 79, but this can be set to a -smaller value also, for example 72.

        -
        ;; Set the number to the number of columns to use.
        -(setq-default fill-column 79)
        -
        -;; Add Autofill mode to mode hooks.
        -(add-hook 'text-mode-hook 'turn-on-auto-fill)
        -
        -;; Show line number in the mode line.
        -(line-number-mode 1)
        -
        -;; Show column number in the mode line.
        -(column-number-mode 1)
        -
        -
        -
        -
        -

        Syntax highlighting

        -

        Enable syntax highlighting. This will also highlight lines that form a -region.

        -
        (global-font-lock-mode 1)
        -
        -
        -
        -
        -
        -

        Python specific settings

        -
        -

        Basic settings

        -

        Indentation is automatically added. When a tab is pressed it is -replaced with 4 spaces. When backspace is pressed on an empty line, the -cursor will jump to the previous indentation level.

        -
        (load-library "python")
        -
        -(autoload 'python-mode "python-mode" "Python Mode." t)
        -(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))
        -(add-to-list 'interpreter-mode-alist '("python" . python-mode))
        -
        -(setq interpreter-mode-alist
        -      (cons '("python" . python-mode)
        -            interpreter-mode-alist)
        -      python-mode-hook
        -      '(lambda () (progn
        -                    (set-variable 'py-indent-offset 4)
        -                    (set-variable 'indent-tabs-mode nil))))
        -
        -
        -
        -
        -

        Highlight the column where a line must stop

        -

        The “fill-column” column is highlighted in red. For this to work, -download column-marker.el and place it in the -Emacs configuration directory.

        -
        ;; Highlight character at "fill-column" position.
        -(require 'column-marker)
        -(set-face-background 'column-marker-1 "red")
        -(add-hook 'python-mode-hook
        -          (lambda () (interactive)
        -            (column-marker-1 fill-column)))
        -
        -
        -
        -
        -

        Flymake

        -

        Flymake will mark lines that do not satisfy syntax requirements in -red. When cursor is on such a line a message is displayed in the -mini-buffer. When mouse pointer is on such a line a “tool tip” message -is also shown.

        -

        For flymake to work with pep8 and pyflakes, create an -executable file named pychecker with the following contents. This -file must be in the system path.

        -
        #!/bin/bash
        -
        -pyflakes "$1"
        -pep8 --ignore=E221,E701,E202 --repeat "$1"
        -true
        -
        -
        -

        Add the following code to Emacs configurations.

        -
        ;; Setup for Flymake code checking.
        -(require 'flymake)
        -(load-library "flymake-cursor")
        -
        -;; Script that flymake uses to check code. This script must be
        -;; present in the system path.
        -(setq pycodechecker "pychecker")
        -
        -(when (load "flymake" t)
        -  (defun flymake-pycodecheck-init ()
        -    (let* ((temp-file (flymake-init-create-temp-buffer-copy
        -                       'flymake-create-temp-inplace))
        -           (local-file (file-relative-name
        -                        temp-file
        -                        (file-name-directory buffer-file-name))))
        -      (list pycodechecker (list local-file))))
        -  (add-to-list 'flymake-allowed-file-name-masks
        -               '("\\.py\\'" flymake-pycodecheck-init)))
        -
        -(add-hook 'python-mode-hook 'flymake-mode)
        -
        -
        -
        -

        Note

        -

        Flymake will save files with suffix _flymake in the current -directory. If it crashes for some reason, then these files will not -get deleted.

        -

        Sometimes there is a delay in refreshing the results.

        -
        -
        -
        -

        Delete trailing white spaces and blank lines

        -

        To manually delete trailing whitespaces, press C-t C-w, which will -run the command “delete-whitespaces`. This command is also run when a -file is saved, and hence all trailing whitespaces will be deleted on -saving a Python file.

        -

        To make sure that all “words” are separated by only one space, type -M-SPC (use the ALT key since M-SPC sometimes brings up a context -menu.).

        -

        To collapse a set of blank lines to one blank line, place the cursor on -one of these and press C-x C-o. This is useful for deleting multiple -black lines at the end of a file.

        -
        ;; Remove trailing whitespace manually by typing C-t C-w.
        -(add-hook 'python-mode-hook
        -          (lambda ()
        -            (local-set-key (kbd "C-t C-w")
        -                           'delete-trailing-whitespace)))
        -
        -;; Automatically remove trailing whitespace when file is saved.
        -(add-hook 'python-mode-hook
        -      (lambda()
        -        (add-hook 'local-write-file-hooks
        -              '(lambda()
        -                 (save-excursion
        -                   (delete-trailing-whitespace))))))
        -
        -;; Use M-SPC (use ALT key) to make sure that words are separated by
        -;; just one space. Use C-x C-o to collapse a set of empty lines
        -;; around the cursor to one empty line. Useful for deleting all but
        -;; one blank line at end of file. To do this go to end of file (M->)
        -;; and type C-x C-o.
        -
        -
        -
        -
        -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/development/docguide.html b/development/docguide.html deleted file mode 100644 index 0f7ea266..00000000 --- a/development/docguide.html +++ /dev/null @@ -1,667 +0,0 @@ - - - - - - - - - - Documentation Guidelines (Draft) — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Documentation Guidelines (Draft)

        -
        -

        Warning

        -

        This document is currently in Draft form and is subject to change.

        -
        -

        TODO: Detailed information about building the documentation should be -added here.

        -
        -

        Astropy Documentation Rules and Recommendations

        -

        This section describes the standards for documentation format affiliated -packages that must follow for consideration of integration into the core -module, as well as the standard Astropy docstring format.

        -
          -
        • Documentation shall use the Sphinx documentation tool.
        • -
        • The template package will provide a recommended general structure for -documentation.
        • -
        • Docstrings must be provided for all public classes, methods, and functions.
        • -
        • Docstrings will be incorporated into the documentation using a version of -numpydoc included with Astropy, and should follow the NumPy/SciPy -docstring standards, included below.
        • -
        • Examples and/or tutorials are strongly encouraged for typical use-cases of a -particular module or class.
        • -
        • Any external package dependencies aside from NumPy, SciPy, or Matplotlib -must be explicitly mentioned in the documentation.
        • -
        • Configuration options using the astropy.config mechanisms must be -explicitly mentioned in the documentation.
        • -
        -
        -
        -

        NumPy/SciPy Docstring Rules

        -

        The original source for these docstring standards is the NumPy project, and -the associated numpydoc tools. The most up-to-date version of these standards -can be found at numpy’s github site. The -guidelines below have been adapted to the Astropy pacakge.

        -
        -

        Overview

        -

        In general, we follow the standard Python style conventions as described here:

        -
        -
        -

        Additional PEPs of interest regarding documentation of code:

        -
        -
        -

        Use a code checker:

        -
        -
        -

        The following import conventions are used throughout the Astropy source -and documentation:

        -
        import numpy as np
        -import matplotlib as mpl
        -import matplotlib.pyplot as plt
        -
        -
        -

        Do not abbreviate scipy. There is no motivating use case to abbreviate -it in the real world, so we avoid it in the documentation to avoid -confusion.

        -

        It is not necessary to do import numpy as np at the beginning of -an example. However, some sub-modules, such as fft, are not -imported by default, and you have to include them explicitly:

        -
        import numpy.fft
        -
        -
        -

        after which you may use it:

        -
        np.fft.fft2(...)
        -
        -
        -
        -
        -

        Docstring Standard

        -

        A documentation string (docstring) is a string that describes a module, -function, class, or method definition. The docstring is a special attribute -of the object (object.__doc__) and, for consistency, is surrounded by -triple double quotes, i.e.:

        -
        """This is the form of a docstring.
        -
        -It can be spread over several lines.
        -
        -"""
        -
        -
        -

        NumPy and SciPy have defined a common convention for docstrings that -provides for consistency, while also allowing our toolchain to produce -well-formatted reference guides. This format should be used for Astropy -docstrings.

        -

        This docstring standard uses re-structured text (reST) syntax and is rendered -using Sphinx (a pre-processor that understands the particular -documentation style we are using). While a rich set of markup is -available, we limit ourselves to a very basic subset, in order to -provide docstrings that are easy to read on text-only terminals.

        -

        A guiding principle is that human readers of the text are given -precedence over contorting docstrings so our tools produce nice output. -Rather than sacrificing the readability of the docstrings, we have -written pre-processors to assist Sphinx in its task.

        -

        The length of docstring lines should be kept to 75 characters to -facilitate reading the docstrings in text terminals.

        -
        -
        -

        Sections

        -

        The sections of the docstring are:

        -
          -
        1. Short summary

          -

          A one-line summary that does not use variable names or the function -name, e.g.

          -
          def add(a, b):
          -   """The sum of two numbers.
          -
          -   """
          -
          -
          -

          The function signature is normally found by introspection and -displayed by the help function. For some functions (notably those -written in C) the signature is not available, so we have to specify -it as the first line of the docstring:

          -
          """
          -add(a, b)
          -
          -The sum of two numbers.
          -
          -"""
          -
          -
          -
        2. -
        3. Deprecation warning

          -

          A section (use if applicable) to warn users that the object is deprecated. -Section contents should include:

          -
            -
          • In what Astropy version the object was deprecated, and when it will -be removed.
          • -
          • Reason for deprecation if this is useful information (e.g., object -is superseded, duplicates functionality found elsewhere, etc.).
          • -
          • New recommended way of obtaining the same functionality.
          • -
          -

          This section should use the note Sphinx directive instead of an -underlined section header.

          -
          .. note:: Deprecated in Astropy 1.2
          -          `ndobj_old` will be removed in Astropy 2.0, it is replaced by
          -          `ndobj_new` because the latter works also with array subclasses.
          -
          -
        4. -
        5. Extended summary

          -

          A few sentences giving an extended description. This section should be used -to clarify functionality, not to discuss implementation detail or -background theory, which should rather be explored in the notes section -below. You may refer to the parameters and the function name, but parameter -descriptions still belong in the parameters section.

          -
        6. -
        7. Parameters

          -

          Description of the function arguments, keywords and their respective types.

          -
          Parameters
          -----------
          -x : type
          -   Description of parameter `x`.
          -
          -

          Enclose variables in single backticks.

          -

          For the parameter types, be as precise as possible. Below are a few -examples of parameters and their types.

          -
          Parameters
          -----------
          -filename : str
          -copy : bool
          -dtype : data-type
          -iterable : iterable object
          -shape : int or tuple of int
          -files : list of str
          -
          -

          If it is not necessary to specify a keyword argument, use optional:

          -
          x : int, optional
          -
          -

          Optional keyword parameters have default values, which are displayed as -part of the function signature. They can also be detailed in the -description:

          -
          Description of parameter `x` (the default is -1, which implies summation
          -over all axes).
          -
          -

          When a parameter can only assume one of a fixed set of values, those values -can be listed in braces:

          -
          order : {'C', 'F', 'A'}
          -    Description of `order`.
          -
          -

          When two or more input parameters have exactly the same type, shape and -description, they can be combined:

          -
          x1, x2 : array_like
          -    Input arrays, description of `x1`, `x2`.
          -
          -
        8. -
        9. Returns

          -

          Explanation of the returned values and their types, of the same format as -parameters.

          -
        10. -
        11. Other parameters

          -

          An optional section used to describe infrequently used parameters. It -should only be used if a function has a large number of keyword parameters, -to prevent cluttering the parameters section.

          -
        12. -
        13. Raises

          -

          An optional section detailing which errors get raised and under what -conditions:

          -
          Raises
          -------
          -InvalidWCSException
          -    If the WCS information is invalid.
          -
          -

          This section should be used judiciously, i.e only for errors that are -non-obvious or have a large chance of getting raised.

          -
        14. -
        15. See Also

          -

          An optional section used to refer to related code. This section can be very -useful, but should be used judiciously. The goal is to direct users to -other functions they may not be aware of, or have easy means of discovering -(by looking at the module docstring, for example). Routines whose -docstrings further explain parameters used by this function are good -candidates.

          -

          As an example, for a hypothetical function astropy.wcs.sky2pix -converting sky to pixel coordinates, we would have:

          -
          See Also
          ---------
          -pix2sky : Convert pixel to sky coordinates
          -
          -

          When referring to functions in the same sub-module, no prefix is needed, -and the tree is searched upwards for a match.

          -

          Prefix functions from other sub-modules appropriately. E.g., whilst -documenting a hypothetical astropy.vo module, refer to a function in -table by

          -
          table.read : Read in a VO table
          -
          -

          When referring to an entirely different module:

          -
          astropy.coords : Coordinate handling routines
          -
          -

          Functions may be listed without descriptions, and this is preferable if the -functionality is clear from the function name:

          -
          See Also
          ---------
          -func_a : Function a with its description.
          -func_b, func_c_, func_d
          -func_e
          -
          -
        16. -
        17. Notes

          -

          An optional section that provides additional information about the code, -possibly including a discussion of the algorithm. This section may include -mathematical equations, written in LaTeX -format:

          -
          The FFT is a fast implementation of the discrete Fourier transform:
          -
          -.. math:: X(e^{j\omega } ) = x(n)e^{ - j\omega n}
          -
          -

          Equations can also be typeset underneath the math directive:

          -
          The discrete-time Fourier time-convolution property states that
          -
          -.. math::
          -
          -     x(n) * y(n) \Leftrightarrow X(e^{j\omega } )Y(e^{j\omega } )\\
          -     another equation here
          -
          -

          Math can furthermore be used inline, i.e.

          -
          The value of :math:`\omega` is larger than 5.
          -
          -

          Variable names are displayed in typewriter font, obtained by using -\mathtt{var}:

          -
          We square the input parameter `alpha` to obtain
          -:math:`\mathtt{alpha}^2`.
          -
          -

          Note that LaTeX is not particularly easy to read, so use equations -sparingly.

          -

          Images are allowed, but should not be central to the explanation; users -viewing the docstring as text must be able to comprehend its meaning -without resorting to an image viewer. These additional illustrations are -included using:

          -
          .. image:: filename
          -
          -

          where filename is a path relative to the reference guide source directory.

          -
        18. -
        19. References

          -
        20. -
        -
        -

        References cited in the notes section may be listed here, -e.g. if you cited the article below using the text [1]_, -include it as in the list as follows:

        -
        .. [1] O. McNoleg, "The integration of GIS, remote sensing,
        -   expert systems and adaptive co-kriging for environmental habitat
        -   modelling of the Highland Haggis using object-oriented, fuzzy-logic
        -   and neural-network techniques," Computers & Geosciences, vol. 22,
        -   pp. 585-588, 1996.
        -
        -

        which renders as

        - - - - - -
        [1]O. McNoleg, “The integration of GIS, remote sensing, -expert systems and adaptive co-kriging for environmental habitat -modelling of the Highland Haggis using object-oriented, fuzzy-logic -and neural-network techniques,” Computers & Geosciences, vol. 22, -pp. 585-588, 1996.
        -

        Referencing sources of a temporary nature, like web pages, is discouraged. -References are meant to augment the docstring, but should not be required -to understand it. References are numbered, starting from one, in the order -in which they are cited.

        -
        -
          -
        1. Examples
        2. -
        -
        -

        An optional section for examples, using the doctest format. This section -is meant to illustrate usage, not to provide a testing framework – for -that, use the tests/ directory. While optional, this section is very -strongly encouraged.

        -

        When multiple examples are provided, they should be separated by blank -lines. Comments explaining the examples should have blank lines both above -and below them:

        -
        >>> astropy.wcs.sky2pix(233.2, -12.3)
        -(134.5, 233.1)
        -
        -Comment explaining the second example
        -
        ->>> astropy.coords.fk5_to_gal("00:42:44.33 +41:16:07.5")
        -(121.1743, -21.5733)
        -
        -
        -

        For tests with a result that is random or platform-dependent, mark the -output as such:

        -
        >>> astropy.coords.randomize_position(244.9, 44.2, radius=0.1)
        -(244.855, 44.13)  #random
        -
        -
        -

        You can run examples using:

        -
        >>> astropy.test(doctests=True)
        -
        -
        -

        It is not necessary to use the doctest markup <BLANKLINE> to indicate -empty lines in the output. Note that the option to run the examples through -numpy.test is provided for checking if the examples work, not for -making the examples part of the testing framework.

        -

        The examples may assume that import numpy as np is executed before the -example code Additional examples may make use of matplotlib -for plotting, but should import it explicitly, e.g., import -matplotlib.pyplot as plt.

        -
        -
        -
        -

        Documenting classes

        -
        -

        Class docstrings

        -

        Use the same sections as outlined above (all except Returns are -applicable). The constructor (__init__) should also be documented here, -the parameters section of the docstring details the constructors -parameters.

        -

        An Attributes section, located below the parameters section, may be -used to describe class variables:

        -
        Attributes
        -----------
        -x : float
        -    The X coordinate.
        -y : float
        -    The Y coordinate.
        -
        -

        Attributes that are properties and have their own docstrings can be simply -listed by name:

        -
        Attributes
        -----------
        -real
        -imag
        -x : float
        -    The X coordinate
        -y : float
        -    The Y coordinate
        -
        -

        In general, it is not necessary to list class methods. Those that are not part -of the public API have names that start with an underscore. In some cases, -however, a class may have a great many methods, of which only a few are -relevant (e.g., subclasses of ndarray). Then, it becomes useful to have an -additional Methods section:

        -
        class Table(ndarray):
        -    """
        -    A class to represent tables of data
        -
        -    ...
        -
        -    Attributes
        -    ----------
        -    columns : list
        -        List of columns
        -
        -    Methods
        -    -------
        -    read(filename)
        -        Read a table from a file
        -    sort(column, order='ascending')
        -        Sort by `column`
        -    """
        -
        -
        -

        If it is necessary to explain a private method (use with care!), it can be -referred to in the extended summary or the notes. Do not list private -methods in the Methods section.

        -

        Note that self is not listed as the first parameter of methods.

        -
        -
        -

        Method docstrings

        -

        Document these as you would any other function. Do not include self in the -list of parameters. If a method has an equivalent function (which is the case -for many ndarray methods for example), the function docstring should contain -the detailed documentation, and the method docstring should refer to it. Only -put brief summary and See Also sections in the method docstring.

        -
        -
        -
        -

        Documenting class instances

        -

        Instances of classes that are part of the Astropy API may require some care. -To give these instances a useful docstring, we do the following:

        -
          -
        • Single instance: If only a single instance of a class is exposed, document -the class. Examples can use the instance name.
        • -
        • Multiple instances: If multiple instances are exposed, docstrings for each -instance are written and assigned to the instances’ __doc__ attributes -at run time. The class is documented as usual, and the exposed instances can -be mentioned in the Notes and See Also sections.
        • -
        -
        -
        -

        Documenting constants

        -

        Use the same sections as outlined for functions where applicable:

        -
        1. summary
        -2. extended summary (optional)
        -3. see also (optional)
        -4. references (optional)
        -5. examples (optional)
        -
        -

        Docstrings for constants will not be visible in text terminals -(constants are of immutable type, so docstrings can not be assigned -to them like for for class instances), but will appear in the -documentation built with Sphinx.

        -
        -
        -

        Documenting modules

        -

        Each module should have a docstring with at least a summary line. Other -sections are optional, and should be used in the same order as for documenting -functions when they are appropriate:

        -
        1. summary
        -2. extended summary
        -3. routine listings
        -4. see also
        -5. notes
        -6. references
        -7. examples
        -
        -

        Routine listings are encouraged, especially for large modules, for which it is -hard to get a good overview of all functionality provided by looking at the -source file(s) or the __all__ dict.

        -

        Note that license and author info, while often included in source files, do not -belong in docstrings.

        -
        -
        -

        Other points to keep in mind

        -
          -
        • Notes and Warnings : If there are points in the docstring that deserve -special emphasis, the reST directives for a note or warning can be used -in the vicinity of the context of the warning (inside a section). Syntax:

          -
          .. warning:: Warning text.
          -
          -.. note:: Note text.
          -
          -

          Use these sparingly, as they do not look very good in text terminals -and are not often necessary. One situation in which a warning can -be useful is for marking a known bug that is not yet fixed.

          -
        • -
        • Questions and Answers : For general questions on how to write docstrings -that are not answered in this document, refer to -http://docs.scipy.org/numpy/Questions+Answers/.

          -
        • -
        • array_like : For functions that take arguments which can have not only -a type ndarray, but also types that can be converted to an ndarray -(i.e. scalar types, sequence types), those arguments can be documented -with type array_like.

          -
        • -
        -
        -
        -

        Common reST concepts

        -

        For paragraphs, indentation is significant and indicates indentation in the -output. New paragraphs are marked with a blank line.

        -

        Use italics, bold, and courier if needed in any explanations (but -not for variable names and doctest code or multi-line code). Variable, module -and class names should be written between single back-ticks (`astropy`).

        -

        A more extensive example of reST markup can be found in this example document; the quick -reference is -useful while editing.

        -

        Line spacing and indentation are significant and should be carefully followed.

        -
        -
        -

        Conclusion

        -

        An example of the -format shown here is available. Refer to How to Build API/Reference -Documentation -on how to use Sphinx to build the manual.

        -
        -
        -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/development/index.html b/development/index.html deleted file mode 100644 index 697a0868..00000000 --- a/development/index.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - Documentation for Developers — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Documentation for Developers

        -

        The information in the following pages are relevant for anyone interesting in -contributing to Astropy. In addition, the Overview is a useful guide -to the layout of the astropy package.

        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.utils.misc: Miscellaneous/uncategorized Utilities

        -

        Next topic

        -

        Vision for a Common Astronomy Python Package

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/scripts.html b/development/scripts.html deleted file mode 100644 index b24d3dee..00000000 --- a/development/scripts.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - - Writing Command-Line Scripts — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Writing Command-Line Scripts

        -

        Command-line scripts in Astropy should follow a consistent scheme to promote -readability and compatibility.

        -

        The actual script should be in the /scripts directory of the Astropy -source distribution, and should do nothing aside from importing a main -function from astropy and execute it. This is partly necessary because the -“2to3” utility that converts python 2.x code to 3.x does not convert scripts. -These scripts should be executable, include #!/usr/bin/env python at the -top, and should not end in .py.

        -

        The main functions these scripts call should accept an optional single -argument that holds the sys.argv list, except for the script name -(e.g., argv[1:]). This function can live in its own module, or be part of a -larger module that implements a class or function for astropy library use. The -main function should do very little actual work - it should only parse the -arguments and pass those arguments on to some library function so that the -library function can be used programmatically when needed. -Command-line options can be parsed however desired, but the argparse -module is recommended when possible, due to its simpler and more flexible -interface relative to the older optparse. argparse is only -available in python >=2.7 and >=3.2, however, so it should be imported as -from astropy.util.compat import argparse .

        -
        -

        Example

        -

        Contents of /scripts/cmdlinescript

        -
        #!/usr/bin/env python
        -# -*- coding: utf-8 -*-
        -"""An astropy command-line script"""
        -
        -import astropy.somepackage.somemod
        -
        -astropy.somepackage.somemod.main()
        -
        -
        -

        Contents of /astropy/somepackage/somemod.py

        -
        def do_something(args, option=False):
        -    for a in args:
        -        if option:
        -            ...do something...
        -        else:
        -            ...do something else...
        -
        -def main(args=None):
        -    from astropy.utils.compat import argparse
        -
        -    parser = argparse.ArgumentParser(description='Process some integers.')
        -    parser.add_argument('-o', '--option', dest='op',action='store_true',
        -                        help='Some option that turns something on.')
        -    parser.add_argument('stuff', metavar='S', nargs='+',
        -                        help='Some input I should be able to get lots of.')
        -
        -    res = parser.parse_args(args)
        -
        -    do_something(res.stuff,res.op)
        -
        -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Building, Cython/C Extensions, and Distribution

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/testguide.html b/development/testguide.html deleted file mode 100644 index e29e8536..00000000 --- a/development/testguide.html +++ /dev/null @@ -1,566 +0,0 @@ - - - - - - - - - - Testing Guidelines (Draft) — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Testing Guidelines (Draft)

        -
        -

        Warning

        -

        This document is currently in Draft form and is subject to change. Not all -described functionality may be implemented.

        -
        -

        This section describes the testing framework and format standards for tests in -Astropy core packages (this also serves as recommendations for affiliated -packages).

        -
        -

        Testing Framework

        -

        The testing framework used by Astropy is the py.test -framework.

        -
        -
        -

        Running Tests

        -

        There are currently three different ways to invoke Astropy tests. Each method -invokes py.test to run the tests but offers different options when calling.

        -

        In addition to running the Astropy tests, these methods can also be called so -that they check Python source code for -PEP8 compliance. All of the PEP8 -testing options require the -pytest-pep8 plugin, which must be -installed separately.

        -
        -

        setup.py test

        -

        The safest way to run the astropy test suite is via the setup command test. -This is invoked by running python setup.py test while in the astropy source -code directory. Run python setup.py test --help to see the options to the -test command.

        -

        Turn on PEP8 checking by passing --pep8 to the test command. This will -turn off regular testing and enable PEP8 testing.

        -
        -

        Note

        -

        This method of running the tests defaults to the version of py.test that -is bundled with Astropy. To use the locally-installed version, you should -either change the use_system_pytest configuration option to “True” -(see Configuration system Documentation) or the py.test method describe below.

        -
        -
        -
        -

        py.test

        -

        An alternative way to run tests from the command line is to switch to the source -code directory of astropy and simply type:

        -
        py.test
        -
        -
        -

        py.test will look for files that look like tests -in the currect directory and all recursive directories then run all the code that -looks like tests -within those files.

        -
        -

        Note

        -

        To test any compiled C/Cython extensions, you must either have run -python setup.py test or python setup.py develop prior to running -the py.test command-line script. Otherwise, any tests that make use of -these extensions will not succeed. Similarly, in python 3, these tests -will not run correctly in the source code, because they need the 2to3 -tool to be run on them.

        -
        -

        You may specify a specific test file or directory at the command line:

        -
        py.test test_file.py
        -
        -

        To run a specific test within a file use the -k option:

        -
        py.test test_file.py -k "test_function"
        -
        -

        You may also use the -k option to not run tests py putting a - in front -of the matching string:

        -
        py.test test_file.py -k "-test_function"
        -
        -

        py.test has a number of command line usage options.

        -

        Turn on PEP8 testing by adding the --pep8 flag to the py.test call. By -default regular tests will also be run but these can be turned off by adding --k pep8:

        -
        py.test some_dir --pep8 -k pep8
        -
        -
        -

        Note

        -

        This method of running the tests uses the locally-installed version of -py.test rather than the bundled one, and hence will fail if the local -version it is not up-to-date enough (py.test 2.2 as of this writing).

        -
        -
        -
        -

        astropy.test()

        -

        AstroPy includes a standalone version of py.test that allows to tests -to be run even if py.test is not installed. Tests can be run from within -AstroPy with:

        -
        import astropy
        -astropy.test()
        -
        -
        -

        This will run all the default tests for AstroPy.

        -

        Tests for a specific package can be run by specifying the package in the call -to the test() function:

        -
        astropy.test('io.fits')
        -
        -
        -

        This method works only with package names that can be mapped to Astropy -directories. As an alternative you can test a specific directory or file -with the test_path option:

        -
        astropy.test(test_path='wcs/tests/test_wcs.py')
        -
        -
        -

        The test_path must be specified either relative to the working directory -or absolutely.

        -

        By default astropy.test() will skip tests which retrieve data from the -internet. To turn these tests on use the remote_data flag:

        -
        astropy.test('io.fits',remote_data=True)
        -
        -
        -

        In addition, the test function supports any of the options that can be -passed to pytest.main(), -and convenience options verbose= and pastebin=.

        -

        Enable PEP8 compliance testing with pep8=True in the call to -astropy.test. This will enable PEP8 checking and disable regular tests.

        -
        -

        Note

        -

        This method of running the tests defaults to the version of py.test that -is bundled with Astropy. To use the locally-installed version, you should -either change the use_system_pytest configuration option to “True” -(see Configuration system Documentation) or the py.test method describe above.

        -
        -
        -
        -
        -

        Regression tests

        -

        Any time a bug is fixed, and wherever possible, one or more regression tests -should be added to ensure that the bug is not introduced in future. Regression -tests should include the ticket URL where the bug was reported.

        -
        -
        -

        Where to put tests

        -
        -

        Package-specific tests

        -

        Each package should include a suite of unit tests, covering as many of the -public methods/functions as possible. These tests should be included inside -each sub-package, either in a tests directory, or in a test.py file, e.g:

        -
        astropy/io/fits/tests/
        -
        -

        or:

        -
        astropy/io/fits/test.py
        -
        -
        -

        tests directories should contain an __init__.py file so that the tests -can be imported and so that they can use relative imports.

        -
        -
        -

        Interoperability tests

        -

        Tests involving two or more sub-packages should be included in:

        -
        astropy/tests/
        -
        -

        and using:

        -
        astropy.test()
        -
        -
        -

        then runs both these interoperability tests, and all the unit tests in the -sub-packages. This functionality is especially important for people who install -packages through bundles and package managers, where the original source code -for the tests is not immediately available.

        -
        -
        -
        -

        Writing tests

        -

        py.test has the following test discovery rules:

        -
        -
          -
        • test_*.py or *_test.py files
        • -
        • Test prefixed classes (without an __init__ method)
        • -
        • test_ prefixed functions and methods
        • -
        -
        -

        Consult the test discovery rules -for detailed information on how to name files and tests so that they are -automatically discovered by py.test.

        -
        -

        Simple example

        -

        The following example shows a simple function and a test to test this -function:

        -
        def func(x):
        -    return x + 1
        -
        -def test_answer():
        -    assert func(3) == 5
        -
        -
        -

        If we place this in a test.py file and then run:

        -
        py.test test.py
        -
        -

        The result is:

        -
        ============================= test session starts ==============================
        -python: platform darwin -- Python 2.7.2 -- pytest-1.1.1
        -test object 1: /Users/tom/tmp/test.py
        -
        -test.py F
        -
        -=================================== FAILURES ===================================
        -_________________________________ test_answer __________________________________
        -
        -    def test_answer():
        ->       assert func(3) == 5
        -E       assert 4 == 5
        -E        +  where 4 = func(3)
        -
        -test.py:5: AssertionError
        -=========================== 1 failed in 0.07 seconds ===========================
        -
        -
        -
        -

        Working with data files

        -

        Tests that need to make use of a data file should use the -get_data_fileobj or -get_data_filename functions. These functions search -locally first, and then on the astropy data server or an arbitrary URL, and -return a file-like object or a local filename, respectively. They automatically -cache the data locally if remote data is obtained, and from then on the local -copy will be used transparently.

        -

        They also support the use of an MD5 hash to get a specific version of a data -file. This hash can be obtained prior to submitting a file to the astropy -data server by using the compute_hash function on a -local copy of the file.

        -

        Tests that may retrieve remote data should be marked with the @remote_data -decorator. Tests marked with this decorator will be skipped by default by -astropy.test() to prevent test runs from taking too long. These tests can -be run by astropy.test() by adding the remote_data=True flag. -Turn on the remote data tests at the command line with -py.test --remote-data.

        -
        -

        Examples

        -
        from ...config import get_data_filename
        -from ...tests.helper import remote_data
        -
        -def test_1():
        -    #if filename.fits is a local file in the source distribution
        -    datafile = get_data_filename('filename.fits')
        -    # do the test
        -
        -@remote_data
        -def test_2():
        -    #this is the hash for a particular version of a file stored on the
        -    #astropy data server.
        -    datafile = get_data_filename('hash/94935ac31d585f68041c08f87d1a19d4')
        -    # do the test
        -
        -
        -

        The get_remote_test_data will place the files in a temporary directory -indicated by the tempfile module, so that the test files will eventually -get removed by the system. In the long term, once test data files become too -large, we will need to design a mechanism for removing test data immediately.

        -
        -
        -
        -

        Tests that create files

        -

        Tests may often be run from directories where users do not have write permissions -so tests which create files should always do so in temporary directories. This -can be done with the py.test tmpdir function argument -or with Python’s built-in tempfile module.

        -
        -
        -

        Setting up/Tearing down tests

        -

        In some cases, it can be useful to run a series of tests requiring something -to be set up first. There are four ways to do this:

        -
        -

        Module-level setup/teardown

        -

        If the setup_module and teardown_module functions are specified in a -file, they are called before and after all the tests in the file respectively. -These functions take one argument, which is the module itself, which makes it -very easy to set module-wide variables:

        -
        def setup_module(module):
        -    module.NUM = 11
        -
        -def add_num(x):
        -    return x + NUM
        -
        -def test_42():
        -    added = add_num(42)
        -    assert added == 53
        -
        -
        -

        We can use this for example to download a remote test data file and have all -the functions in the file access it:

        -
        import os
        -
        -def setup_module(module):
        -    module.DATAFILE = get_remote_test_data('94935ac31d585f68041c08f87d1a19d4')
        -
        -def test():
        -    f = open(DATAFILE, 'rb')
        -    # do the test
        -
        -def teardown_module(module):
        -    os.remove(DATAFILE)
        -
        -
        -
        -
        -

        Class-level

        -

        Tests can be organized into classes that have their own setup/teardown -functions. In the following

        -
        def add_nums(x, y):
        -    return x + y
        -
        -class TestAdd42(object):
        -
        -    def setup_class(self):
        -        self.NUM = 42
        -
        -    def test_1(self):
        -        added = add_nums(11, self.NUM)
        -        assert added == 53
        -
        -    def test_2(self):
        -        added = add_nums(13, self.NUM)
        -        assert added == 55
        -
        -    def teardown_class(self):
        -        pass
        -
        -
        -

        In the above example, the setup_class method is called first, then all the -tests in the class, and finally the teardown_class is called.

        -
        -
        -

        Method-level

        -

        There are cases where one might want setup and teardown methods to be run -before and after each test. For this, use the setup_method and -teardown_method methods:

        -
        def add_nums(x, y):
        -    return x + y
        -
        -class TestAdd42(object):
        -
        -    def setup_method(self, method):
        -        self.NUM = 42
        -
        -    def test_1(self):
        -        added = add_nums(11, self.NUM)
        -        assert added == 53
        -
        -    def test_2(self):
        -        added = add_nums(13, self.NUM)
        -        assert added == 55
        -
        -    def teardown_method(self, method):
        -        pass
        -
        -
        -
        -
        -

        Function-level

        -

        Finally, one can use setup_function and teardown_function to define a -setup/teardown mechanism to be run before and after each function in a module. -These take one argument, which is the function being tested:

        -
        def setup_function(function):
        -    pass
        -
        -def test_1(self):
        -    # do test
        -
        -def test_2(self):
        -    # do test
        -
        -def teardown_method(function):
        -    pass
        -
        -
        -
        -
        -

        Using py.test helper functions

        -

        If your tests need to use py.test helper functions, such as pytest.raises, -import pytest into your test module like so:

        -
        from ...tests.helper import pytest
        -
        -
        -

        You may need to adjust the relative import to work for the depth of your module. -tests.helper imports pytest either from the user’s system or extern.pytest -if the user does not have py.test installed. This is so that users need not -install py.test to run AstroPy’s tests.

        -
        -
        -
        -

        Using data in tests

        -

        Tests can include very small datafiles, but any files significantly larger -than the source code should be placed on a remote server. The base URL for the -test files will be:

        -
        http://data.astropy.org/
        -
        -

        and files will be accessed by their MD5 hash, for example:

        -
        http://data.astropy.org/94935ac31d585f68041c08f87d1a19d4
        -
        -

        Tests then retrieve data via this URL. This implicitly allows versioning, -since different versions of data files will have different hashes. Old data -files should not be removed, so that tests can be run in any version of -AstroPy.

        -

        The details of the server implementation have yet to be decided, but using -these static hash-based URLs ensures that even if we change the backend, the -URL will remain the same.

        -
        -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/development/vision.html b/development/vision.html deleted file mode 100644 index 6ecac35b..00000000 --- a/development/vision.html +++ /dev/null @@ -1,233 +0,0 @@ - - - - - - - - - - Vision for a Common Astronomy Python Package — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Vision for a Common Astronomy Python Package

        -

        The following document summarizes a vision for a common Astronomy Python -package, and how we can best all work together to achieve this. In the -following document, this common package will be referred to as the core -package. This vision is not set in stone, and we are committed to adapting it -to whatever process and guidelines work in practice.

        -

        The ultimate goal that we seek is a package that would contain much of the core -functionality and some common tools required across Astronomy, but not -everything Astronomers will ever need. The aim is primarily to avoid -duplication for common core tasks, and to provide a robust framework upon which -to build more complex tools.

        -

        Such a common package should not preclude any other Astronomy package from -existing, because there will always be more complex and/or specialized tools -required. These tools will be able to rely on a single core library for many -tasks, and thus reduce the number of dependencies, reduce duplication of -functionality, and increase consistency of their interfaces.

        -
        -

        Procedure

        -

        With the help of the community, the coordination committee will start by -identifying a few of key areas where initial development/consolidation will be -needed (such as FITS, WCS, coordinates, tables, photometry, spectra, etc.) and -will encourage teams to be formed to build standalone packages implementing -this functionality. These packages will be referred to as affiliated packages -(meaning that they are intended for future integration in the core package).

        -

        A set of requirements will be set out concerning the interfaces and -classes/methods that affiliated packages will need to make available in order -to ensure consistency between the different components. As the core package -grows, new potential areas/components for the core package will be identified. -Competition cannot be avoided, and will not be actively discouraged, but -whenever possible, developers should strive to work as a team to provide a -single and robust affiliated package, for the benefit of the community.

        -

        The affiliated packages will be developed outside the core package in -independent repositories, which will allow the teams the choice of tool and -organization. Once an affiliated package has implemented the desired -functionality, and satisfies quality criteria for coding style, documentation, -and testing, it will be considered for inclusion in the core package, and -further development will be done directly in the core package either via direct -access to the repository, or via patches/pull requests (exactly how this will -be done will be decided later).

        -

        To ensure uniformity across affiliated packages, and to facilitate integration -with the core package, developers who wish to submit their affiliated packages -for inclusion in the core will need to follow the layout of a ‘template’ -package that will be provided before development starts.

        -
        -
        -

        Dependencies

        -

        Affiliated packages should be able to be imported with only the following -dependencies:

        -
          -
        • The Python Standard Library NumPy, SciPy, and Matplotlib Components already -* in the core Astronomy package
        • -
        -

        Other packages may be used, but must be imported as needed rather than during -the initial import of the package.

        -

        If a dependency is needed, but is an affiliated package, the dependent package -will need to wait until the dependency is integrated into the core package -before being itself considered for inclusion. In the mean time, it can make use -of the other affiliated package in its current form, or other packages, so as -not to stall development. Thus, the first packages to be included in the core -will be those only requiring the standard library, NumPy, SciPy, and -Matplotlib.

        -

        If the required dependency will never be part of a main package, then by -default the dependency can be included but should be imported as needed -(meaning that it only prevents the importing of that component, not the entire -core package), unless a strong case is made and a general consensus is reached -by the community that this dependency is important enough to be required at a -higher level.

        -

        This system means that packages will be integrated into the core package in an -order depending on the dependency tree, and also ensures that the interfaces of -packages being integrated into the core package are consistent with those -already in the core package.

        -

        Initially, no dependency on GUI toolkits will be allowed in the core package. -If the community reaches agrees on a single toolkit that could be used, then -this toolkit will be allowed (but will only be imported as needed).

        -
        -
        -

        Keeping track of affiliated packages

        -

        Affiliated packages will be listed in a central location (in addition to PyPI) -that will allow an easy installation of all the affiliated packages, for -example with a script that will seamlessly download and install all the -affiliated packages. The core package will also include mechanisms to -facilitate this installation process.

        -
        -
        -

        Existing Packages

        -

        Developers who already have existing packages will be encouraged to continue -supporting them for the benefit of users until the core library is considered -stable, contains this functionality, and is released to the community. -Thereafter, developers should encourage users to transition to using the -functionality in the core package, and eventually phase out their own packages, -unless they provide added value over the core package.

        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Documentation for Developers

        -

        Next topic

        -

        Contributing To/Developing Astropy or Affiliated Packages

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/workflow/development_workflow.html b/development/workflow/development_workflow.html deleted file mode 100644 index 97d4610f..00000000 --- a/development/workflow/development_workflow.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - Development workflow — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Development workflow

        -

        This document describes how to contribute to a git repository hosted on -GitHub. The example shown here is that of the core astropy repository, but -the workflow can work equally well for the internal development of an -affiliated package.

        -

        Before following the instructions on this page, make sure you have correctly -installed and configured git:

        - -

        The following documents describe a beginner and advanced workflow for -contributing respectively:

        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        Git resources

        -

        Next topic

        -

        Installing git

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/workflow/development_workflow_advanced.html b/development/workflow/development_workflow_advanced.html deleted file mode 100644 index 55d68db0..00000000 --- a/development/workflow/development_workflow_advanced.html +++ /dev/null @@ -1,609 +0,0 @@ - - - - - - - - - - Development Workflow (Advanced) — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Development Workflow (Advanced)

        -

        In the present document, we refer to the Astropy master branch, as the -trunk.

        -
        -

        Creating a fork

        -

        You need to do this only once for each package you want to contribute to. The -instructions here are very similar to the instructions at -http://help.github.com/fork-a-repo/ — please see that page for more -details. We’re repeating some of it here just to give the specifics for the -Astropy project, and to suggest some default names.

        -
        -

        Set up and configure a GitHub account

        -

        If you don’t have a GitHub account, go to the GitHub page, and make one.

        -

        You then need to configure your account to allow write access — see -the Generating SSH keys help on github help.

        -
        -
        -

        Create your own fork of a repository

        -

        The following example shows how to fork the core astropy repository, but the same applies to other packages:

        -
          -
        1. Log into your GitHub account.

          -
        2. -
        3. Go to the Astropy GitHub home at Astropy github.

          -
        4. -
        5. Click on the fork button:

          -../../_images/forking_button.png -

          Now, after a short pause and some ‘Hardcore forking action’, you -should find yourself at the home page for your own forked copy of Astropy.

          -
        6. -
        -
        -
        -

        Setting up the fork to work on

        -
        -

        Overview

        -

        This is done using:

        -
        git clone git@github.com:your-user-name/astropy.git
        -cd astropy
        -git remote add upstream git://github.com/astropy/astropy.git
        -
        -
        -
        -

        In detail

        -
          -
        1. Clone your fork to the local computer:

          -
          git clone git@github.com:your-user-name/astropy.git
          -
          -
        2. -
        3. Change directory to your new repo:

          -
          cd astropy
          -
          -

          Then type:

          -
          git branch -a
          -
          -

          to show you all branches. You’ll get something like:

          -
          * master
          -remotes/origin/master
          -
          -

          This tells you that you are currently on the master branch, and -that you also have a remote connection to origin/master. -What remote repository is remote/origin? Try git remote -v to -see the URLs for the remote. They will point to your github fork.

          -

          Now you want to connect to the Astropy github repository, so you can -merge in changes from the trunk:

          -
          cd astropy
          -git remote add upstream git://github.com/astropy/astropy.git
          -
          -

          upstream here is just the arbitrary name we’re using to refer to the -main Astropy repository at Astropy github.

          -

          Note that we’ve used git:// for the URL rather than git@. The -git:// URL is read only. This means we that we can’t accidentally (or -deliberately) write to the upstream repo, and we are only going to use it -to merge into our own code.

          -

          Just for your own satisfaction, show yourself that you now have a new -‘remote’, with git remote -v show, giving you something like:

          -
          upstream   git://github.com/astropy/astropy.git (fetch)
          -upstream   git://github.com/astropy/astropy.git (push)
          -origin     git@github.com:your-user-name/astropy.git (fetch)
          -origin     git@github.com:your-user-name/astropy.git (push)
          -
          -

          Your fork is now set up correctly, and you are ready to hack away.

          -
        4. -
        -
        -
        -
        -
        -

        Workflow summary

        -

        This section gives a summary of the workflow once you have successfully forked -the repository, and details are given for each of these steps in the following -sections.

        -
          -
        • Don’t use your master branch for anything. Consider deleting it.
        • -
        • When you are starting a new set of changes, fetch any changes from the -trunk, and start a new feature branch from that.
        • -
        • Make a new branch for each separable set of changes — “one task, one -branch” (ipython git workflow).
        • -
        • Name your branch for the purpose of the changes - e.g. -bugfix-for-issue-14 or refactor-database-code.
        • -
        • If you can possibly avoid it, avoid merging trunk or any other branches into -your feature branch while you are working.
        • -
        • If you do find yourself merging from the trunk, consider Rebasing on trunk
        • -
        • Ask on the Astropy mailing list if you get stuck.
        • -
        • Ask for code review!
        • -
        -

        This way of working helps to keep work well organized, with readable history. -This in turn makes it easier for project maintainers (that might be you) to -see what you’ve done, and why you did it.

        -

        See linux git workflow and ipython git workflow for some explanation.

        -
        -
        -

        Deleting your master branch

        -

        It may sound strange, but deleting your own master branch can help reduce -confusion about which branch you are on. See deleting master on github for -details.

        -
        -
        -

        Updating the mirror of trunk

        -

        From time to time you should fetch the upstream (trunk) changes from github:

        -
        git fetch upstream
        -
        -

        This will pull down any commits you don’t have, and set the remote branches to -point to the right commit. For example, ‘trunk’ is the branch referred to by -(remote/branchname) upstream/master - and if there have been commits since -you last checked, upstream/master will change after you do the fetch.

        -
        -
        -

        Making a new feature branch

        -

        When you are ready to make some changes to the code, you should start a new -branch. Branches that are for a collection of related edits are often called -‘feature branches’.

        -

        Making an new branch for each set of related changes will make it easier for -someone reviewing your branch to see what you are doing.

        -

        Choose an informative name for the branch to remind yourself and the rest of -us what the changes in the branch are for. For example add-ability-to-fly, -or buxfix-for-issue-42.

        -
        # Update the mirror of trunk
        -git fetch upstream
        -
        -# Make new feature branch starting at current trunk
        -git branch my-new-feature upstream/master
        -git checkout my-new-feature
        -
        -

        Generally, you will want to keep your feature branches on your public github -fork of Astropy. To do this, you git push this new branch up to your -github repo. Generally (if you followed the instructions in these pages, and -by default), git will have a link to your GitHub repo, called origin. You -push up to your own repo on GitHub with:

        -
        git push origin my-new-feature
        -
        -

        In git >= 1.7 you can ensure that the link is correctly set by using the ---set-upstream option:

        -
        git push --set-upstream origin my-new-feature
        -
        -

        From now on git will know that my-new-feature is related to the -my-new-feature branch in the GitHub repo.

        -
        -
        -

        The editing workflow

        -
        -

        Overview

        -
        git add my_new_file
        -git commit -am 'NF - some message'
        -git push
        -
        -
        -
        -

        In more detail

        -
          -
        1. Make some changes

          -
        2. -
        3. See which files have changed with git status (see git status). -You’ll see a listing like this one:

          -
          # On branch ny-new-feature
          -# Changed but not updated:
          -#   (use "git add <file>..." to update what will be committed)
          -#   (use "git checkout -- <file>..." to discard changes in working directory)
          -#
          -#  modified:   README
          -#
          -# Untracked files:
          -#   (use "git add <file>..." to include in what will be committed)
          -#
          -#  INSTALL
          -no changes added to commit (use "git add" and/or "git commit -a")
          -
          -
        4. -
        5. Check what the actual changes are with git diff (git diff).

          -
        6. -
        7. Add any new files to version control git add new_file_name (see -git add).

          -
        8. -
        9. To commit all modified files into the local copy of your repo,, do -git commit -am 'A commit message'. Note the -am options to -commit. The m flag just signals that you’re going to type a message -on the command line. The a flag — you can just take on faith -— or see why the -a flag? — and the helpful use-case -description in the tangled working copy problem. The git commit -manual -page might also be useful.

          -
        10. -
        11. To push the changes up to your forked repo on github, do a git -push (see git push).

          -
        12. -
        -
        -
        -
        -

        Asking for your changes to be reviewed or merged

        -

        When you are ready to ask for someone to review your code and consider a merge:

        -
          -
        1. Go to the URL of your forked repo, say -http://github.com/your-user-name/astropy.

          -
        2. -
        3. Use the ‘Switch Branches’ dropdown menu near the top left of the page to -select the branch with your changes:

          -../../_images/branch_dropdown.png -
        4. -
        5. Click on the ‘Pull request’ button:

          -../../_images/pull_button.png -

          Enter a title for the set of changes, and some explanation of what you’ve -done. Say if there is anything you’d like particular attention for - like a -complicated change or some code you are not happy with.

          -

          If you don’t think your request is ready to be merged, just say so in your -pull request message. This is still a good way of getting some preliminary -code review.

          -
        6. -
        -
        -
        -

        Some other things you might want to do

        -
        -

        Delete a branch on github

        -
        # change to the master branch (if you still have one, otherwise change to
        -# another branch)
        -git checkout master
        -
        -# delete branch locally
        -git branch -D my-unwanted-branch
        -
        -# delete branch on github
        -git push origin :my-unwanted-branch
        -
        -

        (Note the colon : before test-branch. See also: -http://github.com/guides/remove-a-remote-branch

        -
        -
        -

        Several people sharing a single repository

        -

        If you want to work on some stuff with other people, where you are all -committing into the same repository, or even the same branch, then just -share it via github.

        -

        First fork Astropy into your account, as from Creating a fork.

        -

        Then, go to your forked repository GitHub page, say -http://github.com/your-user-name/astropy

        -

        Click on the ‘Admin’ button, and add anyone else to the repo as a -collaborator:

        -
        -
        ../../_images/pull_button.png -
        -

        Now all those people can do:

        -
        git clone git@githhub.com:your-user-name/astropy.git
        -
        -

        Remember that links starting with git@ use the ssh protocol and are -read-write; links starting with git:// are read-only.

        -

        Your collaborators can then commit directly into that repo with the -usual:

        -
        git commit -am 'ENH - much better code'
        -git push origin master # pushes directly into your repo
        -
        -
        -
        -

        Explore your repository

        -

        To see a graphical representation of the repository branches and -commits:

        -
        gitk --all
        -
        -
        -

        To see a linear list of commits for this branch:

        -
        git log
        -
        -

        You can also look at the network graph visualizer for your github -repo.

        -

        Finally the Fancy log output lg alias will give you a reasonable -text-based graph of the repository.

        -
        -
        -

        Rebasing on trunk

        -

        Let’s say you thought of some work you’d like to do. You -Updating the mirror of trunk and Making a new feature branch called -cool-feature. At this stage trunk is at some commit, let’s call it E. Now -you make some new commits on your cool-feature branch, let’s call them A, -B, C. Maybe your changes take a while, or you come back to them after a while. -In the meantime, trunk has progressed from commit E to commit (say) G:

        -
              A---B---C cool-feature
        -     /
        -D---E---F---G trunk
        -
        -

        At this stage you consider merging trunk into your feature branch, and you -remember that this here page sternly advises you not to do that, because the -history will get messy. Most of the time you can just ask for a review, and -not worry that trunk has got a little ahead. But sometimes, the changes in -trunk might affect your changes, and you need to harmonize them. In this -situation you may prefer to do a rebase.

        -

        Rebase takes your changes (A, B, C) and replays them as if they had been made -to the current state of trunk. In other words, in this case, it takes the -changes represented by A, B, C and replays them on top of G. After the rebase, -your history will look like this:

        -
                      A'--B'--C' cool-feature
        -             /
        -D---E---F---G trunk
        -
        -

        See rebase without tears for more detail.

        -

        To do a rebase on trunk:

        -
        # Update the mirror of trunk
        -git fetch upstream
        -
        -# Go to the feature branch
        -git checkout cool-feature
        -
        -# Make a backup in case you mess up
        -git branch tmp cool-feature
        -
        -# Rebase cool-feature onto trunk
        -git rebase --onto upstream/master upstream/master cool-feature
        -
        -

        In this situation, where you are already on branch cool-feature, the last -command can be written more succinctly as:

        -
        git rebase upstream/master
        -
        -

        When all looks good you can delete your backup branch:

        -
        git branch -D tmp
        -
        -

        If it doesn’t look good you may need to have a look at -Recovering from mess-ups.

        -

        If you have made changes to files that have also changed in trunk, this may -generate merge conflicts that you need to resolve - see the git rebase man -page for some instructions at the end of the “Description” section. There is -some related help on merging in the git user manual - see resolving a -merge.

        -
        -
        -

        Recovering from mess-ups

        -

        Sometimes, you mess up merges or rebases. Luckily, in git it is relatively -straightforward to recover from such mistakes.

        -

        If you mess up during a rebase:

        -
        git rebase --abort
        -
        -

        If you notice you messed up after the rebase:

        -
        # Reset branch back to the saved point
        -git reset --hard tmp
        -
        -

        If you forgot to make a backup branch:

        -
        # Look at the reflog of the branch
        -git reflog show cool-feature
        -
        -8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately
        -278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d
        -26aa21a cool-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj
        -...
        -
        -# Reset the branch to where it was before the botched rebase
        -git reset --hard cool-feature@{2}
        -
        -
        -
        -

        Rewriting commit history

        -
        -

        Note

        -

        Do this only for your own feature branches.

        -
        -

        There’s an embarrassing typo in a commit you made? Or perhaps the you -made several false starts you would like the posterity not to see.

        -

        This can be done via interactive rebasing.

        -

        Suppose that the commit history looks like this:

        -
        git log --oneline
        -eadc391 Fix some remaining bugs
        -a815645 Modify it so that it works
        -2dec1ac Fix a few bugs + disable
        -13d7934 First implementation
        -6ad92e5 * masked is now an instance of a new object, MaskedConstant
        -29001ed Add pre-nep for a copule of structured_array_extensions.
        -...
        -
        -

        and 6ad92e5 is the last commit in the cool-feature branch. Suppose we -want to make the following changes:

        -
          -
        • Rewrite the commit message for 13d7934 to something more sensible.
        • -
        • Combine the commits 2dec1ac, a815645, eadc391 into a single one.
        • -
        -

        We do as follows:

        -
        # make a backup of the current state
        -git branch tmp HEAD
        -# interactive rebase
        -git rebase -i 6ad92e5
        -
        -

        This will open an editor with the following text in it:

        -
        pick 13d7934 First implementation
        -pick 2dec1ac Fix a few bugs + disable
        -pick a815645 Modify it so that it works
        -pick eadc391 Fix some remaining bugs
        -
        -# Rebase 6ad92e5..eadc391 onto 6ad92e5
        -#
        -# Commands:
        -#  p, pick = use commit
        -#  r, reword = use commit, but edit the commit message
        -#  e, edit = use commit, but stop for amending
        -#  s, squash = use commit, but meld into previous commit
        -#  f, fixup = like "squash", but discard this commit's log message
        -#
        -# If you remove a line here THAT COMMIT WILL BE LOST.
        -# However, if you remove everything, the rebase will be aborted.
        -#
        -
        -

        To achieve what we want, we will make the following changes to it:

        -
        r 13d7934 First implementation
        -pick 2dec1ac Fix a few bugs + disable
        -f a815645 Modify it so that it works
        -f eadc391 Fix some remaining bugs
        -
        -

        This means that (i) we want to edit the commit message for 13d7934, and -(ii) collapse the last three commits into one. Now we save and quit the -editor.

        -

        Git will then immediately bring up an editor for editing the commit message. -After revising it, we get the output:

        -
        [detached HEAD 721fc64] FOO: First implementation
        - 2 files changed, 199 insertions(+), 66 deletions(-)
        -[detached HEAD 0f22701] Fix a few bugs + disable
        - 1 files changed, 79 insertions(+), 61 deletions(-)
        -Successfully rebased and updated refs/heads/my-feature-branch.
        -
        -

        and the history looks now like this:

        -
        0f22701 Fix a few bugs + disable
        -721fc64 ENH: Sophisticated feature
        -6ad92e5 * masked is now an instance of a new object, MaskedConstant
        -
        -

        If it went wrong, recovery is again possible as explained above.

        -
        -
        -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/development/workflow/development_workflow_basic.html b/development/workflow/development_workflow_basic.html deleted file mode 100644 index 776e0dbf..00000000 --- a/development/workflow/development_workflow_basic.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - - - - - Development Workflow (Beginner) — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Development Workflow (Beginner)

        -

        You’ve discovered a bug or something else you want to change -in Astropy — excellent!

        -

        You’ve worked out a way to fix it — even better!

        -

        You want to tell us about it — best of all!

        -

        The easiest way is to make a patch or set of patches. Here we explain how. -Making a patch is the simplest and quickest, but if you’re going to be doing -anything more than simple quick things, please consider following -Development Workflow (Advanced) instead.

        -
        -

        Making patches

        -
        -

        Overview

        -

        If you haven’t already configured git (For the Impatient):

        -
        git config --global user.name "Your Name"
        -git config --global user.email you@yourdomain.example.com
        -
        -

        Then, the workflow is the following:

        -
        # Get the repository if you don't have it
        -git clone git://github.com/astropy/astropy.git
        -
        -# Make a branch for your patching
        -cd astropy
        -git branch the-fix-im-thinking-of
        -git checkout the-fix-im-thinking-of
        -
        -# hack, hack, hack
        -
        -# Tell git about any new files you've made
        -git add somewhere/tests/test_my_bug.py
        -
        -# Commit work in progress as you go
        -git commit -am 'BF - added tests for Funny bug'
        -
        -# hack hack, hack
        -
        -# Commit work
        -git commit -am 'BF - added fix for Funny bug'
        -
        -# Make the patch files
        -git format-patch -M -C master
        -
        -

        Then, send the generated patch files to the Astropy mailing list — -where we will thank you warmly.

        -
        -
        -

        In detail

        -
          -
        1. Tell git who you are so it can label the commits you’ve -made:

          -
          git config --global user.name "Your Name"
          -git config --global user.email you@yourdomain.example.com
          -
          -

          This is only necessary if you haven’t already done this, and you haven’t -followed Configuring git.

          -
        2. -
        3. If you don’t already have one, clone a copy of the -Astropy repository:

          -
          git clone git://github.com/astropy/astropy.git
          -cd astropy
          -
          -
        4. -
        5. Make a ‘feature branch’. This will be where you work on your bug fix. It’s -nice and safe and leaves you with access to an unmodified copy of the code -in the main branch:

          -
          git branch the-fix-im-thinking-of
          -git checkout the-fix-im-thinking-of
          -
          -
        6. -
        7. Do some edits, and commit them as you go:

          -
          # hack, hack, hack
          -
          -# Tell git about any new files you've made
          -git add somewhere/tests/test_my_bug.py
          -
          -# Commit work in progress as you go
          -git commit -am 'BF - added tests for Funny bug'
          -
          -# hack hack, hack
          -
          -# Commit work
          -git commit -am 'BF - added fix for Funny bug'
          -
          -

          Note the -am options to commit. The m flag just -signals that you’re going to type a message on the command -line. The a flag — you can just take on faith — -or see why the -a flag?.

          -
        8. -
        9. When you have finished, check you have committed all your changes:

          -
          git status
          -
          -
        10. -
        11. Finally, make your commits into patches. You want all the commits since you -branched from the master branch:

          -
          git format-patch -M -C master
          -
          -

          You will now have several files named for the commits:

          -
          0001-BF-added-tests-for-Funny-bug.patch
          -0002-BF-added-fix-for-Funny-bug.patch
          -
          -

          Send these files to the Astropy mailing list.

          -
        12. -
        -

        When you are done, to switch back to the main copy of the -code, just return to the master branch:

        -
        git checkout master
        -
        -
        -
        -
        -

        Moving from patching to development

        -

        If you find you have done some patches, and you have one or more feature -branches, you will probably want to switch to a more advanced development -mode. You can do this with the repository you have. See Development Workflow (Advanced) for more details.

        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Configuring git

        -

        Next topic

        -

        Development Workflow (Advanced)

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/workflow/git_configure.html b/development/workflow/git_configure.html deleted file mode 100644 index 0f006b96..00000000 --- a/development/workflow/git_configure.html +++ /dev/null @@ -1,289 +0,0 @@ - - - - - - - - - - Configuring git — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Configuring git

        -
        -

        Bare Minimum

        -

        The only absolutely necessary configuration step is identifying yourself and your contact info:

        -
        git config --global user.name "Your Name"
        -git config --global user.email you@yourdomain.example.com
        -
        -

        Once you’ve done this, you can actually ignore the rest of the document unless you want to customize the behavior of git.

        -
        -
        -

        Overview

        -

        Your personal git configurations are saved in the .gitconfig file in -your home directory.

        -

        Here is an example .gitconfig file:

        -
        [user]
        -        name = Your Name
        -        email = you@yourdomain.example.com
        -
        -[alias]
        -        ci = commit -a
        -        co = checkout
        -        st = status
        -        stat = status
        -        br = branch
        -        wdiff = diff --color-words
        -
        -[core]
        -        editor = vim
        -
        -[merge]
        -        log = true
        -
        -

        You can edit this file directly or you can use the git config --global -command:

        -
        git config --global user.name "Your Name"
        -git config --global user.email you@yourdomain.example.com
        -git config --global alias.ci "commit -a"
        -git config --global alias.co checkout
        -git config --global alias.st "status -a"
        -git config --global alias.stat "status -a"
        -git config --global alias.br branch
        -git config --global alias.wdiff "diff --color-words"
        -git config --global core.editor vim
        -git config --global merge.summary true
        -
        -

        To set up on another computer, you can copy your ~/.gitconfig file, -or run the commands above.

        -
        -
        -

        In detail

        -
        -

        user.name and user.email

        -

        It is good practice to tell git who you are, for labeling any changes -you make to the code. The simplest way to do this is from the command -line:

        -
        git config --global user.name "Your Name"
        -git config --global user.email you@yourdomain.example.com
        -
        -

        This will write the settings into your git configuration file, which -should now contain a user section with your name and email:

        -
        [user]
        -      name = Your Name
        -      email = you@yourdomain.example.com
        -
        -

        Of course you’ll need to replace Your Name and you@yourdomain.example.com -with your actual name and email address.

        -
        -
        -

        Aliases

        -

        You might well benefit from some aliases to common commands.

        -

        For example, you might well want to be able to shorten git checkout -to git co. Or you may want to alias git diff --color-words -(which gives a nicely formatted output of the diff) to git wdiff

        -

        The following git config --global commands:

        -
        git config --global alias.ci "commit -a"
        -git config --global alias.co checkout
        -git config --global alias.st "status -a"
        -git config --global alias.stat "status -a"
        -git config --global alias.br branch
        -git config --global alias.wdiff "diff --color-words"
        -
        -

        will create an alias section in your .gitconfig file with contents -like this:

        -
        [alias]
        -        ci = commit -a
        -        co = checkout
        -        st = status -a
        -        stat = status -a
        -        br = branch
        -        wdiff = diff --color-words
        -
        -
        -
        -

        Editor

        -

        You may also want to make sure that your editor of choice is used

        -
        git config --global core.editor vim
        -
        -
        -
        -

        Merging

        -

        To enforce summaries when doing merges (~/.gitconfig file again):

        -
        [merge]
        -   log = true
        -
        -

        Or from the command line:

        -
        git config --global merge.log true
        -
        -
        -
        -

        Fancy log output

        -

        This is a very nice alias to get a fancy log output; it should go in the -alias section of your .gitconfig file:

        -
        lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative
        -
        -

        You use the alias with:

        -
        git lg
        -
        -

        and it gives graph / text output something like this (but with color!):

        -
        * 6d8e1ee - (HEAD, origin/my-fancy-feature, my-fancy-feature) NF - a fancy file (45 minutes ago) [Matthew Brett]
        -*   d304a73 - (origin/placeholder, placeholder) Merge pull request #48 from hhuuggoo/master (2 weeks ago) [Jonathan Terhorst]
        -|\
        -| * 4aff2a8 - fixed bug 35, and added a test in test_bugfixes (2 weeks ago) [Hugo]
        -|/
        -* a7ff2e5 - Added notes on discussion/proposal made during Data Array Summit. (2 weeks ago) [Corran Webster]
        -* 68f6752 - Initial implimentation of AxisIndexer - uses 'index_by' which needs to be changed to a call on an Axes object - this is all very sketchy right now. (2 weeks ago) [Corr
        -*   376adbd - Merge pull request #46 from terhorst/master (2 weeks ago) [Jonathan Terhorst]
        -|\
        -| * b605216 - updated joshu example to current api (3 weeks ago) [Jonathan Terhorst]
        -| * 2e991e8 - add testing for outer ufunc (3 weeks ago) [Jonathan Terhorst]
        -| * 7beda5a - prevent axis from throwing an exception if testing equality with non-axis object (3 weeks ago) [Jonathan Terhorst]
        -| * 65af65e - convert unit testing code to assertions (3 weeks ago) [Jonathan Terhorst]
        -| *   956fbab - Merge remote-tracking branch 'upstream/master' (3 weeks ago) [Jonathan Terhorst]
        -| |\
        -| |/
        -
        -

        Thanks to Yury V. Zaytsev for posting it.

        -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Installing git

        -

        Next topic

        -

        Development Workflow (Beginner)

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/workflow/git_install.html b/development/workflow/git_install.html deleted file mode 100644 index 1a29172f..00000000 --- a/development/workflow/git_install.html +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - Installing git — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Installing git

        -

        The instructions here are adapted from http://book.git-scm.com/2_installing_git.html

        -
        -

        Debian/Ubuntu

        -
        sudo apt-get install git-core
        -
        -
        -
        -

        Fedora

        -
        sudo yum install git-core
        -
        -
        -
        -

        MacOS X

        -

        There are several ways to install git on Mac. The easiest is to simply download the OS X installer (git-osx-installer). If you have MacPorts installed, you can also do:

        -
        sudo port install git-core
        -
        -

        If you have Fink installed, you can do:

        -
        sudo apt-get install git
        -
        -

        In addition, you may want to use a GUI to manage your git repositories. A good example of a free Mac GUI is GitX. Other (non-free) examples include Tower and SourceTree. GitHub have also recently released GitHub for Mac.

        -
        -
        -

        Windows

        -

        Download and install msysGit

        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Development workflow

        -

        Next topic

        -

        Configuring git

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/workflow/git_resources.html b/development/workflow/git_resources.html deleted file mode 100644 index 6df13578..00000000 --- a/development/workflow/git_resources.html +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - Git resources — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Git resources

        -
        -

        Tutorials and summaries

        - -
        -
        -

        Advanced git workflow

        -

        There are many ways of working with git; here are some posts on the -rules of thumb that other projects have come up with:

        -
          -
        • Linus Torvalds on git management
        • -
        • Linus Torvalds on linux git workflow . Summary; use the git tools -to make the history of your edits as clean as possible; merge from -upstream edits as little as possible in branches where you are doing -active development.
        • -
        -
        -
        -

        Manual pages online

        -

        You can get these on your own machine with (e.g) git help push or -(same thing) git push --help, but, for convenience, here are the -online manual pages for some common commands:

        - -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Configuring git

        -

        Next topic

        -

        Development workflow

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/workflow/index.html b/development/workflow/index.html deleted file mode 100644 index 61104144..00000000 --- a/development/workflow/index.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - Contributing To/Developing Astropy or Affiliated Packages — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Contributing To/Developing Astropy or Affiliated Packages

        -
        -

        Summary

        -

        As described in Vision for a Common Astronomy Python Package, development of components intended for -inclusion in the core astropy package will initially be done by different -teams via affiliated packages. These affiliated packages will then be -submitted for inclusion in the astropy core package by creating a git fork -of the core repository, merging the new component into the fork, and -submitting the package as a pull request. The step of creating a fork and -merging the affiliated package into the fork can be done either by the team -contributing the affiliated package, or by the coordination committee if -requested.

        -

        Once an affiliated package has been accepted and integrated as a component -into the core astropy package, subsequent improvements and bug fixes can -be made in the same way by forking the core repository and submitting a pull -request.

        -

        The bottom line is that teams working on various components are free to choose -the version control system and workflow that they want, but ultimately the -changes need to be merged into a fork of the core repository and submitted via -a pull request to the core repository, either by the team or by the -coordination committee.

        -
        -
        -

        For the Impatient

        -

        The only absolutely necessary configuration step is identifying yourself and your contact info:

        -
        git config --global user.name "Your Name"
        -git config --global user.email you@yourdomain.example.com
        -
        -

        More detailed information and instructions are below.

        -

        After that, if you then just want to get the latest astropy source code, cd to a directory on your computer you want to put the source code, and do:

        -
        git clone git@github.com:astropy/astropy.git
        -
        -

        You will then have a new copy of the source code in the astropy directory.

        -

        Later, if you want to update to the most recent version of the astropy code, just go do:

        -
        cd astropy
        -git pull
        -
        -

        If you find a bug and want to fix it, see Development Workflow (Beginner) or Development Workflow (Advanced) depending on how comfortable you are with git.

        -
        -
        -

        Git Documentation

        -

        The following sections cover the installation of the git software, the basic configuration, and links to resources to learn more about using git. However, you can also directly go to the GitHub help pages which offer a great introduction to git and GitHub.

        - -
        -
        -

        Workflow

        -

        The following two sections describe the workflow for the astropy core -package, but teams working on affiliated packages that have chosen to use git -are encouraged to also follow these guidelines internally.

        - -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Vision for a Common Astronomy Python Package

        -

        Next topic

        -

        Installing git

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/development/workflow/maintainer_workflow.html b/development/workflow/maintainer_workflow.html deleted file mode 100644 index c2ea3581..00000000 --- a/development/workflow/maintainer_workflow.html +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - - - - - Maintainer workflow — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Maintainer workflow

        -

        This page is for maintainers — those of us who merge our own or other -peoples’ changes into the upstream repository.

        -

        Being as how you’re a maintainer, you are completely on top of the basic stuff -in Development workflow.

        - -
        -

        Integrating changes manually

        -

        First, check out the astropy repository. The instructions in Overview add a remote that has read-only -access to the upstream repo. Being a maintainer, you’ve got read-write access.

        -

        It’s good to have your upstream remote have a scary name, to remind you that -it’s a read-write remote:

        -
        git remote add upstream-rw git@github.com:astropy/astropy.git
        -git fetch upstream-rw
        -
        -

        Let’s say you have some changes that need to go into trunk -(upstream-rw/master).

        -

        The changes are in some branch that you are currently on. For example, you are -looking at someone’s changes like this:

        -
        git remote add someone git://github.com/someone/astropy.git
        -git fetch someone
        -git branch cool-feature --track someone/cool-feature
        -git checkout cool-feature
        -
        -

        So now you are on the branch with the changes to be incorporated upstream. The -rest of this section assumes you are on this branch.

        -
        -

        A few commits

        -

        If there are only a few commits, consider rebasing to upstream:

        -
        # Fetch upstream changes
        -git fetch upstream-rw
        -
        -# Rebase
        -git rebase upstream-rw/master
        -
        -

        Remember that, if you do a rebase, and push that, you’ll have to close any -github pull requests manually, because github will not be able to detect the -changes have already been merged.

        -
        -
        -

        A long series of commits

        -

        If there are a longer series of related commits, consider a merge instead:

        -
        git fetch upstream-rw
        -git merge --no-ff upstream-rw/master
        -
        -

        The merge will be detected by github, and should close any related pull -requests automatically.

        -

        Note the --no-ff above. This forces git to make a merge commit, rather -than doing a fast-forward, so that these set of commits branch off trunk then -rejoin the main history with a merge, rather than appearing to have been made -directly on top of trunk.

        -
        -
        -

        Check the history

        -

        Now, in either case, you should check that the history is sensible and you -have the right commits:

        -
        git log --oneline --graph
        -git log -p upstream-rw/master..
        -
        -

        The first line above just shows the history in a compact way, with a text -representation of the history graph. The second line shows the log of commits -excluding those that can be reached from trunk (upstream-rw/master), and -including those that can be reached from current HEAD (implied with the .. -at the end). So, it shows the commits unique to this branch compared to trunk. -The -p option shows the diff for these commits in patch form.

        -
        -
        -

        Push to trunk

        -
        git push upstream-rw my-new-feature:master
        -
        -

        This pushes the my-new-feature branch in this repository to the master -branch in the upstream-rw repository.

        -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Development Workflow (Advanced)

        -

        Next topic

        -

        Coding Guidelines (Draft)

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/genindex.html b/genindex.html index 427293ed..ec26404c 100644 --- a/genindex.html +++ b/genindex.html @@ -2,23 +2,25 @@ - + + - Index — Astropy 0.0.dev664 documentation + Index — Astropy - + + + - - + + + + + + + + + + + + + + + + + + + + - - -
        -
        -
        -
        + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        +

        Index

        - _ - | A - | B - | C - | D - | E - | F - | G - | H - | I - | K - | L - | M - | N - | O - | P - | R - | S - | T - | U - | V - | W - | X - | Z
        -

        _

        - - - -
        - -
        __dict__ (astropy.utils.collections.HomogeneousList attribute) -
        - - -
        __enter__() (astropy.utils.console.ProgressBar method) -
        - -
        - -
        (astropy.utils.console.ProgressBarOrSpinner method) -
        - - -
        (astropy.utils.console.Spinner method) -
        - -
        - -
        __exit__() (astropy.utils.console.ProgressBar method) -
        - -
        - -
        (astropy.utils.console.ProgressBarOrSpinner method) -
        - - -
        (astropy.utils.console.Spinner method) -
        - -
        - -
        __iadd__() (astropy.utils.collections.HomogeneousList method) -
        - -
        - -
        __init__() (astropy.utils.collections.HomogeneousList method) -
        - -
        - -
        (astropy.utils.console.ProgressBar method) -
        - - -
        (astropy.utils.console.ProgressBarOrSpinner method) -
        - - -
        (astropy.utils.console.Spinner method) -
        - - -
        (astropy.utils.xml.writer.XMLWriter method) -
        - -
        - -
        __module__ (astropy.utils.collections.HomogeneousList attribute) -
        - -
        - -
        (astropy.utils.console.ProgressBar attribute) -
        - - -
        (astropy.utils.console.ProgressBarOrSpinner attribute) -
        - - -
        (astropy.utils.console.Spinner attribute) -
        - - -
        (astropy.utils.xml.writer.XMLWriter attribute) -
        - -
        - -
        __setitem__() (astropy.utils.collections.HomogeneousList method) -
        - - -
        __weakref__ (astropy.utils.collections.HomogeneousList attribute) -
        - -
        - -

        A

        - - - -
        - -
        a (astropy.wcs.Sip attribute) -
        - - -
        a_order (astropy.wcs.Sip attribute) -
        - - -
        all_pix2sky() (astropy.wcs.WCS method) -
        - - -
        alt (astropy.wcs.Wcsprm attribute) -
        - - -
        ap (astropy.wcs.Sip attribute) -
        - - -
        ap_order (astropy.wcs.Sip attribute) -
        - - -
        append() (astropy.utils.collections.HomogeneousList method) -
        - - -
        arraysize (astropy.io.vo.tree.Field attribute) -
        - - -
        astropy.config.configs (module) -
        - - -
        astropy.config.data (module) -
        - - -
        astropy.config.paths (module) -
        - - -
        astropy.io.vo.converters (module) -
        - - -
        astropy.io.vo.exceptions (module) -
        - - -
        astropy.io.vo.table (module) -
        - - -
        astropy.io.vo.tree (module) -
        - - -
        astropy.io.vo.ucd (module) -
        - -
        - -
        astropy.io.vo.unit (module) -
        - - -
        astropy.io.vo.util (module) -
        - - -
        astropy.io.vo.validator (module) -
        - - -
        astropy.io.vo.xmlutil (module) -
        - - -
        astropy.tools.misc (module) -
        - - -
        astropy.utils.collections (module) -
        - - -
        astropy.utils.console (module) -
        - - -
        astropy.utils.misc (module) -
        - - -
        astropy.utils.xml.check (module) -
        - - -
        astropy.utils.xml.iterparser (module) -
        - - -
        astropy.utils.xml.validate (module) -
        - - -
        astropy.utils.xml.writer (module) -
        - - -
        astropy.wcs (module) -
        - - -
        astropy.wcs.wcs (module) -
        - - -
        axis_types (astropy.wcs.Wcsprm attribute) -
        - -
        - -

        B

        - - - -
        - -
        b (astropy.wcs.Sip attribute) -
        - - -
        b_order (astropy.wcs.Sip attribute) -
        - -
        - -
        bp (astropy.wcs.Sip attribute) -
        - - -
        bp_order (astropy.wcs.Sip attribute) -
        - -
        - -

        C

        - - - -
        - -
        calcFootprint() (astropy.wcs.WCS method) -
        - - -
        cd (astropy.wcs.Wcsprm attribute) -
        - - -
        cdelt (astropy.wcs.DistortionLookupTable attribute) -
        - -
        - -
        (astropy.wcs.Wcsprm attribute) -
        - -
        - -
        cdfix() (astropy.wcs.Wcsprm method) -
        - - -
        cel_offset (astropy.wcs.Wcsprm attribute) -
        - - -
        celfix() (astropy.wcs.Wcsprm method) -
        - - -
        check_anyuri() (in module astropy.io.vo.xmlutil) -
        - -
        - -
        (in module astropy.utils.xml.check) -
        - -
        - -
        check_id() (in module astropy.io.vo.xmlutil) -
        - -
        - -
        (in module astropy.utils.xml.check) -
        - -
        - -
        check_mime_content_type() (in module astropy.io.vo.xmlutil) -
        - -
        - -
        (in module astropy.utils.xml.check) -
        - -
        - -
        check_token() (in module astropy.io.vo.xmlutil) -
        - -
        - -
        (in module astropy.utils.xml.check) -
        - -
        - -
        check_ucd() (in module astropy.io.vo.ucd) -
        - - -
        check_unit() (in module astropy.io.vo.unit) -
        - - -
        clear_data_cache() (in module astropy.config.data) -
        - - -
        close() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        cname (astropy.wcs.Wcsprm attribute) -
        - - -
        coerce_range_list_param() (in module astropy.io.vo.util) -
        - - -
        colax (astropy.wcs.Wcsprm attribute) -
        - - -
        colnum (astropy.wcs.Wcsprm attribute) -
        - - -
        color_print() (in module astropy.utils.console) -
        - - -
        comment() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        compute_hash() (in module astropy.config.data) -
        - - -
        ConfigurationItem (class in astropy.config.configs) -
        - -
        - -
        content (astropy.io.vo.tree.Info attribute) -
        - -
        - -
        (astropy.io.vo.tree.SimpleElementWithContent attribute) -
        - -
        - -
        content_role (astropy.io.vo.tree.Link attribute) -
        - - -
        content_type (astropy.io.vo.tree.Link attribute) -
        - - -
        convert() (astropy.wcs.UnitConverter method) -
        - - -
        convert_to_writable_filelike() (in module astropy.io.vo.util) -
        - - -
        coord (astropy.wcs._wcs.Tabprm attribute) -
        - - -
        coordinate_systems (astropy.io.vo.tree.Resource attribute) -
        - -
        - -
        (astropy.io.vo.tree.VOTableFile attribute) -
        - -
        - -
        CooSys (class in astropy.io.vo.tree) -
        - - -
        copy() (astropy.wcs.WCS method) -
        - - -
        cpdis1 (astropy.wcs.WCS attribute) -
        - - -
        cpdis2 (astropy.wcs.WCS attribute) -
        - - -
        crder (astropy.wcs.Wcsprm attribute) -
        - - -
        create_arrays() (astropy.io.vo.tree.Table method) -
        - - -
        crota (astropy.wcs.Wcsprm attribute) -
        - - -
        crpix (astropy.wcs.DistortionLookupTable attribute) -
        - -
        - -
        (astropy.wcs.Sip attribute) -
        - - -
        (astropy.wcs.Wcsprm attribute) -
        - -
        - -
        crval (astropy.wcs._wcs.Tabprm attribute) -
        - -
        - -
        (astropy.wcs.DistortionLookupTable attribute) -
        - - -
        (astropy.wcs.Wcsprm attribute) -
        - -
        - -
        csyer (astropy.wcs.Wcsprm attribute) -
        - - -
        ctype (astropy.wcs.Wcsprm attribute) -
        - - -
        cubeface (astropy.wcs.Wcsprm attribute) -
        - - -
        cunit (astropy.wcs.Wcsprm attribute) -
        - - -
        cylfix() (astropy.wcs.Wcsprm method) -
        - -
        - -

        D

        - - - -
        - -
        data (astropy.wcs.DistortionLookupTable attribute) -
        - - -
        data() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        datatype (astropy.io.vo.tree.Field attribute) -
        - - -
        dateavg (astropy.wcs.Wcsprm attribute) -
        - - -
        dateobs (astropy.wcs.Wcsprm attribute) -
        - - -
        datfix() (astropy.wcs.Wcsprm method) -
        - -
        - -
        deepcopy() (astropy.wcs.WCS method) -
        - - -
        delta (astropy.wcs._wcs.Tabprm attribute) -
        - - -
        det2im() (astropy.wcs.WCS method) -
        - - -
        det2im1 (astropy.wcs.WCS attribute) -
        - - -
        det2im2 (astropy.wcs.WCS attribute) -
        - - -
        DistortionLookupTable (class in astropy.wcs) -
        - -
        - -

        E

        - - - -
        - -
        Element (class in astropy.io.vo.tree) -
        - - -
        element() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        end() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        entries (astropy.io.vo.tree.Group attribute) -
        - - -
        epoch (astropy.io.vo.tree.CooSys attribute) -
        - -
        - -
        equinox (astropy.io.vo.tree.CooSys attribute) -
        - -
        - -
        (astropy.wcs.Wcsprm attribute) -
        - -
        - -
        extend() (astropy.utils.collections.HomogeneousList method) -
        - - -
        extra_attributes (astropy.io.vo.tree.Resource attribute) -
        - - -
        extrema (astropy.wcs._wcs.Tabprm attribute) -
        - -
        - -

        F

        - - - -
        - -
        Field (class in astropy.io.vo.tree) -
        - - -
        FieldRef (class in astropy.io.vo.tree) -
        - - -
        fields (astropy.io.vo.tree.Table attribute) -
        - - -
        find_all_wcs() (in module astropy.wcs) -
        - - -
        find_current_module() (in module astropy.utils.misc) -
        - - -
        fix() (astropy.wcs.Wcsprm method) -
        - - -
        fix_id() (in module astropy.io.vo.xmlutil) -
        - -
        - -
        (in module astropy.utils.xml.check) -
        - -
        -
        - -
        flush() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        fnpickle() (in module astropy.utils.misc) -
        - - -
        fnunpickle() (in module astropy.utils.misc) -
        - - -
        foc2pix() (astropy.wcs.Sip method) -
        - - -
        footprint_to_file() (astropy.wcs.WCS method) -
        - - -
        format (astropy.io.vo.tree.Table attribute) -
        - -
        - -

        G

        - - - -
        - -
        get_axis_types() (astropy.wcs.WCS method) -
        - - -
        get_cache_dir() (in module astropy.config.paths) -
        - - -
        get_cdelt() (astropy.wcs.Wcsprm method) -
        - - -
        get_config() (in module astropy.config.configs) -
        - - -
        get_config_dir() (in module astropy.config.paths) -
        - - -
        get_converter() (in module astropy.io.vo.converters) -
        - - -
        get_coosys_by_id() (astropy.io.vo.tree.VOTableFile method) -
        - - -
        get_data_contents() (in module astropy.config.data) -
        - - -
        get_data_filename() (in module astropy.config.data) -
        - - -
        get_data_filenames() (in module astropy.config.data) -
        - - -
        get_data_fileobj() (in module astropy.config.data) -
        - - -
        get_data_fileobjs() (in module astropy.config.data) -
        - - -
        get_field_by_id() (astropy.io.vo.tree.Table method) -
        - -
        - -
        (astropy.io.vo.tree.VOTableFile method) -
        - -
        - -
        get_field_by_id_or_name() (astropy.io.vo.tree.Table method) -
        - -
        - -
        (astropy.io.vo.tree.VOTableFile method) -
        - -
        - -
        get_first_table() (astropy.io.vo.tree.VOTableFile method) -
        - - -
        get_group_by_id() (astropy.io.vo.tree.Table method) -
        - -
        - -
        (astropy.io.vo.tree.VOTableFile method) -
        - -
        -
        - -
        get_indentation() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        get_indentation_spaces() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        get_naxis() (astropy.wcs.WCS method) -
        - - -
        get_offset() (astropy.wcs.DistortionLookupTable method) -
        - - -
        get_pc() (astropy.wcs.Wcsprm method) -
        - - -
        get_ps() (astropy.wcs.Wcsprm method) -
        - - -
        get_pv() (astropy.wcs.Wcsprm method) -
        - - -
        get_ref() (astropy.io.vo.tree.FieldRef method) -
        - -
        - -
        (astropy.io.vo.tree.ParamRef method) -
        - -
        - -
        get_table_by_id() (astropy.io.vo.tree.VOTableFile method) -
        - - -
        get_table_by_index() (astropy.io.vo.tree.VOTableFile method) -
        - - -
        get_values_by_id() (astropy.io.vo.tree.VOTableFile method) -
        - - -
        get_xml_encoding() (in module astropy.utils.xml.iterparser) -
        - - -
        get_xml_iterator() (in module astropy.utils.xml.iterparser) -
        - - -
        Group (class in astropy.io.vo.tree) -
        - - -
        groups (astropy.io.vo.tree.Table attribute) -
        - -
        - -
        (astropy.io.vo.tree.VOTableFile attribute) -
        - -
        -
        - -

        H

        - - - -
        - -
        has_cd() (astropy.wcs.Wcsprm method) -
        - - -
        has_cdi_ja() (astropy.wcs.Wcsprm method) -
        - - -
        has_crota() (astropy.wcs.Wcsprm method) -
        - - -
        has_crotaia() (astropy.wcs.Wcsprm method) -
        - - -
        has_pc() (astropy.wcs.Wcsprm method) -
        - -
        - -
        has_pci_ja() (astropy.wcs.Wcsprm method) -
        - - -
        have (astropy.wcs.UnitConverter attribute) -
        - - -
        HomogeneousList (class in astropy.utils.collections) -
        - - -
        href (astropy.io.vo.tree.Link attribute) -
        - - -
        human_time() (in module astropy.utils.console) -
        - -
        - -

        I

        - - - -
        - -
        ID (astropy.io.vo.tree.CooSys attribute) -
        - - -
        imgpix_matrix (astropy.wcs.Wcsprm attribute) -
        - - -
        Info (class in astropy.io.vo.tree) -
        - - -
        infos (astropy.io.vo.tree.Resource attribute) -
        - -
        - -
        (astropy.io.vo.tree.Table attribute) -
        - - -
        (astropy.io.vo.tree.VOTableFile attribute) -
        - -
        - -
        insert() (astropy.utils.collections.HomogeneousList method) -
        - - -
        InvalidConfigurationItemWarning -
        - -
        IOWarning (class in astropy.io.vo.exceptions) -
        - -
        is_callable() (in module astropy.io.vo.util) -
        - - -
        is_defaults() (astropy.io.vo.tree.Values method) -
        - - -
        is_empty() (astropy.io.vo.tree.Table method) -
        - -
        - -
        is_unit() (in module astropy.io.vo.unit) -
        - - -
        is_unity() (astropy.wcs.Wcsprm method) -
        - - -
        isatty() (in module astropy.utils.console) -
        - - -
        iter_coosys() (astropy.io.vo.tree.Resource method) -
        - -
        - -
        (astropy.io.vo.tree.VOTableFile method) -
        - -
        - -
        iter_fields_and_params() (astropy.io.vo.tree.Group method) -
        - -
        - -
        (astropy.io.vo.tree.Resource method) -
        - - -
        (astropy.io.vo.tree.Table method) -
        - - -
        (astropy.io.vo.tree.VOTableFile method) -
        - -
        - -
        iter_groups() (astropy.io.vo.tree.Group method) -
        - -
        - -
        (astropy.io.vo.tree.Table method) -
        - - -
        (astropy.io.vo.tree.VOTableFile method) -
        - -
        - -
        iter_tables() (astropy.io.vo.tree.Resource method) -
        - -
        - -
        (astropy.io.vo.tree.VOTableFile method) -
        - -
        - -
        iter_values() (astropy.io.vo.tree.VOTableFile method) -
        - - -
        iterate() (astropy.utils.console.ProgressBar class method) -
        - -
        - -

        K

        - - -
        - -
        K (astropy.wcs._wcs.Tabprm attribute) -
        - -
        - -

        L

        - - - -
        - -
        lat (astropy.wcs.Wcsprm attribute) -
        - - -
        latpole (astropy.wcs.Wcsprm attribute) -
        - - -
        lattyp (astropy.wcs.Wcsprm attribute) -
        - - -
        Link (class in astropy.io.vo.tree) -
        - -
        - -
        links (astropy.io.vo.tree.Field attribute) -
        - -
        - -
        (astropy.io.vo.tree.Resource attribute) -
        - - -
        (astropy.io.vo.tree.Table attribute) -
        - -
        - -
        lng (astropy.wcs.Wcsprm attribute) -
        - - -
        lngtyp (astropy.wcs.Wcsprm attribute) -
        - - -
        lonpole (astropy.wcs.Wcsprm attribute) -
        - -
        - -

        M

        - - - -
        - -
        M (astropy.wcs._wcs.Tabprm attribute) -
        - - -
        make_validation_report() (in module astropy.io.vo.validator.main) -
        - - -
        map (astropy.wcs._wcs.Tabprm attribute) -
        - - -
        map() (astropy.utils.console.ProgressBar class method) -
        - - -
        max (astropy.io.vo.tree.Values attribute) -
        - - -
        max_inclusive (astropy.io.vo.tree.Values attribute) -
        - -
        - -
        min (astropy.io.vo.tree.Values attribute) -
        - - -
        min_inclusive (astropy.io.vo.tree.Values attribute) -
        - - -
        mix() (astropy.wcs.Wcsprm method) -
        - - -
        mjdavg (astropy.wcs.Wcsprm attribute) -
        - - -
        mjdobs (astropy.wcs.Wcsprm attribute) -
        - -
        - -

        N

        - - - -
        - -
        name (astropy.io.vo.tree.Info attribute) -
        - -
        - -
        (astropy.wcs.Wcsprm attribute) -
        - -
        - -
        naxis (astropy.wcs.Wcsprm attribute) -
        - - -
        nc (astropy.wcs._wcs.Tabprm attribute) -
        - -
        - -
        nrows (astropy.io.vo.tree.Table attribute) -
        - - -
        null (astropy.io.vo.tree.Values attribute) -
        - -
        - -

        O

        - - - -
        - -
        object_attrs() (astropy.utils.xml.writer.XMLWriter static method) -
        - - -
        obsgeo (astropy.wcs.Wcsprm attribute) -
        - -
        - -
        offset (astropy.wcs.UnitConverter attribute) -
        - - -
        options (astropy.io.vo.tree.Values attribute) -
        - -
        - -

        P

        - - - -
        - -
        p0 (astropy.wcs._wcs.Tabprm attribute) -
        - - -
        p2s() (astropy.wcs.Wcsprm method) -
        - - -
        p4_pix2foc() (astropy.wcs.WCS method) -
        - - -
        Param (class in astropy.io.vo.tree) -
        - - -
        ParamRef (class in astropy.io.vo.tree) -
        - - -
        params (astropy.io.vo.tree.Resource attribute) -
        - -
        - -
        (astropy.io.vo.tree.Table attribute) -
        - - -
        (astropy.io.vo.tree.VOTableFile attribute) -
        - -
        - -
        parse() (astropy.io.vo.tree.Field method) -
        - -
        - -
        (astropy.io.vo.tree.Group method) -
        - - -
        (astropy.io.vo.tree.Resource method) -
        - - -
        (astropy.io.vo.tree.SimpleElement method) -
        - - -
        (astropy.io.vo.tree.Table method) -
        - - -
        (astropy.io.vo.tree.VOTableFile method) -
        - - -
        (astropy.io.vo.tree.Values method) -
        - - -
        (in module astropy.io.vo.table) -
        - -
        - -
        parse_single_table() (in module astropy.io.vo.table) -
        - - -
        parse_ucd() (in module astropy.io.vo.ucd) -
        - - -
        parse_vowarning() (in module astropy.io.vo.exceptions) -
        - - -
        pc (astropy.wcs.Wcsprm attribute) -
        - -
        - -
        phi0 (astropy.wcs.Wcsprm attribute) -
        - - -
        pix2foc() (astropy.wcs.Sip method) -
        - -
        - -
        (astropy.wcs.WCS method) -
        - -
        - -
        piximg_matrix (astropy.wcs.Wcsprm attribute) -
        - - -
        power (astropy.wcs.UnitConverter attribute) -
        - - -
        precision (astropy.io.vo.tree.Field attribute) -
        - - -
        print_code_line() (in module astropy.utils.console) -
        - - -
        print_contents() (astropy.wcs._wcs.Tabprm method) -
        - -
        - -
        (astropy.wcs.Wcsprm method) -
        - -
        - -
        printwcs() (astropy.wcs.WCS method) -
        - - -
        ProgressBar (class in astropy.utils.console) -
        - - -
        ProgressBarOrSpinner (class in astropy.utils.console) -
        - -
        - -

        R

        - - - -
        - -
        radesys (astropy.wcs.Wcsprm attribute) -
        - - -
        ref (astropy.io.vo.tree.Field attribute) -
        - -
        - -
        (astropy.io.vo.tree.FieldRef attribute) -
        - - -
        (astropy.io.vo.tree.Group attribute) -
        - - -
        (astropy.io.vo.tree.Info attribute) -
        - - -
        (astropy.io.vo.tree.ParamRef attribute) -
        - - -
        (astropy.io.vo.tree.Table attribute) -
        - - -
        (astropy.io.vo.tree.Values attribute) -
        - -
        - -
        reload() (astropy.config.configs.ConfigurationItem method) -
        - - -
        reload_config() (in module astropy.config.configs) -
        - - -
        Resource (class in astropy.io.vo.tree) -
        - -
        - -
        resources (astropy.io.vo.tree.Resource attribute) -
        - -
        - -
        (astropy.io.vo.tree.VOTableFile attribute) -
        - -
        - -
        restfrq (astropy.wcs.Wcsprm attribute) -
        - - -
        restwav (astropy.wcs.Wcsprm attribute) -
        - - -
        rotateCD() (astropy.wcs.WCS method) -
        - -
        - -

        S

        - - - -
        - -
        s2p() (astropy.wcs.Wcsprm method) -
        - - -
        save() (astropy.config.configs.ConfigurationItem method) -
        - - -
        save_config() (in module astropy.config.configs) -
        - - -
        scale (astropy.wcs.UnitConverter attribute) -
        - - -
        sense (astropy.wcs._wcs.Tabprm attribute) -
        - - -
        set() (astropy.config.configs.ConfigurationItem method) -
        - -
        - -
        (astropy.wcs.Wcsprm method) -
        - - -
        (astropy.wcs._wcs.Tabprm method) -
        - -
        - -
        set_all_tables_format() (astropy.io.vo.tree.VOTableFile method) -
        - - -
        set_ps() (astropy.wcs.Wcsprm method) -
        - - -
        set_pv() (astropy.wcs.Wcsprm method) -
        - - -
        sigma_clip() (in module astropy.tools.misc) -
        - - -
        SimpleElement (class in astropy.io.vo.tree) -
        - - -
        SimpleElementWithContent (class in astropy.io.vo.tree) -
        - - -
        sip (astropy.wcs.WCS attribute) -
        - -
        - -
        Sip (class in astropy.wcs) -
        - - -
        sip_foc2pix() (astropy.wcs.WCS method) -
        - - -
        sip_pix2foc() (astropy.wcs.WCS method) -
        - - -
        spcfix() (astropy.wcs.Wcsprm method) -
        - - -
        spec (astropy.wcs.Wcsprm attribute) -
        - - -
        specsys (astropy.wcs.Wcsprm attribute) -
        - - -
        Spinner (class in astropy.utils.console) -
        - - -
        sptr() (astropy.wcs.Wcsprm method) -
        - - -
        ssysobs (astropy.wcs.Wcsprm attribute) -
        - - -
        ssyssrc (astropy.wcs.Wcsprm attribute) -
        - - -
        start() (astropy.utils.xml.writer.XMLWriter method) -
        - - -
        sub() (astropy.wcs.WCS method) -
        - -
        - -
        (astropy.wcs.Wcsprm method) -
        - -
        - -
        system (astropy.io.vo.tree.CooSys attribute) -
        - -
        - -

        T

        - - - -
        - -
        tab (astropy.wcs.Wcsprm attribute) -
        - - -
        Table (class in astropy.io.vo.tree) -
        - - -
        tables (astropy.io.vo.tree.Resource attribute) -
        - - -
        Tabprm (class in astropy.wcs._wcs) -
        - - -
        tag() (astropy.utils.xml.writer.XMLWriter method) -
        - -
        - -
        theta0 (astropy.wcs.Wcsprm attribute) -
        - - -
        to_header() (astropy.wcs.WCS method) -
        - -
        - -
        (astropy.wcs.Wcsprm method) -
        - -
        - -
        to_header_string() (astropy.wcs.WCS method) -
        - - -
        to_xml() (astropy.io.vo.tree.Field method) -
        - -
        - -
        (astropy.io.vo.tree.Group method) -
        - - -
        (astropy.io.vo.tree.Param method) -
        - - -
        (astropy.io.vo.tree.Resource method) -
        - - -
        (astropy.io.vo.tree.SimpleElement method) -
        - - -
        (astropy.io.vo.tree.SimpleElementWithContent method) -
        - - -
        (astropy.io.vo.tree.Table method) -
        - - -
        (astropy.io.vo.tree.VOTableFile method) -
        - - -
        (astropy.io.vo.tree.Values method) -
        - -
        - -
        type (astropy.io.vo.tree.Field attribute) -
        - -
        - -
        (astropy.io.vo.tree.Resource attribute) -
        - - -
        (astropy.io.vo.tree.Values attribute) -
        - -
        -
        - -

        U

        - - - -
        - -
        UnimplementedWarning (class in astropy.io.vo.exceptions) -
        - - -
        uniqify_names() (astropy.io.vo.tree.Field class method) -
        - - -
        unit (astropy.io.vo.tree.Field attribute) -
        - -
        - -
        (astropy.io.vo.tree.Info attribute) -
        - -
        -
        - -
        UnitConverter (class in astropy.wcs) -
        - - -
        unitfix() (astropy.wcs.Wcsprm method) -
        - - -
        update() (astropy.utils.console.ProgressBar method) -
        - -
        - -
        (astropy.utils.console.ProgressBarOrSpinner method) -
        - -
        -
        - -

        V

        - - - -
        - -
        validate() (in module astropy.io.vo.table) -
        - - -
        validate_schema() (in module astropy.io.vo.xmlutil) -
        - -
        - -
        (in module astropy.utils.xml.validate) -
        - -
        - -
        value (astropy.io.vo.tree.Info attribute) -
        - -
        - -
        (astropy.io.vo.tree.Param attribute) -
        - -
        - -
        values (astropy.io.vo.tree.Field attribute) -
        - - -
        Values (class in astropy.io.vo.tree) -
        - - -
        velangl (astropy.wcs.Wcsprm attribute) -
        - - -
        velosys (astropy.wcs.Wcsprm attribute) -
        - - -
        version (astropy.io.vo.tree.VOTableFile attribute) -
        - -
        - -
        vo_raise() (in module astropy.io.vo.exceptions) -
        - - -
        vo_reraise() (in module astropy.io.vo.exceptions) -
        - - -
        vo_warn() (in module astropy.io.vo.exceptions) -
        - - -
        VOTableChangeWarning (class in astropy.io.vo.exceptions) -
        - - -
        VOTableFile (class in astropy.io.vo.tree) -
        - - -
        VOTableSpecError (class in astropy.io.vo.exceptions) -
        - - -
        VOTableSpecWarning (class in astropy.io.vo.exceptions) -
        - - -
        VOWarning (class in astropy.io.vo.exceptions) -
        - -
        - -

        W

        - - - -
        - -
        want (astropy.wcs.UnitConverter attribute) -
        - - -
        warn_or_raise() (in module astropy.io.vo.exceptions) -
        - - -
        wcs (astropy.wcs.WCS attribute) -
        - - -
        WCS (class in astropy.wcs) -
        - -
        - -
        wcs_pix2sky() (astropy.wcs.WCS method) -
        - - -
        wcs_sky2pix() (astropy.wcs.WCS method) -
        - - -
        Wcsprm (class in astropy.wcs) -
        - - -
        width (astropy.io.vo.tree.Field attribute) -
        - -
        - -

        X

        - - - -
        - -
        xml_escape() (in module astropy.utils.xml.writer) -
        - - -
        xml_escape_cdata() (in module astropy.utils.xml.writer) -
        - -
        - -
        xml_readlines() (in module astropy.utils.xml.iterparser) -
        - - -
        XMLWriter (class in astropy.utils.xml.writer) -
        - -
        - -

        Z

        - - -
        - -
        zsource (astropy.wcs.Wcsprm attribute) -
        - -
        - - - -
        -
        -
        -
        -
        - - - - - - -
        -
        -
        -
        - - +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +
        +
        \ No newline at end of file diff --git a/index.html b/index.html index 7ead97a2..e4c763f6 100644 --- a/index.html +++ b/index.html @@ -1,22 +1,24 @@ - + + - Welcome to Astropy’s Documentation! — Astropy 0.0.dev664 documentation + Welcome — Astropy - + + + - - - + + + + + + + + + + + + + + + + + + + + - - -
        -
        -
        -
        + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        + +
        _images/astropy_banner_96.png +
        +

        What is Astropy?

        +

        The Astropy project is a common effort to develop a single core package for +Astronomy that brings together almost 100 developers from around the world.

        +

        Development is actively ongoing, with major packages such as PyFITS, +PyWCS, vo, and asciitable already merged in, and many more components +being worked on. In particular, we are developing imaging, photometric, and +spectroscopic functionality, as well as frameworks for cosmology, unit +handling, and coordinate transformations. A first stable release is +tentatively scheduled for early May.

        +

        Stay updated by following @astropy on Twitter, or sign up to the astropy mailing list!

        +

        If you are interested in finding out more about the Astropy project, you can read the original vision for the package.

        +
        +
        +

        Documentation

        +

        The documentation for the latest development version of Astropy can be found +at http://astropy.readthedocs.org. This +documentation is automatically updated any time a commit is made to the +Astropy repository. Once a stable version of Astropy is released, we will +provide links to the documentation for that version.

        +
        +
        +

        Installing

        +

        Detailed installation instructions are provided in the documentation, but +we have included a simplified version here.

        +

        Astropy requires Python 2.6, 2.7, 3.1, or 3.2, and Numpy 1.4 or later. +You can install the latest developer version of Astropy using:

        +
        git clone http://github.com/astropy/astropy.git
        +cd astropy
        +python setup.py install
        +

        Once a stable version of Astropy is released, we will provide links to the tar file, and updated installation instructions!

        +

        You can check that astropy is correctly installed by starting up python or ipython, and importing astropy:

        +
        >>> import astropy
        +
        -
        -

        Indices and Tables

        - +

        If you do not get any errors, the installation was successful!

        +
        +
        +

        Getting help

        +

        If you want to discuss issues with other Astropy users and with the +developers, you can sign up to the astropy mailing list!

        +
        +
        +

        Reporting issues

        +

        If you have come across something that you believe is a bug, please open a +ticket in the Astropy issue tracker, and we will look into it promptly!

        -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Next topic

        -

        Overview

        -

        This Page

        - - - -
        -
        -
        -
        - - +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +

        + + + +

        + +
        +
        - + \ No newline at end of file diff --git a/install.html b/install.html deleted file mode 100644 index 656e9730..00000000 --- a/install.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - - - - - Installation — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Installation

        -
        -

        Requirements

        -

        Astropy has the following strict requirements:

        - -

        Astropy also depends on other projects for optional features.

        -
          -
        • xmllint: To validate VOTABLE XML files.
        • -
        -

        TODO: Link to the planned dependency checker/installer tool.

        -
        -
        -

        Installing Astropy

        -
        -

        Using pip

        -

        TODO: Write once we’re up on PyPI.

        -
        -
        -

        Binary installers

        -

        TODO: Write about where to obtain binary packages (.dmg, .msi etc.)

        -
        -
        -
        -

        Building from source

        -
        -

        Prerequisites

        -

        You will need a compiler suite and the development headers for Python -and Numpy in order to build Astropy. Using the package manager for -your platform will usually be the easiest route.

        -

        The instructions for building Numpy from source are also a good -resource for setting up your environment to build Python packages.

        -
        -
        -

        Obtaining the source

        -
        -

        Source packages

        -

        Source tarballs of past releases and the current development branch of -astropy can be downloaded from here:

        -
        -
        -
        -
        -

        Development repository

        -

        The latest development version of Astropy can be cloned from github -using this command:

        -
        git clone git://github.com/astropy/astropy.git
        -
        -
        -

        Note

        -

        If you wish to participate in the development of Astropy, see -Documentation for Developers. This document covers only the basics -necessary to install Astropy.

        -
        -
        -
        -
        -

        Building and Installing

        -

        Astropy uses the Python distutils framework for building and -installing.

        -

        To build Astropy (from the root of the source tree):

        -
        python setup.py build
        -
        -

        To install Astropy (from the root of the source tree):

        -
        python setup.py install
        -
        -
        -
        -

        Building documentation

        -

        Building the documentation requires some additional packages:

        -
        -
        -
        -

        To build the Astropy documentation (from the root of the source tree):

        -
        python setup.py build_sphinx
        -
        -

        The documentation tree will be built in the docs/_build/html -directory.

        -
        -
        -

        Testing Astropy

        -

        The easiest way to test that your Astropy built correctly is to run -(from the root of the source tree):

        -
        python setup.py test
        -
        -

        There are also alternative methods of Running Tests.

        -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Overview

        -

        Next topic

        -

        Configuration system Documentation

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/np-modindex.html b/np-modindex.html deleted file mode 100644 index 99902659..00000000 --- a/np-modindex.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - - - - - Python Module Index — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - - -

        Python Module Index

        - -
        - a -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         
        - a
        - astropy -
            - astropy.config.configs -
            - astropy.config.data -
            - astropy.config.paths -
            - astropy.io.vo.converters -
            - astropy.io.vo.exceptions -
            - astropy.io.vo.table -
            - astropy.io.vo.tree -
            - astropy.io.vo.ucd -
            - astropy.io.vo.unit -
            - astropy.io.vo.util -
            - astropy.io.vo.validator -
            - astropy.io.vo.xmlutil -
            - astropy.tools.misc -
            - astropy.utils.collections -
            - astropy.utils.console -
            - astropy.utils.misc -
            - astropy.utils.xml.check -
            - astropy.utils.xml.iterparser -
            - astropy.utils.xml.validate -
            - astropy.utils.xml.writer -
            - astropy.wcs -
            - astropy.wcs.wcs -
        - - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/objects.inv b/objects.inv index 932c0c34a3bdb7f9578176b6e88415c82c0b9efa..f773ca521237d1a90420f725be79a89425433027 100644 GIT binary patch delta 97 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 diff --git a/overview.html b/overview.html deleted file mode 100644 index 3b163191..00000000 --- a/overview.html +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - - - Overview — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Overview

        -

        Here we describe a broad overview of the astropy project and its associated -modules and packages.

        -
        -

        astropy Package Layout

        -

        Astropy contains the following base-level subpackages:

        -
          -
        • -
          config
          -

          This subpackage contains configuration and setup utilities, including the -affiliated package install tools.

          -
          -
          -
        • -
        • -
          utils
          -

          This subpackage contains utilities of general use for multiple modules or -affiliated packages.

          -
          -
          -
        • -
        • -
          version
          -

          This subpackage contains the version number information for the package. -Note that the version is also available at the base level of the package as -astropy.__version__.

          -
          -
          -
        • -
        • -
          extern
          -

          This subpackage contains small python packages that are not unique to -astropy but are convinient to include as part of the astropy source code.

          -
          -
          -
        • -
        • -
          tests
          -

          This subpackage contains utilities to run the astropy test suite (the -simplest method is to just call astropy.test()), tools for writing -tests, and general tests that are not associated with a particular package.

          -
          -
          -
        • -
        • -
          wcs
          -

          This subpackage contains a python wrapper around the -wcslib library for -managing FITS world coordinate systems (WCS).

          -
          -
          -
        • -
        -
        -
        -

        Affiliated Packages

        -

        Astropy also includes the concept of “affiliated packages.” An affiliated -package is an astronomy-related python package that is not included as part of -the Astropy source code, but has officially requested to be included in the -Astropy community. Such a package may be a candidate for eventual inclusion in -the main astropy package. Astropy comes with a tool to install a affiliated -packages by name, and a single official index with a list and description of -each package. See the config module documentation for details -regarding this install tool.

        -

        Affiliated packages do not use the astropy namespace, but rather either use -their package name directly, or awastropy.packagename (“affiliated with -astropy”). These packages may later be merged into the astropy package, in -which case the original package may still be used, but it is recommended that -users switch to the astropy.packagename version as soon as possible. -Alternatively, some affiliated packages may not wish to ever be merged with the -astropy source code, but rather remain as separate packages that make use of -other astropy modules or affiliated packages.

        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Welcome to Astropy’s Documentation!

        -

        Next topic

        -

        Installation

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/py-modindex.html b/py-modindex.html deleted file mode 100644 index 6a82acec..00000000 --- a/py-modindex.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - - - - - Python Module Index — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - - -

        Python Module Index

        - -
        - a -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         
        - a
        - astropy -
            - astropy.config.configs -
            - astropy.config.data -
            - astropy.config.paths -
            - astropy.io.vo.converters -
            - astropy.io.vo.exceptions -
            - astropy.io.vo.table -
            - astropy.io.vo.tree -
            - astropy.io.vo.ucd -
            - astropy.io.vo.unit -
            - astropy.io.vo.util -
            - astropy.io.vo.validator -
            - astropy.io.vo.xmlutil -
            - astropy.tools.misc -
            - astropy.utils.collections -
            - astropy.utils.console -
            - astropy.utils.misc -
            - astropy.utils.xml.check -
            - astropy.utils.xml.iterparser -
            - astropy.utils.xml.validate -
            - astropy.utils.xml.writer -
            - astropy.wcs -
            - astropy.wcs.wcs -
        - - -
        -
        -
        -
        -
        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/search.html b/search.html index 03a2b02f..05e84b9b 100644 --- a/search.html +++ b/search.html @@ -1,22 +1,24 @@ - + + - Search — Astropy 0.0.dev664 documentation + Search — Astropy - + + + - - + + + + - + + + + + + + + + + + + + + + + + - - -
        -
        -
        -
        + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        +

        Search

        @@ -80,36 +170,16 @@

        Search

        -
        -
        -
        -
        -
        - -
        -
        -
        -
        - - +
        +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +
        +
        \ No newline at end of file diff --git a/searchindex.js b/searchindex.js index be885895..02cbd9e6 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{"astropy.tools.misc":{sigma_clip:[15,10,1,""]},"astropy.config.configs":{ConfigurationItem:[33,14,1,""],save_config:[33,10,1,""],reload_config:[33,10,1,""],get_config:[33,10,1,""],InvalidConfigurationItemWarning:[33,15,1,""]},"astropy.utils.misc":{find_current_module:[22,10,1,""],fnunpickle:[22,10,1,""],fnpickle:[22,10,1,""]},"astropy.config.paths":{get_cache_dir:[33,10,1,""],get_config_dir:[33,10,1,""]},"astropy.io.vo.tree.SimpleElement":{parse:[8,9,1,""],to_xml:[8,9,1,""]},"astropy.io.vo.tree.CooSys":{epoch:[8,12,1,""],equinox:[8,12,1,""],ID:[8,12,1,""],system:[8,12,1,""]},"astropy.utils.xml.validate":{validate_schema:[6,10,1,""]},"astropy.tools":{misc:[15,8,1,""]},"astropy.io.vo.util":{is_callable:[27,10,1,""],coerce_range_list_param:[27,10,1,""],convert_to_writable_filelike:[27,10,1,""]},"astropy.utils.console.Spinner":{"__module__":[13,12,1,""],"__enter__":[13,9,1,""],"__exit__":[13,9,1,""],"__init__":[13,9,1,""]},"astropy.wcs.WCS":{get_naxis:[41,9,1,""],det2im2:[41,12,1,""],pix2foc:[41,9,1,""],wcs_sky2pix:[41,9,1,""],printwcs:[41,9,1,""],deepcopy:[41,9,1,""],sip_foc2pix:[41,9,1,""],det2im1:[41,12,1,""],wcs:[41,12,1,""],sip:[41,12,1,""],sub:[41,9,1,""],footprint_to_file:[41,9,1,""],to_header_string:[41,9,1,""],p4_pix2foc:[41,9,1,""],rotateCD:[41,9,1,""],wcs_pix2sky:[41,9,1,""],get_axis_types:[41,9,1,""],det2im:[41,9,1,""],copy:[41,9,1,""],to_header:[41,9,1,""],cpdis2:[41,12,1,""],calcFootprint:[41,9,1,""],cpdis1:[41,12,1,""],sip_pix2foc:[41,9,1,""],all_pix2sky:[41,9,1,""]},"astropy.io.vo.table":{parse:[32,10,1,""],validate:[32,10,1,""],parse_single_table:[32,10,1,""]},"astropy.wcs.Wcsprm":{theta0:[5,12,1,""],ssysobs:[5,12,1,""],equinox:[5,12,1,""],is_unity:[5,9,1,""],cubeface:[5,12,1,""],lonpole:[5,12,1,""],cd:[5,12,1,""],restfrq:[5,12,1,""],cdfix:[5,9,1,""],tab:[5,12,1,""],spcfix:[5,9,1,""],crder:[5,12,1,""],lng:[5,12,1,""],dateavg:[5,12,1,""],has_pc:[5,9,1,""],colnum:[5,12,1,""],sptr:[5,9,1,""],mjdobs:[5,12,1,""],specsys:[5,12,1,""],fix:[5,9,1,""],mjdavg:[5,12,1,""],phi0:[5,12,1,""],s2p:[5,9,1,""],get_ps:[5,9,1,""],has_crotaia:[5,9,1,""],has_cd:[5,9,1,""],mix:[5,9,1,""],set_ps:[5,9,1,""],cname:[5,12,1,""],set_pv:[5,9,1,""],velosys:[5,12,1,""],set:[5,9,1,""],cylfix:[5,9,1,""],spec:[5,12,1,""],get_pc:[5,9,1,""],restwav:[5,12,1,""],print_contents:[5,9,1,""],velangl:[5,12,1,""],zsource:[5,12,1,""],celfix:[5,9,1,""],unitfix:[5,9,1,""],get_cdelt:[5,9,1,""],csyer:[5,12,1,""],has_pci_ja:[5,9,1,""],dateobs:[5,12,1,""],crota:[5,12,1,""],cdelt:[5,12,1,""],piximg_matrix:[5,12,1,""],crpix:[5,12,1,""],ctype:[5,12,1,""],p2s:[5,9,1,""],lat:[5,12,1,""],cel_offset:[5,12,1,""],radesys:[5,12,1,""],has_cdi_ja:[5,9,1,""],lngtyp:[5,12,1,""],sub:[5,9,1,""],to_header:[5,9,1,""],datfix:[5,9,1,""],has_crota:[5,9,1,""],cunit:[5,12,1,""],name:[5,12,1,""],alt:[5,12,1,""],colax:[5,12,1,""],pc:[5,12,1,""],imgpix_matrix:[5,12,1,""],naxis:[5,12,1,""],axis_types:[5,12,1,""],lattyp:[5,12,1,""],ssyssrc:[5,12,1,""],get_pv:[5,9,1,""],latpole:[5,12,1,""],obsgeo:[5,12,1,""],crval:[5,12,1,""]},"astropy.wcs":{WCS:[41,14,1,""],Sip:[4,14,1,""],DistortionLookupTable:[45,14,1,""],Wcsprm:[5,14,1,""],wcs:[30,8,1,""],find_all_wcs:[41,10,1,""],UnitConverter:[19,14,1,""]},"astropy.utils.xml.check":{check_id:[6,10,1,""],check_anyuri:[6,10,1,""],check_token:[6,10,1,""],fix_id:[6,10,1,""],check_mime_content_type:[6,10,1,""]},"astropy.io.vo.validator.main":{make_validation_report:[34,10,1,""]},"astropy.utils.xml.writer":{XMLWriter:[6,14,1,""],xml_escape_cdata:[6,10,1,""],xml_escape:[6,10,1,""]},"astropy.io.vo.tree.Resource":{tables:[8,12,1,""],extra_attributes:[8,12,1,""],coordinate_systems:[8,12,1,""],links:[8,12,1,""],iter_coosys:[8,9,1,""],parse:[8,9,1,""],to_xml:[8,9,1,""],params:[8,12,1,""],iter_fields_and_params:[8,9,1,""],infos:[8,12,1,""],type:[8,12,1,""],iter_tables:[8,9,1,""],resources:[8,12,1,""]},"astropy.utils.console":{ProgressBarOrSpinner:[13,14,1,""],isatty:[13,10,1,""],print_code_line:[13,10,1,""],color_print:[13,10,1,""],ProgressBar:[13,14,1,""],Spinner:[13,14,1,""],human_time:[13,10,1,""]},"astropy.io.vo.tree.ParamRef":{ref:[8,12,1,""],get_ref:[8,9,1,""]},"astropy.io.vo.tree.Field":{to_xml:[8,9,1,""],links:[8,12,1,""],datatype:[8,12,1,""],ref:[8,12,1,""],precision:[8,12,1,""],parse:[8,9,1,""],width:[8,12,1,""],uniqify_names:[8,13,1,""],values:[8,12,1,""],arraysize:[8,12,1,""],type:[8,12,1,""],unit:[8,12,1,""]},"astropy.io.vo":{xmlutil:[14,8,1,""],tree:[8,8,1,""],util:[27,8,1,""],ucd:[31,8,1,""],exceptions:[7,8,1,""],table:[32,8,1,""],converters:[35,8,1,""],unit:[37,8,1,""],validator:[34,8,1,""]},"astropy.utils.xml.writer.XMLWriter":{comment:[6,9,1,""],"__module__":[6,12,1,""],end:[6,9,1,""],get_indentation_spaces:[6,9,1,""],element:[6,9,1,""],start:[6,9,1,""],tag:[6,9,1,""],object_attrs:[6,11,1,""],flush:[6,9,1,""],close:[6,9,1,""],get_indentation:[6,9,1,""],data:[6,9,1,""],"__init__":[6,9,1,""]},"astropy.io.vo.tree.Values":{ref:[8,12,1,""],min:[8,12,1,""],max:[8,12,1,""],parse:[8,9,1,""],to_xml:[8,9,1,""],is_defaults:[8,9,1,""],max_inclusive:[8,12,1,""],min_inclusive:[8,12,1,""],"null":[8,12,1,""],type:[8,12,1,""],options:[8,12,1,""]},"astropy.config.data":{get_data_filename:[33,10,1,""],get_data_fileobjs:[33,10,1,""],compute_hash:[33,10,1,""],get_data_fileobj:[33,10,1,""],clear_data_cache:[33,10,1,""],get_data_contents:[33,10,1,""],get_data_filenames:[33,10,1,""]},"astropy.wcs.UnitConverter":{convert:[19,9,1,""],scale:[19,12,1,""],have:[19,12,1,""],power:[19,12,1,""],want:[19,12,1,""],offset:[19,12,1,""]},"astropy.io.vo.tree.Table":{nrows:[8,12,1,""],links:[8,12,1,""],format:[8,12,1,""],fields:[8,12,1,""],iter_groups:[8,9,1,""],parse:[8,9,1,""],is_empty:[8,9,1,""],to_xml:[8,9,1,""],create_arrays:[8,9,1,""],groups:[8,12,1,""],iter_fields_and_params:[8,9,1,""],get_field_by_id_or_name:[8,9,1,""],params:[8,12,1,""],infos:[8,12,1,""],get_group_by_id:[8,9,1,""],ref:[8,12,1,""],get_field_by_id:[8,9,1,""]},"astropy.config.configs.ConfigurationItem":{reload:[33,9,1,""],set:[33,9,1,""],save:[33,9,1,""]},"astropy.utils.console.ProgressBar":{map:[13,13,1,""],"__module__":[13,12,1,""],"__exit__":[13,9,1,""],"__enter__":[13,9,1,""],update:[13,9,1,""],iterate:[13,13,1,""],"__init__":[13,9,1,""]},"astropy.io.vo.tree.Group":{iter_fields_and_params:[8,9,1,""],parse:[8,9,1,""],iter_groups:[8,9,1,""],to_xml:[8,9,1,""],entries:[8,12,1,""],ref:[8,12,1,""]},"astropy.io.vo.tree.VOTableFile":{get_first_table:[8,9,1,""],coordinate_systems:[8,12,1,""],parse:[8,9,1,""],iter_values:[8,9,1,""],set_all_tables_format:[8,9,1,""],iter_coosys:[8,9,1,""],iter_groups:[8,9,1,""],get_field_by_id:[8,9,1,""],version:[8,12,1,""],params:[8,12,1,""],get_table_by_index:[8,9,1,""],get_group_by_id:[8,9,1,""],resources:[8,12,1,""],get_table_by_id:[8,9,1,""],to_xml:[8,9,1,""],groups:[8,12,1,""],iter_fields_and_params:[8,9,1,""],get_field_by_id_or_name:[8,9,1,""],get_values_by_id:[8,9,1,""],infos:[8,12,1,""],iter_tables:[8,9,1,""],get_coosys_by_id:[8,9,1,""]},"astropy.io.vo.xmlutil":{validate_schema:[14,10,1,""],check_id:[14,10,1,""],check_token:[14,10,1,""],fix_id:[14,10,1,""],check_mime_content_type:[14,10,1,""],check_anyuri:[14,10,1,""]},"astropy.io.vo.converters":{get_converter:[35,10,1,""]},"astropy.io.vo.unit":{is_unit:[37,10,1,""],check_unit:[37,10,1,""]},astropy:{wcs:[46,8,1,""]},"astropy.utils":{console:[13,8,1,""],misc:[22,8,1,""],collections:[40,8,1,""]},"astropy.utils.xml":{iterparser:[6,8,1,""],validate:[6,8,1,""],writer:[6,8,1,""],check:[6,8,1,""]},"astropy.wcs._wcs.Tabprm":{print_contents:[5,9,1,""],map:[5,12,1,""],p0:[5,12,1,""],set:[5,9,1,""],K:[5,12,1,""],nc:[5,12,1,""],M:[5,12,1,""],coord:[5,12,1,""],delta:[5,12,1,""],crval:[5,12,1,""],sense:[5,12,1,""],extrema:[5,12,1,""]},"astropy.utils.xml.iterparser":{get_xml_encoding:[6,10,1,""],xml_readlines:[6,10,1,""],get_xml_iterator:[6,10,1,""]},"astropy.io.vo.exceptions":{VOTableSpecWarning:[7,14,1,""],VOWarning:[7,14,1,""],parse_vowarning:[7,10,1,""],IOWarning:[7,14,1,""],vo_raise:[7,10,1,""],UnimplementedWarning:[7,14,1,""],warn_or_raise:[7,10,1,""],VOTableSpecError:[7,14,1,""],vo_warn:[7,10,1,""],VOTableChangeWarning:[7,14,1,""],vo_reraise:[7,10,1,""]},"astropy.utils.collections.HomogeneousList":{insert:[40,9,1,""],"__module__":[40,12,1,""],extend:[40,9,1,""],"__iadd__":[40,9,1,""],"__setitem__":[40,9,1,""],append:[40,9,1,""],"__dict__":[40,12,1,""],"__weakref__":[40,12,1,""],"__init__":[40,9,1,""]},"astropy.io.vo.tree.Info":{content:[8,12,1,""],unit:[8,12,1,""],ref:[8,12,1,""],name:[8,12,1,""],value:[8,12,1,""]},"astropy.io.vo.tree":{Info:[8,14,1,""],FieldRef:[8,14,1,""],Resource:[8,14,1,""],Group:[8,14,1,""],CooSys:[8,14,1,""],SimpleElement:[8,14,1,""],Param:[8,14,1,""],Element:[8,14,1,""],Field:[8,14,1,""],Link:[8,14,1,""],Table:[8,14,1,""],Values:[8,14,1,""],ParamRef:[8,14,1,""],SimpleElementWithContent:[8,14,1,""],VOTableFile:[8,14,1,""]},"astropy.io.vo.tree.Param":{to_xml:[8,9,1,""],value:[8,12,1,""]},"astropy.utils.collections":{HomogeneousList:[40,14,1,""]},"astropy.io.vo.tree.SimpleElementWithContent":{content:[8,12,1,""],to_xml:[8,9,1,""]},"astropy.wcs.DistortionLookupTable":{get_offset:[45,9,1,""],crpix:[45,12,1,""],data:[45,12,1,""],crval:[45,12,1,""],cdelt:[45,12,1,""]},"astropy.utils.console.ProgressBarOrSpinner":{"__module__":[13,12,1,""],"__enter__":[13,9,1,""],"__exit__":[13,9,1,""],update:[13,9,1,""],"__init__":[13,9,1,""]},"astropy.wcs.Sip":{a:[4,12,1,""],b:[4,12,1,""],b_order:[4,12,1,""],foc2pix:[4,9,1,""],bp_order:[4,12,1,""],ap:[4,12,1,""],a_order:[4,12,1,""],bp:[4,12,1,""],ap_order:[4,12,1,""],pix2foc:[4,9,1,""],crpix:[4,12,1,""]},"astropy.io.vo.ucd":{parse_ucd:[31,10,1,""],check_ucd:[31,10,1,""]},"astropy.wcs._wcs":{Tabprm:[5,14,1,""]},"astropy.io.vo.tree.Link":{href:[8,12,1,""],content_type:[8,12,1,""],content_role:[8,12,1,""]},"astropy.config":{paths:[33,8,1,""],configs:[33,8,1,""],data:[33,8,1,""]},"astropy.io.vo.tree.FieldRef":{ref:[8,12,1,""],get_ref:[8,9,1,""]}},terms:{haggi:20,orthogon:11,resist:19,yellow:[13,44],four:[3,5,29],warn_or_rais:7,prefix:[20,30,3,33,19],vspan:5,tcnana:29,cython_skip:1,whose:[20,5,29],moshir:4,typeerror:[40,11,33],get_cache_dir:33,messi:[42,38],deviat:15,under:[1,20,11,30,19],spec:[8,36,7,5,32],suitabl:[27,5],digit:[7,5],everi:[1,7,13,28],risk:19,msg2:11,distort:[30,4,41,28,45,46],lumin:19,quantiz:[41,5],delv:33,affect:[11,42],beam:19,heasarc:34,flymak:39,factori:35,vector:[5,24],phase:23,matric:28,verif:[47,37],readthedoc:1,direct:[11,1,5,4,20,30,23],consequ:29,second:[13,38,20,3,5,24,19],aggreg:30,ill:[41,5],illumin:19,even:[11,36,3,18,29,41,7,5,42,19],asin:19,msysgit:9,insid:[11,1,3,20,7,8],check_id:[14,6],neg:19,get_extens:1,introspect:20,mixpix:5,lightr:13,sigma_clip:15,conduct:19,"new":[11,36,38,20,23,39,18,4,6,7,24,28,42,33,8,26],net:7,ever:[2,23,5,6],nep:42,urlerror:33,manipul:[5,36],hdr:[1,33],submodule1:11,submodule2:11,footprint_to_fil:41,never:[11,1,5,29,41,23],droettboom:46,here:[0,11,20,2,9,17,18,5,6,41,7,43,44,42,8,19],foccrd:4,base64:[7,36],lgpl:46,pos_eq_dec_main:36,path:[20,36,1,39,6,27,14,32,33,34,8],interpret:[39,5,28,33,15,19],"94935ac31d585f68041c08f87d1a19d4":3,iter_group:8,xmllint:[14,6,7,43,32],zsourcea:[5,29],vowarn:7,progressbar:13,precis:[20,8,41,7,5],get_first_t:[8,36],fourier:20,glu:7,yuri:44,set_reference_fram:27,"_test":3,tcdena:29,icsyena:29,unix:33,crder:5,total:[13,19,5],unit:[28,11,36,37,3,5,30,7,47,44,8,19,41],highli:33,plot:[20,41],describ:[11,20,2,3,17,26,29,39,46,33,8,19],would:[11,20,5,29,41,42,28,33,23],ddthh:5,cmdlinescript:25,recommenc:5,readi:[0,42],datadir:33,call:[25,11,13,1,2,46,3,5,22,6,41,7,44,42,33,34,28,36],card:[41,24,19],typo:42,recommend:[25,11,38,1,2,3,5,29,20,7,33,15,19],type:[20,13,40,14,3,39,18,5,6,41,7,28,42,33,8,19,36],until:[1,23,5,22,7,15],relax:[30,5,41,29],relat:[11,38,14,2,5,6,41,42,21,20,15,47],notic:42,warn:[11,36,20,3,5,41,7,45,32,33,47],exce:[11,41,5,29],isatti:13,loss:7,plt:[20,11],hold:[15,8,25],complexarrayvararrai:35,must:[11,13,27,1,15,3,39,5,4,6,20,23,7,24,14,33,8,19,41,36],word:[42,31,39,44],restor:7,setup:[11,1,2,3,39,43,33],work:[0,25,11,13,1,23,3,17,18,26,5,20,42,39,8],coerce_range_list_param:27,xmlutil:[14,47],new_vot:36,reword:42,root:[11,7,33,43,19],obliqu:5,give:[0,1,28,22,20,42,44,33],indic:[10,13,27,20,3,5,6,7],unavail:28,want:[26,1,3,18,5,42,44,33,9,19],lonpol:5,end:[25,13,38,1,39,5,22,6,41,42],turn:[25,13,3,39,42,36],str3:19,str2:19,str1:19,setq:39,ictypn:29,w26:7,how:[0,11,38,20,23,3,17,18,26,5,7,42,33,22,8],w24:7,"0x11f00f0":[],w22:7,w23:7,env:[25,11],w21:7,answer:20,verifi:[27,28,47,37,31],config:[0,11,37,1,2,3,18,26,14,44,7,20,33,8,35],w28:7,updat:[11,13,1,28,26,7,44,42,33],ipvn_ma:29,recogn:[41,5,19,29],hhuuggoo:44,rebas:[42,38],mess:42,after:[11,13,20,3,39,5,26,41,7,42,33],substanc:19,befor:[11,38,20,23,3,17,5,29,7,42,32,8],wrong:42,human_tim:13,currect:3,lat:[41,5],parallel:[34,36],attempt:[11,7],third:[1,11,5],coordinate_system:8,classmethod:[8,13],opaqu:6,bootstrap:1,tcn_ka:29,lost:[42,41,8,5],exclud:38,alias:[30,7,19,44],maintain:[26,42,5,38],environ:[33,43],incorpor:[20,38],enter:[11,42],wcshdo_:29,first:[36,38,20,23,3,42,5,29,22,41,7,32,33,34,8],order:[11,20,23,5,4,29,41,7,43,8,19],mcnoleg:20,origin:[28,20,2,3,5,4,41,7,24,44,42],deci:19,rhetting:11,k93model:33,upstream:[0,42,38,44],becaus:[25,11,38,20,8,3,5,29,42,33,23],wcshdo_al:29,typewrit:20,pascal:19,get_field_by_id_or_nam:8,flexibl:[25,41,36],vari:5,digest:33,ucd1:[7,31],shorter:29,fit:[11,1,2,30,3,5,4,23,7,24,28,46,33,8,19,41],unforeseen:7,fix:[28,26,36,20,3,18,5,41,7,44,42,8,46],tcdltn:29,comprehend:20,better:[42,18,28],persist:11,nelem:[5,4],cred:44,easier:[42,36],them:[11,20,23,3,18,5,42,29,8,19],thei:[11,36,1,23,3,5,26,29,20,41,7,28,42,33,8,19],proce:7,"_xtypeproperti":8,safe:[18,29],colsel:41,axis_typ:[41,5],choic:[23,8,44],tendenc:29,regula:5,unpickl:22,accommod:29,good:[0,11,36,38,20,7,43,44,42,9],tabprm:[30,5],each:[1,2,3,4,7,15,11,13,8,5,20,27,29,41,31,33,34,19,36,42,28,45,46],"29001ed":42,went:42,ictyna:29,side:[1,5],mean:[11,20,15,5,23,7,42,33,8,19,41],voxel:19,ncoord:[5,4],"6ad92e5":42,arrayvararrai:35,is_empti:8,forgot:42,extract:[41,7,5,36],ndobj_new:20,unbound:7,network:[20,42,7],goe:11,content:[25,20,12,14,31,39,5,22,6,7,24,44,46,33,8,47],rewrit:42,laid:[11,5],adapt:[20,23,9],reader:20,got:[42,7,38],unrecogn:[41,5],smallish:22,linear:[11,5,41,42,28,45],p4_pix2foc:[46,41],written:[11,20,5,29,41,7,42,8],get_cdelt:[5,28],situat:[20,42],free:[26,9,33],standard:[1,3,4,6,7,15,11,12,13,8,5,20,23,29,41,31,32,33,19,36,37,46,47],"__setitem__":40,freq:5,validate_schema:[14,6],md5:[33,3],"_idproperti":8,tctypna:29,workaround:7,ds9:41,pkname:33,traceback:[7,13],iso:5,isn:[1,5,22],regress:3,onto:42,rang:[27,13,5],render:20,rydberg:19,independ:[46,23],get_p:5,restrict:[7,5],hook:[1,39],unlik:[33,5,29],alreadi:[11,38,18,5,7,42,33,23],wcshdr_none:29,voidspac:33,primari:[29,5,24],hood:30,"7beda5a":44,xml_readlin:6,airi:24,top:[25,11,36,38,42,33,8],sometim:[42,39],astropi:[1,2,3,4,5,6,7,15,10,11,12,13,14,8,16,17,18,19,20,21,22,24,25,26,27,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,28,45,46,47],underlin:20,master:[1,42,18,38,44],too:[3,7],xiv:4,tom:3,ioerror:33,outag:7,consol:[13,21],namespac:[1,2,11,7,31],tool:[0,10,11,37,20,2,3,39,23,7,43,33,15],coordinate_typ:41,task:[20,42,23,13],tcrdna:29,gitconfig:44,"_nameproperti":8,cdata:6,conserv:19,technic:0,printwc:41,keyword:[36,20,5,29,6,41,27,24,32,8,19],x_fit:28,provid:[11,36,27,1,15,39,5,29,20,23,7,28,32,33,34,8,41,46],offici:2,tree:[11,36,20,23,6,43,32,34,8,35,47],wcshdr_:29,project:[0,10,11,1,2,5,20,7,24,43,42],pressur:19,da34a7b07ef153eede67387bf950bb32:33,minut:[19,44],mathtt:20,beginn:[26,17,18],latitud:[41,5,29],mini:39,rad:19,fashion:33,behavior:[29,44],mind:20,spectrum:27,raw:[5,28],aforement:11,votabl:[36,37,14,7,43,31,32,34,8,35,47],manner:11,increment:[45,13,5],seen:7,seek:23,latter:[20,33,29],matthew:44,get_group_by_id:8,wcshdr_dobsn:29,branchnam:42,simplifi:11,wcsbth:28,glon:5,though:[33,8,28],glob:33,object:[1,3,4,6,7,8,11,13,5,20,24,27,28,29,30,32,33,22,19,36,40,41,42,44,46],terrestri:5,did:[14,42],regular:[3,7],distutils2:1,letter:[7,5],bsd:[46,11],paramref:8,shiningpanda:1,yourdomain:[26,18,44],w42:7,don:[39,18,22,42,5,29,8],nosolutionerror:5,doc:[1,8,20,7,43],doe:[25,11,13,1,3,5,29,20,41,7,33,34,8,19],abbrev:44,declar:[7,24],wildcard:[1,5],tctyna:29,sum:20,dot:[33,7],asid:[20,25],reload_config:33,tcunin:29,random:[20,15,5],radiu:[20,19],syntax:[11,37,20,39,7,8,19],radio:28,pkg:22,identifi:[26,5,6,41,7,44,32,23],autoload:39,involv:[1,3],absolut:[33,11,3,26,44],"0x1525330":15,just:[11,36,38,14,2,39,18,26,5,6,42,46,33],menu:[42,39],explain:[0,20,42,18],configur:[10,11,20,2,3,17,18,26,42,39,44,32,33,35],tcrvlna:29,get_xml_encod:6,rich:20,vo_warn:7,likewis:[41,7,5,29],stop:[42,39],corr:44,viter:5,report:[36,3,7,32,34,47],iter_valu:8,bar:[6,11,13],excel:[0,18],lonpna:29,"public":[11,12,20,3,42,33,15,47],reload:33,bad:11,jcrpna:29,metadata:11,wcsnna:[41,29],epocha:29,commandlin:24,tcrpxna:29,datatyp:[8,7,35,47,36],num:3,mandatori:19,result:[28,20,3,39,5,29,27,41,7,31,34,8],fail:[11,3,5,4,41,7],icrden:29,zaytsev:44,best:[23,18],subject:[20,11,3,29],awar:20,peta:19,fnpickl:22,hopefulli:33,databas:[42,7],discoveri:3,test_fil:3,fcontent:33,figur:7,setup_method:3,simplest:[2,36,18,44],awai:[27,42],approach:5,attribut:[11,36,37,14,5,22,6,41,7,20,8],get_length:13,accord:[11,36,37,5,7,28],extend:[0,20,36,40],write_null_valu:8,crotan:[41,5,29],weak:40,fk5_to_gal:20,contort:20,clear_data_cach:33,extens:[10,11,16,1,3,5,29,20,41,7,8,19],autofil:39,deby:[5,19],func_d:20,func_a:20,func_b:20,icnana:29,accident:[11,42],easi:[0,11,1,3,20,23],impliment:44,howev:[25,11,36,1,5,26,29,20,41,7,42,8,19],crvalia:[45,5,29],against:[14,6,7,31],get_coosys_by_id:8,logic:[20,7],fnunpickl:22,com:[11,38,1,18,26,42,43,44,9],col:[6,13],con:[11,39],kwd:[27,6],calabretta:46,velosysa:[5,29],diff:[0,42,38,44],summat:20,assum:[11,13,38,20,5,22,7],summar:23,ipsn_ma:29,duplic:[20,23,7],wcsnamea:[5,29],foc2pix:4,numpi:[11,36,1,15,5,4,20,23,7,24,43,28,47,8,35,41],three:[3,5,41,42,46,33],been:[10,11,38,1,5,26,22,20,41,7,28,42,33],viewer:20,much:[42,6,28,23,10],interest:[20,16,24],thereaft:23,restfreq:29,"__doc__":20,projpn:29,life:28,search:[10,1,3,5,22,20,33],argument:[25,13,27,20,3,5,29,6,41,7,24,28,32,8,36],multithread:28,child:[8,7],"catch":11,ident:41,tanh:19,servic:[27,7],properti:[20,11,28,5,24],aip:[28,5,29],radecsi:29,air:24,aim:23,calcul:[1,11,41,28],publicli:8,build_sphinx:43,krige:20,toolkit:23,"_flymak":39,kwarg:[27,32,41,8,13],somemodul:11,ictypna:29,perform:[11,12,36,4,22,30,7,46,34,15,19,41],suggest:[42,19],make:[0,28,11,38,44,1,2,3,17,18,5,6,23,7,39,20,42,33,8],oseerror:33,complex:[15,11,23,7,35],split:29,complet:[33,7,13,38,5],reticul:13,galact:[8,7],nil:39,tcdltna:29,pyflak:[20,39],blue:[13,44],hand:11,get_package_data:1,rais:[11,37,40,14,3,5,4,22,20,41,7,31,45,32,33,8,19],configurationitem:[11,33],latpolea:[41,5,29],squar:[20,19],kept:[20,8],thu:[11,5,29,41,23,19],my_new_fil:42,hypothet:20,inherit:[11,29],pvi_2a:5,contact:[26,44],thi:[1,2,3,5,6,7,15,11,13,14,8,17,18,19,20,24,22,23,25,29,41,31,32,33,34,35,36,38,39,42,43,44],gzip:42,everyth:[42,23,33,15,22],left:[1,41,42,5,29],wcssub_stok:[41,5],protocol:[27,8,7,42,22],vararrai:35,modnam:11,tsn_ma:29,newton:19,ordin:8,human:[20,13],"__dict__":40,yet:[10,11,1,3,20,41,33],languag:11,previous:[8,33,7,28],expos:20,wcslib:[2,30,5,29,41,28,46,19],keysel:41,had:[42,7,36,28],builtin:11,fortran:[28,41,5,4,24],spread:20,primit:7,els:[25,11,13,18,22,42,8],save:[36,39,42,24,44,33],radesysa:[5,29],restwav:5,applic:[36,20,5,7,8,19],milli:19,wcshdo_crpxna:29,mayb:42,zsouna:29,textwrap:13,is_default:8,icrvna:29,background:[20,39],aclass:11,specif:[11,36,20,15,3,39,5,29,30,7,31,42,8,19,41],arbitrari:[14,6,3,8,42],transvers:5,manual:[0,11,38,20,39,42,24],colnum:5,remind:[42,38],confid:24,leftrightarrow:20,unnecessari:5,csiro:46,underli:[30,41,28],www:[33,7],right:[1,29,42,38,44],old:[1,11,3,5],cnameia:[5,29],negat:[41,5],interv:5,begin:[20,11,7,33,29],percentag:13,e03:7,j2000:8,intern:[26,17,5,41,7,19],flatten:11,there_is_a_syntax_error_her:13,successfulli:42,insensit:[7,5,19],cooper:11,bottom:26,subclass:[20,40,11,8],"_utypeproperti":8,track:[36,23,13,38,44],scalarvararrai:35,condit:[20,41,5],foo:[6,11,42,33],icunina:29,core:[11,13,1,23,3,17,26,20,30,42,44,46,34,9,41],plu:[5,29],tcunna:29,bold:[20,44],promot:25,repositori:[26,38,9,17,11,18,42,43,23],post:[0,8,44],idref:7,"super":11,unsaf:[5,19,29],obj:[6,42,22],structured_array_extens:42,surround:[20,19],fiduci:5,commit:[0,38,1,18,42,44,23],attrib:6,produc:[11,20,5,6,7,33,15],capacit:19,naxi:[5,4,41,24,28,45],specsysa:[5,29],"float":[36,20,15,5,41,7,24,28,45,8,35],encod:[6,7,36],down:[3,42],barycentr:[8,7],wrap:[1,6],ivn_ma:29,precomput:11,accordingli:[13,5],git:[0,26,38,17,18,42,43,44,9],axisindex:44,some_opt:33,setup_modul:3,transform:[20,5,4,30,24,28,45,46,41],happi:42,avail:[25,11,1,2,3,5,22,20,41,7,28,33,23],stuck:42,reli:[11,23],wordpress:11,editor:[33,42,44],unimplementedwarn:7,gil:28,fork:[26,42,38],head:[42,38,44],creation:1,"_ucdproperti":8,form:[28,11,38,20,3,39,5,29,6,41,7,31,23,19],offer:[26,3],forc:[5,38,19],wcshdr_all:29,solar:19,synonym:5,"true":[13,37,27,20,15,31,3,39,5,29,6,22,41,7,44,32,33,34,8],reset:[42,13,5],electr:19,attr:6,arrays:[8,7,36],bugfix:42,pvi_3a:5,maximum:[39,8,5,19],tell:[42,18,44],absenc:5,atto:19,wcshdr_radecsi:29,emit:[7,36],khz:19,featur:[38,18,42,43,44,7,46],alongsid:13,shim:1,tesla:19,"abstract":27,diagnost:8,exist:[11,13,1,15,5,29,23,7,33,34,8,41],perez:0,quantiti:[41,7,5,19],mole:19,jcrpxn:29,tip:[0,11,39],refactor:42,role:[8,7],test:[10,11,16,28,1,2,3,18,20,23,27,24,43,44,42,33,8],legitim:29,intend:[15,26,23,7],asterisk:[7,19],urllib2:33,get_remote_test_data:3,felo:5,intens:[1,5,19],intent:29,lightmagenta:13,consid:[11,38,18,29,41,7,5,42,23,19],easili:33,get_values_by_id:8,keycom:[41,5],omega:20,makovoz:4,receiv:7,longer:[33,38],furthermor:20,anywher:36,pseudo:5,fileornam:22,"13d7934":42,ignor:[39,5,29,7,44,45,8,19],time:[11,13,20,15,3,5,29,6,23,7,42,8,19],push:[0,42,38],backward:[1,5],"__________________________________":3,osx:9,concept:[0,2,20],chain:11,skip:[3,8],global:[36,26,39,18,44],wcshdo_saf:29,signific:[20,11,41,7,5],invalidcoordinateerror:5,computation:[1,11],"3a1":[46,28],sip_pix2foc:[46,41,4],row:[8,36,7,5,32],arcsec:19,decid:[3,23],depend:[11,13,20,23,5,26,6,41,7,43,8,36],uniqify_nam:8,graph:[42,38,44],decim:[41,7,5],readabl:[25,20,6,42,32,33],fft2:20,inconsistentaxistypeserror:[41,5],environment:20,cheat:0,quasi:29,singularmatrixerror:[41,5],bitpix:[41,5],wcshdr_cnamn:29,"_debug_python_based_pars":[32,8],giga:19,wcshdr_auximg:29,pywc:[46,28,29],brown:13,sourc:[1,2,3,6,7,15,10,11,13,14,8,5,20,25,26,27,22,31,32,33,34,35,37,40,43],"__exit__":13,string:[28,20,13,37,27,14,15,3,5,6,41,7,31,32,33,34,8,19,36],ndobj_old:20,w35:7,pixcrd:[5,4,24],icr:[8,7,5,36],cyan:13,cool:[42,38],level:[36,27,2,3,39,5,6,8,32,33,23,47],tear:[3,42],gui:[23,9],henri:[5,19],ssysobsa:[5,29],iter:[13,20,15,5,6,33,8],magnet:19,item:[11,13,40,1,27,33],unsupport:7,sine:19,team:[26,23],quick:[20,18],tcsyen:29,round:[8,19],prevent:[36,20,8,3,44,23,19],telescop:46,vsouna:29,cosh:19,whiich:33,sensibl:[42,5,38],port:9,spectral:[27,41,5,28],appear:[38,20,5,29,6,41,7,8],lightblu:13,pyplot:[20,11],favour:29,uniform:23,current:[10,11,36,38,1,23,3,39,6,44,7,43,20,42,33,34,8,19],exception_class:7,erg:19,ground:19,meld:42,tangenc:5,defici:8,deriv:[1,7,5,19],dropdown:42,urlopen:33,gener:[11,13,1,2,18,5,20,22,23,7,47,15,42,33,34,8,19,41,36],coeffici:46,satisfi:[39,23],tangent:19,address:[36,44],along:[1,8],do_someth:25,wait:23,primaryhdu:24,icdena:29,trial:5,atom:19,commonli:[1,46,5,19],ourselv:20,regardless:[41,7,5],fileobj:33,extra:[6,8],dtype:[20,36],modul:[10,11,13,25,1,2,3,29,6,41,7,20,32,33,22,15,35,36],prefer:[20,42,19],backtick:20,leav:18,xdg_config_hom:33,marker:39,configspec:33,set_all_tables_format:[8,36],red:[39,13],memori:[6,41,5,4,32],distortionlookupt:[45,30,41],subvers:0,live:[25,22],theta_0:5,criteria:23,msg:[11,13],black:[39,13],checkout:[0,42,18,38,44],capit:7,nadia:46,peopl:[3,42,38],claus:11,pylint:20,finit:5,ctype:[41,5,24],enhanc:11,visual:42,accept:[25,26,36,27,11,5,40,41,7,33,29,19],examin:36,easiest:[9,18,43],content_typ:[14,6,8],tcrvln:29,fly:42,icnamna:29,graphic:42,local:[3,39,42,7,33,34],uniqu:[2,33,7,38,8],descriptor:[7,36,47,31],vega:33,whatev:[11,23],imped:11,webster:44,purpos:[5,22,42,28,7,8],overwritten:22,point_3d:7,stream:[27,6],add_argu:25,janski:19,abort:42,spc:39,occur:[1,5,22,41,7,33,19],alwai:[11,13,1,23,3,29,6,41,7,28,33,8,19,36],"956fbab":44,multipl:[11,20,2,39,7,15,19],satisfact:42,write:[20,2,3,6,7,8,10,11,13,16,5,24,25,27,29,30,33,34,36,38,39,41,42,43,44],anyon:[16,42],pure:[11,8],vo_rerais:7,parameter:[5,29],get_color:11,map:[13,1,3,5,6,7,33,36],product:5,mar:11,atan:19,max:[8,7,24],clone:[0,26,42,18,43],crotaia:[5,29],mac:9,mag:19,mai:[20,2,3,4,7,8,11,13,9,5,24,23,27,29,41,31,32,33,19,36,42,44,45,46],underscor:[14,6,20,7],data:[11,36,1,15,3,6,44,7,20,45,33,8,41],grow:23,harmon:42,subsequ:[26,41,5,19,29],stress:19,tpsn_ma:29,practic:[36,5,41,7,44,33,23],array_lik:20,quot:20,favorit:33,ghz:19,enh:42,"switch":[1,2,3,42,18],preced:[20,7,19],combin:[36,20,5,41,42,8],maskedarr:15,callabl:[27,15],adass:4,yocto:19,tty:13,comfort:26,creset:44,graphviz:43,cmod:22,lsr:5,still:[11,36,1,2,20,7,42],pointer:[39,8],dynam:5,divis:[5,19,24],conjunct:[5,29],group:[8,41,7,5,29],thank:[18,44],w27:7,platform:[20,3,43],window:[9,28],w25:7,mail:[42,18],main:[25,38,2,3,18,42,33,34,23],recoveri:42,non:[11,36,14,44,5,29,6,41,7,20,46,9,19],w20:7,halv:5,supersed:20,alist:39,initi:[26,5,40,41,44,33,23,19],nation:46,underneath:20,"try":[11,42],half:5,now:[36,38,28,18,7,24,44,42],discuss:[20,44],nor:[19,29],introduct:[0,10,26,12,36],term:[3,5,41],name:[1,2,3,5,6,7,8,11,13,14,18,20,24,25,26,27,22,41,32,33,19,36,38,39,42,44],drop:[39,29],another_opt:33,vegaurl:33,tera:19,linspac:11,separ:[1,2,3,39,5,29,20,30,7,42,19,41],x10:19,dictproxi:40,collaps:[42,39],ters:29,compil:[11,3,43,34],domain:[8,7],replai:42,inhert:11,replac:[20,14,39,29,6,7,44],individu:[39,8,47,22],continu:[15,23,7],significantli:3,year:[8,7,5,19],icrvln:29,happen:7,shown:[20,39,33,17,29],dencheva:46,space:[11,13,20,39,5,6,7,46,19],storag:[8,36],wcshdo_tpcn_ka:29,cobe:5,internet:[11,3],usecpickl:22,correct:[11,13,5,4,30,7,31,46,33,15,41],earlier:[28,7,31],variant:29,runtimeerror:33,setup_funct:3,argv:[25,24],mime:[14,6,7,8],theori:20,exc_typ:13,org:[1,20,33,3],"byte":[33,7,19,36],"0x240078":[32,13],sollum:19,care:[20,5],suffici:[11,29],frequenc:[5,19],recov:[42,7],thing:[0,36,1,18,27,42],place:[11,3,39,5,4,22,7,28,33,15],principl:[20,7],think:[42,18],lambda:39,oper:[11,13,5,30,8,19,41],filtereddata:15,directli:[11,38,26,2,5,22,41,7,15,44,42,33,23],onc:[11,26,3,5,22,7,43,44,42,33,34,23],arrai:[11,36,20,15,28,5,4,29,41,7,24,19,44,45,32,8,35],"65af65":44,yourself:[26,42,44],stsci:33,submit:[26,3,23,33],oppos:11,sip_foc2pix:[46,41,4],open:[13,27,3,22,6,42,24,32,33],size:[11,13,5,4,41,7,28,45,8,36],given:[11,13,40,1,28,42,5,22,6,20,41,7,19,14,32,33,34,8,35,36],sheet:0,silent:13,convent:[11,20,5,4,29,30,7,28,46,41],width:[8,41,7,13,15],teardown:3,analog:[19,29],fobj:[33,41],checker:[20,43],necessarili:[1,15],draft:[10,11,16,36,20,3,39,29],iau:19,white:[39,13],conveni:[0,36,3,5,6,41],cite:20,"26aa21a":42,courier:20,especi:[20,3,29],copi:[26,20,3,39,18,5,41,7,44,42,33,15],compute_hash:[33,3],"short":[36,20,7,42,8,35],enclos:[20,8,19],complexvararrai:35,than:[11,13,38,1,15,3,18,5,6,23,7,24,20,42,22,29,8,19,41],progn:39,serv:3,wide:[3,29],vicin:20,obsgzn:29,were:[5,29,41,7,24,28,32,33],posit:[13,39,35,41,7,8,19],seri:[0,3,19,38],pre:[20,4,6,7,15,13,14,8,5,35,21,27,22,41,31,32,34,19,36,37,40,42,45],parse_vowarn:7,sai:[42,11,7,38],ap_i_j:4,tcsyena:29,pro:[0,11],save_config:33,ani:[11,13,38,44,1,15,46,3,18,5,6,23,7,20,42,33,29,8,19,41,36],dash:[7,5],measur:5,repeatedli:36,wcshdr_longkei:29,techniqu:[20,15],institut:46,note:[1,2,3,4,5,7,15,11,36,8,18,20,29,41,33,34,19,38,39,42,43,44],unitconvers:28,unitconvert:[30,19],take:[20,3,18,41,7,42,33,15],advis:42,phi0:5,green:[41,13],noth:[25,15],channel:19,pc1_1:5,pc1_2:5,sure:[17,8,39,38,44],normal:[20,5],multipli:19,compress:5,tcsyna:29,exclus:29,pair:[13,30,5,41,45,8,19],latex:20,annum:19,wcsaxesa:[5,29],renam:7,later:[26,2,7,43,23,8],typeset:20,parse_single_t:[32,36],axi:[5,4,29,41,44,45],sigma:15,bp_i_j:4,show:[42,11,3,39,38],joshu:44,luminos:19,wcshdr_allimg:29,subprocess:6,permiss:[3,7,5,41,19],hack:[42,7,18],corner:41,label:[44,18,5],has_pci_ja:5,"0f22701":42,xml:[36,14,6,7,21,43,32,8,35,47],onli:[20,3,4,5,7,15,11,34,13,14,8,18,23,25,26,28,29,41,32,33,22,19,36,38,39,40,42,43,44],explicitli:[20,8,7,31],favor:7,activ:[0,23],behind:0,k_1:5,dict:[20,6,41,5,35],test_2:3,test_1:3,restfrq:5,over:[11,13,20,8,29,6,23,7,15,36],backspac:39,variou:[26,14,6,27,33,35],get:[0,25,11,36,28,20,8,3,39,18,26,5,6,41,42,44,33,9,35],repr:5,icunin:29,secondari:28,repo:[42,38],progressbarorspinn:13,cannot:[11,23,33,19,22],ssh:42,theta:[41,5],requir:[10,11,20,23,3,39,5,41,7,43,31,32,33,8,19],icdltna:29,randvar:15,median:15,b1950:8,icrdna:29,restfrqa:[5,29],"376adbd":44,where:[0,11,13,20,15,3,39,18,4,5,23,7,43,42,32,33,29,8,19],vision:[10,26,16,23],summari:[0,26,20,7,44,42,33],wiki:10,wcssub_latitud:[41,5],"__module__":[6,13,40],mixcel:5,xtype:8,bitarrai:35,icrvlna:29,index_bi:44,davgn:29,reserv:[11,8],lng:[41,5],maskedarrai:15,concern:23,detect:[33,38],"__all__":[20,11,15,22],specna:29,review:42,enumer:13,pc2_2:5,pc2_1:5,"278dd2a":42,enough:[23,11,3,15],between:[20,5,29,7,19,23,35,47],"import":[25,11,36,1,23,3,22,20,41,24,46,33,15],bytes_read:13,warning_class:7,across:[23,15,5],pixcrd2:24,parent:[8,7],ctypeia:[41,5,29],pypi:[11,23,43],rare:[7,5,19],teardown_funct:3,add_legacy_alia:1,come:[0,2,39,13,42],"0x14432b0":[],copul:42,sketchi:44,pkgname:33,region:[41,39],tutori:[0,20],ssyssrc:5,improv:[11,26],scope:29,configobj:33,wcssub_celesti:[41,5],color:[11,41,13,44],overview:[10,38,20,2,16,18,42,44],ap_ord:4,latpol:5,pole:5,colon:[42,31,7,29],xml_escape_cdata:6,typic:[1,20,33],sourcetre:9,caret:13,obsgyn:29,implictli:7,invers:5,mark:[20,46,3,39],velangla:29,valueerror:[11,37,14,5,4,41,7,31,19],qsc:5,wcse:41,rotatecd:41,resolut:11,photon:19,squash:42,check_controlled_vocabulari:31,votablechangewarn:7,impati:[26,18],former:33,varfunc:15,icsyen:29,sound:42,hdu:24,interoper:3,tcnamna:29,pedant:[32,7,36],float64:7,cast:0,invok:[3,5],syntaxwarn:7,invoc:5,argpars:25,zenith:[5,24],ctrl:19,metric:19,tcunina:29,henc:[39,3,15],worri:42,scipi:[20,11,23],clutter:20,"__init__":[11,13,40,20,3,6,33],get_config_dir:33,develop:[0,10,11,16,38,26,23,3,17,18,42,43,33,15],cpickl:22,author:[20,7,36],same:[0,26,20,8,3,5,29,6,41,7,24,42,33,15,19],trip:8,binari:[36,5,22,43,41,7,19,28,29,8,35],epoch:[8,5,29],inconsist:[41,5],eventu:[2,3,23],week:44,exhaust:29,finish:[42,18],kelvin:19,nest:[32,8,36],assist:20,driver:33,someon:[42,38],mani:[0,11,36,20,23,3,5,22,7,8],extern:[11,1,2,3,20,8],tcrvna:29,appropri:[14,6,20,35,33],moder:36,vstep:5,choos:[26,42],markup:20,get_ref:8,pep8:[20,11,3,39],without:[11,20,3,5,4,29,7,28,42,33,19],test_answ:3,model:[20,7],dimension:[45,41,7,5,29],noao:7,execut:[20,25,39],when:[25,11,36,28,1,3,39,18,5,6,44,7,20,42,32,33,29,8,19,41],rest:[38,20,39,5,42,44,8],kilo:19,speed:[1,5],get_data_filenam:[1,11,3,33],is_cal:27,miscellan:[21,22],hint:[8,11,7],except:[25,11,36,14,5,29,20,7,44,32,33,8,47],littl:[0,25,42],pvi_ma:[5,29],ssysob:5,versa:5,ufunc:44,translate_unit:[5,19],real:[20,8],around:[2,8,39],"\u03c9":19,rejoin:38,check_token:[14,6],temperatur:19,grid:[45,33],mol:19,world:[20,2,5,29,41,24],mod:22,sternli:42,"0x14ec4f0":15,whitespac:[39,7,5,19],d304a73:44,integ:[25,27,5,41,7,33,35],server:[11,3,8,33],benefit:[23,44],wcshdo_pvn_ma:29,either:[11,13,38,26,2,3,5,29,27,23,7,15,33,8,19,41,36],a_i_j:4,output:[13,27,20,8,42,5,6,41,7,21,44,32,15,36],tower:9,manag:[0,38,2,3,43,9],supplementari:[41,19],iterpars:[6,21],test_wc:3,ascend:20,twcsna:[41,29],crpixja:[45,5,4,29],assertionerror:3,mixin:11,invalidtabularparamet:5,add_num:3,definit:[20,8,7,36],extnum:7,legal:[8,7],cylindr:5,parse_ucd:31,notabl:20,refer:[10,40,20,15,42,5,4,27,23,7,28,45,32,33,8],power:19,table_numb:[32,8],refere:7,convert_to_writable_filelik:27,debug:5,datanam:33,fulli:1,immut:[20,8],"throw":[32,44],stone:23,central:[1,20,23,15],floatingpoint:35,aco:19,greater:[41,5,19,29],degre:[41,5,19],"2x2":[36,28],backup:42,processor:[20,13],routin:[20,5,31],w09:7,effici:[6,5],wcshdr_vsourc:29,redshift:5,stoke:[41,5],your:[0,26,38,1,3,18,42,43,44,33,9],certainli:[41,5],complianc:[6,11,3,12,36],area:[23,19],set_p:5,wcshdo_dobsn:29,k_2:5,hex:33,overwrit:33,start:[20,3,5,6,42,24,33,23,19],interfac:[25,11,23,33,38],low:[27,47],lot:[25,28],hel:5,strictli:[7,29],stage:42,wcaxna:29,svn:0,seek_gzip_factori:42,programmat:[25,24,46],verbatim:27,tupl:[13,20,5,6,41,27,31,45,8,35],bundl:[11,3],regard:[20,2,11],packageormod:33,denomin:19,conclus:20,faster:[32,36,22],pull:[0,26,38,6,42,44,23],tripl:20,coulomb:19,possibl:[0,25,11,36,38,1,2,3,5,20,7,42,23],"default":[28,11,13,20,15,3,39,5,29,27,22,23,7,31,42,32,33,34,8,41],k_m:5,embed:7,connect:42,ohm:19,creat:[11,36,1,3,39,26,4,29,6,44,7,24,14,42,33,34,8,19],deep:[41,5],strongli:[20,11],crderia:[5,29],decreas:5,file:[1,3,6,7,8,11,13,14,18,20,24,27,22,41,31,32,33,34,35,36,39,42,43,44,46,47],fill:[28,39,5,36],incorrect:7,again:[42,8,44],vsysna:29,upcom:1,event:[6,19],field:[36,5,29,41,7,19,32,8,35],wai:[0,26,38,27,1,9,3,39,18,5,20,28,7,43,44,42,33,29,8],check_ucd:31,writabl:[27,6,8,13,32],you:[0,11,36,38,1,9,3,17,18,26,5,20,7,43,44,42,33,8,46],latpna:29,ftp:[33,8],sequenc:[13,40,20,5,6,41,27,32,7],symbol:19,docstr:[20,11,33],multidimension:[8,41,7,5],ansi:13,arcmin:19,radomain:7,extra_attribut:8,vocabulari:[7,31],reduc:[42,23],deliber:42,unbalanc:19,cunit:[5,28],obsgxn:29,directori:[25,11,1,3,39,26,20,42,43,44,33,34],descript:[25,11,36,20,2,42,5,41,7,32,33,8],kilogram:19,construtor:29,mass:19,potenti:[23,5,19,29],escap:[6,13],scm:9,represent:[13,38,5,29,42,28],all:[1,3,5,6,7,15,29,11,13,8,18,20,24,23,22,30,32,33,34,19,36,39,41,42,44,46],consider:[20,12,36],illustr:[20,11],alg:15,forbidden:19,scalar:[20,36],"2_installing_git":9,abil:42,follow:[1,2,3,5,7,8,11,36,16,17,18,20,23,25,26,28,22,41,32,33,29,19,38,39,42,43,44,46],alt:[39,5],csyeria:[5,29],get_xml_iter:6,pycodecheck:39,articl:20,init:39,radena:29,deka:19,scratch:36,testadd42:3,tpvn_ma:29,"case":[11,36,38,20,2,3,5,29,27,7,24,42,33,23,19],liter:[40,13,37,27,14,15,5,4,22,6,41,7,21,19,31,45,32,34,8,35,36],straightforward:42,fals:[25,13,27,8,42,5,29,6,41,7,31,32,33,22,15,36],mpl:[20,11],util:[10,11,40,13,25,14,2,22,6,27,7,21,15,47],print:[11,13,5,22,24,32,33],candid:[20,2],mechan:[11,1,3,29,20,32,23],ssyssrca:[5,29],veri:[25,11,1,3,5,29,20,42,44],unoffici:19,ticket:3,strang:42,induct:19,votablespecerror:[14,7],list:[20,2,5,6,7,8,29,36,18,1,24,23,25,27,22,41,31,32,33,34,19,39,40,42,28],object_attr:6,amend:42,adjust:3,cosin:19,stderr:[14,6],small:[2,11,3],dimens:[41,7,5,28],test_path:3,setup_help:1,maout:15,past:43,zero:[41,8,5],b605216:44,design:[13,1,3,20,7,33,47],pass:[25,11,13,27,3,5,29,6,7,22,36],further:[20,23,11,7],what:[11,1,5,29,20,7,42,33,19],sub:[11,1,8,3,5,20,41,33,15,19],nano:19,sun:19,section:[11,38,20,3,39,26,27,42,44,33,19],abl:[25,38,20,7,44,23],brief:20,delet:[45,42,33,39,5],abbrevi:20,version:[11,36,37,1,2,31,3,5,26,29,14,28,7,43,20,42,33,8,46],intersect:5,consecut:19,eq_fk5:[8,7],method:[11,36,20,2,3,5,6,23,27,43,28,46,33,8,19,41],restwava:[5,29],full:[33,5,29],hash:[11,3,33],variat:[15,5],unmodifi:18,iraf:5,icrotn:29,trunk:[42,38],strong:23,modifi:[5,42,28,33,8,47],valu:[20,4,6,7,15,11,13,8,5,24,23,27,29,41,32,33,19,36,39,40,28,45],tpcn_ka:29,narron:4,ahead:42,hecto:19,prior:[3,7],amount:19,pico:19,keyvalu:[5,29],doctest:20,pick:42,action:[42,25,8],awastropi:[2,11],narrow:46,magnitud:19,via:[11,38,1,3,5,26,41,42,33,23],packagenam:[2,11],declin:36,intermedi:[0,5],transit:23,cfgtype:33,vim:44,filenam:[20,36,14,3,22,6,41,7,32,33],href:[8,7],decrement:5,dangl:19,select:[41,42,5,28],convini:2,regist:11,two:[26,36,20,3,5,29,41,7,28,22,19],book:[0,9],"0x8afe3b0":40,taken:33,wcshdr_crotaia:29,more:[1,3,5,6,7,15,10,11,13,8,18,20,23,25,26,41,32,33,19,36,42,28],flat:[8,36],wrapper:[2,30,46],desir:[25,33,23],equina:[41,29],canon:[5,28],wcsprm:[28,30,5,41,29],is_un:5,ital:20,glat:5,cdelt:[45,5,24],flag:[3,42,18,41,29],particular:[11,13,20,2,3,5,29,41,42,33,8,19],known:[20,11,13],set_valu:11,check_anyuri:[14,6],cach:[33,3,7,34],none:[25,11,13,37,27,14,15,5,29,6,22,41,7,32,33,34,8,35],hour:[5,19],attr_nam:[14,37],oversight:29,outlin:[20,11],histori:[0,10,38,42,28,46],angl:[5,19],remain:[2,33,3,42,5],paragraph:20,del:[45,5],learn:[0,26],dec:[36,41,5,24],def:[25,11,13,1,3,22,20,33],deg:[36,5,19],w50:7,find_current_modul:22,share:42,templat:[1,20,11,23],tabular:[41,5],iter_t:[8,36],minimum:[8,5,44],explor:[20,42],magenta:13,coosi:[8,7],cours:[0,29,44],goal:[20,23],rather:[11,38,1,2,3,6,20,7,24,14,42,23],anoth:[1,5,20,7,44,42,8,19],hugo:44,csc:5,snippet:[0,7],reject:[15,29],mjdobn:29,scienc:46,simpl:[11,27,15,3,18,5,6,41,7,8],unabl:7,resourc:[0,11,36,26,7,43,32,33,8],referenc:[20,8,7],brett:44,reflect:33,catalog:7,plane:[30,5,4,41,46,19],buffer:39,remote_data:3,varianc:15,associ:[20,2,5,29,41,33,8],circumst:[1,5],github:[0,10,26,38,1,17,18,20,42,43,9],e20:7,e21:7,read:[0,11,13,38,20,42,5,4,29,6,30,7,28,32,33,8,41,36],confus:[20,42,19,29],spectra:23,ambigu:[11,19],caus:[39,7,36,29],mjdob:5,csyer:5,votablefil:[32,8,36],simpleelementwithcont:8,help:[0,25,11,1,3,39,26,20,42,23],fft:20,equatori:[8,5],soon:[2,11,33],cross:[8,5],paper:[30,5,29,41,45,46,19],through:[11,1,3,5,20,8],hierarchi:11,"__weakref__":40,e701:39,paramet:[20,13,40,1,15,31,5,4,22,6,41,27,19,14,45,32,33,34,8,35],style:[11,13,20,41,33,23],get_valu:11,dobsn:29,geoscienc:20,resort:20,wrt:19,html:[6,43,33,34,9,47],onelin:[42,38],might:[11,36,3,42,44,33],color_print:13,clariti:11,"return":[20,3,4,5,6,15,13,14,8,18,35,1,27,22,41,31,32,33,29,19,36,37,28,45],sentenc:20,tcrotna:29,framework:[20,3,23,43],compound:19,detach:42,parenthesi:19,document:[1,2,3,7,15,10,11,12,36,8,16,17,20,21,23,26,30,33,39,42,43,44,46,47],cpdis2:41,cpdis1:41,solver:5,instruct:[26,38,17,42,43,9],refresh:[34,39],micro:19,token:[14,6,7],radian:19,radial:5,found:[20,5,29,6,32,33,22],unicod:[6,7,13,8,36],errata:29,truncat:[7,13],memoryerror:[41,5,4],inplac:[39,15],icunna:29,monoton:5,procedur:23,realli:38,expect:[11,36,1,5,27,7,33],energi:19,beyond:13,todo:[20,27,43],orient:[20,11,15],phi_0:5,agre:23,shortcom:36,publish:[41,5],get_convert:35,set_pv:[5,24],sparingli:20,difficulti:29,qualifi:5,advanc:[0,42,26,17,18],tcrpna:29,votlint:34,reason:[11,38,20,39,29,42],base:[11,36,40,2,3,5,6,41,7,24,28,42,33,34,8,19],put:[20,26,3,33],bash:39,basi:36,veloc:[5,28],upsilon_m:5,perhap:[42,5],amper:19,lightgrei:13,assign:[20,7],excurs:39,velo:[5,28],obviou:[20,7,29],upper:[41,5],feel:33,misc:[15,21,19,22],number:[40,13,27,20,2,3,39,5,29,6,23,7,24,15,28,32,22,8,19,41,36],velangl:5,placehold:44,footprint:41,smaller:39,done:[26,38,1,3,18,5,41,42,44,23],construct:[8,5],stdlib:41,blank:[20,39,5,29],stabl:[1,23],miss:[8,7,36],fanci:[42,44],differ:[26,13,20,3,39,5,22,27,30,7,33,23,41],exponenti:19,lightcyan:13,farad:19,interact:[42,39],radesi:5,least:[20,14,29,6,7,19],statement:[6,33,13],natur:[20,19,29],illeg:7,steradian:19,scheme:[1,25,11,33],store:[11,36,1,3,5,29,41,7,33,8],schema:[14,6,7,32],adher:11,luckili:42,stdout:[14,6,32,13,5],option:[1,3,5,7,8,11,13,18,35,20,25,27,22,41,31,32,33,34,19,38,39,40,42,43,46],ncp:5,similarli:[11,3],tabwidth:13,pars:[25,36,5,7,24,31,32,8,47],consult:3,setup_packag:1,simplist:[14,6],whenev:[23,7,38],remot:[0,38,20,3,42,44,33],remov:[20,3,39,5,42,34],dtd:[14,6,32],gref:7,stall:23,str:[20,13,27,14,5,22,6,7,31,32,33,8,36],cunitia:[41,5,29],pvi_4a:5,comput:[26,20,5,29,42,44,33,15,19],cubefac:[41,5],packag:[10,11,16,36,1,2,3,17,26,22,20,43,23,42,15,28,33,8],doublecomplex:[8,7,35,36],"null":[8,7],lie:5,built:[11,13,1,3,20,43,33,34],equival:[11,36,20,5,29,7,19],check:[20,38,14,3,39,18,5,6,7,21,42],self:[20,11,3,5,41],violat:[32,7],get_naxi:41,also:[26,36,20,2,3,39,5,29,43,23,7,8,44,42,32,33,9,19,41],build:[10,11,36,1,23,16,6,28,24,43,20,46,8],joul:19,brace:20,imgpix_matrix:5,zepto:19,w40:7,w41:7,pipelin:[46,30],w43:7,w44:7,distribut:[10,11,16,13,25,1,3,33,15],w46:7,w47:7,w48:7,w49:7,previou:[42,39],reach:[23,38],most:[11,13,1,26,29,6,7,20,42,33,22],get_table_by_id:8,exc_valu:13,plan:[1,43],conic:5,maco:9,alpha:20,hashorurl:33,numericarrai:35,charg:19,exc:7,exa:19,clear:[20,33,8,22],cover:[26,3,43],part:[25,11,27,14,2,30,31,6,23,7,20,33,8,19,47],clean:0,warmli:18,icrdena:29,microsoft:28,somewhat:7,cdb:33,carefulli:20,tcdn_ka:29,fink:9,session:[33,3],particularli:20,font:[20,39,13],utyp:[8,7],find:[26,1,18,22,41,42,33],e19:7,cell:[7,36],coerc:27,randn:15,pretti:44,e11:7,e10:7,e13:7,ultim:[26,23],solut:5,e14:7,e17:7,e16:7,factor:19,darwin:3,"6d8e1e":44,hit:11,unus:11,express:[7,19],nativ:5,celementtre:6,fastest:[7,5],stc:7,coord:[20,45,41,5],rfc:[14,6,7],common:[0,10,11,20,23,16,26,41,44,33,15,19],new_file_nam:42,nowher:[8,5],seamlessli:23,votable1:7,set:[1,3,5,7,8,11,36,18,20,24,23,27,28,29,41,32,33,34,38,39,40,42,43,44],equinox:[8,5],decompos:5,mutabl:[8,28],emac:[11,39],arc:19,bare:44,arg:[25,11,13,27,6,41,7],close:[38,6,42,7,33,19],configdir:33,barn:19,expert:20,jenkin:1,someth:[25,11,36,3,18,6,42,44,33],particip:43,struct:[28,29],has_crotaia:5,lonpolea:[41,5,29],won:11,teardown_modul:3,find2:22,find1:22,altern:[2,3,5,29,6,7,43],signatur:20,catalogu:[7,37],syntact:[14,6,41,5],web:[20,34,38],numer:[27,8,7,35,19],complement:5,cproject:7,disallow:[7,19],func_c_:20,lowercas:7,cachedir:33,len:13,ipython:42,"_generate_all_config_item":33,popul:[33,36],both:[11,36,1,3,5,4,29,20,41],last:[27,5,29,41,7,42,15],mega:19,numpydoc:20,package_data:1,f2w:5,context:[13,20,39,5,7,19],whole:[1,33,36,29],iowarn:7,load:[36,1,39,41,24,46,32,33,47],simpli:[11,36,20,8,3,5,29,33,9,19],celesti:[41,5],point:[11,20,8,5,6,41,7,24,45,42,15],format:[28,36,20,3,18,5,27,41,7,44,33,8,35],returncod:[14,6],header:[20,1,5,4,29,6,30,7,24,43,28,46,41],"5e9":11,param:[8,7],linux:[0,42],mistak:[42,29],throughout:[20,15,7],e221:39,backend:3,sever:[20,39,18,42,28,9],extrema:5,java:[11,34],tctypn:29,devic:19,due:[25,11,7],empti:[20,8,39,7,13],get_legacy_alia:1,check_unit:37,imag:[36,20,5,4,29,30,7,28,45,46,19,41],great:[20,26],append:[8,40,7,36,22],wcshdr_cd00i00j:29,coordin:[11,20,2,5,4,29,23,7,24,28,45,46,33,8,26,41],understand:[20,11],func:3,det2im:[46,41],repetit:7,iter_coosi:8,look:[13,38,1,3,20,7,42,33,8,36],solid:19,erron:[5,29],histor:[5,29],"while":[13,1,3,5,29,20,7,42,33],unifi:[7,19,47,31],abov:[11,13,38,1,3,5,29,20,7,44,42,33],error:[13,14,5,19,20,41,7,24,28,32,35,36],pix2ski:20,anonym:8,loop:36,earli:29,vol:20,transfor:5,readm:42,wcs_sky2pix:[46,41,24],"2dec1ac":42,centi:19,itself:[36,1,23,3,29,7,33,8,19],limit:[10,20,15,5,29,7,8],decor:3,irrelev:5,fedora:9,minim:19,zopt:5,belong:20,shorten:44,instal:[10,11,1,2,3,17,26,23,42,39,43,32,9],cd00i00j:29,funni:18,lengthi:11,pytest:3,simpleel:8,conflict:[42,7],higher:[32,23],"_descriptionproperti":8,archiv:[11,7],optic:28,tvn_ma:29,optim:5,wherea:[7,5,19],moment:[14,6,36],temporari:[20,3,41],user:[0,10,11,13,1,2,3,18,26,29,20,23,42,44,33,15,19,41],robust:[11,23],wherev:[11,3,8],stack:22,focal:[46,41,4],recent:[6,26,9,22],subpackag:[1,2,11,33],lower:5,has_crota:5,machineri:[1,8],discourag:[20,11,23],older:[25,11,7,5],entri:[8,5,28],pickl:22,person:44,expens:11,runtimewarn:7,propos:[7,44],explan:[20,42,7],unicodechar:[8,7,35,36],det2im1:41,det2im2:41,collabor:42,shape:[20,15,19],cel_offset:5,sugget:11,unicodestr:7,somepackag:25,botch:42,wcshdo_wcsnna:29,appli:[5,22,41,42,33,29,8,19],input:[25,11,36,20,5,41,7,15,35],"395dd6493cc584df1e78b474fb150840":33,float32:7,obsgeo:[5,29],bin:[25,11,39,19],sobsna:29,australia:46,eoferror:22,transpar:3,invalidwcsexcept:20,bit:[36,35,5,29,41,7,8,19],analogu:29,"2e991e8":44,formal:[5,19,29],fixup:42,jcrpxna:29,e08:7,e09:7,e06:7,docutil:[20,4,6,7,15,13,14,8,5,35,21,27,22,41,31,32,34,19,36,37,40,45],signal:[42,18],e05:7,e02:7,resolv:42,e01:7,"3d_cd":[1,33],collect:[6,34,42,21,40],mjdan:29,eadc391:42,encount:[32,7],to_header_str:[41,29],often:[11,20,3,42,8,19],visibl:[20,5],some:[0,1,2,3,5,6,7,11,13,18,20,24,23,25,28,33,36,38,39,42,43,44],back:[36,20,18,22,7,24,42,8],iter_fields_and_param:8,understood:5,unspecifi:5,sampl:[11,15],mirror:42,w45:7,affili:[10,11,16,1,2,3,17,26,20,33,23],scale:[41,5,19],support:[11,36,1,23,3,5,30,7,28,46,33,8,19,41],ijcdna:29,shall:20,pep:[20,11],per:[11,13,36],substitut:5,mathemat:[20,19],larg:[20,3,34],slash:19,mhz:19,machin:[0,34],print_cont:[5,24],run:[20,2,3,39,28,43,44,33,34],solrad:19,sacrif:20,step:[26,36,5,42,44,45,13],prerequisit:43,meantim:42,faith:[42,18],idx:8,constraint:29,preclud:23,wcshdr_projpn:29,optpars:25,buxfix:42,block:[11,7,33],repair:7,"__future__":24,emphasi:20,primarili:[23,11,15],within:[1,15,3,5,7,33,8,19],pvi_1a:5,pastebin:3,watt:19,randomize_posit:20,ensur:[11,13,3,39,41,7,42,23],dateavg:5,test_my_bug:18,inclus:[2,26,23,19],span:[40,13,37,27,14,15,5,4,22,6,41,7,21,19,31,45,32,34,8,35,36],make_validation_report:34,question:20,fast:[20,6,38],custom:[1,44],"__enter__":13,wcsunit:5,includ:[25,11,13,38,1,2,3,5,6,23,42,15,8,20,32,33,9,19,41,36],suit:[2,3,43],forward:38,parse_arg:25,xdg_cache_hom:33,properli:28,msi:43,poster:42,linu:0,gauss:19,link:[0,26,1,7,43,42,8],translat:[28,41,5,19],newer:[1,7],delta:5,line:[10,11,16,13,38,25,20,3,39,18,26,6,41,7,44,42],info:[11,20,26,7,44,8],utf:[25,36],tcrpxn:29,consist:[20,25,11,23,5],yotta:19,those:[0,25,13,38,1,23,3,5,29,20,7,24,28,42,33,15,36],highlight:[39,13],yyyi:5,similar:[42,33,41,15],curv:5,constant:[20,5,29,30,8,41],zetta:19,lyr:19,parser:[25,29,6,7,19,34,8,35],chan:19,doesn:[1,5,6,41,7,42,33,8,19],repres:[13,20,5,4,7,45,42,8,19,36],"char":[8,36,7,13,35],parsec:19,darkgrei:13,fieldref:8,specsi:5,titl:[42,8],nan:[45,7,5],invalid:[20,5,4,41,7,31,32,19],bracket:19,angstrom:19,new_wc:[41,5],nice:[0,6,20,18,44],test_funct:3,floatcomplex:[8,7,35,36],introduc:[3,29],meaning:[41,5],crota:[5,28],lightgreen:13,longitud:[41,5],deserv:20,ago:44,infrequ:20,algorithm:[20,11,41,15,5],vice:5,max_inclus:8,depth:[0,3,22],summit:44,broad:2,far:22,unboundedstr:7,velref:[28,29],code:[10,11,16,13,25,1,2,3,39,18,26,5,20,41,7,44,42,33,23],partial:[41,5],queri:[8,33,7],cenfunc:15,edu:[33,7],rfrqna:[41,29],compact:[36,38],cython:[1,10,11,3,16],privat:[20,12,47],sensit:[33,19],elsewher:[20,8],func_:20,friendli:[41,13,19],send:[32,18],macport:9,somemod:25,aris:[7,5],fatal:7,logarithm:[41,5,19],datafil:3,print_code_lin:13,distribute_setup:1,minerr:41,mous:39,electron:19,implicitli:[6,3],relev:[11,1,16,5,20,7,33],tri:[41,5],magic:0,unsignedbyt:[8,7,35,36],meant:[20,8,7],complic:[11,42,5],button:42,michael:46,fewer:[7,22],undistort:41,update_package_fil:1,w29:7,set_color:11,blocksiz:13,pleas:[42,18],impli:[20,7,38],cdfix:5,cfg:33,zsourc:5,submultipl:19,jump:39,blanklin:20,video:0,download:[11,9,3,39,43,33,34,23],click:42,quadcub:[41,5],compat:[1,25,11,5],index:[10,11,2,5,4,22,19],compar:38,fine:29,access:[11,38,1,15,3,18,5,27,23,7,28,42,33,34,8,47],geo_app:[8,7],can:[0,1,3,5,6,7,9,11,13,14,8,17,18,20,24,23,25,26,28,41,33,19,36,38,39,42,43,44,46],equinoxa:[5,29],consolid:23,usag:[10,11,36,20,3,5,29,41,24,46,33,15],matplotlib:[20,11,23],bodi:6,piximg_matrix:5,let:[42,11,39,38],sinh:19,ubuntu:9,layout:[2,11,16,23,10],safer:11,becom:[20,3],sinc:[11,14,3,39,18,5,6,7,28,42,8,19],convert:[25,13,20,28,5,4,19,6,41,7,24,44,32,8,35,47,46],to_head:[29,5,41,24],convers:[28,35,47,19],larger:[20,25,3],fix_id:[14,6],converg:15,chang:[28,11,38,20,3,18,4,5,41,7,44,42,33,29,26],chanc:20,writer:[6,21],danger:11,e15:7,foundat:0,submodul:11,apt:9,volt:19,api:[10,12,20,30,21,44,46,33,15,47],"__name__":22,underflow:19,subimag:[41,5],from:[0,1,3,5,6,7,8,9,10,11,36,14,15,18,19,20,24,23,25,28,22,41,33,34,35,38,39,42,43,44,45,46],commun:[0,2,23],isn_ma:29,doubl:[36,20,5,4,19,7,45,33,8,35],upgrad:7,next:[33,11,13],websit:39,eleven:19,usr:[25,11],crab:19,deepcopi:41,jonathan:44,sort:20,datfix:5,trail:[39,5],get_offset:45,toolchain:20,getter:11,iii:[5,29],w33:7,account:[41,42],alik:29,retriev:[6,33,3,7,36],augment:[20,28],dest:25,alia:[41,42,5,44],meet:11,fetch:[42,38],control:[11,1,42,5,26,29,7,31,32,33,19],malform:[7,5],vsourcea:29,process:[25,11,13,1,5,20,28,23],lock:39,sudo:9,high:[32,24],tag:[6,7],some_func:33,tab:[11,39,13,5],tarbal:43,onlin:0,serial:8,has_colon:31,imgcrd:5,sip:[41,46,30,4,28],pycheck:39,six:5,pci_ja:[41,5,29],tabledata:[8,7,35,36],has_cd:5,sig:15,teardown_method:3,instead:[11,38,1,15,39,18,5,20,22,7,33,29,8],narg:25,sin:[5,19],delai:39,int16:7,recomput:28,singular:[41,5],keithdeven:11,pyfit:[1,46,41,24,28],differenti:5,attent:42,ijpcna:29,mjd:[5,29],alloc:[41,8,5,4],store_tru:25,light:19,correspond:[8,33,41,7,5],element:[13,40,27,5,6,41,7,32,33,8,19,36],issu:[42,32,11,7,33],prettifi:13,allow:[11,1,23,3,39,5,29,20,7,42,8,19],cdi_ja:[45,5,29],get_field_or_param_by_id:36,fallback:7,move:[11,18],kbd:39,whilst:[20,19],comma:7,bunch:6,finddiff:22,mod2:22,outer:44,e04:7,consensu:23,chosen:26,tsc:5,therefor:[32,41,7],pixel:[20,5,4,29,41,24,28,45,46,19],weber:19,pci_j:[41,5],crash:[0,39],fourth:5,python:[1,2,3,6,7,10,11,13,16,5,20,24,23,25,26,27,22,41,32,33,36,39,43,28,46],auto:39,dai:[5,19],xml_escap:6,dat:33,mention:20,facilit:[20,23],front:[3,13],strive:23,multiprocess:[34,13],somewher:18,recarrai:8,anyth:[11,42,18],edit:[0,20,18,42,44,33],wdiff:44,astronom:[8,23,7,19,37],create_arrai:[8,36],scrollbar:13,mode:[36,39,18,22,7,32,13],mnemon:29,astroyear:7,tmpdir:3,upward:20,few:[20,42,11,23,38],w19:7,w18:7,w17:7,subset:[20,5],w15:7,strip:5,w13:7,w12:7,localfn:33,w10:7,consum:32,meta:[8,7],"static":[6,3],wcshdr_pc00i00j:29,hyperbol:19,patch:[23,18,38,28],metavar:25,special:[40,1,8,5,20,23,21,28,15,41],out:[11,13,38,23,18,5,6,41,7,24,32,8,36],variabl:[11,36,20,3,39,7,33,8],overridden:29,contigu:5,defaultvalu:33,mjdavg:5,"4aff2a8":44,spline:13,reflog:42,rel:[25,11,1,3,39,5,20,41,7,44,42,33,15],calcfootprint:41,ref:[42,8,7,5],reg:41,math:20,clarifi:20,nonseparablesubimagecoordinatesystem:[41,5],workflow:[0,26,38,17,18,42,46],md5hash:33,standalon:[1,3,23],crval:[45,5,24],dictionari:[1,5,6,41,8,35],latest:[26,7,43],releas:[1,23,9,43,28],embarrass:42,log:[0,42,19,38,44],find_diff:22,indent:[20,6,11,39],unwant:42,could:[6,28,23,5,29],ask:42,supergalact:[8,7],keep:[20,42,23,36],scari:38,length:[13,20,5,41,7,8,19,36],cname:5,outsid:[11,23],all_pix2ski:[46,41],ivoa:[7,31],softwar:[26,7],suffix:39,parabl:0,qualiti:23,date:[20,3,5,29,7,44],"68f6752":44,some_dir:3,hertz:19,lib:42,facil:46,"long":[11,13,38,3,29,7,28,8,35,36],strict:43,unknown:[7,5],licens:[20,46,11],system:[10,11,20,2,3,39,5,26,23,7,33,34,8,19,41],messag:[13,14,39,18,7,28,42,32,35],eighth:5,is_valid:32,get_field_by_id:8,lumen:19,termin:[20,13],man:42,"final":[36,3,42,18,5],prone:11,shell:34,icrotna:29,wavelength:5,fuzzi:20,shallow:41,has_length:13,rst:11,exactli:[20,23,7,13,22],haven:18,succinctli:42,tangl:42,colax:5,see:[10,11,1,2,3,42,18,26,5,20,22,41,7,43,32,33,29,8,19],structur:[36,20,5,24,46,8],charact:[20,13,14,39,5,29,6,7,19],siemen:[5,19],sens:[20,41,7,5],sec:19,exp:19,cylfix:5,e18:7,clip:15,terribl:7,falsi:5,julian:[7,5,19],icdltn:29,corran:44,teardown_class:3,have:[0,1,3,5,7,9,11,13,14,8,17,18,20,24,23,26,22,41,33,29,19,36,38,42],tabl:[10,12,36,20,23,5,29,30,7,47,28,45,32,8,19,41,46],need:[25,11,38,1,23,3,39,5,26,29,20,7,43,44,42,8,19,46],tidi:38,cfg_option:33,ecl_fk5:[8,7],ecl_fk4:[8,7],min:[8,7,19],rout:43,mid:5,accuraci:8,mix:5,unawar:11,discret:20,"_wc":5,which:[1,2,3,6,7,8,11,13,14,5,20,23,26,27,28,29,32,33,22,19,36,39,42,44],discrep:15,int64:7,detector:[46,30,19,41],singl:[25,11,36,1,2,5,22,20,23,42,45,33,8,19,41],uppercas:7,pyx:[1,11],a7ff2e5:44,unless:[11,29,23,19,44],preliminari:42,githhub:42,who:[3,23,18,38,44],discov:[20,3,18],sfl:5,eight:29,dateob:5,has_pc:5,judici:20,why:[11,42,18],"_build":43,crpix:[45,5,4,24],shupe:4,url:[32,33,3,42,34],test_42:3,request:[11,38,2,26,42,44,33,23],uri:[14,6,7,8],face:[39,5],yum:9,determin:[11,13,5,22,6,41,33,8],flux:19,occasion:19,hardcor:42,fact:[11,29],text:[38,20,39,6,42,44,33,19],syntaxerror:19,verbos:3,invalidsubimagespecificationerror:[41,5],bring:[42,39,36],stilt:34,cfgoption:33,tcrdena:29,trivial:[11,29],wcspih:[41,28],setter:11,homogeneouslist:40,maskedconst:42,locat:[11,1,23,5,20,7,33,8],xmlwriter:6,jar:34,should:[25,11,36,38,1,23,3,5,29,20,41,7,24,44,42,33,22,15,19],schema_fil:6,suppos:[1,33,42,36],wcsax:[41,5],discontinu:5,"721fc64":42,wcssub_longitud:[41,5],cube:5,contribut:[42,10,26,16,17],celfix:5,disagre:5,velrefa:29,autom:[1,33],get_table_by_index:8,meter:[5,19],increas:[23,5],cdeltia:[45,5,29],lngtyp:[41,5],a725fa6ba642587436612c2df0451956:33,wcshdr_epocha:29,enabl:[11,3,39,29],organ:[42,11,3,23],stuff:[25,42,38],shd:[5,19],integr:[11,38,20,23,26,7,8],contain:[11,40,36,38,44,1,2,31,3,5,22,6,23,7,15,20,32,33,8,19,41],view:[20,33,5],conform:[11,36,29,7,8,19],legaci:1,modulo:24,frame:[27,5],min_inclus:8,statu:[0,44,42,18,5],correctli:[42,6,3,17,43],record:[8,7,5,36],lux:19,pattern:[11,7,33],thumb:[0,7],e12:7,state:[20,42,7,13],quickest:18,progress:[42,18,13],neither:[33,8],email:[26,18,44],w08:7,terhorst:44,kei:[8,39,5,41,42,33,23],mod1:22,w04:7,w05:7,w06:7,w07:7,w01:7,w02:7,w03:7,tempfil:3,job:1,entir:[11,20,8,6,32,23,47],crotai:29,w38:7,eclipt:[8,5],addit:[11,16,20,23,3,39,5,41,7,43,34,9,19],plugin:3,admin:42,equal:[17,5,44],configpars:33,etc:[38,20,8,5,29,41,43,23],admit:[41,5],instanc:[11,36,20,42,7,32,8,35],grain:29,equat:20,committe:[11,23,26],highland:20,comment:[11,20,5,6,41,33],theta0:5,ra_dec_ord:41,icsyna:29,guidelin:[10,11,16,20,3,39,26,23,19],argumentpars:25,gitk:42,solv:5,ucd:[8,7,36,47,31],sky2pix:20,respect:[20,3,17,5,41,7],gitx:9,quit:42,get_indentation_spac:6,addition:[11,30,8],writeto:24,get_pv:5,compon:[26,11,5,7,31,23,19],treat:[28,7,29],"0x8758990":[],immedi:[33,3,42,5,19],get_pc:[5,28],e202:39,get_data_cont:33,presenc:5,assert:[3,24,44],untrack:42,x_2:7,togeth:[46,30,23,29],solmass:19,velosi:5,b_i_j:4,present:[11,1,39,5,29,41,7,28,45,42,33,15],rightward:29,simpletyp:7,multi:[20,7],besselian:7,wcshdo_non:29,to_xml:[8,36],get_indent:6,"__iadd__":40,cursor:39,defin:[1,3,6,7,8,11,13,14,5,20,24,27,29,30,31,33,36,37,40,41,45,47],wild:[8,7,36],pc00i00j:29,observ:5,tpn_ka:29,get_axis_typ:41,helper:[1,33,3],almost:[41,5],setup_class:3,pix2foc:[41,4],unitfix:5,site:20,mulitpl:11,inform:[10,11,16,36,1,2,3,42,5,26,29,20,41,7,24,46,32,33,8,19],motiv:20,get_:11,revis:42,avg:[5,29],uncategor:[21,22],uniti:[41,5,19],wcshdr_velrefa:29,mutat:36,welcom:10,parti:[1,11],began:28,defun:39,sqrt:19,member:[36,5,41,28,8,13],handl:[20,5,29,30,7,28,42,35],s2p:5,float_:24,psi_ma:[5,29],failur:3,"__version__":2,infer:33,competit:23,phi:5,http:[11,1,9,3,20,7,43,42,33,34,8],booleanarrai:35,a_ord:4,upon:[23,7],effect:[36,19,22],hdulist:[46,24],get_config:33,icnamn:29,femto:19,set_:11,distutil:[1,43],expand:0,chunk_siz:32,off:[36,38,3,5,41,7],center:[15,36],neural:20,well:[11,20,17,5,29,6,42,44],thought:[33,42],weblog:11,exampl:[1,3,5,7,8,9,10,11,36,15,17,18,20,24,23,25,26,27,22,41,33,29,19,38,39,42,44,46],command:[0,10,11,16,25,3,39,18,42,43,44],achiev:[42,23,15],interpol:5,undefin:[45,8,5],usual:[20,42,5,43],test1:36,spcaip:28,test2:36,paus:42,less:[11,41,13,19,5],"boolean":[36,15,5,7,8,35],check_mime_content_typ:[14,6],wcshdo_cnamna:29,obtain:[20,3,39,43],settabl:8,spcfix:5,sptr:5,systemat:5,"_________________________________":3,expon:19,adu:19,omit:[6,7,5,36],wcssub_spectr:[41,5],onward:28,sky:[20,46,41,5,24],vangna:29,spinner:13,script:[10,11,16,25,1,3,39,33,23],add:[0,38,20,28,39,18,6,42,44],valid:[37,27,14,28,5,6,7,21,43,31,32,33,34,8,47],densiti:19,lookup:[5,30,28,45,46,8,41],warrant:15,c16:36,match:[13,20,3,5,6,7,33,15,19],int32:7,eq_fk4:[8,7],torvald:0,"11ee694744f2552d":42,branch:[0,38,18,42,43,44],tcnamn:29,b_order:4,hard:[20,41,42,5],punctuat:7,know:[42,11,8],press:39,tick:20,recurs:[3,8],is_unit:37,insert:[42,40,39,13],like:[11,13,38,20,15,3,42,29,6,27,24,44,32,33,22,8,19,36],success:5,safest:3,fernando:0,test_:3,use_system_pytest:3,necessari:[25,11,20,18,26,5,43,44,33,8],resiz:[36,4],page:[0,10,26,38,20,16,17,42],cfgobj:33,photometri:23,specifi:[28,11,36,20,15,3,39,5,4,29,40,41,7,31,33,22,8,19],habitat:20,revert:5,suppli:[11,5,24],destdir:34,sophist:42,get_data_fileobj:[1,11,3,33],superclass:11,flush:6,proper:[11,7],home:[33,42,44],wcssub_cubefac:[41,5],librari:[25,11,13,6,1,2,39,14,27,32,33,23,47],tmp:[3,42],guid:[0,11,20,16,42,33],lead:11,leak:42,avoid:[11,20,7,42,23,19],rwavna:29,disk:36,estim:15,filesystem:33,speak:[7,29],encourag:[20,11,23,26],bintabl:29,importerror:11,deprec:[20,46,41,7,5],symlink:33,stellar:19,host:[1,11,17],cgreen:44,although:[41,5,19],offset:[45,6,39,5,19],has_cdi_ja:5,simpler:[25,11],about:[11,36,20,15,18,26,41,7,43,42,33,8],actual:[25,5,29,7,44,42,33,8],interven:19,polynomi:[41,46,30,4],column:[13,20,39,5,29,7,46,32,8,36],cleans:7,justif:11,candela:19,invalidtransformerror:[41,5],constructor:[20,46,13,29],discard:42,compute_color:11,disabl:[1,3,42],metr:19,own:[0,25,38,1,23,3,20,7,42,15],convolut:20,inlin:[20,7,19],easy_instal:39,automat:[38,1,3,39,7,33],diagon:[41,5],ssrcna:29,merg:[0,26,38,2,42,44],dec_targ:36,val:33,bp_order:4,rotat:5,pacakg:20,"var":[20,15],anno_opt:33,"function":[1,3,6,15,11,13,5,35,20,23,25,22,30,31,32,33,19,36,41,28,46,47],basic:[26,38,20,39,5,41,43,46,33,19],gaussian:15,astro:7,w11:7,wcs_pix2ski:[46,41,24],overflow:19,highest:5,bug:[11,36,20,3,18,26,28,7,44,42],test_bugfix:44,count:[27,19],succe:3,made:[26,36,38,11,18,7,5,44,42,33,23,19],temp:39,dmg:43,whether:[28,41,13,5],wish:[2,33,23,43],"_astropy_vers":8,writeabl:13,displai:[20,39,13],w31:7,w30:7,below:[11,1,8,3,39,5,26,29,20,41,33,22,15,19],w32:7,lattyp:[41,5],w34:7,w37:7,w36:7,w39:7,otherwis:[11,8,3,42,5,22,6,41,7,31,32,33,15],problem:[42,11,7,33],subordin:29,a815645:42,"int":[20,13,14,15,5,4,29,6,41,7,28,32,22,8,35,36],mask:[36,15,39,7,42,32,8],dure:[1,42,23,36,44],pix:19,implement:[25,11,36,20,23,3,7,42,33,8,19],our:[20,42,38],pip:[39,43],probabl:[1,18,5],"2to3":[25,11,3],detail:[0,28,26,36,1,2,3,18,5,20,41,42,44,33,22,8],other:[0,1,2,7,8,11,36,15,5,20,23,29,41,32,33,22,38,9,40,42,43,28],bool:[13,20,8,5,22,27,41,31,32,33,34,15],futur:[36,1,8,3,5,29,6,23],rememb:[42,19,38],varieti:11,stat:[5,44],repeat:[42,39],star:11,"class":[20,3,4,6,7,15,11,13,14,8,5,19,21,23,25,27,22,30,31,32,33,34,35,36,37,40,41,28,45,46,47],astronomi:[10,26,2,16,15,23],invalidconfigurationitemwarn:33,imppedi:11,ndarrai:[20,15],tcrden:29,content_rol:8,vo_rais:7,debian:9,tan:19,matrix:[36,5,4,41,28,45],sphinx:[20,43],find_all_wc:[41,29],nrow:[8,7,36],complexarrai:35,rule:[0,20,11,3,19],votablespecwarn:[7,36],auxiliari:[5,29],partli:25,enforc:44,cookbook:27},objtypes:{"0":"py:module","1":"py:method","2":"py:function","3":"py:staticmethod","4":"py:attribute","5":"py:classmethod","6":"py:class","7":"py:exception","8":"np:module","9":"np:method","10":"np:function","11":"np:staticmethod","12":"np:attribute","13":"np:classmethod","14":"np:class","15":"np:exception"},titles:["Git resources","Building, Cython/C Extensions, and Distribution","Overview","Testing Guidelines (Draft)","Sip","Wcsprm","astropy.utils.xml: Utilities related to XML","astropy.io.vo.exceptions","astropy.io.vo.tree: Accessing and modifying the individual parts of VOTable files","Installing git","Welcome to Astropy’s Documentation!","Coding Guidelines (Draft)","astropy.io.vo Documentation","astropy.utils.console: Utilities for console output","astropy.io.vo.xmlutil: XML-related utilities used by the library","astropy.tools documentation","Documentation for Developers","Development workflow","Development Workflow (Beginner)","UnitConverter","Documentation Guidelines (Draft)","astropy.utils documentation","astropy.utils.misc: Miscellaneous/uncategorized Utilities","Vision for a Common Astronomy Python Package","Example Usage","Writing Command-Line Scripts","Contributing To/Developing Astropy or Affiliated Packages","astropy.io.vo.util: Low-level utilities used by the library","astropy.wcs History","Relax constants","API Documentation","astropy.io.vo.ucd: Functions to parse and verify unified content descriptors","astropy.io.vo.table: Loading entire VOTable files","Configuration system Documentation","astropy.io.vo.validator: Generates HTML validation reports","astropy.io.vo.converters: Conversions between XML and Numpy datatypes","Introduction to astropy.io.vo.table","astropy.io.vo.unit: Verification of units as defined in the VOTable standard","Maintainer workflow","Emacs setup for following coding guidelines","astropy.utils.collections: Specialized collection classes","WCS","Development Workflow (Advanced)","Installation","Configuring git","DistortionLookupTable","astropy.wcs Documentation","API documentation"],objnames:{"0":["py","module","Python module"],"1":["py","method","Python method"],"2":["py","function","Python function"],"3":["py","staticmethod","Python static method"],"4":["py","attribute","Python attribute"],"5":["py","classmethod","Python class method"],"6":["py","class","Python class"],"7":["py","exception","Python exception"],"8":["np","module","Python module"],"9":["np","method","Python method"],"10":["np","function","Python function"],"11":["np","staticmethod","Python static method"],"12":["np","attribute","Python attribute"],"13":["np","classmethod","Python class method"],"14":["np","class","Python class"],"15":["np","exception","Python exception"]},filenames:["development/workflow/git_resources","development/building_packaging","overview","development/testguide","wcs/api_sip","wcs/api_wcsprm","utils/api_xml","vo/api_exceptions","vo/api_tree","development/workflow/git_install","index","development/codeguide","vo/index","utils/api_console","vo/api_xmlutil","tools","development/index","development/workflow/development_workflow","development/workflow/development_workflow_basic","wcs/api_units","development/docguide","utils/index","utils/api_misc","development/vision","wcs/examples","development/scripts","development/workflow/index","vo/api_util","wcs/history","wcs/relax","wcs/api","vo/api_ucd","vo/api_table","configs","vo/api_validator","vo/api_converters","vo/intro_table","vo/api_unit","development/workflow/maintainer_workflow","development/codeguide_emacs","utils/api_collections","wcs/api_wcs","development/workflow/development_workflow_advanced","install","development/workflow/git_configure","wcs/api_distortion","wcs/index","vo/api"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{all:2,code:[0,2],steve:3,follow:[1,2,3],decid:2,depend:2,send:[0,3],decis:3,ginsburg:3,mechan:2,grollier:3,level:2,gui:2,list:[0,1,2,3],barbari:3,team:[2,3],div:1,readthedoc:1,pleas:[0,1,3],prevent:2,cfa:3,direct:2,nair:3,sign:1,across:[1,2],download:2,further:2,even:0,what:1,abl:2,uniform:2,access:2,version:1,"new":[0,2],ever:2,method:2,ongo:1,berkelei:3,gener:2,never:2,droettboom:3,here:[0,1,3],satisfi:2,layout:2,strong:2,valu:2,wait:2,current:2,prasanth:3,chang:0,via:[0,2],lawrenc:3,transit:2,prefer:0,instal:[1,2],unit:1,from:[1,2],would:2,commun:2,univers:3,websit:0,few:2,criteria:2,crighton:3,until:2,more:[1,2],desir:2,photometr:1,particular:1,effort:1,must:2,irvin:3,join:0,setup:1,work:[0,1,2],dev:[0,3],can:[0,1,2],asciit:1,tar:1,process:2,templat:2,want:[0,1],alwai:2,goal:2,rather:2,nyu:3,how:2,updat:1,astropi:[0,1,2,3],clone:1,pyfit:1,lab:3,befor:2,mai:[1,2],grow:2,github:[0,1],spectra:2,issu:[0,1],maintain:3,allow:2,order:2,help:[1,2],over:[0,2],becaus:2,robitail:3,report:[0,1],ticket:1,greenfield:3,style:2,thank:3,fit:2,fix:0,onc:[1,2],mail:[0,1,3],main:2,them:2,scipi:2,thei:2,handl:1,wolfgang:3,initi:2,nation:3,framework:[1,2],facilit:2,discuss:[1,3],strive:2,choic:2,term:2,eventu:2,name:3,photometri:2,astronom:2,found:1,sato:3,mean:2,neil:3,michael:3,individu:3,idea:0,procedur:2,ensur:2,manifesto:2,http:1,special:2,out:[1,2],matt:3,open:[1,3],perri:3,integr:[0,2],after:0,standard:2,standalon:2,believ:1,releas:[1,2],org:1,promptli:1,could:2,keep:2,outsid:2,adrian:3,first:[1,2],origin:[1,2],major:1,notifi:0,directli:2,christoph:3,demitri:3,independ:2,qualiti:2,number:2,stsci:3,instruct:[0,1],alreadi:[0,1,2],done:2,"long":2,stabl:[1,2],agre:2,miss:3,differ:[0,2],script:2,system:2,tom:3,juli:2,part:2,exactli:2,than:2,whenev:2,provid:[1,2],seamlessli:2,tree:2,project:[0,1,2,3],stall:2,cosmolog:1,mpia:3,rene:3,thereaft:2,mpik:3,ani:[0,1,2],anu:3,have:[0,1,2,3],tabl:2,need:2,seek:2,also:2,build:2,which:2,thoma:3,tool:2,singl:[1,2],simplifi:1,sure:0,unless:2,track:2,price:3,who:2,reach:2,phase:2,"class":[1,2],southampton:3,don:0,adopt:2,request:[0,2,3],pyidlastro:3,salt:3,bring:1,find:1,consolid:2,onli:2,locat:2,activ:[1,2],should:2,contribut:[0,3],get:[0,1],spectroscop:1,pypi:2,muna:3,cannot:2,increas:2,requir:[1,2],organ:[0,2],patch:[0,2],whether:0,common:[1,2],contain:2,where:2,vision:[1,2],set:2,specutil:3,concern:2,correctli:1,someth:1,enough:2,between:2,freder:3,"import":[1,2],email:3,deil:3,tent:1,kei:2,entir:2,matplotlib:2,ipython:1,come:1,addit:[2,3],consensu:2,etc:2,committe:[2,3],mani:[0,1,2,3],brai:3,com:1,schedul:1,summar:2,duplic:2,ultim:2,numpi:[1,2],compon:[1,2],much:2,interest:[0,1],kcorrect:3,crawford:3,imag:1,coordin:[1,2,3],togeth:1,davi:3,"case":2,look:1,packag:[0,1,2,3],aim:2,whelan:3,error:1,everyon:3,almost:1,toolkit:2,itself:2,breton:3,develop:[0,1,2],welcom:1,make:[0,2],python:[1,2],complex:2,document:[0,1,2],higher:2,competit:2,columbia:3,upon:2,user:[1,2],robust:2,implement:2,task:2,discourag:2,thu:2,well:1,kyle:3,exampl:2,thi:[0,1,2],everyth:2,latest:1,pywc:1,identifi:2,easi:2,earli:1,around:1,read:1,world:1,success:1,benefit:2,either:[0,2],page:0,twitter:1,some:2,librari:2,affili:[0,2,3],avoid:2,tracker:[0,1],refer:2,core:[0,1,2,3],encourag:2,repositori:[0,1,2],about:1,central:2,preclud:2,logo_bann:1,kerzendorf:3,commit:1,own:2,colorado:3,primarili:2,automat:1,contributor:3,your:[0,3],merg:1,inclus:2,git:1,wai:0,area:2,support:2,transform:1,submit:[0,2],avail:2,start:[0,1,2],reli:2,aldcroft:3,interfac:2,includ:[1,2],"function":[1,2],head:0,photutil:3,form:2,continu:2,link:1,tollerud:3,bug:1,pull:[0,2,3],made:[1,2],consist:2,possibl:2,"default":2,wish:2,those:2,later:[1,2],creat:0,dure:2,exist:2,erik:3,file:1,check:1,taro:3,detail:1,other:[0,1,2],futur:2,test:2,you:[0,1,3],fork:0,intend:2,astronomi:[0,1,2],intent:0,consid:2,stai:1,reduc:2,adam:3,potenti:2,time:[0,1,2]},objtypes:{},titles:["Contributing to Astropy","Welcome","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","vision","team"]}) \ No newline at end of file diff --git a/team.html b/team.html new file mode 100644 index 00000000..94d47a7a --- /dev/null +++ b/team.html @@ -0,0 +1,207 @@ + + + + + + + + + + + The Astropy team — Astropy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        + +
        +

        The Astropy team

        +
        +

        Project Coordinators

        + +
        +
        +

        Core package maintainers

        +

        In addition to the coordination committee, the following individuals maintain the core package:

        + +
        +
        +

        Affiliated package maintainers

        + +
        +
        +

        Contributors

        + +

        ... and thanks to everyone on the astropy-dev mailing list for contributing to many discussions and decisions!

        +

        (If you have contribute to the Astropy project, and your name is missing, please send an email to the coordinators, or open a pull request here!)

        +
        +
        + + +
        +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +
        +
        + + \ No newline at end of file diff --git a/tools.html b/tools.html deleted file mode 100644 index c413496c..00000000 --- a/tools.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - - - - - astropy.tools documentation — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.tools documentation

        -

        The tools package holds general astronomy functions or algorithms -that are likely of use to users, but either not related to functionality in -an existing package or of general use across multiple packages.

        -
        -

        Note

        -

        For functions and classes that are more developer-oriented, the correct -package is astropy.utils. astropy.tools is intended primarily for -functionality that is astronomy-specific and/or of use to users.

        -
        -
        -

        Reference/API

        -

        Below are the reference documentation for the tools sub-packages. All public -functions and classes in these packages will be imported into the -astropy.tools package, so the recommended usage is e.g. -from astropy.tools import sigma_clip or import astropy.tools instead of -from astropy.tools.misc import sigma_clip or similar.

        -
        -

        astropy.tools.misc

        -

        This module contains simple algorithmic functionality common in astronomy or -used in multiple places throughout Astropy, but are not complex enough to -necessarily warrant their own module.

        -

        This package should generally not be used directly. Everything in __all__ is -imported into astropy.tools, and hence that package should be used for -access.

        -
        -
        -astropy.tools.misc.sigma_clip(data, sig=3, iters=1, cenfunc=<function median at 0x14ec4f0>, varfunc=<function var at 0x1525330>, maout=False)[source]
        -

        Perform sigma-clipping on the provided data.

        -

        This performs the sigma clipping algorithm - i.e. the data will be iterated -over, each time rejecting points that are more than a specified number of -standard deviations discrepant.

        - --- - - - - - -
        Parameters :

        data : array-like

        -
        -

        The data to be sigma-clipped (any shape).

        -
        -

        sig : float

        -
        -

        The number of standard deviations (not variances) to use as the -clipping limit.

        -
        -

        iters : int or None

        -
        -

        The number of iterations to perform clipping for, or None to clip until -convergence is achieved (i.e. continue until the last iteration clips -nothing).

        -
        -

        cenfunc : callable

        -
        -

        The technique to compute the center for the clipping. Must be a -callable that takes in a 1D data array and outputs the central value. -Defaults to the median.

        -
        -

        varfunc : callable

        -
        -

        The technique to compute the variance about the center. Must be a -callable that takes in a 1D data array and outputs the width estimator -that will be interpreted as a variance. Defaults to the variance.

        -
        -

        maout : bool or ‘copy’

        -
        -

        If True, a masked array will be returned. If the special string -‘inplace’, the masked array will contain the same array as data, -otherwise the array data will be copied.

        -
        -
        Returns :

        filtereddata : numpy.ndarray or numpy.masked.MaskedArray

        -
        -

        If maout is True, this is a masked array with a shape matching the -input that is masked where the algorithm has rejected those values. -Otherwise, a 1D array of values including only those that are not -clipped.

        -
        -

        mask : boolean array

        -
        -

        Only present if maout is False. A boolean array with a shape matching -the input data that is False for rejected values and True for all -others.

        -
        -
        -

        Examples

        -

        This will generate random variates from a Gaussian distribution and return -only the points that are within 2 sample standard deviation from the -median:

        -
        >>> from astropy.tools.alg import sigma_clip
        ->>> from numpy.random import randn
        ->>> randvar = randn(10000)
        ->>> data,mask = sigma_clip(randvar,2,1)
        -
        -
        -

        This will clipping on a similar distribution, but for 3 sigma relative to -the sample mean, will clip until converged, and produces a -numpy.masked.MaskedArray:

        -
        >>> from astropy.tools.alg import sigma_clip
        ->>> from numpy.random import randn
        ->>> from numpy import mean
        ->>> randvar = randn(10000)
        ->>> maskedarr = sigma_clip(randvar,3,None,mean,maout=True)
        -
        -
        -
        - -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        -

        Next topic

        -

        astropy.utils documentation

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/utils/api_collections.html b/utils/api_collections.html deleted file mode 100644 index eff0b3f4..00000000 --- a/utils/api_collections.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - - - astropy.utils.collections: Specialized collection classes — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.utils.collections: Specialized collection classes

        -

        A number of specialized collection classes.

        -
        -
        -class astropy.utils.collections.HomogeneousList(types, values=[])[source]
        -

        Bases: list

        -

        A subclass of list that contains only elements of a given type or -types. If an item that is not of the specified type is added to -the list, a TypeError is raised.

        -
        -
        -__dict__ = <dictproxy object at 0x8afe3b0>
        -
        - -
        -
        -__iadd__(other)[source]
        -
        - -
        -
        -__init__(types, values=[])[source]
        -
        --- - - - -
        Parameters :

        types : sequence of types

        -
        -

        The types to accept.

        -
        -

        values : sequence, optional

        -
        -

        An initial set of values.

        -
        -
        -
        - -
        -
        -__module__ = 'astropy.utils.collections'
        -
        - -
        -
        -__setitem__(x)[source]
        -
        - -
        -
        -__weakref__
        -

        list of weak references to the object (if defined)

        -
        - -
        -
        -append(x)[source]
        -
        - -
        -
        -extend(x)[source]
        -
        - -
        -
        -insert(i, x)[source]
        -
        - -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.utils documentation

        -

        Next topic

        -

        astropy.utils.console: Utilities for console output

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/utils/api_console.html b/utils/api_console.html deleted file mode 100644 index 8c48ac93..00000000 --- a/utils/api_console.html +++ /dev/null @@ -1,545 +0,0 @@ - - - - - - - - - - astropy.utils.console: Utilities for console output — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.utils.console: Utilities for console output

        -

        Utilities for prettifying output to the console.

        -
        -
        -astropy.utils.console.isatty(file)[source]
        -

        Returns True if file is a tty.

        -

        Most built-in Python file-like objects have an isatty member, -but some user-defined types may not, so this assumes those are not -ttys.

        -
        - -
        -
        -astropy.utils.console.color_print(*args, **kwargs)[source]
        -

        Prints colors and styles to the terminal uses ANSI escape -sequences:

        -
        color_print('This is the color ', 'default', 'GREEN', 'green')
        -
        -
        - --- - - - -
        Parameters :

        positional args : strings

        -
        -

        The positional arguments come in pairs (msg, color), where -msg is the string to display and color is the color to -display it in.

        -

        color is an ANSI terminal color name. Must be one of: -black, red, green, brown, blue, magenta, cyan, lightgrey, -default, darkgrey, lightred, lightgreen, yellow, lightblue, -lightmagenta, lightcyan, white, or ‘’ (the empty string).

        -
        -

        file : writeable file-like object, optional

        -
        -

        Where to write to. Defaults to sys.stdout. If file is not -a tty (as determined by calling its isatty member, if one -exists), no coloring will be included.

        -
        -

        end : str, optional

        -
        -

        The ending of the message. Defaults to \n. The end will -be printed after resetting any color or font state.

        -
        -
        -
        - -
        -
        -astropy.utils.console.human_time(seconds)[source]
        -

        Returns a human-friendly time string that is always exactly 6 -characters long.

        -

        Depending on the number of seconds given, can be one of:

        -
        1w 3d
        -2d 4h
        -1h 5m
        -1m 4s
        -  15s
        -
        -

        Will be in color if console coloring is turned on.

        - --- - - - - - -
        Parameters :

        seconds : int

        -
        -

        The number of seconds to represent

        -
        -
        Returns :

        time : str

        -
        -

        A human-friendly representation of the given number of seconds -that is always exactly 6 characters.

        -
        -
        -
        - -
        -
        -class astropy.utils.console.ProgressBar(total, file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        -

        A class to display a progress bar in the terminal.

        -

        It is designed to be used with the with statement:

        -
        with ProgressBar(len(items)) as bar:
        -    for item in enumerate(items):
        -        bar.update()
        -
        -
        -
        -
        -__enter__()[source]
        -
        - -
        -
        -__exit__(exc_type, exc_value, traceback)[source]
        -
        - -
        -
        -__init__(total, file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        -
        --- - - - -
        Parameters :

        total : int

        -
        -

        The number of increments in the process being tracked.

        -
        -

        file : writable file-like object, optional

        -
        -

        The file to write the progress bar to. Defaults to -sys.stdout. If file is not a tty (as determined by -calling its isatty member, if any), the scrollbar will -be completely silent.

        -
        -
        -
        - -
        -
        -__module__ = 'astropy.utils.console'
        -
        - -
        -
        -classmethod iterate(items, file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        -

        Iterate over a sequence while indicating progress with a progress -bar in the terminal:

        -
        for item in ProgressBar.iterate(items):
        -    pass
        -
        -
        - --- - - - - - -
        Parameters :

        items : sequence

        -
        -

        A sequence of items to iterate over

        -
        -

        file : writeable file-like object, optional

        -
        -

        The file to write the progress bar to. Defaults to -sys.stdout. If file is not a tty (as determined by -calling its isatty member, if any), the scrollbar will -be completely silent.

        -
        -
        Returns :

        generator : :

        -
        -

        A generator over items

        -
        -
        -
        - -
        -
        -classmethod map(function, items, multiprocess=False, file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        -

        Does a map operation while displaying a progress bar with -percentage complete:

        -
        def work(i):
        -    print(i)
        -
        -ProgressBar.map(work, range(50))
        -
        -
        - --- - - - -
        Parameters :

        function : function

        -
        -

        Function to call for each step

        -
        -

        items : sequence

        -
        -

        Sequence where each element is a tuple of arguments to pass to -function.

        -
        -

        multiprocess : bool, optional

        -
        -

        If True, use the multiprocessing module to distribute each -task to a different processor core.

        -
        -

        file : writeable file-like object, optional

        -
        -

        The file to write the progress bar to. Defaults to -sys.stdout. If file is not a tty (as determined by -calling its isatty member, if any), the scrollbar will -be completely silent.

        -
        -
        -
        - -
        -
        -update(value=None)[source]
        -

        Update the progress bar to the given value (out of the total -given to the constructor.

        -
        - -
        - -
        -
        -class astropy.utils.console.Spinner(msg, color='default', file=<open file '<stdout>', mode 'w' at 0x240078>, step=1, chars=None)[source]
        -

        A class to display a spinner in the terminal.

        -

        It is designed to be used with the with statement:

        -
        with Spinner("Reticulating splines", "green") as s:
        -    for item in enumerate(items):
        -        s.next()
        -
        -
        -
        -
        -__enter__()[source]
        -
        - -
        -
        -__exit__(exc_type, exc_value, traceback)[source]
        -
        - -
        -
        -__init__(msg, color='default', file=<open file '<stdout>', mode 'w' at 0x240078>, step=1, chars=None)[source]
        -
        --- - - - -
        Parameters :

        msg : str

        -
        -

        The message to print

        -
        -

        color : str, optional

        -
        -

        An ANSI terminal color name. Must be one of: black, red, -green, brown, blue, magenta, cyan, lightgrey, default, -darkgrey, lightred, lightgreen, yellow, lightblue, -lightmagenta, lightcyan, white.

        -
        -

        file : writeable file-like object, optional

        -
        -

        The file to write the spinner to. Defaults to -sys.stdout. If file is not a tty (as determined by -calling its isatty member, if any), the scrollbar will -be completely silent.

        -
        -

        step : int, optional

        -
        -

        Only update the spinner every step steps

        -
        -

        chars : str, optional

        -
        -

        The character sequence to use for the spinner

        -
        -
        -
        - -
        -
        -__module__ = 'astropy.utils.console'
        -
        - -
        - -
        -
        -astropy.utils.console.print_code_line(line, col=None, file=<open file '<stdout>', mode 'w' at 0x240078>, tabwidth=8, width=70)[source]
        -

        Prints a line of source code, highlighting a particular character -position in the line. Useful for displaying the context of error -messages.

        -

        If the line is more than width characters, the line is truncated -accordingly and ‘…’ characters are inserted at the front and/or -end.

        -

        It looks like this:

        -
        there_is_a_syntax_error_here :
        -                             ^
        -
        - --- - - - -
        Parameters :

        line : unicode

        -
        -

        The line of code to display

        -
        -

        col : int, optional

        -
        -

        The character in the line to highlight. col must be less -than len(line).

        -
        -

        file : writeable file-like object, optional

        -
        -

        Where to write to. Defaults to sys.stdout.

        -
        -

        tabwidth : int, optional

        -
        -

        The number of spaces per tab ('       ') character. Default is -8. All tabs will be converted to spaces to ensure that the -caret lines up with the correct column.

        -
        -

        width : int, optional

        -
        -

        The width of the display, beyond which the line will be -truncated. Defaults to 70 (this matches the default in the -standard library’s textwrap module).

        -
        -
        -
        - -
        -
        -class astropy.utils.console.ProgressBarOrSpinner(total, msg, color='default', file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        -

        A class that displays either a ProgressBar or Spinner -depending on whether the total size of the operation is -known or not.

        -

        It is designed to be used with the with statement:

        -
        if file.has_length():
        -    length = file.get_length()
        -else:
        -    length = None
        -bytes_read = 0
        -with ProgressBarOrSpinner(length) as bar:
        -    while file.read(blocksize):
        -        bytes_read += blocksize
        -        bar.update(bytes_read)
        -
        -
        -
        -
        -__enter__()[source]
        -
        - -
        -
        -__exit__(exc_type, exc_value, traceback)[source]
        -
        - -
        -
        -__init__(total, msg, color='default', file=<open file '<stdout>', mode 'w' at 0x240078>)[source]
        -
        --- - - - -
        Parameters :

        total : int or None

        -
        -

        If an int, the number of increments in the process being -tracked and a ProgressBar is displayed. If None, a -Spinner is displayed.

        -
        -

        msg : str

        -
        -

        The message to display above the ProgressBar or -alongside the Spinner.

        -
        -

        color : str, optional

        -
        -

        The color of msg, if any. Must be an ANSI terminal -color name. Must be one of: black, red, green, brown, -blue, magenta, cyan, lightgrey, default, darkgrey, -lightred, lightgreen, yellow, lightblue, lightmagenta, -lightcyan, white.

        -
        -

        file : writable file-like object, optional

        -
        -

        The file to write the to. Defaults to sys.stdout. If -file is not a tty (as determined by calling its isatty -member, if any), only msg will be displayed: the -ProgressBar or Spinner will be silent.

        -
        -
        -
        - -
        -
        -__module__ = 'astropy.utils.console'
        -
        - -
        -
        -update(value)[source]
        -

        Update the progress bar to the given value (out of the total -given to the constructor.

        -
        - -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.utils.collections: Specialized collection classes

        -

        Next topic

        -

        astropy.utils.xml: Utilities related to XML

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/utils/api_misc.html b/utils/api_misc.html deleted file mode 100644 index 96b33ca8..00000000 --- a/utils/api_misc.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - - - - - astropy.utils.misc: Miscellaneous/uncategorized Utilities — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.utils.misc: Miscellaneous/uncategorized Utilities

        -

        This package contains smallish general-purpose utilities that don’t have a -clear other module to live in.

        -

        This module should not be used directly, as everything in __all__` is -imported into astropy.utils

        -
        -
        -astropy.utils.misc.find_current_module(depth=1, finddiff=False)[source]
        -

        Determines the module/package this function is called from.

        - --- - - - - - -
        Parameters :

        depth : int

        -
        -

        Specifies how far back to go in the call stack (0-indexed, so that -passing in 0 gives back astropy.utils.misc).

        -
        -

        finddiff : bool

        -
        -

        If True, once the module at depth is determined, a search will be -performed up the call stack until a different module is found -from the one at depth.

        -
        -
        Returns :

        mod : module or None

        -
        -

        The module object or None if the package cannot be found. The name of -the module is available as the __name__ attribute of the returned -object (if it isn’t None).

        -
        -
        -

        Examples

        -

        The examples below assume that there are two modules in a package named -pkg. mod1.py:

        -
        def find1():
        -    from astropy.utils import find_current_module
        -    print find_current_module(1).__name__
        -def find2():
        -    from astropy.utils import find_current_module
        -    cmod = find_current_module(2)
        -    if cmod is None:
        -        print 'None'
        -    else:
        -        print cmod.__name__
        -def find_diff():
        -    from astropy.utils import find_current_module
        -    print find_current_module(0,True).__name__
        -
        -
        -

        mod2.py:

        -
        def find():
        -    from .mod1 import find2
        -    find2()
        -
        -
        -

        With these modules in place, the following occurs:

        -
        >>> from pkg import mod1, mod2
        ->>> from astropy.utils import find_current_module
        ->>> mod1.find1()
        -pkg.mod1
        ->>> mod1.find2()
        -None
        ->>> mod2.find()
        -pkg.mod2
        ->>> find_current_module(0)
        -<module 'astropy.utils.misc' from 'astropy/utils/misc.py'>
        ->>> mod1.find_diff()
        -pkg.mod1
        -
        -
        -
        - -
        -
        -astropy.utils.misc.fnpickle(object, fileorname, usecPickle=True, protocol=None, append=False)[source]
        -

        Pickle an object to a specified file.

        - --- - - - -
        Parameters :

        object :

        -
        -

        The python object to pickle.

        -
        -

        fileorname : str or file-like

        -
        -

        The filename or file into which the object should be pickled. If a -file object, it should have been opened in binary mode.

        -
        -

        usecPickle : bool

        -
        -

        If True (default), the cPickle module is to be used in place of -pickle (cPickle is faster). This only applies for python 2.x.

        -
        -

        protocol : int or None

        -
        -

        Pickle protocol to use - see the pickle module for details on -these options. If None, the most recent protocol will be used.

        -
        -

        append : bool

        -
        -

        If True, the object is appended to the end of the file, otherwise the -file will be overwritten (if a file object is given instead of a -file name, this has no effect).

        -
        -
        -
        - -
        -
        -astropy.utils.misc.fnunpickle(fileorname, number=0, usecPickle=True)[source]
        -

        Unpickle pickled objects from a specified file and return the contents.

        - --- - - - - - - - -
        Parameters :

        fileorname : str or file-like

        -
        -

        The file name or file from which to unpickle objects. If a file object, -it should have been opened in binary mode.

        -
        -

        number : int

        -
        -

        If 0, a single object will be returned (the first in the file). If >0, -this specifies the number of objects to be unpickled, and a list will be -returned with exactly that many objects. If <0, all objects in the file -will be unpickled and returned as a list.

        -
        -

        usecPickle : bool

        -
        -

        If True, the cPickle module is to be used in place of -pickle (cPickle is faster). This only applies for python 2.x.

        -
        -
        Returns :

        contents : obj or list

        -
        -

        If number is 0, this is a individual object - the first one unpickled -from the file. Otherwise, it is a list of objects unpickled from the -file.

        -
        -
        Raises :

        EOFError :

        -
        -

        If number is >0 and there are fewer than number objects in the -pickled file.

        -
        -
        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.utils.xml: Utilities related to XML

        -

        Next topic

        -

        Documentation for Developers

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/utils/api_xml.html b/utils/api_xml.html deleted file mode 100644 index c090a93d..00000000 --- a/utils/api_xml.html +++ /dev/null @@ -1,532 +0,0 @@ - - - - - - - - - - astropy.utils.xml: Utilities related to XML — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - - - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        astropy.utils.console: Utilities for console output

        -

        Next topic

        -

        astropy.utils.misc: Miscellaneous/uncategorized Utilities

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/utils/index.html b/utils/index.html deleted file mode 100644 index bb99423f..00000000 --- a/utils/index.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - astropy.utils documentation — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vision.html b/vision.html new file mode 100644 index 00000000..9fafe0a5 --- /dev/null +++ b/vision.html @@ -0,0 +1,256 @@ + + + + + + + + + + + Vision for a Common Astronomy Python Package — Astropy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        + +
        +

        Vision for a Common Astronomy Python Package

        +

        The following document summarizes the original ‘manifesto’ for the Astropy +project which was adopted in July 2011.

        +
        +

        Long-term Vision

        +

        The ultimate goal that we seek is a package that would contain much of the +core functionality and some common tools required across Astronomy, but not +everything Astronomers will ever need. The aim is primarily to avoid +duplication for common core tasks, and to provide a robust framework upon +which to build more complex tools.

        +

        Such a common package should not preclude any other Astronomy package from +existing, because there will always be more complex and/or specialized tools +required. These tools will be able to rely on a single core library for many +tasks, and thus reduce the number of dependencies, reduce duplication of +functionality, and increase consistency of their interfaces.

        +
        +
        +

        Procedure

        +

        With the help of the community, the coordination committee will start by +identifying a few of key areas where initial development/consolidation will be +needed (such as FITS, WCS, coordinates, tables, photometry, spectra, etc.) and +will encourage teams to be formed to build standalone packages implementing +this functionality. These packages will be referred to as affiliated packages +(meaning that they are intended for future integration in the core package).

        +

        A set of requirements will be set out concerning the interfaces and +classes/methods that affiliated packages will need to make available in order +to ensure consistency between the different components. As the core package +grows, new potential areas/components for the core package will be identified. +Competition cannot be avoided, and will not be actively discouraged, but +whenever possible, developers should strive to work as a team to provide a +single and robust affiliated package, for the benefit of the community.

        +

        The affiliated packages will be developed outside the core package in +independent repositories, which will allow the teams the choice of tool and +organization. Once an affiliated package has implemented the desired +functionality, and satisfies quality criteria for coding style, documentation, +and testing, it will be considered for inclusion in the core package, and +further development will be done directly in the core package either via +direct access to the repository, or via patches/pull requests (exactly how +this will be done will be decided later).

        +

        To ensure uniformity across affiliated packages, and to facilitate integration +with the core package, developers who wish to submit their affiliated packages +for inclusion in the core will need to follow the layout of a template +package that will be provided before development starts.

        +
        +
        +

        Dependencies

        +

        Affiliated packages should be able to be imported with only the following +dependencies:

        +
          +
        • The Python Standard Library
        • +
        • NumPy, SciPy, and Matplotlib
        • +
        • Components already in the core Astronomy package
        • +
        +

        Other packages may be used, but must be imported as needed rather than during +the initial import of the package.

        +

        If a dependency is needed, but is an affiliated package, the dependent package +will need to wait until the dependency is integrated into the core package +before being itself considered for inclusion. In the mean time, it can make +use of the other affiliated package in its current form, or other packages, so +as not to stall development. Thus, the first packages to be included in the +core will be those only requiring the standard library, NumPy, SciPy, and +Matplotlib.

        +

        If the required dependency will never be part of a main package, then by +default the dependency can be included but should be imported as needed +(meaning that it only prevents the importing of that component, not the entire +core package), unless a strong case is made and a general consensus is reached +by the community that this dependency is important enough to be required at a +higher level.

        +

        This system means that packages will be integrated into the core package in an +order depending on the dependency tree, and also ensures that the interfaces +of packages being integrated into the core package are consistent with those +already in the core package.

        +

        Initially, no dependency on GUI toolkits will be allowed in the core package. +If the community reaches agrees on a single toolkit that could be used, then +this toolkit will be allowed (but will only be imported as needed).

        +
        +
        +

        Keeping track of affiliated packages

        +

        Affiliated packages will be listed in a central location (in addition to PyPI) +that will allow an easy installation of all the affiliated packages, for +example with a script that will seamlessly download and install all the +affiliated packages. The core package will also include mechanisms to +facilitate this installation process.

        +
        +
        +

        Existing Packages

        +

        Developers who already have existing packages will be encouraged to continue +supporting them for the benefit of users until the core library is considered +stable, contains this functionality, and is released to the community. +Thereafter, developers should encourage users to transition to using the +functionality in the core package, and eventually phase out their own +packages, unless they provide added value over the core package.

        +
        +
        + + +
        +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +
        +
        + + \ No newline at end of file diff --git a/vo/api.html b/vo/api.html deleted file mode 100644 index 5e2935b0..00000000 --- a/vo/api.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - API documentation — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vo/api_converters.html b/vo/api_converters.html deleted file mode 100644 index 3a2c7b44..00000000 --- a/vo/api_converters.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - astropy.io.vo.converters: Conversions between XML and Numpy datatypes — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        -

        -Inheritance diagram of astropy.io.vo.converters -

        -

        This module handles the conversion of various VOTABLE datatypes -to/from TABLEDATA and BINARY formats.

        -
        -
        -astropy.io.vo.converters.get_converter(field, config={}, pos=None)[source]
        -

        Factory function to get an appropriate converter instance for a -given field.

        - --- - - - - - -
        Parameters :

        field : astropy.io.vo.tree.Field

        -

        config : dict, optional

        -
        -

        Parser configuration dictionary

        -
        -

        pos : tuple

        -
        -

        Position in the input XML file. Used for error messages.

        -
        -
        Returns :

        converter : astropy.io.vo.converters.Converter

        -
        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.io.vo.xmlutil: XML-related utilities used by the library

        -

        Next topic

        -

        astropy.tools documentation

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/api_exceptions.html b/vo/api_exceptions.html deleted file mode 100644 index 0a4775c7..00000000 --- a/vo/api_exceptions.html +++ /dev/null @@ -1,1034 +0,0 @@ - - - - - - - - - - astropy.io.vo.exceptions — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.exceptions

        -
        -

        Contents

        - -
        -
        -

        Warnings

        -
        -

        Note

        -

        Most of the following warnings indicate violations of the VOTable -specification. They should be reported to the authors of the -tools that produced the VOTable file.

        -

        To control the warnings emitted, use the standard Python -warnings module. Most of these are of the type -VOTableSpecWarning.

        -
        -
        -

        W01: Array uses commas rather than whitespace

        -

        The VOTable spec states:

        -
        -
        If a cell contains an array or complex number, it should be -encoded as multiple numbers separated by whitespace.
        -

        Many VOTable files in the wild use commas as a separator instead, -and vo.table supports this convention when not in -Pedantic mode.

        -

        vo.table always outputs files using only spaces, regardless of -how they were input.

        -

        References: 1.1, -1.2

        -
        -
        -

        W02: x attribute ‘y’ is invalid. Must be a standard XML id

        -

        XML ids must match the following regular expression:

        -
        ^[A-Za-z_][A-Za-z0-9_\.\-]*$
        -
        -

        The VOTable 1.1 says the following:

        -
        -
        According to the XML standard, the attribute ID is a -string beginning with a letter or underscore (_), followed -by a sequence of letters, digits, or any of the punctuation -characters . (dot), - (dash), _ (underscore), or -: (colon).
        -

        However, this is in conflict with the XML standard, which says -colons may not be used. VOTable 1.1’s own schema does not allow a -colon here. Therefore, vo.table disallows the colon.

        -

        VOTable 1.2 corrects this error in the specification.

        -

        References: 1.1, -XML Names

        -
        -
        -

        W03: Implictly generating an ID from a name ‘x’ -> ‘y’

        -

        The VOTable 1.1 spec says the following about name vs. ID -on FIELD and VALUE elements:

        -
        -
        ID and name attributes have a different role in -VOTable: the ID is meant as a unique identifier of an -element seen as a VOTable component, while the name is -meant for presentation purposes, and need not to be unique -throughout the VOTable document. The ID attribute is -therefore required in the elements which have to be -referenced, but in principle any element may have an ID -attribute. ... In summary, the ID is different from the -name attribute in that (a) the ID attribute is made -from a restricted character set, and must be unique throughout -a VOTable document whereas names are standard XML attributes -and need not be unique; and (b) there should be support in the -parsing software to look up references and extract the -relevant element with matching ID.
        -

        It is further recommended in the VOTable 1.2 spec:

        -
        -
        While the ID attribute has to be unique in a VOTable -document, the name attribute need not. It is however -recommended, as a good practice, to assign unique names within -a TABLE element. This recommendation means that, between a -TABLE and its corresponding closing TABLE tag, -name attributes of FIELD, PARAM and optional -GROUP elements should be all different.
        -

        Since vo.table requires a unique identifier for each of its -columns, ID is used for the column name when present. -However, when ID is not present, (since it is not required by -the specification) name is used instead. However, name -must be cleansed by replacing invalid characters (such as -whitespace) with underscores.

        -
        -

        Note

        -

        This warning does not indicate that the input file is invalid -with respect to the VOTable specification, only that the -column names in the record array may not match exactly the -name attributes specified in the file.

        -
        -

        References: 1.1, -1.2

        -
        -
        -

        W04: content-type ‘x’ must be a valid MIME content type

        -

        The content-type attribute must use MIME content-type syntax as -defined in RFC 2046.

        -

        The current check for validity is somewhat over-permissive.

        -

        References: 1.1, -1.2

        -
        -
        -

        W05: ‘x’ is not a valid URI

        -

        The attribute must be a valid URI as defined in RFC 2396.

        -
        -
        -

        W06: Invalid UCD ‘x’: explanation

        -

        This warning is emitted when a ucd attribute does not match -the syntax of a unified content descriptor.

        -

        If the VOTable version is 1.2 or later, the UCD will also be -checked to ensure it conforms to the controlled vocabulary defined -by UCD1+.

        -

        References: 1.1, -1.2

        -
        -
        -

        W07: Invalid astroYear in x: ‘y’

        -

        As astro year field is a Besselian or Julian year matching the -regular expression:

        -
        ^[JB]?[0-9]+([.][0-9]*)?$
        -
        -

        Defined in this XML Schema snippet:

        -
        <xs:simpleType  name="astroYear">
        -  <xs:restriction base="xs:token">
        -    <xs:pattern  value="[JB]?[0-9]+([.][0-9]*)?"/>
        -  </xs:restriction>
        -</xs:simpleType>
        -
        -
        -
        -

        W08: ‘x’ must be a str or unicode object

        -

        To avoid local-dependent number parsing differences, vo.table -may require a string or unicode string where a numeric type may -make more sense.

        -
        -
        -

        W09: ID attribute not capitalized

        -

        The VOTable specification uses the attribute name ID (with -uppercase letters) to specify unique identifiers. Some -VOTable-producing tools use the more standard lowercase id -instead. vo.table accepts id and emits this warning when -not in pedantic mode.

        -

        References: 1.1, -1.2

        -
        -
        -

        W10: Unknown tag ‘x’. Ignoring

        -

        The parser has encountered an element that does not exist in the -specification, or appears in an invalid context. Check the file -against the VOTable schema (with a tool such as xmllint. If the file validates -against the schema, and you still receive this warning, this may -indicate a bug in vo.table.

        -

        References: 1.1, -1.2

        -
        - -
        -

        W12: ‘x’ element must have at least one of ‘ID’ or ‘name’ attributes

        -

        In order to name the columns of the Numpy record array, each -FIELD element must have either an ID or name attribute -to derive a name from. Strictly speaking, according to the -VOTable schema, the name attribute is required. However, if -name is not present by ID is, and pedantic mode is off, -vo.table will continue without a name defined.

        -

        References: 1.1, -1.2

        -
        -
        -

        W13: ‘x’ is not a valid VOTable datatype, should be ‘y’

        -

        Some VOTable files in the wild use non-standard datatype names. These -are mapped to standard ones using the following mapping:

        -
        string        -> char
        -unicodeString -> unicodeChar
        -int16         -> short
        -int32         -> int
        -int64         -> long
        -float32       -> float
        -float64       -> double
        -
        -

        References: 1.1, -1.2

        -
        -
        -

        W15: x element missing required ‘name’ attribute

        -

        The name attribute is required on every FIELD element. -However, many VOTable files in the wild omit it and provide only -an ID instead. In this case, when pedantic mode is off, -vo.table will copy the name attribute to a new ID -attribute.

        -

        References: 1.1, -1.2

        -
        -
        -

        W17: x element contains more than one DESCRIPTION element

        -

        A DESCRIPTION element can only appear once within its parent -element.

        -

        According to the schema, it may only occur once (1.1, -1.2)

        -

        However, it is a proposed extension -to VOTable 1.2.

        -
        -
        -

        W18: TABLE specified nrows=x, but table contains y rows

        -

        The number of rows explicitly specified in the nrows attribute -does not match the actual number of rows (TR elements) present -in the TABLE. This may indicate truncation of the file, or an -internal error in the tool that produced it. If pedantic mode -is off, parsing will proceed, with the loss of some performance.

        -

        References: 1.1, -1.2

        -
        -
        -

        W19: The fields defined in the VOTable do not match those in the embedded FITS file

        -

        The column fields as defined using FIELD elements do not match -those in the headers of the embedded FITS file. If pedantic -mode is off, the embedded FITS file will take precedence.

        -
        -
        -

        W20: No version number specified in file. Assuming 1.1

        -

        If no version number is explicitly given in the VOTable file, the -parser assumes it is written to the VOTable 1.1 specification.

        -
        -
        -

        W21: vo.table is designed for VOTable version 1.1 and 1.2, but this file is x

        -

        Unknown issues may arise using vo.table with VOTable files -from a version other than 1.1 or 1.2.

        -
        -
        -

        W22: The DEFINITIONS element is deprecated in VOTable 1.1. Ignoring

        -

        Version 1.0 of the VOTable specification used the DEFINITIONS -element to define coordinate systems. Version 1.1 now uses -COOSYS elements throughout the document.

        -

        References: 1.1, -1.2

        -
        -
        -

        W23: Unable to update service information for ‘x’

        -

        Raised when the VO service database can not be updated (possibly -due to a network outage). This is only a warning, since an older -and possible out-of-date VO service database was available -locally.

        -
        -
        -

        W24: The VO catalog database is for a later version of vo.table

        -

        The VO catalog database retrieved from the www is designed for a -newer version of vo.table. This may cause problems or limited -features performing service queries. Consider upgrading vo.table -to the latest version.

        -
        -
        -

        W25: ‘service’ failed with: ...

        -

        A VO service query failed due to a network error or malformed -arguments. Another alternative service may be attempted. If all -services fail, an exception will be raised.

        -
        -
        -

        W26: ‘child’ inside ‘parent’ added in VOTable X.X

        -

        The given element was not supported inside of the given element -until the specified VOTable version, however the version declared -in the file is for an earlier version. These attributes may not -be written out to the file.

        -
        -
        -

        W27: COOSYS deprecated in VOTable 1.2

        -

        The COOSYS element was deprecated in VOTABLE version 1.2 in -favor of a reference to the Space-Time Coordinate (STC) data -model (see utype -and the IVOA note referencing STC in VOTable.

        -
        -
        -

        W28: ‘attribute’ on ‘element’ added in VOTable X.X

        -

        The given attribute was not supported on the given element until the -specified VOTable version, however the version declared in the file is -for an earlier version. These attributes may not be written out to -the file.

        -
        -
        -

        W29: Version specified in non-standard form ‘v1.0’

        -

        Some VOTable files specify their version number in the form “v1.0”, -when the only supported forms in the spec are “1.0”.

        -

        References: 1.1, -1.2

        -
        -
        -

        W30: Invalid literal for float ‘x’. Treating as empty.

        -

        Some VOTable files write missing floating-point values in non-standard -ways, such as “null” and “-”. In non-pedantic mode, any non-standard -floating-point literals are treated as missing values.

        -

        References: 1.1, -1.2

        -
        -
        -

        W31: NaN given in an integral field without a specified null value

        -

        Since NaN’s can not be represented in integer fields directly, a null -value must be specified in the FIELD descriptor to support reading -NaN’s from the tabledata.

        -

        References: 1.1, -1.2

        -
        -
        -

        W32: Duplicate ID ‘x’ renamed to ‘x_2’ to ensure uniqueness

        -

        Each field in a table must have a unique ID. If two or more fields -have the same ID, some will be renamed to ensure that all IDs are -unique.

        -

        From the VOTable 1.2 spec:

        -
        -
        The ID and ref attributes are defined as XML types -ID and IDREF respectively. This means that the -contents of ID is an identifier which must be unique -throughout a VOTable document, and that the contents of the -ref attribute represents a reference to an identifier -which must exist in the VOTable document.
        -

        References: 1.1, -1.2

        -
        -
        -

        W33: Column name ‘x’ renamed to ‘x_2’ to ensure uniqueness

        -

        Each field in a table must have a unique name. If two or more -fields have the same name, some will be renamed to ensure that all -names are unique.

        -

        References: 1.1, -1.2

        -
        -
        -

        W34: ‘x’ is an invalid token for attribute ‘y’

        -

        The attribute requires the value to be a valid XML token, as -defined by XML 1.0.

        -
        -
        -

        W35: ‘x’ attribute required for INFO elements

        -

        The name and value attributes are required on all INFO -elements.

        -

        References: 1.1, -1.2

        -
        -
        -

        W36: null value ‘x’ does not match field datatype, setting to 0

        -

        If the field specifies a null value, that value must conform -to the given datatype.

        -

        References: 1.1, -1.2

        -
        -
        -

        W37: Unsupported data format ‘x’

        -

        The 3 datatypes defined in the VOTable specification and supported by -vo.table are TABLEDATA, BINARY and FITS.

        -

        References: 1.1, -1.2

        -
        -
        -

        W38: Inline binary data must be base64 encoded, got ‘x’

        -

        The only encoding for local binary data supported by the VOTable -specification is base64.

        -
        -
        -

        W39: Bit values can not be masked

        -

        Bit values do not support masking. This warning is raised upon -setting masked data in a bit column.

        -

        References: 1.1, -1.2

        -
        -
        -

        W40: ‘cprojection’ datatype repaired

        -

        This is a terrible hack to support Simple Image Access Protocol -results from archive.noao.edu. It creates a field for the -coordinate projection type of type “double”, which -actually contains character data. We have to hack the field -to store character data, or we can’t read it in. A warning -will be raised when this happens.

        -
        -
        -

        W41: An XML namespace is specified, but is incorrect. Expected ‘x’, got ‘y’

        -

        An XML namespace was specified on the VOTABLE element, but the -namespace does not match what is expected for a VOTABLE file.

        -

        The VOTABLE namespace is:

        -
        http://www.ivoa.net/xml/VOTable/vX.X
        -
        -

        where “X.X” is the version number.

        -

        Some files in the wild set the namespace to the location of the -VOTable schema, which is not correct and will not pass some -validating parsers.

        -
        -
        -

        W42: No XML namespace specified

        -

        The root element should specify a namespace.

        -

        The VOTABLE namespace is:

        -
        http://www.ivoa.net/xml/VOTable/vX.X
        -
        -

        where “X.X” is the version number.

        -
        -
        -

        W43: element ref=’x’ which has not already been defined

        -

        Referenced elements should be defined before referees. From the -VOTable 1.2 spec:

        -
        -
        In VOTable1.2, it is further recommended to place the ID -attribute prior to referencing it whenever possible.
        -
        -
        -

        W44: VALUES element with ref attribute has content (‘element’)

        -

        VALUES elements that reference another element should not have -their own content.

        -

        From the VOTable 1.2 spec:

        -
        -
        The ref attribute of a VALUES element can be used to -avoid a repetition of the domain definition, by referring to a -previously defined VALUES element having the referenced -ID attribute. When specified, the ref attribute -defines completely the domain without any other element or -attribute, as e.g. <VALUES ref="RAdomain"/>
        -
        -
        -

        W45: content-role attribute ‘x’ invalid

        -

        The content-role attribute on the LINK element must be one of -the following:

        -
        query, hints, doc, location
        -
        -
        -

        References: 1.1, -1.2

        -
        -
        -

        W46: char or unicode value is too long for specified length of x

        -

        The given char or unicode string is too long for the specified -field length.

        -
        -
        -

        W47: Missing arraysize indicates length 1

        -

        If no arraysize is specified on a char field, the default of ‘1’ -is implied, but this is rarely what is intended.

        -
        -
        -

        W48: Unknown attribute ‘attribute’ on element

        -

        The attribute is not defined in the specification.

        -
        -
        -

        W49: Empty cell illegal for integer fields.

        -

        Empty cell illegal for integer fields.

        -

        If a “null” value was specified for the cell, it will be used -for the value, otherwise, 0 will be used.

        -
        - -
        -
        -

        Exceptions

        -
        -

        Note

        -

        This is a list of many of the fatal exceptions emitted by vo.table -when the file does not conform to spec. Other exceptions may be -raised due to unforeseen cases or bugs in vo.table itself.

        -
        -
        -

        E01: Invalid size specifier ‘x’ for a char/unicode field (in field ‘y’)

        -

        The size specifier for a char or unicode field must be -only a number followed, optionally, by an asterisk. -Multi-dimensional size specifiers are not supported for these -datatypes.

        -

        Strings, which are defined as a set of characters, can be -represented in VOTable as a fixed- or variable-length array of -characters:

        -
        <FIELD name="unboundedString" datatype="char" arraysize="*"/>
        -
        -

        A 1D array of strings can be represented as a 2D array of -characters, but given the logic above, it is possible to define a -variable-length array of fixed-length strings, but not a -fixed-length array of variable-length strings.

        -
        -
        -

        E02: Incorrect number of elements in array. Expected multiple of x, got y

        -

        The number of array elements in the data does not match that specified -in the FIELD specifier.

        -
        -
        -

        E03: ‘x’ does not parse as a complex number

        -

        Complex numbers should be two values separated by whitespace.

        -

        References: 1.1, -1.2

        -
        -
        -

        E04: Invalid bit value ‘x’

        -

        A bit array should be a string of ‘0’s and ‘1’s.

        -

        References: 1.1, -1.2

        -
        -
        -

        E05: Invalid boolean value ‘x’

        -

        A boolean value should be one of the following strings (case -insensitive) in the TABLEDATA format:

        -
        'TRUE', 'FALSE', '1', '0', 'T', 'F', '\0', ' ', '?'
        -
        -
        -

        and in BINARY format:

        -
        'T', 'F', '1', '0', '\0', ' ', '?'
        -
        -
        -

        References: 1.1, -1.2

        -
        -
        -

        E06: Unknown datatype ‘x’ on field ‘y’

        -

        The supported datatypes are:

        -
        double, float, bit, boolean, unsignedByte, short, int, long,
        -floatComplex, doubleComplex, char, unicodeChar
        -
        -
        -

        The following non-standard aliases are also supported, but in -these case W13 will be raised:

        -
        string        -> char
        -unicodeString -> unicodeChar
        -int16         -> short
        -int32         -> int
        -int64         -> long
        -float32       -> float
        -float64       -> double
        -
        -

        References: 1.1, -1.2

        -
        - -
        -

        E09: ‘x’ must have a value attribute

        -

        The MIN, MAX and OPTION elements must always have a -value attribute.

        -

        References: 1.1, -1.2

        -
        -
        -

        E10: ‘datatype’ attribute required on all ‘FIELD’ elements

        -

        From VOTable 1.1 and later, FIELD and PARAM elements must have -a datatype field.

        -

        References: 1.1, -1.2

        -
        -
        -

        E11: precision ‘x’ is invalid

        -

        The precision attribute is meant to express the number of significant -digits, either as a number of decimal places (e.g. precision="F2" or -equivalently precision="2" to express 2 significant figures -after the decimal point), or as a number of significant figures -(e.g. precision="E5" indicates a relative precision of 10-5).

        -

        It is validated using the following regular expression:

        -
        [EF]?[1-9][0-9]*
        -
        -

        References: 1.1, -1.2

        -
        -
        -

        E12: width must be a positive integer, got ‘x’

        -

        The width attribute is meant to indicate to the application the -number of characters to be used for input or output of the -quantity.

        -

        References: 1.1, -1.2

        -
        -
        -

        E13: Invalid arraysize attribute ‘x’

        -

        From the VOTable 1.2 spec:

        -
        -

        A table cell can contain an array of a given primitive type, -with a fixed or variable number of elements; the array may -even be multidimensional. For instance, the position of a -point in a 3D space can be defined by the following:

        -
        <FIELD ID="point_3D" datatype="double" arraysize="3"/>
        -
        -

        and each cell corresponding to that definition must contain -exactly 3 numbers. An asterisk (*) may be appended to -indicate a variable number of elements in the array, as in:

        -
        <FIELD ID="values" datatype="int" arraysize="100*"/>
        -
        -

        where it is specified that each cell corresponding to that -definition contains 0 to 100 integer numbers. The number may -be omitted to specify an unbounded array (in practice up to -=~2×10⁹ elements).

        -

        A table cell can also contain a multidimensional array of a -given primitive type. This is specified by a sequence of -dimensions separated by the x character, with the first -dimension changing fastest; as in the case of a simple array, -the last dimension may be variable in length. As an example, -the following definition declares a table cell which may -contain a set of up to 10 images, each of 64×64 bytes:

        -
        <FIELD ID="thumbs" datatype="unsignedByte" arraysize="64×64×10*"/>
        -
        -
        -

        References: 1.1, -1.2

        -
        -
        -

        E14: value attribute is required for all PARAM elements

        -

        All PARAM elements must have a value attribute.

        -

        References: 1.1, -1.2

        -
        -
        -

        E15: ID attribute is required for all COOSYS elements

        -

        All COOSYS elements must have an ID attribute.

        -

        Note that the VOTable 1.1 specification says this attribute is -optional, but its corresponding schema indicates it is required.

        -

        In VOTable 1.2, the COOSYS element is deprecated.

        -
        -
        -

        E16: Invalid system attribute ‘x’

        -

        The system attribute on the COOSYS element must be one of the -following:

        -
        'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic',
        -'supergalactic', 'xy', 'barycentric', 'geo_app'
        -
        -
        -

        References: 1.1

        -
        -
        -

        E17: extnum must be a positive integer

        -

        extnum attribute must be a positive integer.

        -

        References: 1.1, -1.2

        -
        -
        -

        E18: type must be ‘results’ or ‘meta’, not ‘x’

        -

        The type attribute of the RESOURCE element must be one of -“results” or “meta”.

        -

        References: 1.1, -1.2

        -
        -
        -

        E19: File does not appear to be a VOTABLE

        -

        Raised either when the file doesn’t appear to be XML, or the root -element is not VOTABLE.

        -
        -
        -

        E20: Data has more columns than are defined in the header (x)

        -

        The table had only x fields defined, but the data itself has more -columns than that.

        -
        -
        -

        E21: Data has fewer columns (x) than are defined in the header (y)

        -

        The table had x fields defined, but the data itself has only y -columns.

        -
        -
        -
        -

        Exception utilities

        -
        -
        -astropy.io.vo.exceptions.warn_or_raise(warning_class, exception_class=None, args=(), config={}, pos=None)[source]
        -

        Warn or raise an exception, depending on the pedantic setting.

        -
        - -
        -
        -astropy.io.vo.exceptions.vo_raise(exception_class, args=(), config={}, pos=None)[source]
        -

        Raise an exception, with proper position information if available.

        -
        - -
        -
        -astropy.io.vo.exceptions.vo_reraise(exc, config={}, pos=None, additional='')[source]
        -

        Raise an exception, with proper position information if available.

        -

        Restores the original traceback of the exception, and should only -be called within an “except:” block of code.

        -
        - -
        -
        -astropy.io.vo.exceptions.vo_warn(warning_class, args=(), config={}, pos=None)[source]
        -

        Warn, with proper position information if available.

        -
        - -
        -
        -astropy.io.vo.exceptions.parse_vowarning(line)[source]
        -

        Parses the vo warning string back into its parts.

        -
        - -
        -
        -class astropy.io.vo.exceptions.VOWarning(args, config={}, pos=None)[source]
        -

        Bases: exceptions.Warning

        -

        The base class of all VO warnings and exceptions. Handles the -formatting of the message with a warning or exception code, -filename, line and column number.

        -
        - -
        -
        -class astropy.io.vo.exceptions.VOTableChangeWarning(args, config={}, pos=None)[source]
        -

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.SyntaxWarning

        -

        Warning emitted when a change has been made to the input XML file.

        -
        - -
        -
        -class astropy.io.vo.exceptions.VOTableSpecWarning(args, config={}, pos=None)[source]
        -

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.SyntaxWarning

        -

        Warning emitted when the input XML file violates the spec, but -there is an obvious workaround.

        -
        - -
        -
        -class astropy.io.vo.exceptions.UnimplementedWarning(args, config={}, pos=None)[source]
        -

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.SyntaxWarning

        -

        Warning emitted when the a feature of VOTABLE is not implemented.

        -
        - -
        -
        -class astropy.io.vo.exceptions.IOWarning(args, config={}, pos=None)[source]
        -

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.RuntimeWarning

        -

        Warning emitted when a network or IO error occurred, but the -system is able to recover using a cached copy of the data or some -other fallback.

        -
        - -
        -
        -class astropy.io.vo.exceptions.VOTableSpecError(args, config={}, pos=None)[source]
        -

        Bases: astropy.io.vo.exceptions.VOWarning, exceptions.ValueError

        -

        Error raised when the input XML file violates the spec and there -is no good workaround.

        -
        - -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        -

        Next topic

        -

        astropy.io.vo.ucd: Functions to parse and verify unified content descriptors

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/api_table.html b/vo/api_table.html deleted file mode 100644 index aa2350d4..00000000 --- a/vo/api_table.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - - - - - astropy.io.vo.table: Loading entire VOTable files — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.table: Loading entire VOTable files

        -

        This file contains a contains the high-level functions to read a -VOTable file.

        -
        -
        -astropy.io.vo.table.parse(source, columns=None, invalid='exception', pedantic=None, chunk_size=256, table_number=None, filename=None, _debug_python_based_parser=False)[source]
        -

        Parses a VOTABLE xml file (or file-like object), and returns a -VOTable object, with nested -Resource instances and -Table instances.

        - --- - - - - - -
        Parameters :

        source : str or readable file-like object

        -
        -

        Path or file object containing a VOTABLE xml file.

        -
        -

        columns : sequence of str, optional

        -
        -

        List of field names to include in the output. The default is -to include all fields.

        -
        -

        invalid : str, optional

        -
        -

        One of the following values:

        -
        -
          -
        • ‘exception’: throw an exception when an invalid value is -encountered (default)
        • -
        • ‘mask’: mask out invalid values
        • -
        -
        -
        -

        pedantic : bool, optional

        -
        -

        When True, raise an error when the file violates the spec, -otherwise issue a warning. Warnings may be controlled using -the standard Python mechanisms. See the warnings -module in the Python standard library for more information. -When not provided, uses the configuration setting -astropy.io.vo.pedantic, which defaults to True.

        -
        -

        chunk_size : int, optional

        -
        -

        The number of rows to read before converting to an array. -Higher numbers are likely to be faster, but will consume more -memory.

        -
        -

        table_number : int, optional

        -
        -

        The number of table in the file to read in. If None, all -tables will be read. If a number, 0 refers to the first table -in the file, and only that numbered table will be parsed and -read in.

        -
        -

        filename : str, optional

        -
        -

        A filename, URL or other identifier to use in error messages. -If filename is None and source is a string (i.e. a path), -then source will be used as a filename for error messages. -Therefore, filename is only required when source is a -file-like object.

        -
        -
        Returns :

        votable : astropy.io.vo.tree.VOTableFile object

        -
        -
        -

        See also

        -
        -
        astropy.io.vo.exceptions
        -
        The exceptions this function may raise.
        -
        -
        -
        - -
        -
        -astropy.io.vo.table.parse_single_table(source, **kwargs)[source]
        -

        Parses a VOTABLE xml file (or file-like object), reads only the -first TABLE element, and returns a Table -instance.

        -

        See parse for a description of the keyword arguments.

        - --- - - - -
        Returns :votable : astropy.io.vo.tree.Table object
        -
        - -
        -
        -astropy.io.vo.table.validate(filename, output=<open file '<stdout>', mode 'w' at 0x240078>, xmllint=False)[source]
        -

        Prints a validation report for the given file.

        - --- - - - - - -
        Parameters :

        filename : str path

        -
        -

        Path to a VOTABLE xml file.

        -
        -

        output : writable file-like object, optional

        -
        -

        Where to output the report. Defaults to sys.stdout. -If None, the output will be returned as a string.

        -
        -

        xmllint : bool, optional

        -
        -

        When True, also send the file to xmllint for schema and -DTD validation. Requires that xmllint is installed. The -default is False.

        -
        -
        Returns :

        is_valid : bool or str

        -
        -

        Returns True if no warnings were found. If output is -None, the return value will be a string.

        -
        -
        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        API documentation

        -

        Next topic

        -

        astropy.io.vo.tree: Accessing and modifying the individual parts of VOTable files

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/api_tree.html b/vo/api_tree.html deleted file mode 100644 index c69da93b..00000000 --- a/vo/api_tree.html +++ /dev/null @@ -1,1064 +0,0 @@ - - - - - - - - - - astropy.io.vo.tree: Accessing and modifying the individual parts of VOTable files — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.tree: Accessing and modifying the individual parts of VOTable files

        -

        -Inheritance diagram of astropy.io.vo.tree - - - - - - - - - - - - - - - - - -

        -
        -
        -class astropy.io.vo.tree.Element[source]
        -

        Bases: object

        -

        A base class for all classes that represent XML elements in the -VOTABLE file.

        -
        - -
        -
        -class astropy.io.vo.tree.SimpleElement[source]
        -

        Bases: astropy.io.vo.tree.Element

        -

        A base class for simple elements, such as FIELD, PARAM and INFO -that don’t require any special parsing or outputting machinery.

        -
        -
        -parse(iterator, config)[source]
        -
        - -
        -
        -to_xml(w, **kwargs)[source]
        -
        - -
        - -
        -
        -class astropy.io.vo.tree.SimpleElementWithContent[source]
        -

        Bases: astropy.io.vo.tree.SimpleElement

        -

        A base class for simple elements, such as FIELD, PARAM and INFO -that don’t require any special parsing or outputting machinery.

        -
        -
        -content[source]
        -

        The content of the element.

        -
        - -
        -
        -to_xml(w, **kwargs)[source]
        -
        - -
        - -
        -
        -class astropy.io.vo.tree.VOTableFile(ID=None, id=None, config={}, pos=None, version='1.2')[source]
        -

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._DescriptionProperty

        -

        A class to represent the top-level VOTABLE element.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -

        version is settable at construction time only, since conformance -tests for building the rest of the structure depend on it.

        -
        -
        -coordinate_systems[source]
        -

        A list of coordinate system descriptions for the file. Must -contain only CooSys objects.

        -
        - -
        -
        -get_coosys_by_id(ref, before=None)
        -

        Looks up a COOSYS element by the given ID.

        -
        - -
        -
        -get_field_by_id(ref, before=None)
        -

        Looks up a FIELD element by the given ID. Used by the field’s -“ref” attribute.

        -
        - -
        -
        -get_field_by_id_or_name(ref, before=None)
        -

        Looks up a FIELD element by the given ID or name.

        -
        - -
        -
        -get_first_table()[source]
        -

        Often, you know there is only one table in the file, and -that’s all you need. This method returns that first table.

        -
        - -
        -
        -get_group_by_id(ref, before=None)
        -

        Looks up a GROUP element by the given ID. Used by the group’s -“ref” attribute

        -
        - -
        -
        -get_table_by_id(ref, before=None)
        -

        Looks up a TABLE element by the given ID. Used by the table -“ref” attribute.

        -
        - -
        -
        -get_table_by_index(idx)[source]
        -

        Get a table by its ordinal position in the file.

        -
        - -
        -
        -get_values_by_id(ref, before=None)
        -

        Looks up a VALUES element by the given ID. Used by the values -“ref” attribute.

        -
        - -
        -
        -groups[source]
        -

        A list of groups, in the order they appear in the file. Only -supported as a child of the VOTABLE element in VOTable 1.2 or -later.

        -
        - -
        -
        -infos[source]
        -

        A list of informational parameters (key-value pairs) for the -entire file. Must only contain Info objects.

        -
        - -
        -
        -iter_coosys()[source]
        -

        Recursively iterate over all COOSYS elements in the VOTABLE -file.

        -
        - -
        -
        -iter_fields_and_params()[source]
        -

        Recursively iterate over all FIELD and PARAM elements in the -VOTABLE file.

        -
        - -
        -
        -iter_groups()[source]
        -

        Recursively iterate over all GROUP elements in the VOTABLE -file.

        -
        - -
        -
        -iter_tables()[source]
        -

        Iterates over all tables in the VOTable file in a “flat” way, -ignoring the nesting of resources etc.

        -
        - -
        -
        -iter_values()[source]
        -

        Recursively iterate over all VALUES elements in the VOTABLE -file.

        -
        - -
        -
        -params[source]
        -

        A list of parameters (constant-valued columns) that apply to -the entire file. Must contain only Param objects.

        -
        - -
        -
        -parse(iterator, config)[source]
        -
        - -
        -
        -resources[source]
        -

        A list of resources, in the order they appear in the file. -Must only contain Resource objects.

        -
        - -
        -
        -set_all_tables_format(format)[source]
        -

        Set the output storage format of all tables in the file.

        -
        - -
        -
        -to_xml(fd, write_null_values=False, _debug_python_based_parser=False, _astropy_version=None)[source]
        -

        Write to an XML file.

        - --- - - - -
        Parameters :

        fd : str path or writable file-like object

        -
        -

        Where to write the file.

        -
        -

        write_null_values : bool

        -
        -

        When True, write the ‘null’ value (specified in the null -attribute of the VALUES element for each FIELD) for empty -values. When False (default), simply write no value.

        -
        -
        -
        - -
        -
        -version[source]
        -

        The version of the VOTable specification that the file uses.

        -
        - -
        - -
        -
        -class astropy.io.vo.tree.Resource(name=None, ID=None, utype=None, type='results', id=None, config={}, pos=None, **kwargs)[source]
        -

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._NameProperty, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._DescriptionProperty

        -

        A class to store the information in a RESOURCE element. Each -resource may contain zero-or-more TABLE elements and zero-or-more -nested RESOURCE elements.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -
        -
        -coordinate_systems[source]
        -

        A list of coordinate system definitions (COOSYS elements) for -the RESOURCE. Must contain only CooSys objects.

        -
        - -
        -
        -extra_attributes[source]
        -

        A dictionary of string keys to string values containing any -extra attributes of the RESOURCE element that are not defined -in the specification. (The specification explicitly allows -for extra attributes here, but nowhere else.)

        -
        - -
        -
        -infos[source]
        -

        A list of informational parameters (key-value pairs) for the -resource. Must only contain Info objects.

        -
        - -
        -
        -iter_coosys()[source]
        -

        Recursively iterates over all the COOSYS elements in the -resource and nested resources.

        -
        - -
        -
        -iter_fields_and_params()[source]
        -

        Recursively iterates over all FIELD and PARAM elements in -the resource, its tables and nested resources.

        -
        - -
        -
        -iter_tables()[source]
        -

        Recursively iterates over all tables in the resource and -nested resources.

        -
        - -
        - -

        A list of links (pointers to other documents or servers -through a URI) for the resource. Must contain only Link -objects.

        -
        - -
        -
        -params[source]
        -

        A list of parameters (constant-valued columns) for the -resource. Must contain only Param objects.

        -
        - -
        -
        -parse(votable, iterator, config)[source]
        -
        - -
        -
        -resources[source]
        -

        A list of nested resources inside this resource. Must contain -only Resource objects.

        -
        - -
        -
        -tables[source]
        -

        A list of tables in the resource. Must contain only -Table objects.

        -
        - -
        -
        -to_xml(w, **kwargs)[source]
        -
        - -
        -
        -type[source]
        -

        [required] The type of the resource. Must be either:

        -
        -
          -
        • ‘results’: This resource contains actual result values -(default)
        • -
        • ‘meta’: This resource contains only datatype descriptions -(FIELD elements), but no actual data.
        • -
        -
        -
        - -
        - -
        -
        -class astropy.io.vo.tree.Table(votable, ID=None, name=None, ref=None, ucd=None, utype=None, nrows=None, id=None, config={}, pos=None, **extra)[source]
        -

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._NameProperty, astropy.io.vo.tree._UcdProperty, astropy.io.vo.tree._DescriptionProperty

        -

        A class to store a TABLE element, which optionally contains data.

        -

        It contains the following publicly-accessible members, all of -which are mutable:

        -
        -

        array: A Numpy recarray of the data itself, where each row -is a row of votable data, and columns are named and typed -based on the <FIELD> elements of the table.

        -

        mask: A Numpy recarray of only boolean values, set to True -wherever a value is undefined.

        -
        -

        If the Table contains no data, (for example, its enclosing -Resource has type == ‘meta’) array -and mask will be zero-length arrays.

        -
        -

        Note

        -

        In a future version of the vo package, the array and mask -elements will likely be combined into a single Numpy masked -record array. However, there are a number of deficiencies the -current implementation of Numpy that prevent this.

        -
        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -
        -
        -create_arrays(nrows=0, config={})[source]
        -

        Create new arrays to hold the data based on the current set of -fields, and store them in the array and mask member -variables. Any data in existing arrays will be lost.

        -

        nrows, if provided, is the number of rows to allocate.

        -
        - -
        -
        -fields[source]
        -

        A list of Field objects describing the types of each -of the data columns.

        -
        - -
        -
        -format[source]
        -

        [required] The serialization format of the table. Must be -one of:

        -
        -
        ‘tabledata’ (TABLEDATA), ‘binary’ (BINARY), ‘fits’ (FITS).
        -

        Note that the ‘fits’ format, since it requires an external -file, can not be written out. Any file read in with ‘fits’ -format will be read out, by default, in ‘tabledata’ format.

        -
        - -
        -
        -get_field_by_id(ref, before=None)
        -

        Looks up a FIELD or PARAM element by the given ID.

        -
        - -
        -
        -get_field_by_id_or_name(ref, before=None)
        -

        Looks up a FIELD or PARAM element by the given ID or name.

        -
        - -
        -
        -get_group_by_id(ref, before=None)
        -

        Looks up a GROUP element by the given ID. Used by the group’s -“ref” attribute

        -
        - -
        -
        -groups[source]
        -

        A list of Group objects describing how the columns -and parameters are grouped. Currently this information is -only kept around for round-tripping and informational -purposes.

        -
        - -
        -
        -infos[source]
        -

        A list of Info objects for the table. Allows for -post-operational diagnostics.

        -
        - -
        -
        -is_empty()[source]
        -

        Returns True if this table doesn’t contain any real data -because it was skipped over by the parser (through use of the -table_number kwarg).

        -
        - -
        -
        -iter_fields_and_params()[source]
        -

        Recursively iterate over all FIELD and PARAM elements in the -TABLE.

        -
        - -
        -
        -iter_groups()[source]
        -

        Recursively iterate over all GROUP elements in the TABLE.

        -
        - -
        - -

        A list of Link objects (pointers to other documents -or servers through a URI) for the table.

        -
        - -
        -
        -nrows[source]
        -

        [immutable] The number of rows in the table, as specified in -the XML file.

        -
        - -
        -
        -params[source]
        -

        A list of parameters (constant-valued columns) for the -table. Must contain only Param objects.

        -
        - -
        -
        -parse(iterator, config)[source]
        -
        - -
        -
        -ref[source]
        -
        - -
        -
        -to_xml(w, **kwargs)[source]
        -
        - -
        - -
        -
        -class astropy.io.vo.tree.Group(table, ID=None, name=None, ref=None, ucd=None, utype=None, id=None, config={}, pos=None, **extra)[source]
        -

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._NameProperty, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._UcdProperty, astropy.io.vo.tree._DescriptionProperty

        -

        Stores information about the grouping of FIELD and PARAM -elements.

        -

        This information is currently ignored by the vo package—that is -the columns in the recarray are always flat—but the grouping -information is stored so that it can be written out again to the -XML file.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -
        -
        -entries[source]
        -

        [read-only] A list of members of the GROUP. This list may -only contain objects of type Param, Group, -ParamRef and FieldRef.

        -
        - -
        -
        -iter_fields_and_params()[source]
        -

        Recursively iterate over all Param elements in this -Group.

        -
        - -
        -
        -iter_groups()[source]
        -

        Recursively iterate over all sub-Group instances in -this Group.

        -
        - -
        -
        -parse(iterator, config)[source]
        -
        - -
        -
        -ref[source]
        -

        Currently ignored, as it’s not clear from the spec how this is -meant to work.

        -
        - -
        -
        -to_xml(w, **kwargs)[source]
        -
        - -
        - -
        -
        -class astropy.io.vo.tree.Info(ID=None, name=None, value=None, id=None, xtype=None, ref=None, unit=None, ucd=None, utype=None, config={}, pos=None, **extra)[source]
        -

        Bases: astropy.io.vo.tree.SimpleElementWithContent, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._XtypeProperty, astropy.io.vo.tree._UtypeProperty

        -

        A class for storing INFO elements, which contain arbitrary -key-value pairs for extensions to the standard.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -
        -
        -content[source]
        -

        The content inside the INFO element.

        -
        - -
        -
        -name[source]
        -

        [required] The key of the key-value pair.

        -
        - -
        -
        -ref[source]
        -

        Refer to another INFO element by ID, defined previously in -the document.

        -
        - -
        -
        -unit[source]
        -

        A string specifying the units for the INFO.

        -
        - -
        -
        -value[source]
        -

        [required] The value of the key-value pair. (Always stored -as a string or unicode string).

        -
        - -
        - -
        -
        -class astropy.io.vo.tree.Field(votable, ID=None, name=None, datatype=None, arraysize=None, ucd=None, unit=None, width=None, precision=None, utype=None, ref=None, type=None, id=None, xtype=None, config={}, pos=None, **extra)[source]
        -

        Bases: astropy.io.vo.tree.SimpleElement, astropy.io.vo.tree._IDProperty, astropy.io.vo.tree._NameProperty, astropy.io.vo.tree._XtypeProperty, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._UcdProperty

        -

        A class that represents the FIELD element, which describes the -datatype of a particular column of data.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -

        If ID is provided, it is used for the column name in the -resulting recarray of the table. If no ID is provided, name -is used instead. If neither is provided, an exception will be -raised.

        -
        -
        -arraysize[source]
        -

        Specifies the size of the multidimensional array if this -FIELD contains more than a single value.

        -

        See multidimensional arrays.

        -
        - -
        -
        -datatype[source]
        -

        [required] The datatype of the column. Valid values (as -defined by the spec) are:

        -
        -
        ‘boolean’, ‘bit’, ‘unsignedByte’, ‘short’, ‘int’, ‘long’, -‘char’, ‘unicodeChar’, ‘float’, ‘double’, ‘floatComplex’, or -‘doubleComplex’
        -

        Many VOTABLE files in the wild use ‘string’ instead of ‘char’, -so that is also a valid option, though ‘string’ will always be -converted to ‘char’ when writing the file back out.

        -
        - -
        - -

        A list of Link instances used to reference more -details about the meaning of the FIELD. This is purely -informational and is not used by the astropy.io.vo package.

        -
        - -
        -
        -parse(iterator, config)[source]
        -
        - -
        -
        -precision[source]
        -

        Along with width, defines the numerical accuracy -associated with the data. These values are used to limit the -precision when writing floating point values back to the XML -file. Otherwise, it is purely informational – the Numpy -recarray containing the data itself does not use this -information.

        -
        - -
        -
        -ref[source]
        -

        On FIELD elements, ref is used only for informational -purposes, for example to refer to a COOSYS element.

        -
        - -
        -
        -to_xml(w, **kwargs)[source]
        -
        - -
        -
        -type[source]
        -

        The type attribute on FIELD elements is reserved for future -extensions.

        -
        - -
        -
        -classmethod uniqify_names(fields)[source]
        -

        Make sure that all names and titles in a list of fields are -unique, by appending numbers if necessary.

        -
        - -
        -
        -unit[source]
        -

        A string specifying the units for the FIELD.

        -
        - -
        -
        -values[source]
        -

        A Values instance (or None) defining the domain -of the column.

        -
        - -
        -
        -width[source]
        -

        Along with precision, defines the numerical -accuracy associated with the data. These values are used to -limit the precision when writing floating point values back to -the XML file. Otherwise, it is purely informational – the -Numpy recarray containing the data itself does not use this -information.

        -
        - -
        - -
        -
        -class astropy.io.vo.tree.Param(votable, ID=None, name=None, value=None, datatype=None, arraysize=None, ucd=None, unit=None, width=None, precision=None, utype=None, type=None, id=None, config={}, pos=None, **extra)[source]
        -

        Bases: astropy.io.vo.tree.Field

        -

        A class to represent the PARAM element, which are constant-valued -columns in the data.

        -

        Param objects are a subclass of Field, and have -all of its methods and members. Additionally, it defines value.

        -
        -
        -to_xml(w, **kwargs)[source]
        -
        - -
        -
        -value[source]
        -

        [required] The constant value of the parameter. Its type is -determined by the datatype member.

        -
        - -
        - -
        - -

        Bases: astropy.io.vo.tree.SimpleElement, astropy.io.vo.tree._IDProperty

        -

        A class for storing LINK elements, which are used to reference -external documents and servers through a URI.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -
        -
        -content_role[source]
        -

        Defines the MIME role of the referenced object. Must be one of:

        -
        -
        None, ‘query’, ‘hints’, ‘doc’ or ‘location’
        -
        - -
        -
        -content_type[source]
        -

        Defines the MIME content type of the referenced object.

        -
        - -
        -
        -href[source]
        -

        A URI to an arbitrary protocol. The vo package only supports -http and anonymous ftp.

        -
        - -
        - -
        -
        -class astropy.io.vo.tree.CooSys(ID=None, equinox=None, epoch=None, system=None, id=None, config={}, pos=None, **extra)[source]
        -

        Bases: astropy.io.vo.tree.SimpleElement

        -

        A class representing the COOSYS element, which defines a -coordinate system.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -
        -
        -ID[source]
        -

        [required] The XML ID of the COOSYS element, used for -cross-referencing. May be None or a string conforming to -XML ID syntax.

        -
        - -
        -
        -epoch[source]
        -

        Specifies the epoch of the positions. It must be a string -specifying an astronomical year.

        -
        - -
        -
        -equinox[source]
        -

        A parameter required to fix the equatorial or ecliptic systems -(as e.g. “J2000” as the default “eq_FK5” or “B1950” as the -default “eq_FK4”).

        -
        - -
        -
        -system[source]
        -

        Specifies the type of coordinate system. Valid choices are:

        -
        -
        ‘eq_FK4’, ‘eq_FK5’, ‘ICRS’, ‘ecl_FK4’, ‘ecl_FK5’, ‘galactic’, -‘supergalactic’, ‘xy’, ‘barycentric’, or ‘geo_app’
        -
        - -
        - -
        -
        -class astropy.io.vo.tree.FieldRef(table, ref, ucd=None, utype=None, config={}, pos=None, **extra)[source]
        -

        Bases: astropy.io.vo.tree.SimpleElement, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._UcdProperty

        -

        A class representing the FIELDref element, which is used inside -of GROUP elements to refer to FIELD elements defined elsewhere.

        -
        -
        -get_ref()[source]
        -

        Lookup the Field instance that this FieldRef -references.

        -
        - -
        -
        -ref[source]
        -

        The ID of the FIELD that this FIELDref references.

        -
        - -
        - -
        -
        -class astropy.io.vo.tree.ParamRef(table, ref, ucd=None, utype=None, config={}, pos=None)[source]
        -

        Bases: astropy.io.vo.tree.SimpleElement, astropy.io.vo.tree._UtypeProperty, astropy.io.vo.tree._UcdProperty

        -

        A class representing the PARAMref element, which is used inside -of GROUP elements to refer to PARAM elements defined elsewhere.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -

        It contains the following publicly-accessible members:

        -
        -
        ref: An XML ID refering to a <PARAM> element.
        -
        -
        -get_ref()[source]
        -

        Lookup the Param instance that this PARAMref -references.

        -
        - -
        -
        -ref[source]
        -

        The ID of the PARAM that this PARAMref references.

        -
        - -
        - -
        -
        -class astropy.io.vo.tree.Values(votable, field, ID=None, null=None, ref=None, type='legal', id=None, config={}, pos=None, **extras)[source]
        -

        Bases: astropy.io.vo.tree.Element, astropy.io.vo.tree._IDProperty

        -

        A class to represent the VALUES element, used within FIELD and -PARAM elements to define the domain of values.

        -

        The keyword arguments correspond to setting members of the same -name, documented below.

        -
        -
        -is_defaults()[source]
        -
        - -
        -
        -max[source]
        -

        The maximum value of the domain. See max_inclusive.

        -
        - -
        -
        -max_inclusive[source]
        -

        When True, the domain includes the maximum value.

        -
        - -
        -
        -min[source]
        -

        The minimum value of the domain. See min_inclusive.

        -
        - -
        -
        -min_inclusive[source]
        -

        When True, the domain includes the minimum value.

        -
        - -
        -
        -null[source]
        -

        For integral datatypes, null is used to define the value -used for missing values.

        -
        - -
        -
        -options[source]
        -

        A list of string key-value tuples defining other OPTION -elements for the domain. All options are ignored – they are -stored for round-tripping purposes only.

        -
        - -
        -
        -parse(iterator, config)[source]
        -
        - -
        -
        -ref[source]
        -

        Refer to another VALUES element by ID, defined previously in -the document, for MIN/MAX/OPTION information.

        -
        - -
        -
        -to_xml(w, **kwargs)[source]
        -
        - -
        -
        -type[source]
        -

        [required] Defines the applicability of the domain defined -by this VALUES element. Must be one of the following -strings:

        -
        -
          -
        • ‘legal’: The domain of this column applies in general to -this datatype. (default)
        • -
        • ‘actual’: The domain of this column applies only to the -data enclosed in the parent table.
        • -
        -
        -
        - -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.io.vo.table: Loading entire VOTable files

        -

        Next topic

        -

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/api_ucd.html b/vo/api_ucd.html deleted file mode 100644 index e2dc9495..00000000 --- a/vo/api_ucd.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - - - - astropy.io.vo.ucd: Functions to parse and verify unified content descriptors — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.ucd: Functions to parse and verify unified content descriptors

        -

        This file contains routines to verify the correctness of UCD strings.

        -
        -
        -astropy.io.vo.ucd.parse_ucd(ucd, check_controlled_vocabulary=False, has_colon=False)[source]
        -

        Parse the UCD into its component parts.

        - --- - - - - - - - -
        Parameters :

        ucd : str

        -
        -

        The UCD string

        -
        -

        check_controlled_vocabulary : bool, optional

        -
        -

        If True, then each word in the UCD will be verified against -the UCD1+ controlled vocabulary, (as required by the VOTable -specification version 1.2), otherwise not.

        -
        -

        has_colon : bool, optional

        -
        -

        If True, the UCD may contain a colon (as defined in earlier -versions of the standard).

        -
        -
        Returns :

        parts : list

        -
        -

        The result is a list of tuples of the form:

        -
        -

        (namespace, word)

        -
        -

        If no namespace was explicitly specified, namespace will be -returned as 'ivoa' (i.e., the default namespace).

        -
        -
        Raises :

        ValueError : ucd is invalid

        -
        -
        - -
        -
        -astropy.io.vo.ucd.check_ucd(ucd, check_controlled_vocabulary=False, has_colon=False)[source]
        -

        Returns False if ucd is not a valid unified content -descriptor.

        - --- - - - - - -
        Parameters :

        ucd : str

        -
        -

        The UCD string

        -
        -

        check_controlled_vocabulary : bool, optional

        -
        -

        If True, then each word in the UCD will be verified against -the UCD1+ controlled vocabulary, (as required by the VOTable -specification version 1.2), otherwise not.

        -
        -
        Returns :

        valid : bool

        -
        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.io.vo.exceptions

        -

        Next topic

        -

        astropy.io.vo.unit: Verification of units as defined in the VOTable standard

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/api_unit.html b/vo/api_unit.html deleted file mode 100644 index 761d4aa2..00000000 --- a/vo/api_unit.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - astropy.io.vo.unit: Verification of units as defined in the VOTable standard — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.unit: Verification of units as defined in the VOTable standard

        -

        Tools to verify the syntax of unit attributes according to the -Standards for Astronomical Catalogues, Version 2.0

        -
        -
        -astropy.io.vo.unit.is_unit(s)[source]
        -

        Returns True if s is a valid unit string as defined by -Standards for Astronomical Catalogues, Version 2.0

        -
        - -
        -
        -astropy.io.vo.unit.check_unit(unit, attr_name, config={}, pos=None)[source]
        -

        Raises a ValueError if unit is not a valid unit as defined by -Standards for Astronomical Catalogues, Version 2.0

        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.io.vo.ucd: Functions to parse and verify unified content descriptors

        -

        Next topic

        -

        astropy.io.vo.util: Low-level utilities used by the library

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/api_util.html b/vo/api_util.html deleted file mode 100644 index 32ae6351..00000000 --- a/vo/api_util.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - astropy.io.vo.util: Low-level utilities used by the library — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.util: Low-level utilities used by the library

        -

        Various utilities and cookbook-like things.

        -
        -
        -astropy.io.vo.util.convert_to_writable_filelike(*args, **kwds)[source]
        -

        Returns a writable file-like object suitable for streaming output.

        - --- - - - - - -
        Parameters :

        fd : file path string or writable file-like object

        -
        -

        May be:

        -
        -
          -
        • a file path, in which case it is opened, and the file -object is returned.
        • -
        • an object with a write() method, in which case that -object.
        • -
        -
        -
        -
        Returns :

        fd : writable file-like object

        -
        -
        - -
        -
        -astropy.io.vo.util.coerce_range_list_param(p, frames=None, numeric=True)[source]
        -

        Coerces and/or verifies the object p into a valid -range-list-format parameter as defined in Section 8.7.2 of Simple -Spectral Access Protocol.

        - --- - - - - - -
        Parameters :

        p : str or sequence

        -
        -

        May be a string as passed verbatim to the service expecting a -range-list, or a sequence. If a sequence, each item must be -either:

        -
        -
          -
        • a numeric value
        • -
        • a named value, such as, for example, ‘J’ for named -spectrum (if the numeric kwarg is False)
        • -
        • a 2-tuple indicating a range
        • -
        • the last item my be a string indicating the frame of -reference
        • -
        -
        -
        -

        frames : sequence of str, optional

        -
        -

        A sequence of acceptable frame of reference keywords. If not -provided, the default set in set_reference_frames will be -used.

        -
        -

        numeric : bool, optional

        -
        -

        TODO

        -
        -
        Returns :

        parts : tuple

        -
        -
        -
        The result is a tuple:
        -
          -
        • a string suitable for passing to a service as a range-list -argument
        • -
        • an integer counting the number of elements
        • -
        -
        -
        -
        -
        -
        - -
        -
        -astropy.io.vo.util.is_callable(o)[source]
        -

        Abstracts away the different ways to test for a callable object in -Python 2.x and 3.x.

        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.io.vo.unit: Verification of units as defined in the VOTable standard

        -

        Next topic

        -

        astropy.io.vo.validator: Generates HTML validation reports

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/api_validator.html b/vo/api_validator.html deleted file mode 100644 index 050a7f1d..00000000 --- a/vo/api_validator.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - astropy.io.vo.validator: Generates HTML validation reports — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.validator: Generates HTML validation reports

        -

        Validates a large collection of web-accessible VOTable files, -and generates a report as a directory tree of HTML files.

        -
        -
        -astropy.io.vo.validator.main.make_validation_report(urls=None, destdir='astropy.io.vo.validator.results', multiprocess=True, stilts=None)[source]
        -

        Validates a large collection of web-accessible VOTable files, -and generates a report as a directory tree of HTML files.

        - --- - - - -
        Parameters :

        urls : list of strings, optional

        -
        -

        If provided, is a list of HTTP urls to download VOTable files -from. If not provided, a built-in set of ~22,000 urls -compiled by HEASARC will be used.

        -
        -

        destdir : path, optional

        -
        -

        The directory to write the report to. By default, this is a -directory called astropy.io.vo.validator.results in the -current directory. If the directory does not exist, it will -be created.

        -
        -

        multiprocess : bool, optional

        -
        -

        If True (default), perform validations in parallel using all -of the cores on this machine.

        -
        -

        stilts : path, optional

        -
        -

        To perform validation with votlint from the the Java-based -STILTS VOTable -parser, in addition to astropy.io.vo, set this to the path -of the stilts.jar file. java on the system shell path -will be used to run it.

        -
        -
        -

        Notes

        -

        Downloads of each given URL will be performed only once and cached -locally in destdir. To refresh the cache, remove destdir -first.

        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.io.vo.util: Low-level utilities used by the library

        -

        Next topic

        -

        astropy.io.vo.xmlutil: XML-related utilities used by the library

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/api_xmlutil.html b/vo/api_xmlutil.html deleted file mode 100644 index 2decdb80..00000000 --- a/vo/api_xmlutil.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - - - astropy.io.vo.xmlutil: XML-related utilities used by the library — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.io.vo.xmlutil: XML-related utilities used by the library

        -

        Various XML-related utilities

        -
        -
        -astropy.io.vo.xmlutil.check_id(ID, name='ID', config={}, pos=None)[source]
        -

        Raises a astropy.io.vo.exceptions.VOTableSpecError if ID is not a -valid XML ID. name is the name of the attribute being checked -(used only for error messages).

        -
        - -
        -
        -astropy.io.vo.xmlutil.fix_id(ID, config={}, pos=None)[source]
        -

        Given an arbitrary string, create one that can be used as an xml -id. This is rather simplistic at the moment, since it just -replaces non-valid characters with underscores.

        -
        - -
        -
        -astropy.io.vo.xmlutil.check_token(token, attr_name, config={}, pos=None)[source]
        -

        Raises a ValueError if token is not a valid XML token, as -defined by XML Schema Part 2.

        -
        - -
        -
        -astropy.io.vo.xmlutil.check_mime_content_type(content_type, config={}, pos=None)[source]
        -

        Raises a astropy.io.vo.exceptions.VOTableSpecError if -content_type is not a valid MIME content type (syntactically at -least), as defined by RFC 2045.

        -
        - -
        -
        -astropy.io.vo.xmlutil.check_anyuri(uri, config={}, pos=None)[source]
        -

        Raises a astropy.io.vo.exceptions.VOTableSpecError if uri is -not a valid URI as defined in RFC 2396.

        -
        - -
        -
        -astropy.io.vo.xmlutil.validate_schema(filename, version='1.2')[source]
        -

        Validates the given file against the appropriate VOTable schema.

        - --- - - - - - -
        Parameters :

        filename : str

        -
        -

        The path to the XML file to validate

        -
        -

        version : str

        -
        -

        The VOTABLE version to check, which must be a string “1.0”, -“1.1”, or “1.2”.

        -

        For version “1.0”, it is checked against a DTD, since that -version did not have an XML Schema.

        -
        -
        Returns :

        returncode, stdout, stderr : int, str, str

        -
        -

        Returns the returncode from xmllint and the stdout and stderr -as strings

        -
        -
        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        astropy.io.vo.validator: Generates HTML validation reports

        -

        Next topic

        -

        astropy.io.vo.converters: Conversions between XML and Numpy datatypes

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/index.html b/vo/index.html deleted file mode 100644 index bc1c8bc2..00000000 --- a/vo/index.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - astropy.io.vo Documentation — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - -
        - -
        -
        - -

        Previous topic

        -

        astropy.wcs History

        -

        Next topic

        -

        Introduction to astropy.io.vo.table

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/vo/intro_table.html b/vo/intro_table.html deleted file mode 100644 index 4bd67fd2..00000000 --- a/vo/intro_table.html +++ /dev/null @@ -1,439 +0,0 @@ - - - - - - - - - - Introduction to astropy.io.vo.table — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Introduction to astropy.io.vo.table

        -

        astropy.io.vo.table is a Python package to read and write VOTable -files into Numpy record arrays.

        -
        -

        Standard compliance

        -

        astropy.io.vo.table supports the VOTable Format Definition Version -1.1 -and Version 1.2. -Some flexibility is provided to support the 1.0 draft version and -other non-standard usage in the wild. To support these cases, set the -keyword argument pedantic to False when parsing.

        -
        -

        Note

        -

        Each warning and VOTABLE-specific exception emitted has a number and -is documented in more detail in Warnings and -Exceptions.

        -
        -

        Output always conforms to the 1.1 or 1.2 spec, depending on the input.

        -
        -
        -

        Using astropy.io.vo.table

        -
        -

        Reading a VOTable file

        -

        To read in a VOTable file, pass a file path to -astropy.io.vo.table.parse:

        -
        from astropy.io.vo.table import parse
        -votable = parse("votable.xml")
        -
        -
        -

        votable is a VOTableFile object, which can -be used to retrieve and manipulate the data and save it back out to -disk.

        -

        VOTable files are made up of nested RESOURCE elements, each of -which may contain one or more TABLE elements. The TABLE -elements contain the arrays of data.

        -

        To get at the TABLE elements, one can write a loop over the -resources in the VOTABLE file:

        -
        for resource in votable.resources:
        -  for table in resource.tables:
        -    # ... do something with the table ...
        -    pass
        -
        -
        -

        However, if the nested structure of the resources is not important, -one can use iter_tables to return a flat -list of all tables:

        -
        for table in votable.iter_tables():
        -  # ... do something with the table ...
        -  pass
        -
        -
        -

        Finally, if there is expected to be only one table in the file, it -might be simplest to just use -get_first_table:

        -
        table = votable.get_first_table()
        -
        -
        -

        Even easier, there is a convenience method to parse a VOTable file and -return the first table all in one step:

        -
        from astropy.io.vo.table import parse_single_table
        -table = parse_single_table("votable.xml")
        -
        -
        -

        From a Table object, one can get the data itself -in the array member variable:

        -
        data = table.array
        -
        -
        -

        This data is a Numpy record array. The columns get their names from -both the ID and name attributes of the FIELD elements in -the VOTABLE file. For example, suppose we had a FIELD -specified as follows:

        -
        <FIELD ID="Dec" name="dec_targ" datatype="char" ucd="POS_EQ_DEC_MAIN"
        -       unit="deg">
        - <DESCRIPTION>
        -  representing the ICRS declination of the center of the image.
        - </DESCRIPTION>
        -</FIELD>
        -
        -
        -

        This column of data can be extracted from the record array using:

        -
        >>> table.array['dec_targ']
        -array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826,
        -       17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136,
        -       17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055,
        -       17.1553884541, 17.15539736932, 17.15539752176,
        -       17.25736014763,
        -       # ...
        -       17.2765703], dtype=object)
        -
        -
        -

        or equivalently:

        -
        >>> table.array['Dec']
        -array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826,
        -       17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136,
        -       17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055,
        -       17.1553884541, 17.15539736932, 17.15539752176,
        -       17.25736014763,
        -       # ...
        -       17.2765703], dtype=object)
        -
        -
        -
        -

        Pedantic mode

        -

        Many VOTABLE files in the wild do not conform to the VOTABLE -specification. If reading one of these files causes exceptions, you -may turn off pedantic mode in astropy.io.vo by passing -pedantic=False to the parse or -parse_single_table functions:

        -
        from astropy.io.vo.table import parse
        -votable = parse("votable.xml", pedantic=False)
        -
        -
        -

        Note, however, that it is good practice to report these errors to the -author of the application that generated the VOTABLE file to bring the -file into compliance with the specification.

        -

        Even with pedantic turned off, many warnings may still be omitted. -These warnings are all of the type -VOTableSpecWarning and can be turned off -using the standard Python warnings module.

        -
        -
        -
        -

        Building a new table from scratch

        -

        It is also possible to build a new table, define some field datatypes -and populate it with data:

        -
        from astropy.io.vo.tree import VOTableFile, Resource, Table, Field
        -
        -# Create a new VOTable file...
        -votable = VOTableFile()
        -
        -# ...with one resource...
        -resource = Resource()
        -votable.resources.append(resource)
        -
        -# ... with one table
        -table = Table(votable)
        -resource.tables.append(table)
        -
        -# Define some fields
        -table.fields.extend([
        -        Field(votable, ID="filename", datatype="char"),
        -        Field(votable, ID="matrix", datatype="double", arraysize="2x2")])
        -
        -# Now, use those field definitions to create the numpy record arrays, with
        -# the given number of rows
        -table.create_arrays(2)
        -
        -# Now table.array can be filled with data
        -table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
        -table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
        -
        -# Now write the whole thing to a file.
        -# Note, we have to use the top-level votable file object
        -votable.to_xml("new_votable.xml")
        -
        -
        -
        -
        -

        Missing values

        -

        Any value in the table may be “missing”. astropy.io.vo.table stores -a parallel array in each Table instance called -mask to keep track of missing values. -This array is False anywhere the value is missing.

        -
        -

        Note

        -

        In the future, the array and mask members will likely be -combined into a single masked record array. There are -implementation bugs in current versions of Numpy that prevent this -at the moment.

        -
        -
        -
        -

        Datatype mappings

        -

        The datatype specified by a FIELD element is mapped to a Numpy -type according to the following table:

        -
        -
        ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        VOTABLE typeNumpy type
        booleanb1
        bitb1
        unsignedByteu1
        char (variable length)O - In Python 2.x, a str object; in 3.x, a bytes object.
        char (fixed length)S
        unicodeChar (variable length)O - In Python 2.x, a unicode object, in utf-16; in 3.x a str object
        unicodeChar (fixed length)U
        shorti2
        inti4
        longi8
        floatf4
        doublef8
        floatComplexc8
        doubleComplexc16
        -
        -

        If the field is a fixed size array, the data is stored as a Numpy -fixed-size array.

        -

        If the field is a variable size array (that is arraysize contains -a ‘*’), the cell will contain a Python list of Numpy values. Each -value may be either an array or scalar depending on the arraysize -specifier.

        -
        -
        -

        Examining field types

        -

        To look up more information about a field in a table, one can use the -get_field_or_param_by_id method, which -returns the Field object with the given ID. For -example:

        -
        >>> field = table.get_field_or_param_by_id('Dec')
        ->>> field.datatype
        -'char'
        ->>> field.unit
        -'deg'
        -
        -
        -
        -

        Note

        -

        Field descriptors should not be mutated – they will have no effect -on the record arrays storing the data. This shortcoming will be -addressed in a future version of astropy.io.vo.

        -
        -
        -
        -

        Outputting a VOTable file

        -

        To save a VOTable file, simply call the -to_xml method. It accepts either a -string or unicode path, or a Python file-like object:

        -
        votable.to_xml('output.xml')
        -
        -
        -

        There are currently two data storage formats supported by -astropy.io.vo. The TABLEDATA format is XML-based and stores -values as strings representing numbers. The BINARY format is more -compact, and stores numbers in base64-encoded binary. The storage -format can be set on a per-table basis using the -format attribute, or globally using the -set_all_tables_format method:

        -
        votable.get_first_table().format = 'binary'
        -votable.set_all_tables_format('binary')
        -votable.to_xml('binary.xml')
        -
        -
        -
        -
        -
        -

        Performance considerations

        -

        File reads will be moderately faster if the TABLE element includes -an nrows attribute. If the number of rows is not specified, the -record array must be resized repeatedly during load.

        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        astropy.io.vo Documentation

        -

        Next topic

        -

        API documentation

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/api.html b/wcs/api.html deleted file mode 100644 index 6c4a9b82..00000000 --- a/wcs/api.html +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - API Documentation — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        API Documentation

        -
        -

        astropy.wcs

        -

        Under the hood, there are 3 separate classes that perform different -parts of the transformation:

        -
        -
        -
        -

        Additionally, the class WCS aggregates all of these transformations -together in a pipeline:

        -
        -
        -
        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Example Usage

        -

        Next topic

        -

        WCS

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/api_distortion.html b/wcs/api_distortion.html deleted file mode 100644 index ef701f6d..00000000 --- a/wcs/api_distortion.html +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - - - - - DistortionLookupTable — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        DistortionLookupTable

        -
        -
        -class astropy.wcs.DistortionLookupTable
        -

        Represents a single lookup table for a Paper IV distortion -transformation.

        - --- - - - -
        Parameters :

        table : 2-dimensional array

        -
        -

        The distortion lookup table.

        -
        -

        crpix : 2-tuple

        -
        -

        The distortion array reference pixel

        -
        -

        crval : 2-tuple

        -
        -

        The image array pixel coordinate

        -
        -

        cdelt : 2-tuple

        -
        -

        The grid step size

        -
        -
        -
        -
        -cdelt
        -

        double array[naxis]

        -

        Coordinate increments (CDELTia) for each coord axis.

        -

        If a CDi_ja linear transformation matrix is present, a warning is -raised and cdelt is ignored. The CDi_ja -matrix may be deleted by:

        -
        del wcs.wcs.cd
        -
        -
        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -crpix
        -

        double array[naxis]

        -

        Coordinate reference pixels (CRPIXja) for each pixel axis.

        -
        - -
        -
        -crval
        -

        double array[naxis]

        -

        Coordinate reference values (CRVALia) for each coordinate axis.

        -
        - -
        -
        -data
        -

        float array

        -

        The array data for the DistortionLookupTable.

        -
        - -
        -
        -get_offset(*x, y*) -> (*x, y*)
        -

        Returns the offset as defined in the distortion lookup table.

        - --- - - - -
        Returns :

        coordinate : coordinate pair

        -
        -

        The offset from the distortion table for pixel point (x, y).

        -
        -
        -
        - -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        Wcsprm

        -

        Next topic

        -

        Sip

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/api_sip.html b/wcs/api_sip.html deleted file mode 100644 index 6ca40be4..00000000 --- a/wcs/api_sip.html +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - Sip — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Sip

        -
        -
        -class astropy.wcs.Sip
        -

        The Sip class performs polynomial distortion correction -using the SIP convention in both directions.

        - --- - - - -
        Parameters :

        a : double array[m+1][m+1]

        -
        -

        The A_i_j polynomial for pixel to focal plane transformation. -Its size must be (m + 1, m + 1) where m = A_ORDER.

        -
        -

        b : double array[m+1][m+1]

        -
        -

        The B_i_j polynomial for pixel to focal plane transformation. -Its size must be (m + 1, m + 1) where m = B_ORDER.

        -
        -

        ap : double array[m+1][m+1]

        -
        -

        The AP_i_j polynomial for pixel to focal plane transformation. -Its size must be (m + 1, m + 1) where m = AP_ORDER.

        -
        -

        bp : double array[m+1][m+1]

        -
        -

        The BP_i_j polynomial for pixel to focal plane transformation. -Its size must be (m + 1, m + 1) where m = BP_ORDER.

        -
        -

        crpix : double array[2]

        -
        -

        The reference pixel.

        -
        -
        -

        Notes

        -

        Shupe, D. L., M. Moshir, J. Li, D. Makovoz and R. Narron. 2005. -“The SIP Convention for Representing Distortion in FITS Image -Headers.” ADASS XIV.

        -
        -
        -a
        -

        double array[a_order+1][a_order+1]

        -

        The SIP A_i_j matrix used for pixel to focal plane -transformation.

        -

        Its values may be changed in place, but it may not be resized, without -creating a new Sip object.

        -
        - -
        -
        -a_order
        -

        int (read-only)

        -

        The order of the polynomial in the SIP A_i_j array (A_ORDER).

        -
        - -
        -
        -ap
        -

        double array[ap_order+1][ap_order+1]

        -

        The SIP AP_i_j matrix used for focal plane to pixel -transformation. Its values may be changed in place, but it may not be -resized, without creating a new Sip object.

        -
        - -
        -
        -ap_order
        -

        int (read-only)

        -

        The order of the polynomial in the SIP AP_i_j array -(AP_ORDER).

        -
        - -
        -
        -b
        -

        double array[b_order+1][b_order+1]

        -

        The SIP B_i_j matrix used for pixel to focal plane -transformation. Its values may be changed in place, but it may not be -resized, without creating a new Sip object.

        -
        - -
        -
        -b_order
        -

        int (read-only)

        -

        The order of the polynomial in the SIP B_i_j array -(B_ORDER).

        -
        - -
        -
        -bp
        -

        double array[bp_order+1][bp_order+1]

        -

        The SIP BP_i_j matrix used for focal plane to pixel -transformation. Its values may be changed in place, but it may not be -resized, without creating a new Sip object.

        -
        - -
        -
        -bp_order
        -

        int (read-only)

        -

        The order of the polynomial in the SIP BP_i_j array -(BP_ORDER).

        -
        - -
        -
        -crpix
        -

        double array[naxis]

        -

        Coordinate reference pixels (CRPIXja) for each pixel axis.

        -
        - -
        -
        -foc2pix()
        -

        sip_foc2pix(foccrd, origin) -> double array[ncoord][nelem]

        -

        Convert focal plane coordinates to pixel coordinates using the SIP -polynomial distortion convention.

        - --- - - - - - - - -
        Parameters :

        foccrd : double array[ncoord][nelem]

        -
        -

        Array of focal plane coordinates.

        -
        -

        origin : int

        -
        -

        Specifies the origin of pixel values. The Fortran and FITS -standards use an origin of 1. Numpy and C use array indexing with -origin at 0.

        -
        -
        Returns :

        pixcrd : double array[ncoord][nelem]

        -
        -

        Returns an array of pixel coordinates.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -
        -
        - -
        -
        -pix2foc()
        -

        sip_pix2foc(pixcrd, origin) -> double array[ncoord][nelem]

        -

        Convert pixel coordinates to focal plane coordinates using the SIP -polynomial distortion convention.

        - --- - - - - - - - -
        Parameters :

        pixcrd : double array[ncoord][nelem]

        -
        -

        Array of pixel coordinates.

        -
        -

        origin : int

        -
        -

        Specifies the origin of pixel values. The Fortran and FITS -standards use an origin of 1. Numpy and C use array indexing with -origin at 0.

        -
        -
        Returns :

        foccrd : double array[ncoord][nelem]

        -
        -

        Returns an array of focal plane coordinates.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -
        -
        - -
        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        DistortionLookupTable

        -

        Next topic

        -

        UnitConverter

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/api_units.html b/wcs/api_units.html deleted file mode 100644 index 8c73323f..00000000 --- a/wcs/api_units.html +++ /dev/null @@ -1,991 +0,0 @@ - - - - - - - - - - UnitConverter — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        UnitConverter

        -
        -
        -class astropy.wcs.UnitConverter
        -

        Creates an object for performing conversion from one system of units -to another.

        -

        Use the returned object’s convert method -to convert values from have to want.

        -

        This function is permissive in accepting whitespace in all contexts in -a units specification where it does not create ambiguity (e.g. not -between a metric prefix and a basic unit string), including in strings -like "log (m ** 2)" which is formally disallowed.

        - --- - - - - - -
        Parameters :

        have : string

        -
        -

        FITS unit specification to convert from, with or without surrounding -square brackets (for inline specifications); text following the -closing bracket is ignored.

        -
        -

        want : string

        -
        -

        FITS unit specification to convert to, with or without surrounding square -brackets (for inline specifications); text following the closing -bracket is ignored.

        -
        -

        ctrl : string, optional

        -
        -

        Do potentially unsafe translations of non-standard unit strings.

        -

        Although "S" is commonly used to represent seconds, its -recognizes "S" formally as Siemens, however rarely that may -be translation to "s" is potentially unsafe since the -standard used. The same applies to "H" for hours (Henry), -and "D" for days (Debye).

        -

        This string controls what to do in such cases, and is -case-insensitive.

        -
          -
        • If the string contains "s", translate "S" to "s".
        • -
        • If the string contains "h", translate "H" to "h".
        • -
        • If the string contains "d", translate "D" to "d".
        • -
        -

        Thus '' doesn’t do any unsafe translations, whereas 'shd' -does all of them.

        -

        See FITS unit specification for more information.

        -
        -
        Raises :

        ValueError :

        -
        -

        Invalid numeric multiplier.

        -
        -

        SyntaxError :

        -
        -

        Dangling binary operator.

        -
        -

        SyntaxError :

        -
        -

        Invalid symbol in INITIAL context.

        -
        -

        SyntaxError :

        -
        -

        Function in invalid context.

        -
        -

        SyntaxError :

        -
        -

        Invalid symbol in EXPON context.

        -
        -

        SyntaxError :

        -
        -

        Unbalanced bracket.

        -
        -

        SyntaxError :

        -
        -

        Unbalanced parenthesis.

        -
        -

        SyntaxError :

        -
        -

        Consecutive binary operators.

        -
        -

        SyntaxError :

        -
        -

        Internal parser error.

        -
        -

        SyntaxError :

        -
        -

        Non-conformant unit specifications.

        -
        -

        SyntaxError :

        -
        -

        Non-conformant functions.

        -
        -

        ValueError :

        -
        -

        Potentially unsafe translation.

        -
        -
        -
        -
        -convert(array)
        -

        Perform the unit conversion on the elements of the given array, -returning an array of the same shape.

        -
        - -
        -
        -have
        -

        The name of the unit being converted from.

        -

        This value always uses standard unit names, even if the -UnitConverter was initialized with a non-standard unit name.

        -
        - -
        -
        -offset
        -

        double

        -

        The offset of the unit conversion.

        -
        - -
        -
        -power
        -

        double

        -

        The exponent of the unit conversion.

        -
        - -
        -
        -scale
        -

        double

        -

        The scaling factor for the unit conversion.

        -
        - -
        -
        -want
        -

        The name of the unit being converted to.

        -

        This value always uses standard unit names, even if the -UnitConverter was initialized with a non-standard unit name.

        -
        - -
        - -
        -
        -

        FITS unit specification

        -
        -

        Supported units

        -

        The following units are supported by the FITS standard:

        -

        SI base & supplementary units

        - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        QuantityUnit StringMeaning
        lengthmmetre
        masskgkilogram
        timessecond of time
        plane angleradradian
        solid anglesrsteradian
        temperatureKkelvin
        electric currentAampere
        amount of substancemolmole
        luminous intensitycdcandela
        -

        IAU-recognized derived units

        - ------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        QuantityUnit StringMeaningEquivalence
        frequencyHzhertzs-1
        energyJjouleN m
        powerWwattJ s-1
        electric potentialVvoltsJ C-1
        forceNnewtonkg m s-2
        pressure, stressPapascalN m-2
        electric chargeCcoulombA s
        electric resistanceohmohm (Ω)V A-1
        electric conductanceSsiemensA V-1
        electric capacitanceFfaradC V-1
        magnetic fluxWbweberV s
        magnetic flux densityTteslaWb m-2
        inductanceHhenryWb A-1
        luminous fluxlmlumencd sr
        illuminancelxluxlm m-2
        -

        Additional units

        - ------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        QuantityUnit StringMeaningEquivalence
        massuunified atomic mass unit1.6605387 x 10-27 kg
        masssolMasssolar mass1.9891 x 1030 kg
        plane angledegdegree of arc1.745533 x 10-2 rad
        plane anglearcsecsecond of arc4.848137 x 10-6 rad
        plane anglearcminminute of arc2.90888 x 10-4 rad
        timeminminute 
        timehhour 
        timedday8.64 x 104 s
        timeyryear (Julian)3.15576 x10-7 s (365.25 d)
        energyeVelectron volt1.602177 x 10-19 J
        energyergerg10-7 J
        energyRyRydberg13.605692 eV
        lengthangstromangstrom10-10 m
        lengthAUastronomical unit1.49598 x 1011 m
        lengthlyrlight year9.460530 x 10-15 m
        lengthpcparsec3.0857 x 10-16 m
        lengthsolRadsolar radius6.9599 x 108 m
        eventscountcounts 
        eventsphotonphotons 
        flux densityJyjansky10-16 W m-2 Hz-1
        flux densitymag(stellar) magnitude 
        flux densityCrab‘crab’ 
        flux densitybeambeamJy/beam
        flux densitysolLumsolar luminosity 
        magnetic fieldGgauss10-4 T
        areapixel(image/detector) pixel 
        areavoxel3-d analog of pixel 
        areabarnbarn10-28 m2
        devicechan(detector) channel 
        devicebyte(computer) byte 
        devicebit(computer) bits 
        deviceaduA/D converter units 
        miscbinnumerous applications 
        miscSunwrt. sun 
        -

        Potentially unsafe translations of "D", "H", and "S", are -optional, using the translate_units parameter.

        -
        -
        -

        Unit aliases

        -

        When converting non-standard units to standard ones, a case-sensitive -match is required for the aliases listed below, in particular the only -recognized aliases with metric prefixes are "KM", "KHZ", -"MHZ", and "GHZ".

        - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        UnitRecognized aliases
        Angstromangstrom
        arcminarcmins, ARCMIN, ARCMINS
        arcsecarcsecs, ARCSEC, ARCSECS
        beamBEAM
        byteByte
        countct
        dday, days, (D), DAY, DAYS
        degdegree, degrees, DEG, DEGREE, DEGREES
        GHzGHZ
        hhr, (H), HR
        Hzhz, HZ
        kHzKHZ
        JyJY
        Kkelvin, kelvins, Kelvin, Kelvins, KELVIN, KELVINS
        kmKM
        mmetre, meter, metres, meters, M, METRE, METER, METRES, METERS
        minMIN
        MHzMHZ
        Ohmohm
        Papascal, pascals, Pascal, Pascals, PASCAL, PASCALS
        photonph
        pixelpixels, PIXEL, PIXELS, pix
        radradian, radians, RAD, RADIAN, RADIANS
        ssec, second, seconds, (S), SEC, SECOND, SECONDS
        Vvolt, volts, Volt, Volts, VOLT, VOLTS
        yryear, years, YR, YEAR, YEARS
        -

        The aliases "angstrom", "ohm", and "Byte" for (Angstrom, -Ohm, and byte) are recognized by astropy.wcs/wcslib itself as an -unofficial extension of the standard, but they are converted to the -standard form here.

        -
        -
        -

        Prefixes

        -

        The following metric prefixes are supported:

        - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        PrefixStringMagnitude
        yoctoy10-24
        zeptoz10-21
        attoa10-18
        femtof10-15
        picop10-12
        nanon10-9
        microu10-6
        millim10-3
        centic10-2
        decid10-1
        dekada101
        hectoh102
        kilok103
        MegaM106
        GigaG109
        TeraT1012
        PetaP1015
        ExaE1018
        ZettaZ1021
        YottaY1024
        -

        Table 6 of WCS Paper I lists eleven units for which metric prefixes -are allowed. However, in this implementation only prefixes greater -than unity are allowed for "a" (annum), "yr" (year), "pc" -(parsec), "bit", and "byte", and only prefixes less than unity -are allowed for "mag" (stellar magnitude).

        -

        Metric prefix "P" (peta) is specifically forbidden for "a" -(annum) to avoid confusion with "Pa" (Pascal, not peta-annum). -Note that metric prefixes are specifically disallowed for "h" -(hour) and "d" (day) so that "ph" (photons) cannot be -interpreted as pico-hours, nor "cd" (candela) as centi-days.

        -
        -
        -

        Operators

        -

        A compound unit is considered to be formed by a series of sub-strings -of component units & mathematical operations. Each of these -sub-strings must be separated by at least one space or a mathematical -operator (* or /).

        -
        -

        Multiplication

        -

        Multiplicative units can be specified either:

        -
          -
        • by simply using one or more preceding spaces, e.g. str1 str2 -(The recommended method).
        • -
        • by the use of a single asterisk (*) with optional whitespace, -e.g. str1 * str2.
        • -
        -
        -
        -

        Division

        -

        Units which form the denominator of a compound expression can be -specified either:

        -
          -
        • by using a slash (/) with optional whitespace, e.g. str1 / -str2. If such a syntax is used, it is recommended that no space -is included between the slash and the unit string.
        • -
        • by raising a multiplicative unit to a negative power (see below).
        • -
        -

        It should be stressed that the slash character only effects the -sub-string it immediately precedes. Thus, unless brackets are used, -subsequent sub-strings which also form part of the denominator of the -compound expression must also be preceded by a slash. For example, -str1 /str2 str3 is equivalent to str1 str3 /str2 whilst str1 -/str2 /str3 is equivalent to str1 /(str2 * str3).

        -
        -
        -

        Raising to Powers

        -

        A unit string raised to the power y is specified:

        -
          -
        • by using two asterisks (**) followed by the index enclosed -within round brackets and with no preceding or intervening spaces, -e.g. str1**(y) or str1**(-y).
        • -
        -

        However, if y is positive, then the brackets need not be included, -but a following space is recommended if additional sub-strings follow.

        -
        -
        -

        Use of brackets

        -

        Any number of pairs of round brackets (()) may be used within the -string for a compound unit in order to prevent ambiguities. As -described within this section, a number of rules always/often require -their use. However, it is suggested that conservative use is made of -such pairs of brackets in order to minimize the total length of -compound strings. (It should be remembered that a maximum of 68 -characters are allowed in the card image of keywords.)

        -
        -
        -

        Avoidance of underflows & overflows

        -

        The inclusion of numerical factors within the unit string should -generally be avoided (by the use of multiples and/or submultiples of -component basic units).

        -

        However, occasionally it may be preferable to include such factors on -the grounds of user-friendliness and/or to minimize the risk of -computer under- or overflows. In such cases, the numerical factor can -simply be considered a basic unit string.

        -

        The following additional guidelines are suggested:

        -
          -
        • the numerical factor should precede any unit strings
        • -
        • only powers of 10 are used as numerical factors
        • -
        -
        -
        -

        Mathematical Operations & Functions

        -

        A number of mathematical operations are supported. It should be noted -that the (round) brackets are mandatory in all cases in which they are -included in the table.

        - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        StringMeaning
        str1*str2Multiplication
        str1 /str2Division
        str1**(y)Raised to the power y
        log(str1)Common Logarithm (to base 10)
        ln(str1)Natural Logarithm
        exp(str1)Exponential (expstr1)
        sqrt(str1)Square root
        sin(str1)Sine
        cos(str1)Cosine
        tan(str1)Tangent
        asin(str1)Arc Sine
        acos(str1)Arc Cosine
        atan(str1)Arc Tangent
        sinh(str1)Hyperbolic Sine
        cosh(str1)Hyperbolic Cosine
        tanh(str1)Hyperbolic Tangent
        -

        Function types log(), ln() and exp() may only occur at the -start of the units specification.

        -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Sip

        -

        Next topic

        -

        Relax constants

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/api_wcs.html b/wcs/api_wcs.html deleted file mode 100644 index 48c8f69f..00000000 --- a/wcs/api_wcs.html +++ /dev/null @@ -1,1065 +0,0 @@ - - - - - - - - - - WCS — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        WCS

        -
        -
        -class astropy.wcs.WCS(header=None, fobj=None, key=' ', minerr=0.0, relax=False, naxis=None, keysel=None, colsel=None, fix=True)
        -

        WCS objects perform standard WCS transformations, and correct for -SIP and Paper IV table-lookup distortions, based on the WCS -keywords and supplementary data read from a FITS file.

        -
        -
        -all_pix2sky(*args, **kwargs)
        -

        Transforms pixel coordinates to sky coordinates.

        -

        Performs all of the following in order:

        -
        -
          -
        • Detector to image plane correction (optionally)
        • -
        • SIP distortion correction (optionally)
        • -
        • Paper IV table-lookup distortion correction (optionally)
        • -
        • wcslib WCS transformation
        • -
        -
        - --- - - - - - - - -
        Parameters :

        args : flexible

        -
        -

        Either two or three arguments may be provided.

        -
        -
          -
        • 2 arguments: An N x naxis array of x- and -y-coordinates, and an origin.
        • -
        • 3 arguments: 2 one-dimensional arrays of x and y -coordinates, and an origin.
        • -
        -
        -

        Here, origin is the coordinate in the upper left corner of the -image. In FITS and Fortran standards, this is 1. In Numpy and C -standards this is 0.

        -

        For a transformation that is not two-dimensional, the -two-argument form must be used.

        -
        -

        ra_dec_order : bool, optional

        -
        -

        When True will ensure that sky coordinates are always given and -returned in as (ra, dec) pairs, regardless of the order of the -axes specified by the in the CTYPE keywords.

        -
        -
        Returns :

        result : array

        -
        -

        Returns the sky coordinates, in degrees. If the input was a single array and -origin, a single array is returned, otherwise a tuple of arrays is -returned.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        SingularMatrixError :

        -
        -

        Linear transformation matrix is singular.

        -
        -

        InconsistentAxisTypesError :

        -
        -

        Inconsistent or unrecognized coordinate axis types.

        -
        -

        ValueError :

        -
        -

        Invalid parameter value.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        ValueError :

        -
        -

        x- and y-coordinate arrays are not the same size.

        -
        -

        InvalidTransformError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        InvalidTransformError :

        -
        -

        Ill-conditioned coordinate transformation parameters.

        -
        -
        -

        Notes

        -

        The order of the axes for the result is determined by the -CTYPEia keywords in the FITS header, therefore it may not -always be of the form (ra, dec). The -lat, lng, -lattyp and lngtyp -members can be used to determine the order of the axes.

        -
        - -
        -
        -calcFootprint(header=None, undistort=True)
        -

        Calculates the footprint of the image on the sky.

        -

        A footprint is defined as the positions of the corners of the -image on the sky after all available distortions have been -applied.

        - --- - - - - - -
        Parameters :

        header : pyfits header object, optional

        -

        undistort : bool, optional

        -
        -

        If True, take SIP and distortion lookup table into account

        -
        -
        Returns :

        coord : (4, 2) array of (x, y) coordinates.

        -
        -
        - -
        -
        -copy()
        -

        Return a shallow copy of the object.

        -

        Convenience method so user doesn’t have to import the copy -stdlib module.

        -
        - -
        -
        -cpdis1
        -

        DistortionLookupTable

        -

        The pre-linear transformation distortion lookup table, CPDIS1.

        -
        - -
        -
        -cpdis2
        -

        DistortionLookupTable

        -

        The pre-linear transformation distortion lookup table, CPDIS2.

        -
        - -
        -
        -deepcopy()
        -

        Return a deep copy of the object.

        -

        Convenience method so user doesn’t have to import the copy -stdlib module.

        -
        - -
        -
        -det2im(*args, **kwargs)
        -

        Convert detector coordinates to image plane coordinates using -Paper IV table-lookup distortion correction.

        - --- - - - - - - - -
        Parameters :

        args : flexible

        -
        -

        Either two or three arguments may be provided.

        -
        -
          -
        • 2 arguments: An N x 2 array of x- and -y-coordinates, and an origin.
        • -
        • 3 arguments: 2 one-dimensional arrays of x and y -coordinates, and an origin.
        • -
        -
        -

        Here, origin is the coordinate in the upper left corner of the -image. In FITS and Fortran standards, this is 1. In Numpy and C -standards this is 0.

        -
        -
        Returns :

        result : array

        -
        -

        Returns the pixel coordinates. If the input was a single array and -origin, a single array is returned, otherwise a tuple of arrays is -returned.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -
        -
        - -
        -
        -det2im1
        -

        A DistortionLookupTable object for detector to image plane -correction in the x-axis.

        -
        - -
        -
        -det2im2
        -

        A DistortionLookupTable object for detector to image plane -correction in the y-axis.

        -
        - -
        -
        -footprint_to_file(filename=None, color='green', width=2)
        -

        Writes out a ds9 style regions file. It can be loaded -directly by ds9.

        - --- - - - -
        Parameters :

        filename : string, optional

        -
        -

        Output file name - default is 'footprint.reg'

        -
        -

        color : string, optional

        -
        -

        Color to use when plotting the line.

        -
        -

        width : int, optional

        -
        -

        Width of the region line.

        -
        -
        -
        - -
        -
        -get_axis_types()
        -

        Similar to self.wcsprm.axis_types -but provides the information in a more Python-friendly format.

        - --- - - - -
        Returns :

        result : list of dicts

        -
        -

        Returns a list of dictionaries, one for each axis, each -containing attributes about the type of that axis.

        -

        Each dictionary has the following keys:

        -
          -
        • ‘coordinate_type’:
            -
          • None: Non-specific coordinate type.
          • -
          • ‘stokes’: Stokes coordinate.
          • -
          • ‘celestial’: Celestial coordinate (including CUBEFACE).
          • -
          • ‘spectral’: Spectral coordinate.
          • -
          -
        • -
        • ‘scale’:
            -
          • ‘linear’: Linear axis.
          • -
          • ‘quantized’: Quantized axis (STOKES, CUBEFACE).
          • -
          • ‘non-linear celestial’: Non-linear celestial axis.
          • -
          • ‘non-linear spectral’: Non-linear spectral axis.
          • -
          • ‘logarithmic’: Logarithmic axis.
          • -
          • ‘tabular’: Tabular axis.
          • -
          -
        • -
        • ‘group’
            -
          • Group number, e.g. lookup table number
          • -
          -
        • -
        • ‘number’
            -
          • For celestial axes:
              -
            • 0: Longitude coordinate.
            • -
            • 1: Latitude coordinate.
            • -
            • 2: CUBEFACE number.
            • -
            -
          • -
          • For lookup tables:
              -
            • the axis number in a multidimensional table.
            • -
            -
          • -
          -
        • -
        -

        CTYPEia in "4-3" form with unrecognized algorithm code will -generate an error.

        -
        -
        -
        - -
        -
        -get_naxis(header=None)
        -
        - -
        -
        -p4_pix2foc(*args, **kwargs)
        -

        Convert pixel coordinates to focal plane coordinates using -Paper IV table-lookup distortion correction.

        - --- - - - - - - - -
        Parameters :

        args : flexible

        -
        -

        Either two or three arguments may be provided.

        -
        -
          -
        • 2 arguments: An N x 2 array of x- and -y-coordinates, and an origin.
        • -
        • 3 arguments: 2 one-dimensional arrays of x and y -coordinates, and an origin.
        • -
        -
        -

        Here, origin is the coordinate in the upper left corner of the -image. In FITS and Fortran standards, this is 1. In Numpy and C -standards this is 0.

        -
        -
        Returns :

        result : array

        -
        -

        Returns the focal coordinates. If the input was a single array and -origin, a single array is returned, otherwise a tuple of arrays is -returned.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -
        -
        - -
        -
        -pix2foc(*args, **kwargs)
        -

        Convert pixel coordinates to focal plane coordinates using the -SIP polynomial distortion convention and Paper IV -table-lookup distortion correction.

        - --- - - - - - - - -
        Parameters :

        args : flexible

        -
        -

        Either two or three arguments may be provided.

        -
        -
          -
        • 2 arguments: An N x 2 array of x- and -y-coordinates, and an origin.
        • -
        • 3 arguments: 2 one-dimensional arrays of x and y -coordinates, and an origin.
        • -
        -
        -

        Here, origin is the coordinate in the upper left corner of the -image. In FITS and Fortran standards, this is 1. In Numpy and C -standards this is 0.

        -
        -
        Returns :

        result : array

        -
        -

        Returns the focal coordinates. If the input was a single array and -origin, a single array is returned, otherwise a tuple of arrays is -returned.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -
        -
        - -
        -
        -printwcs()
        -

        Temporary function for internal use.

        -
        - -
        -
        -rotateCD(theta)
        -
        - -
        -
        -sip
        -

        Get/set the Sip object for performing SIP distortion -correction.

        -
        - -
        -
        -sip_foc2pix(*args, **kwargs)
        -

        Convert focal plane coordinates to pixel coordinates using the -SIP polynomial distortion convention.

        -

        Paper IV table lookup distortion correction is not applied, -even if that information existed in the FITS file that -initialized this WCS object.

        - --- - - - - - - - -
        Parameters :

        args : flexible

        -
        -

        Either two or three arguments may be provided.

        -
        -
          -
        • 2 arguments: An N x 2 array of x- and -y-coordinates, and an origin.
        • -
        • 3 arguments: 2 one-dimensional arrays of x and y -coordinates, and an origin.
        • -
        -
        -

        Here, origin is the coordinate in the upper left corner of the -image. In FITS and Fortran standards, this is 1. In Numpy and C -standards this is 0.

        -
        -
        Returns :

        result : array

        -
        -

        Returns the pixel coordinates. If the input was a single array and -origin, a single array is returned, otherwise a tuple of arrays is -returned.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -
        -
        - -
        -
        -sip_pix2foc(*args, **kwargs)
        -

        Convert pixel coordinates to focal plane coordinates using the -SIP polynomial distortion convention.

        -

        Paper IV table lookup distortion correction is not applied, -even if that information existed in the FITS file that -initialized this WCS object. To correct -for that, use pix2foc or -p4_pix2foc.

        - --- - - - - - - - -
        Parameters :

        args : flexible

        -
        -

        Either two or three arguments may be provided.

        -
        -
          -
        • 2 arguments: An N x 2 array of x- and -y-coordinates, and an origin.
        • -
        • 3 arguments: 2 one-dimensional arrays of x and y -coordinates, and an origin.
        • -
        -
        -

        Here, origin is the coordinate in the upper left corner of the -image. In FITS and Fortran standards, this is 1. In Numpy and C -standards this is 0.

        -
        -
        Returns :

        result : array

        -
        -

        Returns the focal coordinates. If the input was a single array and -origin, a single array is returned, otherwise a tuple of arrays is -returned.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -
        -
        - -
        -
        -sub(axes)
        -

        Extracts the coordinate description for a subimage from a -WCS object.

        -

        The world coordinate system of the subimage must be separable in the -sense that the world coordinates at any point in the subimage must -depend only on the pixel coordinates of the axes extracted. In -practice, this means that the PCi_ja matrix of the original image -must not contain non-zero off-diagonal terms that associate any of the -subimage axes with any of the non-subimage axes.

        - --- - - - - - - - -
        Parameters :

        axes : int or a sequence.

        -
        -
          -
        • If an int, include the first N axes in their original order.
        • -
        • If a sequence, may contain a combination of image axis numbers -(1-relative) or special axis identifiers (see below). Order is -significant; axes[0] is the axis number of the input image -that corresponds to the first axis in the subimage, etc.
        • -
        • If 0, [] or None, do a deep copy.
        • -
        -

        Coordinate axes types may be specified using either strings or -special integer constants. The available types are:

        -
          -
        • 'longitude' / WCSSUB_LONGITUDE: Celestial longitude
        • -
        • 'latitude' / WCSSUB_LATITUDE: Celestial latitude
        • -
        • 'cubeface' / WCSSUB_CUBEFACE: Quadcube CUBEFACE axis
        • -
        • 'spectral' / WCSSUB_SPECTRAL: Spectral axis
        • -
        • 'stokes' / WCSSUB_STOKES: Stokes axis
        • -
        • 'celestial' / WCSSUB_CELESTIAL: An alias for the -combination of 'longitude', 'latitude' and 'cubeface'.
        • -
        -
        -
        Returns :

        new_wcs : WCS object

        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        InvalidSubimageSpecificationError :

        -
        -

        Invalid subimage specification (no spectral axis).

        -
        -

        NonseparableSubimageCoordinateSystem :

        -
        -

        Non-separable subimage coordinate system.

        -
        -
        -

        Notes

        -

        Combinations of subimage axes of particular types may be extracted in -the same order as they occur in the input image by combining the -integer constants with the ‘binary or’ (|) operator. For -example:

        -
        wcs.sub([WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_SPECTRAL])
        -
        -
        -

        would extract the longitude, latitude, and spectral axes in the same -order as the input image. If one of each were present, the resulting -object would have three dimensions.

        -

        For convenience, WCSSUB_CELESTIAL is defined as the combination -WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_CUBEFACE.

        -

        The codes may also be negated to extract all but the types specified, -for example:

        -
        wcs.sub([
        -  WCSSUB_LONGITUDE,
        -  WCSSUB_LATITUDE,
        -  WCSSUB_CUBEFACE,
        -  -(WCSSUB_SPECTRAL | WCSSUB_STOKES)])
        -
        -
        -

        The last of these specifies all axis types other than spectral or -Stokes. Extraction is done in the order specified by axes, i.e. a -longitude axis (if present) would be extracted first (via axes[0]) -and not subsequently (via axes[3]). Likewise for the latitude and -cubeface axes in this example.

        -

        The number of dimensions in the returned object may be less than or -greater than the length of axes. However, it will never exceed the -number of axes in the input image.

        -
        - -
        -
        -to_header(relax=False)
        -

        Generate a pyfits header object with the WCS information -stored in this object.

        -
        -

        Warning

        -

        This function does not write out SIP or Paper IV distortion -keywords, yet, only the core WCS support by wcslib.

        -
        -

        The output header will almost certainly differ from the input in a -number of respects:

        -
        -
          -
        1. The output header only contains WCS-related keywords. In -particular, it does not contain syntactically-required -keywords such as SIMPLE, NAXIS, BITPIX, or -END.
        2. -
        3. Deprecated (e.g. CROTAn) or non-standard usage will -be translated to standard (this is partially dependent on -whether fix was applied).
        4. -
        5. Quantities will be converted to the units used internally, -basically SI with the addition of degrees.
        6. -
        7. Floating-point quantities may be given to a different decimal -precision.
        8. -
        9. Elements of the PCi_j matrix will be written if and -only if they differ from the unit matrix. Thus, if the -matrix is unity then no elements will be written.
        10. -
        11. Additional keywords such as WCSAXES, CUNITia, -LONPOLEa and LATPOLEa may appear.
        12. -
        13. The original keycomments will be lost, although -to_header tries hard to write meaningful comments.
        14. -
        15. Keyword order may be changed.
        16. -
        -
        - --- - - - - - -
        Parameters :

        relax : bool or int

        -
        -

        Degree of permissiveness:

        -
          -
        • False: Recognize only FITS keywords defined by the -published WCS standard.
        • -
        • True: Admit all recognized informal extensions of the -WCS standard.
        • -
        • int: a bit field selecting specific extensions to -write. See Header-writing relaxation constants for details.
        • -
        -
        -
        Returns :

        header : pyfits Header object

        -
        -
        - -
        -
        -to_header_string(relax=False)
        -

        Identical to to_header, but returns a string containing the -header cards.

        -
        - -
        -
        -wcs
        -

        A Wcsprm object to perform the basic wcslib WCS -transformation.

        -
        - -
        -
        -wcs_pix2sky(*args, **kwargs)
        -

        Transforms pixel coordinates to sky coordinates by doing only -the basic wcslib transformation.

        -

        No SIP or Paper IV table lookup distortion correction is -applied. To perform distortion correction, see -all_pix2sky, -sip_pix2foc, p4_pix2foc, -or pix2foc.

        - --- - - - - - - - -
        Parameters :

        args : flexible

        -
        -

        Either two or three arguments may be provided.

        -
        -
          -
        • 2 arguments: An N x naxis array of x- and -y-coordinates, and an origin.
        • -
        • 3 arguments: 2 one-dimensional arrays of x and y -coordinates, and an origin.
        • -
        -
        -

        Here, origin is the coordinate in the upper left corner of the -image. In FITS and Fortran standards, this is 1. In Numpy and C -standards this is 0.

        -

        For a transformation that is not two-dimensional, the -two-argument form must be used.

        -
        -

        ra_dec_order : bool, optional

        -
        -

        When True will ensure that sky coordinates are always given and -returned in as (ra, dec) pairs, regardless of the order of the -axes specified by the in the CTYPE keywords.

        -
        -
        Returns :

        result : array

        -
        -

        Returns the sky coordinates, in degrees. If the input was a single array and -origin, a single array is returned, otherwise a tuple of arrays is -returned.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        SingularMatrixError :

        -
        -

        Linear transformation matrix is singular.

        -
        -

        InconsistentAxisTypesError :

        -
        -

        Inconsistent or unrecognized coordinate axis types.

        -
        -

        ValueError :

        -
        -

        Invalid parameter value.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        ValueError :

        -
        -

        x- and y-coordinate arrays are not the same size.

        -
        -

        InvalidTransformError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        InvalidTransformError :

        -
        -

        Ill-conditioned coordinate transformation parameters.

        -
        -
        -

        Notes

        -

        The order of the axes for the result is determined by the -CTYPEia keywords in the FITS header, therefore it may not -always be of the form (ra, dec). The -lat, lng, -lattyp and lngtyp -members can be used to determine the order of the axes.

        -
        - -
        -
        -wcs_sky2pix(*args, **kwargs)
        -

        Transforms sky coordinates to pixel coordinates, using only -the basic wcslib WCS transformation. No SIP or Paper -IV table lookup distortion is applied.

        - --- - - - - - - - -
        Parameters :

        args : flexible

        -
        -

        Either two or three arguments may be provided.

        -
        -
          -
        • 2 arguments: An N x naxis array of x- and -y-coordinates, and an origin.
        • -
        • 3 arguments: 2 one-dimensional arrays of x and y -coordinates, and an origin.
        • -
        -
        -

        Here, origin is the coordinate in the upper left corner of the -image. In FITS and Fortran standards, this is 1. In Numpy and C -standards this is 0.

        -

        For a transformation that is not two-dimensional, the -two-argument form must be used.

        -
        -

        ra_dec_order : bool, optional

        -
        -

        When True will ensure that sky coordinates are always given and -returned in as (ra, dec) pairs, regardless of the order of the -axes specified by the in the CTYPE keywords.

        -
        -
        Returns :

        result : array

        -
        -

        Returns the pixel coordinates. If the input was a single array and -origin, a single array is returned, otherwise a tuple of arrays is -returned.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        SingularMatrixError :

        -
        -

        Linear transformation matrix is singular.

        -
        -

        InconsistentAxisTypesError :

        -
        -

        Inconsistent or unrecognized coordinate axis types.

        -
        -

        ValueError :

        -
        -

        Invalid parameter value.

        -
        -

        ValueError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        ValueError :

        -
        -

        x- and y-coordinate arrays are not the same size.

        -
        -

        InvalidTransformError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        InvalidTransformError :

        -
        -

        Ill-conditioned coordinate transformation parameters.

        -
        -
        -

        Notes

        -

        The order of the axes for the input sky array is determined by -the CTYPEia keywords in the FITS header, therefore it may -not always be of the form (ra, dec). The -lat, lng, -lattyp and lngtyp -members can be used to determine the order of the axes.

        -
        - -
        - -
        -
        -

        functions

        -
        -
        -astropy.wcs.find_all_wcs(header, relax=False, keysel=None)
        -

        Find all the WCS transformations in the given header.

        - --- - - - - - -
        Parameters :

        header : string or PyFITS header object.

        -

        relax : bool or int, optional

        -
        -

        Degree of permissiveness:

        -
          -
        • False: Recognize only FITS keywords defined by the -published WCS standard.
        • -
        • True: Admit all recognized informal extensions of the -WCS standard.
        • -
        • int: a bit field selecting specific extensions to accept. -See Header-reading relaxation constants for details.
        • -
        -
        -

        keysel : sequence of flags, optional

        -
        -

        A list of flags used to select the keyword types considered by -wcslib. When None, only the standard image header -keywords are considered (and the underlying wcspih() C -function is called). To use binary table image array or pixel -list keywords, keysel must be set.

        -

        Each element in the list should be one of the following strings:

        -
        -
          -
        • ‘image’: Image header keywords
        • -
        • ‘binary’: Binary table image array keywords
        • -
        • ‘pixel’: Pixel list keywords
        • -
        -
        -

        Keywords such as EQUIna or RFRQna that are common to -binary table image arrays and pixel lists (including -WCSNna and TWCSna) are selected by both ‘binary’ and -‘pixel’.

        -
        -
        Returns :

        wcses : list of WCS objects

        -
        -
        - -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        API Documentation

        -

        Next topic

        -

        Wcsprm

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/api_wcsprm.html b/wcs/api_wcsprm.html deleted file mode 100644 index 84dffc5f..00000000 --- a/wcs/api_wcsprm.html +++ /dev/null @@ -1,1943 +0,0 @@ - - - - - - - - - - Wcsprm — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Wcsprm

        -
        -
        -class astropy.wcs.Wcsprm[source]
        -
        -
        -alt
        -

        str

        -

        Character code for alternate coordinate descriptions. For example, -the "a" in keyword names such as CTYPEia. This is a space -character for the primary coordinate description, or one of the 26 -upper-case letters, A-Z.

        -
        - -
        -
        -axis_types
        -

        int array[naxis]

        -

        An array of four-digit type codes for each axis.

        -
          -
        • First digit (i.e. 1000s):
            -
          • 0: Non-specific coordinate type.
          • -
          • 1: Stokes coordinate.
          • -
          • 2: Celestial coordinate (including CUBEFACE).
          • -
          • 3: Spectral coordinate.
          • -
          -
        • -
        • Second digit (i.e. 100s):
            -
          • 0: Linear axis.
          • -
          • 1: Quantized axis (STOKES, CUBEFACE).
          • -
          • 2: Non-linear celestial axis.
          • -
          • 3: Non-linear spectral axis.
          • -
          • 4: Logarithmic axis.
          • -
          • 5: Tabular axis.
          • -
          -
        • -
        • Third digit (i.e. 10s):
            -
          • 0: Group number, e.g. lookup table number
          • -
          -
        • -
        • The fourth digit is used as a qualifier depending on the axis type.
            -
          • For celestial axes:
              -
            • 0: Longitude coordinate.
            • -
            • 1: Latitude coordinate.
            • -
            • 2: CUBEFACE number.
            • -
            -
          • -
          • For lookup tables: the axis number in a multidimensional table.
          • -
          -
        • -
        -

        CTYPEia in "4-3" form with unrecognized algorithm code will -have its type set to -1 and generate an error.

        -
        - -
        -
        -cd
        -

        double array[naxis][naxis]

        -

        The CDi_ja linear transformation matrix.

        -

        For historical compatibility, three alternate specifications of the -linear transforations are available in wcslib. The canonical -PCi_ja with CDELTia, and the deprecated CDi_ja and -CROTAia keywords. Although the deprecated versions may not -formally co-exist with PCi_ja, the approach here is simply to -ignore them if given in conjunction with PCi_ja.

        -

        has_pc, has_cd and -has_crota can be used to determine which of -these alternatives are present in the header.

        -

        These alternate specifications of the linear transformation matrix are -translated immediately to PCi_ja by set and -are nowhere visible to the lower-level routines. In particular, -set resets cdelt to unity -if CDi_ja is present (and no PCi_ja). If no CROTAia is -associated with the latitude axis, set reverts -to a unity PCi_ja matrix.

        -
        - -
        -
        -cdelt
        -

        double array[naxis]

        -

        Coordinate increments (CDELTia) for each coord axis.

        -

        If a CDi_ja linear transformation matrix is present, a warning is -raised and cdelt is ignored. The CDi_ja -matrix may be deleted by:

        -
        del wcs.wcs.cd
        -
        -
        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -cdfix()
        -

        Fix erroneously omitted CDi_ja keywords.

        -

        Sets the diagonal element of the CDi_ja matrix to unity if all -CDi_ja keywords associated with a given axis were omitted. -According to Paper I, if any CDi_ja keywords at all are given in a -FITS header then those not given default to zero. This results in a -singular matrix with an intersecting row and column of zeros.

        - --- - - - -
        Returns :

        success : int

        -
        -

        Returns 0 for success; -1 if no change required.

        -
        -
        -
        - -
        -
        -cel_offset
        -

        boolean

        -

        If True, an offset will be applied to (x, y) to force (x,y) = -(0,0) at the fiducial point, (phi_0, theta_0). Default is -False.

        -
        - -
        -
        -celfix()
        -

        Translates AIPS-convention celestial projection types, -NCP and --GLS.

        - --- - - - -
        Returns :

        success : int

        -
        -

        Returns 0 for success; -1 if no change required.

        -
        -
        -
        - -
        -
        -cname
        -

        list of strings

        -

        A list of the coordinate axis names, from CNAMEia.

        -
        - -
        -
        -colax
        -

        int array[naxis]

        -

        An array recording the column numbers for each axis in a pixel list.

        -
        - -
        -
        -colnum
        -

        int

        -

        Where the coordinate representation is associated with an image-array -column in a FITS binary table, this property may be used to record the -relevant column number.

        -

        It should be set to zero for an image header or pixel list.

        -
        - -
        -
        -crder
        -

        double array[naxis]

        -

        The random error in each coordinate axis, CRDERia.

        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -crota
        -

        double array[naxis]

        -

        CROTAia keyvalues for each coordinate axis.

        -

        For historical compatibility, three alternate specifications of the -linear transforations are available in wcslib. The canonical -PCi_ja with CDELTia, and the deprecated CDi_ja and -CROTAia keywords. Although the deprecated versions may not -formally co-exist with PCi_ja, the approach here is simply to -ignore them if given in conjunction with PCi_ja.

        -

        has_pc, has_cd and -has_crota can be used to determine which of -these alternatives are present in the header.

        -

        These alternate specifications of the linear transformation matrix are -translated immediately to PCi_ja by set and -are nowhere visible to the lower-level routines. In particular, -set resets cdelt to unity -if CDi_ja is present (and no PCi_ja). If no CROTAia is -associated with the latitude axis, set reverts -to a unity PCi_ja matrix.

        -
        - -
        -
        -crpix
        -

        double array[naxis]

        -

        Coordinate reference pixels (CRPIXja) for each pixel axis.

        -
        - -
        -
        -crval
        -

        double array[naxis]

        -

        Coordinate reference values (CRVALia) for each coordinate axis.

        -
        - -
        -
        -csyer
        -

        double array[naxis]

        -

        The systematic error in the coordinate value axes, CSYERia.

        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -ctype
        -

        list of strings[naxis]

        -

        List of CTYPEia keyvalues.

        -

        The ctype keyword values must be in upper case -and there must be zero or one pair of matched celestial axis types, -and zero or one spectral axis.

        -
        - -
        -
        -cubeface
        -

        int

        -

        Index into the pixcrd (pixel coordinate) array for the -CUBEFACE axis. This is used for quadcube projections where the -cube faces are stored on a separate axis.

        -

        The quadcube projections (TSC, CSC, QSC) may be -represented in FITS in either of two ways:

        -
        -
          -
        • The six faces may be laid out in one plane and numbered as -follows:

          -
                   0
          -
          -4  3  2  1  4  3  2
          -
          -         5
          -
          -

          Faces 2, 3 and 4 may appear on one side or the other (or both). -The sky-to-pixel routines map faces 2, 3 and 4 to the left but -the pixel-to-sky routines accept them on either side.

          -
        • -
        • The COBE convention in which the six faces are stored in a -three-dimensional structure using a CUBEFACE axis indexed -from 0 to 5 as above.

          -
        • -
        -
        -

        These routines support both methods; set -determines which is being used by the presence or absence of a -CUBEFACE axis in ctype. -p2s and s2p translate the -CUBEFACE axis representation to the single plane representation -understood by the lower-level projection routines.

        -
        - -
        -
        -cunit
        -

        list of strings[naxis]

        -

        List of CUNITia keyvalues which define the units of measurement of -the CRVALia, CDELTia and CDi_ja keywords.

        -

        As CUNITia is an optional header keyword, -cunit may be left blank but otherwise is -expected to contain a standard units specification as defined by WCS -Paper I. unitfix is available to translate -commonly used non-standard units specifications but this must be done -as a separate step before invoking set.

        -

        For celestial axes, if cunit is not blank, -set uses wcsunits to parse it and scale -cdelt, crval, and -cd to decimal degrees. It then resets -cunit to "deg".

        -

        For spectral axes, if cunit is not blank, -set uses wcsunits to parse it and scale -cdelt, crval, and -cd to SI units. It then resets -cunit accordingly.

        -

        set ignores cunit for -other coordinate types; cunit may be used to -label coordinate values.

        -
        - -
        -
        -cylfix()
        -

        Fixes WCS keyvalues for malformed cylindrical projections.

        - --- - - - -
        Returns :

        success : int

        -
        -

        Returns 0 for success; -1 if no change required.

        -
        -
        -
        - -
        -
        -dateavg
        -

        string

        -

        Representative mid-point of the date of observation in ISO format, -yyyy-mm-ddThh:mm:ss.

        - -
        - -
        -
        -dateobs
        -

        string

        -

        Start of the date of observation in ISO format, -yyyy-mm-ddThh:mm:ss.

        - -
        - -
        -
        -datfix()
        -

        Translates the old DATE-OBS date format to year-2000 standard form -(yyyy-mm-ddThh:mm:ss) and derives MJD-OBS from it if not -already set.

        -

        Alternatively, if mjdobs is set and -dateobs isn’t, then datfix -derives dateobs from it. If both are set but -disagree by more than half a day then ValueError is raised.

        - --- - - - -
        Returns :

        success : int

        -
        -

        Returns 0 for success; -1 if no change required.

        -
        -
        -
        - -
        -
        -equinox
        -

        double

        -

        The equinox associated with dynamical equatorial or ecliptic -coordinate systems, EQUINOXa (or EPOCH in older headers). Not -applicable to ICRS equatorial or ecliptic coordinates.

        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -fix(translate_units='', naxis=0)
        -

        Applies all of the corrections handled separately by -datfix, unitfix, -celfix, spcfix, -cylfix and cdfix.

        - --- - - - - - -
        Parameters :

        translate_units : str

        -
        -

        Do potentially unsafe translations of non-standard unit strings.

        -

        Although "S" is commonly used to represent seconds, its -translation to "s" is potentially unsafe since the standard -recognizes "S" formally as Siemens, however rarely that may be -used. The same applies to "H" for hours (Henry), and "D" -for days (Debye).

        -

        This string controls what to do in such cases, and is -case-insensitive.

        -
          -
        • If the string contains "s", translate "S" to "s".
        • -
        • If the string contains "h", translate "H" to "h".
        • -
        • If the string contains "d", translate "D" to "d".
        • -
        -

        Thus '' doesn’t do any unsafe translations, whereas 'shd' -does all of them.

        -
        -

        naxis : int array[naxis]

        -
        -

        Image axis lengths. If this array is set to zero or None, -then cylfix will not be invoked.

        -
        -
        Returns :

        status : dict

        -
        -

        Returns a dictionary containing the following keys, each referring -to a status string for each of the sub-fix functions that were -called:

        - -
        -
        -
        - -
        -
        -get_cdelt() → double array[naxis]
        -

        Coordinate increments (CDELTia) for each coord axis.

        -

        Returns the CDELT offsets in read-only form. Unlike the -cdelt property, this works even when the header -specifies the linear transformation matrix in one of the deprecated -CDi_ja or CROTAia forms. This is useful when you want access -to the linear transformation matrix, but don’t care how it was -specified in the header.

        -
        - -
        -
        -get_pc() → double array[naxis][naxis]
        -

        Returns the PC matrix in read-only form. Unlike the -pc property, this works even when the header -specifies the linear transformation matrix in one of the deprecated -CDi_ja or CROTAia forms. This is useful when you want access -to the linear transformation matrix, but don’t care how it was -specified in the header.

        -
        - -
        -
        -get_ps() → list of tuples
        -

        Returns PSi_ma keywords for each i and m.

        - --- - - - -
        Returns :

        ps : list of tuples

        -
        -

        Returned as a list of tuples of the form (i, m, value):

        -
          -
        • i: int. Axis number, as in PSi_ma, (i.e. 1-relative)
        • -
        • m: int. Parameter number, as in PSi_ma, (i.e. 0-relative)
        • -
        • value: string. Parameter value.
        • -
        -
        -
        -
        -

        See also

        -
        -
        astropy.wcs.Wcsprm.set_ps
        -
        Set PSi_ma values
        -
        -
        -
        - -
        -
        -get_pv() → list of tuples
        -

        Returns PVi_ma keywords for each i and m.

        - --- - - - -
        Returns :

        Returned as a list of tuples of the form (*i*, *m*, *value*): :

        -
        -
          -
        • i: int. Axis number, as in PVi_ma, (i.e. 1-relative)
        • -
        • m: int. Parameter number, as in PVi_ma, (i.e. 0-relative)
        • -
        • value: string. Parameter value.
        • -
        -
        -
        -
        -

        See also

        -
        -
        astropy.wcs.Wcsprm.set_pv
        -
        Set PVi_ma values
        -
        -
        -

        Notes

        -

        Note that, if they were not given, set resets -the entries for PVi_1a, PVi_2a, PVi_3a, and PVi_4a for -longitude axis i to match (phi_0, theta_0), the native -longitude and latitude of the reference point given by LONPOLEa -and LATPOLEa.

        -
        - -
        -
        -has_cd() → bool
        -

        Returns True if CDi_ja is present.

        -

        CDi_ja is an alternate specification of the linear transformation -matrix, maintained for historical compatibility.

        -

        Matrix elements in the IRAF convention are equivalent to the product -CDi_ja = CDELTia * PCi_ja, but the defaults differ from that of -the PCi_ja matrix. If one or more CDi_ja keywords are present -then all unspecified CDi_ja default to zero. If no CDi_ja (or -CROTAia) keywords are present, then the header is assumed to be in -PCi_ja form whether or not any PCi_ja keywords are present -since this results in an interpretation of CDELTia consistent with -the original FITS specification.

        -

        While CDi_ja may not formally co-exist with PCi_ja, it may -co-exist with CDELTia and CROTAia which are to be ignored.

        -
        -

        See also

        -
        -
        astropy.wcs.Wcsprm.cd
        -
        Get the raw CDi_ja values.
        -
        -
        -
        - -
        -
        -has_cdi_ja() → bool
        -

        Alias for has_cd. Maintained for backward -compatibility.

        -
        - -
        -
        -has_crota() → bool
        -

        Returns True if CROTAia is present.

        -

        CROTAia is an alternate specification of the linear transformation -matrix, maintained for historical compatibility.

        -

        In the AIPS convention, CROTAia may only be associated with the -latitude axis of a celestial axis pair. It specifies a rotation in -the image plane that is applied after the CDELTia; any other -CROTAia keywords are ignored.

        -

        CROTAia may not formally co-exist with PCi_ja. CROTAia and -CDELTia may formally co-exist with CDi_ja but if so are to be -ignored.

        -
        -

        See also

        -
        -
        astropy.wcs.Wcsprm.crota
        -
        Get the raw CROTAia values
        -
        -
        -
        - -
        -
        -has_crotaia() → bool
        -

        Alias for has_crota. Maintained for backward -compatibility.

        -
        - -
        -
        -has_pc() → bool
        -

        Returns True if PCi_ja is present. PCi_ja is the -recommended way to specify the linear transformation matrix.

        -
        -

        See also

        -
        -
        astropy.wcs.Wcsprm.pc
        -
        Get the raw PCi_ja values
        -
        -
        -
        - -
        -
        -has_pci_ja() → bool
        -

        Alias for has_pc. Maintained for backward -compatibility.

        -
        - -
        -
        -imgpix_matrix
        -

        double array[2][2] (read-only)

        -

        Inverse of the matrix containing the product of the CDELTia -diagonal matrix and the PCi_ja matrix.

        -
        - -
        -
        -is_unity() → bool
        -

        Returns True if the linear transformation matrix -(cd) is unity.

        -
        - -
        -
        -lat
        -

        int (read-only)

        -

        The index into the sky coordinate array containing latitude values.

        -
        - -
        -
        -latpole
        -

        double

        -

        The native latitude of the celestial pole, LATPOLEa (deg).

        -
        - -
        -
        -lattyp
        -

        string (read-only)

        -

        Celestial axis type for latitude, e.g. “RA”, “DEC”, “GLON”, “GLAT”, -etc. extracted from ‘RA–’, ‘DEC-‘, ‘GLON’, ‘GLAT’, etc. in the first -four characters of CTYPEia but with trailing dashes removed.

        -
        - -
        -
        -lng
        -

        int (read-only)

        -

        The index into the sky coordinate array containing longitude values.

        -
        - -
        -
        -lngtyp
        -

        string (read-only)

        -

        Celestial axis type for longitude, e.g. “RA”, “DEC”, “GLON”, “GLAT”, -etc. extracted from ‘RA–’, ‘DEC-‘, ‘GLON’, ‘GLAT’, etc. in the first -four characters of CTYPEia but with trailing dashes removed.

        -
        - -
        -
        -lonpole
        -

        double

        -

        The native longitude of the celestial pole, LONPOLEa (deg).

        -
        - -
        -
        -mix(mixpix, mixcel, vspan, vstep, viter, world, pixcrd, origin)
        -

        Given either the celestial longitude or latitude plus an element of -the pixel coordinate, solves for the remaining elements by iterating -on the unknown celestial coordinate element using -s2p.

        - --- - - - - - - - -
        Parameters :

        mixpix : int

        -
        -

        Which element on the pixel coordinate is given.

        -
        -

        mixcel : int

        -
        -

        Which element of the celestial coordinate is given. If mixcel = -1, celestial longitude is given in world[self.lng], -latitude returned in world[self.lat]. If mixcel = 2, -celestial latitude is given in world[self.lat], longitude -returned in world[self.lng].

        -
        -

        vspan : pair of floats

        -
        -

        Solution interval for the celestial coordinate, in degrees. The -ordering of the two limits is irrelevant. Longitude ranges may be -specified with any convenient normalization, for example -(-120,+120) is the same as (240,480), except that the -solution will be returned with the same normalization, i.e. lie -within the interval specified.

        -
        -

        vstep : float

        -
        -

        Step size for solution search, in degrees. If 0, a sensible, -although perhaps non-optimal default will be used.

        -
        -

        viter : int

        -
        -

        If a solution is not found then the step size will be halved and -the search recommenced. viter controls how many times the step -size is halved. The allowed range is 5 - 10.

        -
        -

        world : double array[naxis]

        -
        -

        World coordinate elements. world[self.lng] and -world[self.lat] are the celestial longitude and latitude, in -degrees. Which is given and which returned depends on the value -of mixcel. All other elements are given. The results will be -written to this array in-place.

        -
        -

        pixcrd : double array[naxis].

        -
        -

        Pixel coordinates. The element indicated by mixpix is given and -the remaining elements will be written in-place.

        -
        -

        origin : int

        -
        -

        Specifies the origin of pixel values. The Fortran and FITS -standards use an origin of 1. Numpy and C use array indexing with -origin at 0.

        -
        -
        Returns :

        result : dict

        -
        -

        Returns a dictionary with the following keys:

        -
          -
        • phi (double array[naxis])

          -
        • -
        • theta (double array[naxis])

          -
          -
            -
          • Longitude and latitude in the native coordinate system of -the projection, in degrees.
          • -
          -
          -
        • -
        • imgcrd (double array[naxis])

          -
          -
            -
          • Image coordinate elements. imgcrd[self.lng] and -imgcrd[self.lat] are the projected x- and -y-coordinates, in decimal degrees.
          • -
          -
          -
        • -
        • world (double array[naxis])

          -
          -
            -
          • Another reference to the world argument passed in.
          • -
          -
          -
        • -
        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        SingularMatrixError :

        -
        -

        Linear transformation matrix is singular.

        -
        -

        InconsistentAxisTypesError :

        -
        -

        Inconsistent or unrecognized coordinate axis types.

        -
        -

        ValueError :

        -
        -

        Invalid parameter value.

        -
        -

        InvalidTransformError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        InvalidTransformError :

        -
        -

        Ill-conditioned coordinate transformation parameters.

        -
        -

        InvalidCoordinateError :

        -
        -

        Invalid world coordinate.

        -
        -

        NoSolutionError :

        -
        -

        No solution found in the specified interval.

        -
        -
        - -

        Notes

        -

        Initially, the specified solution interval is checked to see if it’s a -“crossing” interval. If it isn’t, a search is made for a crossing -solution by iterating on the unknown celestial coordinate starting at -the upper limit of the solution interval and decrementing by the -specified step size. A crossing is indicated if the trial value of -the pixel coordinate steps through the value specified. If a crossing -interval is found then the solution is determined by a modified form -of “regula falsi” division of the crossing interval. If no crossing -interval was found within the specified solution interval then a -search is made for a “non-crossing” solution as may arise from a -point of tangency. The process is complicated by having to make -allowance for the discontinuities that occur in all map projections.

        -

        Once one solution has been determined others may be found by -subsequent invocations of mix with suitably -restricted solution intervals.

        -

        Note the circumstance that arises when the solution point lies at a -native pole of a projection in which the pole is represented as a -finite curve, for example the zenithals and conics. In such cases two -or more valid solutions may exist but mix only -ever returns one.

        -

        Because of its generality, mix is very -compute-intensive. For compute-limited applications, more efficient -special-case solvers could be written for simple projections, for -example non-oblique cylindrical projections.

        -
        - -
        -
        -mjdavg
        -

        double

        -

        Modified Julian Date (MJD = JD - 2400000.5), MJD-AVG, -corresponding to DATE-AVG.

        -

        An undefined value is represented by NaN.

        - -
        - -
        -
        -mjdobs
        -

        double

        -

        Modified Julian Date (MJD = JD - 2400000.5), MJD-OBS, -corresponding to DATE-OBS.

        -

        An undefined value is represented by NaN.

        - -
        - -
        -
        -name
        -

        string

        -

        The name given to the coordinate representation WCSNAMEa.

        -
        - -
        -
        -naxis
        -

        int (read-only)

        -

        The number of axes (pixel and coordinate), given by the NAXIS or -WCSAXESa keyvalues.

        -

        The number of coordinate axes is determined at parsing time, and can -not be subsequently changed.

        -

        It is determined from the highest of the following:

        -
        -
          -
        1. NAXIS
        2. -
        3. WCSAXESa
        4. -
        5. The highest axis number in any parameterized WCS keyword. The -keyvalue, as well as the keyword, must be syntactically valid -otherwise it will not be considered.
        6. -
        -
        -

        If none of these keyword types is present, i.e. if the header only -contains auxiliary WCS keywords for a particular coordinate -representation, then no coordinate description is constructed for it.

        -

        This value may differ for different coordinate representations of the -same image.

        -
        - -
        -
        -obsgeo
        -

        double array[3]

        -

        Location of the observer in a standard terrestrial reference frame, -OBSGEO-X, OBSGEO-Y, OBSGEO-Z (in meters).

        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -p2s(pixcrd, origin)
        -

        Converts pixel to sky coordinates.

        - --- - - - - - - - -
        Parameters :

        pixcrd : double array[ncoord][nelem]

        -
        -

        Array of pixel coordinates.

        -
        -

        origin : int

        -
        -

        Specifies the origin of pixel values. The Fortran and FITS -standards use an origin of 1. Numpy and C use array indexing with -origin at 0.

        -
        -
        Returns :

        result : dict

        -
        -

        Returns a dictionary with the following keys:

        -
          -
        • imgcrd: double array[ncoord][nelem]
            -
          • Array of intermediate sky coordinates. For celestial axes, -imgcrd[][self.lng] and imgcrd[][self.lat] are the -projected x-, and y-coordinates, in pseudo degrees. For -spectral axes, imgcrd[][self.spec] is the intermediate -spectral coordinate, in SI units.
          • -
          -
        • -
        • phi: double array[ncoord]
        • -
        • theta: double array[ncoord]
            -
          • Longitude and latitude in the native coordinate system of the -projection, in degrees.
          • -
          -
        • -
        • world: double array[ncoord][nelem]
            -
          • Array of sky coordinates. For celestial axes, -world[][self.lng] and world[][self.lat] are the -celestial longitude and latitude, in degrees. For spectral -axes, world[][self.spec] is the intermediate spectral -coordinate, in SI units.
          • -
          -
        • -
        • stat: int array[ncoord]
            -
          • Status return value for each coordinate. 0 for success, -1+ for invalid pixel coordinate.
          • -
          -
        • -
        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        SingularMatrixError :

        -
        -

        Linear transformation matrix is singular.

        -
        -

        InconsistentAxisTypesError :

        -
        -

        Inconsistent or unrecognized coordinate axis types.

        -
        -

        ValueError :

        -
        -

        Invalid parameter value.

        -
        -

        ValueError :

        -
        -

        x- and y-coordinate arrays are not the same size.

        -
        -

        InvalidTransformError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        InvalidTransformError :

        -
        -

        Ill-conditioned coordinate transformation parameters.

        -
        -
        - -
        - -
        -
        -pc
        -

        double array[naxis][naxis]

        -

        The PCi_ja (pixel coordinate) transformation matrix. The order is:

        -
        [[PC1_1, PC1_2],
        - [PC2_1, PC2_2]]
        -
        -
        -

        For historical compatibility, three alternate specifications of the -linear transforations are available in wcslib. The canonical -PCi_ja with CDELTia, and the deprecated CDi_ja and -CROTAia keywords. Although the deprecated versions may not -formally co-exist with PCi_ja, the approach here is simply to -ignore them if given in conjunction with PCi_ja.

        -

        has_pc, has_cd and -has_crota can be used to determine which of -these alternatives are present in the header.

        -

        These alternate specifications of the linear transformation matrix are -translated immediately to PCi_ja by set and -are nowhere visible to the lower-level routines. In particular, -set resets cdelt to unity -if CDi_ja is present (and no PCi_ja). If no CROTAia is -associated with the latitude axis, set reverts -to a unity PCi_ja matrix.

        -
        - -
        -
        -phi0
        -

        double

        -

        The native latitude of the fiducial point, i.e. the point whose -celestial coordinates are given in ref[1:2]. If undefined (NaN) -the initialization routine, set, will set this -to a projection-specific default.

        - -
        - -
        -
        -piximg_matrix
        -

        double array[2][2] (read-only)

        -

        Matrix containing the product of the CDELTia diagonal matrix and -the PCi_ja matrix.

        -
        - -
        -
        -print_contents()
        -

        Print the contents of the Wcsprm object to stdout. -Probably only useful for debugging purposes, and may be removed in the -future.

        -

        To get a string of the contents, use repr.

        -
        - -
        -
        -radesys
        -

        string

        -

        The equatorial or ecliptic coordinate system type, RADESYSa.

        -
        - -
        -
        -restfrq
        -

        double

        -

        Rest frequency (Hz) from RESTFRQa.

        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -restwav
        -

        double

        -

        Rest wavelength (m) from RESTWAVa.

        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -s2p(sky, origin)
        -

        Transforms sky coordinates to pixel coordinates.

        - --- - - - - - - - -
        Parameters :

        sky : double array[ncoord][nelem]

        -
        -

        Array of sky coordinates, in decimal degrees.

        -
        -

        origin : int

        -
        -

        Specifies the origin of pixel values. The Fortran and FITS -standards use an origin of 1. Numpy and C use array indexing with -origin at 0.

        -
        -
        Returns :

        result : dict

        -
        -

        Returns a dictionary with the following keys:

        -
          -
        • phi: double array[ncoord]

          -
        • -
        • theta: double array[ncoord]

          -
          -
            -
          • Longitude and latitude in the native coordinate system of -the projection, in degrees.
          • -
          -
          -
        • -
        • imgcrd: double array[ncoord][nelem]

          -
          -
            -
          • Array of intermediate sky coordinates. For celestial axes, -imgcrd[][self.lng] and imgcrd[][self.lat] are the -projected x-, and y-coordinates, in pseudo “degrees”. -For quadcube projections with a CUBEFACE axis, the face -number is also returned in imgcrd[][self.cubeface]. For -spectral axes, imgcrd[][self.spec] is the intermediate -spectral coordinate, in SI units.
          • -
          -
          -
        • -
        • pixcrd: double array[ncoord][nelem]

          -
          -
            -
          • Array of pixel coordinates. Pixel coordinates are -zero-based.
          • -
          -
          -
        • -
        • stat: int array[ncoord]

          -
          -
            -
          • Status return value for each coordinate. 0 for success, -1+ for invalid pixel coordinate.
          • -
          -
          -
        • -
        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        SingularMatrixError :

        -
        -

        Linear transformation matrix is singular.

        -
        -

        InconsistentAxisTypesError :

        -
        -

        Inconsistent or unrecognized coordinate axis types.

        -
        -

        ValueError :

        -
        -

        Invalid parameter value.

        -
        -

        InvalidTransformError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        InvalidTransformError :

        -
        -

        Ill-conditioned coordinate transformation parameters.

        -
        -
        - -
        - -
        -
        -set()
        -

        Sets up a WCS object for use according to information supplied within -it.

        -

        Note that this routine need not be called directly; it will be invoked -by p2s and s2p if -necessary.

        -

        Some attributes that are based on other attributes (such as -lattyp on ctype) may not -be correct until after set is called.

        -

        set strips off trailing blanks in all string -members.

        -

        set recognizes the NCP projection and -converts it to the equivalent SIN projection and it also -recognizes GLS as a synonym for SFL. It does alias -translation for the AIPS spectral types (FREQ-LSR, FELO-HEL, -etc.) but without changing the input header keywords.

        - --- - - - -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        SingularMatrixError :

        -
        -

        Linear transformation matrix is singular.

        -
        -

        InconsistentAxisTypesError :

        -
        -

        Inconsistent or unrecognized coordinate axis types.

        -
        -

        ValueError :

        -
        -

        Invalid parameter value.

        -
        -

        InvalidTransformError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        InvalidTransformError :

        -
        -

        Ill-conditioned coordinate transformation parameters.

        -
        -
        -
        - -
        -
        -set_ps(list)
        -

        Sets PSi_ma keywords for each i and m.

        - --- - - - -
        Parameters :

        ps : sequence of tuples

        -
        -

        The input must be a sequence of tuples of the form (i, m, -value):

        -
          -
        • i: int. Axis number, as in PSi_ma, (i.e. 1-relative)
        • -
        • m: int. Parameter number, as in PSi_ma, (i.e. 0-relative)
        • -
        • value: string. Parameter value.
        • -
        -
        -
        - -
        - -
        -
        -set_pv(list)
        -

        Sets PVi_ma keywords for each i and m.

        - --- - - - -
        Parameters :

        pv : list of tuples

        -
        -

        The input must be a sequence of tuples of the form (i, m, -value):

        -
          -
        • i: int. Axis number, as in PVi_ma, (i.e. 1-relative)
        • -
        • m: int. Parameter number, as in PVi_ma, (i.e. 0-relative)
        • -
        • value: float. Parameter value.
        • -
        -
        -
        - -
        - -
        -
        -spcfix() → int
        -

        Translates AIPS-convention spectral coordinate types. {FREQ, -VELO, FELO}-{OBS, HEL, LSR} (e.g. FREQ-LSR, -VELO-OBS, FELO-HEL)

        - --- - - - -
        Returns :

        success : int

        -
        -

        Returns 0 for success; -1 if no change required.

        -
        -
        -
        - -
        -
        -spec
        -

        int (read-only)

        -

        The index containing the spectral axis values.

        -
        - -
        -
        -specsys
        -

        string

        -

        Spectral reference frame (standard of rest), SPECSYSa.

        - -
        - -
        -
        -sptr(ctype, i=-1)
        -

        Translates the spectral axis in a WCS object.

        -

        For example, a FREQ axis may be translated into ZOPT-F2W and -vice versa.

        - --- - - - - - -
        Parameters :

        ctype : string

        -
        -

        Required spectral CTYPEia, maximum of 8 characters. The first -four characters are required to be given and are never modified. -The remaining four, the algorithm code, are completely determined -by, and must be consistent with, the first four characters. -Wildcarding may be used, i.e. if the final three characters are -specified as "???", or if just the eighth character is -specified as "?", the correct algorithm code will be -substituted and returned.

        -
        -

        i : int

        -
        -

        Index of the spectral axis (0-relative). If i < 0 (or not -provided), it will be set to the first spectral axis identified -from the CTYPE keyvalues in the FITS header.

        -
        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        SingularMatrixError :

        -
        -

        Linear transformation matrix is singular.

        -
        -

        InconsistentAxisTypesError :

        -
        -

        Inconsistent or unrecognized coordinate axis types.

        -
        -

        ValueError :

        -
        -

        Invalid parameter value.

        -
        -

        InvalidTransformError :

        -
        -

        Invalid coordinate transformation parameters.

        -
        -

        InvalidTransformError :

        -
        -

        Ill-conditioned coordinate transformation parameters.

        -
        -

        InvalidSubimageSpecificationError :

        -
        -

        Invalid subimage specification (no spectral axis).

        -
        -
        -
        - -
        -
        -ssysobs
        -

        string

        -

        The actual spectral reference frame in which there is no differential -variation in the spectral coordinate across the field-of-view, -SSYSOBSa.

        - -
        - -
        -
        -ssyssrc
        -

        string

        -

        The spectral reference frame (standard of rest) in which the redshift -was measured, SSYSSRCa.

        -
        - -
        -
        -sub(axes)
        -

        Extracts the coordinate description for a subimage from a -WCS object.

        -

        The world coordinate system of the subimage must be separable in the -sense that the world coordinates at any point in the subimage must -depend only on the pixel coordinates of the axes extracted. In -practice, this means that the PCi_ja matrix of the original image -must not contain non-zero off-diagonal terms that associate any of the -subimage axes with any of the non-subimage axes.

        - --- - - - - - - - -
        Parameters :

        axes : int or a sequence.

        -
        -
          -
        • If an int, include the first N axes in their original order.
        • -
        • If a sequence, may contain a combination of image axis numbers -(1-relative) or special axis identifiers (see below). Order is -significant; axes[0] is the axis number of the input image -that corresponds to the first axis in the subimage, etc.
        • -
        • If 0, [] or None, do a deep copy.
        • -
        -

        Coordinate axes types may be specified using either strings or -special integer constants. The available types are:

        -
          -
        • 'longitude' / WCSSUB_LONGITUDE: Celestial longitude
        • -
        • 'latitude' / WCSSUB_LATITUDE: Celestial latitude
        • -
        • 'cubeface' / WCSSUB_CUBEFACE: Quadcube CUBEFACE axis
        • -
        • 'spectral' / WCSSUB_SPECTRAL: Spectral axis
        • -
        • 'stokes' / WCSSUB_STOKES: Stokes axis
        • -
        • 'celestial' / WCSSUB_CELESTIAL: An alias for the -combination of 'longitude', 'latitude' and 'cubeface'.
        • -
        -
        -
        Returns :

        new_wcs : WCS object

        -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        InvalidSubimageSpecificationError :

        -
        -

        Invalid subimage specification (no spectral axis).

        -
        -

        NonseparableSubimageCoordinateSystem :

        -
        -

        Non-separable subimage coordinate system.

        -
        -
        -

        Notes

        -

        Combinations of subimage axes of particular types may be extracted in -the same order as they occur in the input image by combining the -integer constants with the ‘binary or’ (|) operator. For -example:

        -
        wcs.sub([WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_SPECTRAL])
        -
        -
        -

        would extract the longitude, latitude, and spectral axes in the same -order as the input image. If one of each were present, the resulting -object would have three dimensions.

        -

        For convenience, WCSSUB_CELESTIAL is defined as the combination -WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_CUBEFACE.

        -

        The codes may also be negated to extract all but the types specified, -for example:

        -
        wcs.sub([
        -  WCSSUB_LONGITUDE,
        -  WCSSUB_LATITUDE,
        -  WCSSUB_CUBEFACE,
        -  -(WCSSUB_SPECTRAL | WCSSUB_STOKES)])
        -
        -
        -

        The last of these specifies all axis types other than spectral or -Stokes. Extraction is done in the order specified by axes, i.e. a -longitude axis (if present) would be extracted first (via axes[0]) -and not subsequently (via axes[3]). Likewise for the latitude and -cubeface axes in this example.

        -

        The number of dimensions in the returned object may be less than or -greater than the length of axes. However, it will never exceed the -number of axes in the input image.

        -
        - -
        -
        -tab
        -

        list of Tabprm

        -

        A list of tabular coordinate objects associated with this WCS.

        -
        - -
        -
        -theta0
        -

        double

        -

        The native longitude of the fiducial point, i.e. the point whose -celestial coordinates are given in ref[1:2]. If undefined (NaN) -the initialization routine, set, will set this -to a projection-specific default.

        - -
        - -
        -
        -to_header(relax=False)
        -

        to_header translates a WCS object into a FITS header.

        -

        The details of the header depends on context:

        -
        -
          -
        • If the colnum member is non-zero then a -binary table image array header will be produced.
        • -
        • Otherwise, if the colax member is set -non-zero then a pixel list header will be produced.
        • -
        • Otherwise, a primary image or image extension header will be -produced.
        • -
        -
        -

        The output header will almost certainly differ from the input in a -number of respects:

        -
        -
          -
        1. The output header only contains WCS-related keywords. In -particular, it does not contain syntactically-required keywords -such as SIMPLE, NAXIS, BITPIX, or END.
        2. -
        3. Deprecated (e.g. CROTAn) or non-standard usage will be -translated to standard (this is partially dependent on whether -fix was applied).
        4. -
        5. Quantities will be converted to the units used internally, -basically SI with the addition of degrees.
        6. -
        7. Floating-point quantities may be given to a different decimal -precision.
        8. -
        9. Elements of the PCi_j matrix will be written if and only if -they differ from the unit matrix. Thus, if the matrix is unity -then no elements will be written.
        10. -
        11. Additional keywords such as WCSAXES, CUNITia, -LONPOLEa and LATPOLEa may appear.
        12. -
        13. The original keycomments will be lost, although -to_header tries hard to write meaningful -comments.
        14. -
        15. Keyword order may be changed.
        16. -
        -
        -

        Keywords can be translated between the image array, binary table, and -pixel lists forms by manipulating the colnum or -colax members of the WCS -object.

        - --- - - - - - -
        Parameters :

        relax : bool or int

        -
        -

        Degree of permissiveness:

        -
          -
        • False: Recognize only FITS keywords defined by the published -WCS standard.
        • -
        • True: Admit all recognized informal extensions of the WCS -standard.
        • -
        • int: a bit field selecting specific extensions to write. -See Header-writing relaxation constants for details.
        • -
        -
        -
        Returns :

        header : str

        -
        -

        Raw FITS header as a string.

        -
        -
        -
        - -
        -
        -unitfix(translate_units='')
        -

        Translates non-standard CUNITia keyvalues.

        -

        For example, DEG -> deg, also stripping off unnecessary -whitespace.

        - --- - - - - - -
        Parameters :

        translate_units : string, optional

        -
        -

        Do potentially unsafe translations of non-standard unit strings.

        -

        Although "S" is commonly used to represent seconds, its -recognizes "S" formally as Siemens, however rarely that may -be translation to "s" is potentially unsafe since the -standard used. The same applies to "H" for hours (Henry), -and "D" for days (Debye).

        -

        This string controls what to do in such cases, and is -case-insensitive.

        -
          -
        • If the string contains "s", translate "S" to "s".
        • -
        • If the string contains "h", translate "H" to "h".
        • -
        • If the string contains "d", translate "D" to "d".
        • -
        -

        Thus '' doesn’t do any unsafe translations, whereas 'shd' -does all of them.

        -

        See FITS unit specification for more information.

        -
        -
        Returns :

        success : int

        -
        -

        Returns 0 for success; -1 if no change required.

        -
        -
        -
        - -
        -
        -velangl
        -

        double

        -

        The angle in degrees that should be used to decompose an observed -velocity into radial and transverse components.

        -

        An undefined value is represented by NaN.

        -
        - -
        -
        -velosys
        -

        double

        -

        The relative radial velocity (m/s) between the observer and the -selected standard of rest in the direction of the celestial reference -coordinate, VELOSYSa.

        -

        An undefined value is represented by NaN.

        - -
        - -
        -
        -zsource
        -

        double

        -

        The redshift, ZSOURCEa, of the source.

        -

        An undefined value is represented by NaN.

        -
        - -
        - -
        -
        -

        Tabprm

        -
        -
        -class astropy.wcs._wcs.Tabprm
        -

        A class to store the information related to tabular coordinates, -i.e. coordinates that are defined via a lookup table.

        -

        This class can not be constructed directly from Python, but instead is -returned from tab.

        -
        -
        -K
        -

        int array[M] (read-only)

        -

        An array of length M whose elements record the lengths of the axes of -the coordinate array and of each indexing vector.

        -
        - -
        -
        -M
        -

        int (read-only)

        -

        Number of tabular coordinate axes.

        -
        - -
        -
        -coord
        -

        double array[K_M]...[K_2][K_1][M]

        -

        The tabular coordinate array, with the dimensions:

        -
        (K_M, ... K_2, K_1, M)
        -
        -

        (see K) i.e. with the M dimension -varying fastest so that the M elements of a coordinate vector are -stored contiguously in memory.

        -
        - -
        -
        -crval
        -

        double array[M]

        -

        Array whose elements contain the index value for the reference pixel -for each of the tabular coordinate axes.

        -
        - -
        -
        -delta
        -

        double array[M] (read-only)

        -

        Array of interpolated indices into the coordinate array such that -Upsilon_m, as defined in Paper III, is equal to -(p0 [m] + 1) + delta[m].

        -
        - -
        -
        -extrema
        -

        double array[K_M]...[K_2][2][M] (read-only)

        -

        An array recording the minimum and maximum value of each element of -the coordinate vector in each row of the coordinate array, with the -dimensions:

        -
        (K_M, ... K_2, 2, M)
        -
        -

        (see K). The minimum is recorded -in the first element of the compressed K_1 dimension, then the -maximum. This array is used by the inverse table lookup function to -speed up table searches.

        -
        - -
        -
        -map
        -

        int array[M]

        -

        A vector of length M that defines -the association between axis m in the M-dimensional coordinate -array (1 <= m <= M) and the indices of the intermediate world -coordinate and world coordinate arrays.

        -

        When the intermediate and world coordinate arrays contain the full -complement of coordinate elements in image-order, as will usually be -the case, then map[m-1] == i-1 for axis i in the N-dimensional -image (1 <= i <= N). In terms of the FITS keywords:

        -
        map[PVi_3a - 1] == i - 1.
        -
        -
        -

        However, a different association may result if the intermediate -coordinates, for example, only contains a (relevant) subset of -intermediate world coordinate elements. For example, if M == 1 for -an image with N > 1, it is possible to fill the intermediate -coordinates with the relevant coordinate element with nelem set to -1. In this case map[0] = 0 regardless of the value of i.

        -
        - -
        -
        -nc
        -

        int (read-only)

        -

        Total number of coordinate vectors in the coordinate array being the -product K_1 * K_2 * ... * K_M.

        -
        - -
        -
        -p0
        -

        int array[M]

        -

        Vector of length M of interpolated -indices into the coordinate array such that Upsilon_m, as defined in -Paper III, is equal to (p0[m] + 1) + delta[m].

        -
        - -
        -
        -print_contents()
        -

        Print the contents of the Tabprm object to -stdout. Probably only useful for debugging purposes, and may be -removed in the future.

        -

        To get a string of the contents, use repr.

        -
        - -
        -
        -sense
        -

        int array[M]

        -

        A vector of length M whose elements -indicate whether the corresponding indexing vector is monotonically -increasing (+1), or decreasing (-1).

        -
        - -
        -
        -set()
        -

        Allocates memory for work arrays in the Tabprm class and sets up -the class according to information supplied within it.

        -

        Note that this routine need not be called directly; it will be invoked by -functions that need it.

        - --- - - - -
        Raises :

        MemoryError :

        -
        -

        Memory allocation failed.

        -
        -

        InvalidTabularParameters :

        -
        -

        Invalid tabular parameters.

        -
        -
        -
        - -
        - -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        WCS

        -

        Next topic

        -

        DistortionLookupTable

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/examples.html b/wcs/examples.html deleted file mode 100644 index 7b732af5..00000000 --- a/wcs/examples.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - - - - Example Usage — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Example Usage

        -
        -

        Loading WCS information from a FITS file

        -

        This example loads a FITS file (supplied on the commandline) and uses -the WCS cards in its primary header to transform.

        -
        # Load the WCS information from a fits header, and use it
        -# to convert pixel coordinates to world coordinates.
        -
        -from __future__ import division # confidence high
        -
        -import numpy
        -from astropy import wcs
        -import pyfits
        -import sys
        -
        -# Load the FITS hdulist using pyfits
        -hdulist = pyfits.open(sys.argv[-1])
        -
        -# Parse the WCS keywords in the primary HDU
        -w = wcs.WCS(hdulist[0].header)
        -
        -# Print out the "name" of the WCS, as defined in the FITS header
        -print w.wcs.name
        -
        -# Print out all of the settings that were parsed from the header
        -w.wcs.print_contents()
        -
        -# Some pixel coordinates of interest.
        -pixcrd = numpy.array([[0,0],[24,38],[45,98]], numpy.float_)
        -
        -# Convert pixel coordinates to world coordinates
        -# The second argument is "origin" -- in this case we're declaring we
        -# have 1-based (Fortran-like) coordinates.
        -sky = w.wcs_pix2sky(pixcrd, 1)
        -print sky
        -
        -# Convert the same coordinates back to pixel coordinates.
        -pixcrd2 = w.wcs_sky2pix(sky, 1)
        -print pixcrd2
        -
        -# These should be the same as the original pixel coordinates, modulo
        -# some floating-point error.
        -assert numpy.max(numpy.abs(pixcrd - pixcrd2)) < 1e-6
        -
        -
        -
        -
        -

        Building a WCS structure programmatically

        -

        This example, rather than starting from a FITS header, sets WCS values -programmatically, uses those settings to transform some points, and then -saves those settings to a new FITS header.

        -
        # Set the WCS information manually by setting properties of the WCS
        -# object.
        -
        -from __future__ import division # confidence high
        -
        -import numpy
        -from astropy import wcs
        -import pyfits
        -import sys
        -
        -# Create a new WCS object.  The number of axes must be set
        -# from the start
        -w = wcs.WCS(naxis=2)
        -
        -# Set up an "Airy's zenithal" projection
        -# Vector properties may be set with Python lists, or Numpy arrays
        -w.wcs.crpix = [-234.75, 8.3393]
        -w.wcs.cdelt = numpy.array([-0.066667, 0.066667])
        -w.wcs.crval = [0, -90]
        -w.wcs.ctype = ["RA---AIR", "DEC--AIR"]
        -w.wcs.set_pv([(2, 1, 45.0)])
        -
        -# Print out all of the contents of the WCS object
        -w.wcs.print_contents()
        -
        -# Some pixel coordinates of interest.
        -pixcrd = numpy.array([[0,0],[24,38],[45,98]], numpy.float_)
        -
        -# Convert pixel coordinates to world coordinates
        -world = w.wcs_pix2sky(pixcrd, 1)
        -print world
        -
        -# Convert the same coordinates back to pixel coordinates.
        -pixcrd2 = w.wcs_sky2pix(world, 1)
        -print pixcrd2
        -
        -# These should be the same as the original pixel coordinates, modulo
        -# some floating-point error.
        -assert numpy.max(numpy.abs(pixcrd - pixcrd2)) < 1e-6
        -
        -# Now, write out the WCS object as a FITS header
        -header = w.to_header()
        -
        -# header is a PyFITS Header object.  We can use it to create a new
        -# PrimaryHDU and write it to a file.
        -hdu = pyfits.PrimaryHDU(header=header)
        -hdu.writeto('test.fits')
        -
        -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        astropy.wcs Documentation

        -

        Next topic

        -

        API Documentation

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/history.html b/wcs/history.html deleted file mode 100644 index 1982400f..00000000 --- a/wcs/history.html +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - astropy.wcs History — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.wcs History

        -

        astropy.wcs began life as pywcs. Earlier version numbers refer to -that package.

        -
        -

        pywcs Version 1.11

        -
          -
        • Updated to wcslib version 4.8, which gives much more detailed error -messages.
        • -
        • Added functions get_pc() and get_cdelt(). These provide a way to -always get the canonical representation of the linear transformation -matrix, whether the header specified it in PC, CD or CROTA form.
        • -
        • Long-running process will now release the Python GIL to better -support Python multithreading.
        • -
        • The dimensions of the cd and -pc matrices were always returned as 2x2. They -now are sized according to naxis.
        • -
        • Supports Python 3.x
        • -
        • Builds on Microsoft Windows without severely patching wcslib.
        • -
        • Lots of new unit tests
        • -
        • pywcs will now run without pyfits, though the SIP and distortion -lookup table functionality is unavailable.
        • -
        • Setting cunit will now verify that the values -are valid unit strings.
        • -
        -
        -
        -

        pywcs Version 1.10

        -
          -
        • Adds a UnitConversion class, which gives access to wcslib’s unit -conversion functionality. Given two convertible unit strings, pywcs -can convert arrays of values from one to the other.
        • -
        • Now uses wcslib 4.7
        • -
        • Changes to some wcs values would not always calculate secondary values.
        • -
        -
        -
        -

        pywcs Version 1.9

        -
          -
        • Support binary image arrays and pixel list format WCS by presenting -a way to call wcslib’s wcsbth()

          -
        • -
        • Updated underlying wcslib to version 4.5, which fixes the following:

          -
          -
            -
          • Fixed the interpretation of VELREF when translating -AIPS-convention spectral types. Such translation is now handled -by a new special- purpose function, spcaips(). The wcsprm -struct has been augmented with an entry for velref which is -filled by wcspih() and wcsbth(). Previously, selection by -VELREF of the radio or optical velocity convention for type VELO -was not properly handled.
          • -
          -
          -
        • -
        -
        -

        Bugs

        -
          -
        • The pc member is now available with a default -raw Wcsprm object.
        • -
        • Make properties that return arrays read-only, since modifying a -(mutable) array could result in secondary values not being -recomputed based on those changes.
        • -
        • float properties can now be set using int values
        • -
        -
        -
        -
        -

        pywcs Version 1.3a1

        -

        Earlier versions of pywcs had two versions of every conversion method:

        -
        X(...)      -- treats the origin of pixel coordinates at (0, 0)
        -X_fits(...) -- treats the origin of pixel coordinates at (1, 1)
        -
        -

        From version 1.3 onwards, there is only one method for each -conversion, with an ‘origin’ argument:

        -
        -
          -
        • 0: places the origin at (0, 0), which is the C/Numpy convention.
        • -
        • 1: places the origin at (1, 1), which is the Fortran/FITS -convention.
        • -
        -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        Relax constants

        -

        Next topic

        -

        astropy.io.vo Documentation

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/index.html b/wcs/index.html deleted file mode 100644 index e0e0b8ff..00000000 --- a/wcs/index.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - - - astropy.wcs Documentation — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        astropy.wcs Documentation

        -

        Python wrappers, SIP, Paper IV support (BSD License):

        -
        -

        Michael Droettboom, Nadia Dencheva

        -

        Space Telescope Science Institute

        -
        -

        wcslib (LGPL License):

        -
        -

        Mark Calabretta

        -

        Australia Telescope National Facility, CSIRO (wcslib)

        -
        -

        astropy.wcs provides transformations following the SIP conventions, -Paper IV table lookup distortion, and the core WCS functionality -provided by wcslib. Each of these transformations can be used -independently or together in a standard pipeline.

        -

        The basic workflow is as follows:

        -
        -
          -
        1. from astropy import wcs
        2. -
        3. Call the wcs.WCS constructor with a pyfits header -and/or hdulist object.
        4. -
        5. Optionally, if the FITS file uses any deprecated or -non-standard features, you may need to call one of the -fix methods on the object.
        6. -
        7. Use one of the following transformation methods:
            -
          • all_pix2sky: Perform all three transformations from -pixel to sky coordinates.
          • -
          • wcs_pix2sky: Perform just the core WCS transformation -from pixel to sky coordinates.
          • -
          • wcs_sky2pix: Perform just the core WCS transformation -from sky to pixel coordinates.
          • -
          • sip_pix2foc: Convert from pixel to focal plane -coordinates using the SIP polynomial coefficients.
          • -
          • sip_foc2pix: Convert from focal plane to pixel -coordinates using the SIP polynomial coefficients.
          • -
          • p4_pix2foc: Convert from pixel to focal plane -coordinates using the table lookup distortion method -described in Paper IV.
          • -
          • det2im: Convert from detector coordinates to image -coordinates. Commonly used for narrow column correction.
          • -
          -
        8. -
        -
        -

        Contents:

        - -
        - - -
        -
        -
        -
        -
        - -

        Previous topic

        -

        Configuration system Documentation

        -

        Next topic

        -

        Example Usage

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file diff --git a/wcs/relax.html b/wcs/relax.html deleted file mode 100644 index c53e74c6..00000000 --- a/wcs/relax.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - - - - - Relax constants — Astropy 0.0.dev664 documentation - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Relax constants

        -
        -

        Header-reading relaxation constants

        -

        WCS, Wcsprm and -find_all_wcs have a relax argument, which may be -either True, False or an int.

        -
          -
        • If True, all non-standard WCS extensions recognized by the parser -will be handled.

          -
        • -
        • If False (default), none of the extensions (even those in the -errata) will be handled. Non-conformant keywords will be handled in -the same way as non-WCS keywords in the header, i.e. by simply -ignoring them.

          -
        • -
        • If an int, is is a bit field to provide fine-grained control over -what non-standard WCS keywords to accept. The flag bits are subject -to change in future and should be set by using the constants -beginning with WCSHDR_ in the astropy.wcs module.

          -

          For example, to accept CD00i00j and PC00i00j use:

          -
          relax = astropy.wcs.WCSHDR_CD00i00j | astropy.wcs.WCSHDR_PC00i00j
          -
          -
          -

          The parser always treats EPOCH as subordinate to EQUINOXa if -both are present, and VSOURCEa is always subordinate to -ZSOURCEa.

          -

          Likewise, VELREF is subordinate to the formalism of WCS Paper -III.

          -
        • -
        -

        The flag bits are:

        -
          -
        • WCSHDR_none: Don’t accept any extensions (not even those in the -errata). Treat non-conformant keywords in the same way as non-WCS -keywords in the header, i.e. simply ignore them. (This is -equivalent to the default behavior or passing False)

          -
        • -
        • WCSHDR_all: Accept all extensions recognized by the parser. (This -is equivalent to passing True).

          -
        • -
        • WCSHDR_CROTAia: Accept CROTAia, iCROTna, TCROTna

          -
        • -
        • WCSHDR_EPOCHa: Accept EPOCHa.

          -
        • -
        • WCSHDR_VELREFa: Accept VELREFa.

          -
          -

          The constructor always recognizes the AIPS-convention -keywords, CROTAn, EPOCH, and VELREF for the -primary representation (a = ' ') but alternates are -non-standard.

          -

          The constructor accepts EPOCHa and VELREFa only if -WCSHDR_AUXIMG is also enabled.

          -
          -
        • -
        • WCSHDR_CD00i00j: Accept CD00i00j.

          -
        • -
        • WCSHDR_PC00i00j: Accept PC00i00j.

          -
        • -
        • WCSHDR_PROJPn: Accept PROJPn

          -
          -

          These appeared in early drafts of WCS Paper I+II (before they -were split) and are equivalent to CDi_ja, PCi_ja, and -PVi_ma for the primary representation (a = ' '). -PROJPn is equivalent to PVi_ma with m = n <= -9, and is associated exclusively with the latitude axis.

          -
          -
        • -
        • -
          WCSHDR_RADECSYS: Accept RADECSYS. This appeared in early
          -

          drafts of WCS Paper I+II and was subsequently replaced by -RADESYSa. The construtor accepts RADECSYS only if -WCSHDR_AUXIMG is also enabled.

          -
          -
          -
        • -
        • WCSHDR_VSOURCE: Accept VSOURCEa or VSOUna. This appeared -in early drafts of WCS Paper III and was subsequently dropped in -favour of ZSOURCEa and ZSOUna. The constructor accepts -VSOURCEa only if WCSHDR_AUXIMG is also enabled.

          -
        • -
        • WCSHDR_DOBSn: Allow DOBSn, the column-specific analogue of -DATE-OBS. By an oversight this was never formally defined in -the standard.

          -
        • -
        • WCSHDR_LONGKEY: Accept long forms of the alternate binary table -and pixel list WCS keywords, i.e. with “a” non- blank. -Specifically:

          -
          jCRPXna  TCRPXna  :  jCRPXn  jCRPna  TCRPXn  TCRPna  CRPIXja
          -   -     TPCn_ka  :    -     ijPCna    -     TPn_ka  PCi_ja
          -   -     TCDn_ka  :    -     ijCDna    -     TCn_ka  CDi_ja
          -iCDLTna  TCDLTna  :  iCDLTn  iCDEna  TCDLTn  TCDEna  CDELTia
          -iCUNIna  TCUNIna  :  iCUNIn  iCUNna  TCUNIn  TCUNna  CUNITia
          -iCTYPna  TCTYPna  :  iCTYPn  iCTYna  TCTYPn  TCTYna  CTYPEia
          -iCRVLna  TCRVLna  :  iCRVLn  iCRVna  TCRVLn  TCRVna  CRVALia
          -iPVn_ma  TPVn_ma  :    -     iVn_ma    -     TVn_ma  PVi_ma
          -iPSn_ma  TPSn_ma  :    -     iSn_ma    -     TSn_ma  PSi_ma
          -
          -

          where the primary and standard alternate forms together with the -image-header equivalent are shown rightwards of the colon.

          -

          The long form of these keywords could be described as quasi- -standard. TPCn_ka, iPVn_ma, and TPVn_ma appeared by -mistake in the examples in WCS Paper II and subsequently these and -also TCDn_ka, iPSn_ma and TPSn_ma were legitimized by -the errata to the WCS papers.

          -

          Strictly speaking, the other long forms are non-standard and in fact -have never appeared in any draft of the WCS papers nor in the -errata. However, as natural extensions of the primary form they are -unlikely to be written with any other intention. Thus it should be -safe to accept them provided, of course, that the resulting keyword -does not exceed the 8-character limit.

          -

          If WCSHDR_CNAMn is enabled then also accept:

          -
          iCNAMna  TCNAMna  :   ---   iCNAna    ---   TCNAna  CNAMEia
          -iCRDEna  TCRDEna  :   ---   iCRDna    ---   TCRDna  CRDERia
          -iCSYEna  TCSYEna  :   ---   iCSYna    ---   TCSYna  CSYERia
          -
          -

          Note that CNAMEia, CRDERia, CSYERia, and their variants -are not used by astropy.wcs but are stored as auxiliary information.

          -
        • -
        • WCSHDR_CNAMn: Accept iCNAMn, iCRDEn, iCSYEn, -TCNAMn, TCRDEn, and TCSYEn, i.e. with a blank. -While non-standard, these are the obvious analogues of iCTYPn, -TCTYPn, etc.

          -
        • -
        • WCSHDR_AUXIMG: Allow the image-header form of an auxiliary WCS -keyword with representation-wide scope to provide a default value -for all images. This default may be overridden by the -column-specific form of the keyword.

          -

          For example, a keyword like EQUINOXa would apply to all image -arrays in a binary table, or all pixel list columns with alternate -representation a unless overridden by EQUIna.

          -

          Specifically the keywords are:

          -
          LATPOLEa  for LATPna
          -LONPOLEa  for LONPna
          -RESTFREQ  for RFRQna
          -RESTFRQa  for RFRQna
          -RESTWAVa  for RWAVna
          -
          -

          whose keyvalues are actually used by WCSLIB, and also keywords that -provide auxiliary information that is simply stored in the wcsprm -struct:

          -
          EPOCH         -       ... (No column-specific form.)
          -EPOCHa        -       ... Only if WCSHDR_EPOCHa is set.
          -EQUINOXa  for EQUIna
          -RADESYSa  for RADEna
          -RADECSYS  for RADEna  ... Only if WCSHDR_RADECSYS is set.
          -SPECSYSa  for SPECna
          -SSYSOBSa  for SOBSna
          -SSYSSRCa  for SSRCna
          -VELOSYSa  for VSYSna
          -VELANGLa  for VANGna
          -VELREF        -       ... (No column-specific form.)
          -VELREFa       -       ... Only if WCSHDR_VELREFa is set.
          -VSOURCEa  for VSOUna  ... Only if WCSHDR_VSOURCE is set.
          -WCSNAMEa  for WCSNna  ... Or TWCSna (see below).
          -ZSOURCEa  for ZSOUna
          -
          -DATE-AVG  for DAVGn
          -DATE-OBS  for DOBSn
          -MJD-AVG   for MJDAn
          -MJD-OBS   for MJDOBn
          -OBSGEO-X  for OBSGXn
          -OBSGEO-Y  for OBSGYn
          -OBSGEO-Z  for OBSGZn
          -
          -

          where the image-header keywords on the left provide default values -for the column specific keywords on the right.

          -

          Keywords in the last group, such as MJD-OBS, apply to all -alternate representations, so MJD-OBS would provide a default -value for all images in the header.

          -

          This auxiliary inheritance mechanism applies to binary table image -arrays and pixel lists alike. Most of these keywords have no -default value, the exceptions being LONPOLEa and LATPOLEa, -and also RADESYSa and EQUINOXa which provide defaults for -each other. Thus the only potential difficulty in using -WCSHDR_AUXIMG is that of erroneously inheriting one of these four -keywords.

          -

          Unlike WCSHDR_ALLIMG, the existence of one (or all) of these -auxiliary WCS image header keywords will not by itself cause a -Wcsprm object to be created for alternate -representation a. This is because they do not provide -sufficient information to create a non-trivial coordinate -representation when used in conjunction with the default values of -those keywords, such as CTYPEia, that are parameterized by axis -number.

          -
        • -
        • WCSHDR_ALLIMG: Allow the image-header form of all image header -WCS keywords to provide a default value for all image arrays in a -binary table (n.b. not pixel list). This default may be overridden -by the column-specific form of the keyword.

          -

          For example, a keyword like CRPIXja would apply to all image -arrays in a binary table with alternate representation a -unless overridden by jCRPna.

          -

          Specifically the keywords are those listed above for WCSHDR_AUXIMG -plus:

          -
          WCSAXESa  for WCAXna
          -
          -

          which defines the coordinate dimensionality, and the following -keywords which are parameterized by axis number:

          -
          CRPIXja   for jCRPna
          -PCi_ja    for ijPCna
          -CDi_ja    for ijCDna
          -CDELTia   for iCDEna
          -CROTAi    for iCROTn
          -CROTAia        -      ... Only if WCSHDR_CROTAia is set.
          -CUNITia   for iCUNna
          -CTYPEia   for iCTYna
          -CRVALia   for iCRVna
          -PVi_ma    for iVn_ma
          -PSi_ma    for iSn_ma
          -
          -CNAMEia   for iCNAna
          -CRDERia   for iCRDna
          -CSYERia   for iCSYna
          -
          -

          where the image-header keywords on the left provide default values -for the column specific keywords on the right.

          -

          This full inheritance mechanism only applies to binary table image -arrays, not pixel lists, because in the latter case there is no -well-defined association between coordinate axis number and column -number.

          -

          Note that CNAMEia, CRDERia, CSYERia, and their variants -are not used by pywcs but are stored in the Wcsprm -object as auxiliary information.

          -

          Note especially that at least one Wcsprm object will -be returned for each a found in one of the image header keywords -listed above:

          -
          -
            -
          • If the image header keywords for a are not inherited by -a binary table, then the struct will not be associated with any -particular table column number and it is up to the user to -provide an association.
          • -
          • If the image header keywords for a are inherited by a -binary table image array, then those keywords are considered to -be “exhausted” and do not result in a separate -Wcsprm object.
          • -
          -
          -
        • -
        -
        -
        -

        Header-writing relaxation constants

        -

        to_header and to_header_string -has a relax argument which may be either True, False or an -int.

        -
          -
        • If True, write all recognized extensions.
        • -
        • If False (default), none of the extensions (even those in the -errata) will be written.
        • -
        • If an int, is is a bit field to provide fine-grained control over -what non-standard WCS keywords to accept. The flag bits are subject -to change in future and should be set by using the constants -beginning with WCSHDO_ in the astropy.wcs module.
        • -
        -

        The flag bits are:

        -
          -
        • WCSHDO_none: Don’t use any extensions.

          -
        • -
        • WCSHDO_all: Write all recognized extensions, equivalent to setting -each flag bit.

          -
        • -
        • WCSHDO_safe: Write all extensions that are considered to be safe -and recommended.

          -
        • -
        • WCSHDO_DOBSn: Write DOBSn, the column-specific analogue of -DATE-OBS for use in binary tables and pixel lists. WCS Paper -III introduced DATE-AVG and DAVGn but by an oversight -DOBSn (the obvious analogy) was never formally defined by the -standard. The alternative to using DOBSn is to write -DATE-OBS which applies to the whole table. This usage is -considered to be safe and is recommended.

          -
        • -
        • WCSHDO_TPCn_ka: WCS Paper I defined

          -
            -
          • TPn_ka and TCn_ka for pixel lists

            -

            but WCS Paper II uses TPCn_ka in one example and subsequently -the errata for the WCS papers legitimized the use of

            -
          • -
          • TPCn_ka and TCDn_ka for pixel lists

            -

            provided that the keyword does not exceed eight characters. This -usage is considered to be safe and is recommended because of the -non-mnemonic terseness of the shorter forms.

            -
          • -
          -
        • -
        • WCSHDO_PVn_ma: WCS Paper I defined

          -
            -
          • iVn_ma and iSn_ma for bintables and

            -
          • -
          • TVn_ma and TSn_ma for pixel lists

            -

            but WCS Paper II uses iPVn_ma and TPVn_ma in the examples -and subsequently the errata for the WCS papers legitimized the use -of

            -
          • -
          • iPVn_ma and iPSn_ma for bintables and

            -
          • -
          • TPVn_ma and TPSn_ma for pixel lists

            -

            provided that the keyword does not exceed eight characters. This -usage is considered to be safe and is recommended because of the -non-mnemonic terseness of the shorter forms.

            -
          • -
          -
        • -
        • WCSHDO_CRPXna: For historical reasons WCS Paper I defined

          -
            -
          • jCRPXn, iCDLTn, iCUNIn, iCTYPn, and iCRVLn for -bintables and

            -
          • -
          • TCRPXn, TCDLTn, TCUNIn, TCTYPn, and TCRVLn for -pixel lists

            -

            for use without an alternate version specifier. However, because -of the eight-character keyword constraint, in order to accommodate -column numbers greater than 99 WCS Paper I also defined

            -
          • -
          • jCRPna, iCDEna, iCUNna, iCTYna and iCRVna for -bintables and

            -
          • -
          • TCRPna, TCDEna, TCUNna, TCTYna and TCRVna for -pixel lists

            -

            for use with an alternate version specifier (the a). Like the -PC, CD, PV, and PS keywords there is an obvious -tendency to confuse these two forms for column numbers up to 99. -It is very unlikely that any parser would reject keywords in the -first set with a non-blank alternate version specifier so this -usage is considered to be safe and is recommended.

            -
          • -
          -
        • -
        • WCSHDO_CNAMna: WCS Papers I and III defined

          -
            -
          • iCNAna, iCRDna, and iCSYna for bintables and

            -
          • -
          • TCNAna, TCRDna, and TCSYna for pixel lists

            -

            By analogy with the above, the long forms would be

            -
          • -
          • iCNAMna, iCRDEna, and iCSYEna for bintables and

            -
          • -
          • TCNAMna, TCRDEna, and TCSYEna for pixel lists

            -

            Note that these keywords provide auxiliary information only, none -of them are needed to compute world coordinates. This usage is -potentially unsafe and is not recommended at this time.

            -
          • -
          -
        • -
        • WCSHDO_WCSNna: Write WCSNna instead of TWCSna for pixel -lists. While the constructor treats WCSNna and TWCSna as -equivalent, other parsers may not. Consequently, this usage is -potentially unsafe and is not recommended at this time.

          -
        • -
        -
        -
        - - -
        -
        -
        -
        -
        - -

        Table Of Contents

        - - -

        Previous topic

        -

        UnitConverter

        -

        Next topic

        -

        astropy.wcs History

        -

        This Page

        - - - -
        -
        -
        -
        - - - - \ No newline at end of file From 4bcc767ce487ba9a81c0fcc0dd7b37b403a2c747 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 18 Apr 2012 21:12:19 +0200 Subject: [PATCH 13/69] Updated README --- README | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README b/README index 96449d94..f5325ea9 100644 --- a/README +++ b/README @@ -1 +1,6 @@ -This repository contains the static web page for the Astropy project. Right now it is a fixed build of the docs. +This repository contains the Sphinx build for the Astropy website. The latest +source can be found at: + + https://github.com/astropy/astropy-website + +Pull requests should be opened in that repository instead of this one. \ No newline at end of file From 3eccd25d40c390e1d1a993542c807f5dfbad50c3 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 18 Apr 2012 21:24:33 +0200 Subject: [PATCH 14/69] Improved metadata for sharing (e0a0e7eabc7986ddf488742f848f2d8cd6bcbd18 in astropy-website) --- contributing.html | 2 +- genindex.html | 2 +- index.html | 4 ++-- search.html | 2 +- team.html | 2 +- vision.html | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contributing.html b/contributing.html index 3127a809..39486bd5 100644 --- a/contributing.html +++ b/contributing.html @@ -90,7 +90,7 @@ - + diff --git a/genindex.html b/genindex.html index ec26404c..c1fcd21c 100644 --- a/genindex.html +++ b/genindex.html @@ -92,7 +92,7 @@ - + diff --git a/index.html b/index.html index e4c763f6..5bfacbbf 100644 --- a/index.html +++ b/index.html @@ -90,7 +90,7 @@ - + @@ -206,7 +206,7 @@

        Reporting issues - + diff --git a/team.html b/team.html index 94d47a7a..b4b601f3 100644 --- a/team.html +++ b/team.html @@ -90,7 +90,7 @@ - + diff --git a/vision.html b/vision.html index 9fafe0a5..29eea2ad 100644 --- a/vision.html +++ b/vision.html @@ -90,7 +90,7 @@ - + From 3949d181ee07e5a7dc60b3f9ed27adfd49ed15fb Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 18 Apr 2012 21:34:26 +0200 Subject: [PATCH 15/69] Updated CNAME --- CNAME | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CNAME b/CNAME index 89f4f2d2..e70ba9e6 100644 --- a/CNAME +++ b/CNAME @@ -1,2 +1,2 @@ -astropy.org +www.astropy.org From b3a175ea4081ea734a4df66e070ad2ebe7477c6f Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 7 Jun 2012 10:56:17 -0700 Subject: [PATCH 16/69] added affiliated package registry (57181062b50c234d55ee54219b98773862db5f4e in astropy-website) --- _sources/contributing.txt | 4 +++- _sources/team.txt | 2 ++ _sources/vision.txt | 2 ++ affiliated/registry.json | 40 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 affiliated/registry.json diff --git a/_sources/contributing.txt b/_sources/contributing.txt index f273b4c5..295f99ea 100644 --- a/_sources/contributing.txt +++ b/_sources/contributing.txt @@ -1,3 +1,5 @@ +:orphan: + Contributing to Astropy ======================= @@ -32,4 +34,4 @@ an affiliated package! After joining the `astropy-dev`_ list and notifying other developers of your intent to develop an affiliated package, you can head over `here `_ for instructions on getting started! We can even create a repository for your affiliated package -in the `astropy` organization on GitHub! \ No newline at end of file +in the `astropy` organization on GitHub! diff --git a/_sources/team.txt b/_sources/team.txt index 084e4acd..03b0dc81 100644 --- a/_sources/team.txt +++ b/_sources/team.txt @@ -1,3 +1,5 @@ +:orphan: + The Astropy team ---------------- diff --git a/_sources/vision.txt b/_sources/vision.txt index 0bd2dadc..817f39c3 100644 --- a/_sources/vision.txt +++ b/_sources/vision.txt @@ -1,3 +1,5 @@ +:orphan: + Vision for a Common Astronomy Python Package ============================================ diff --git a/affiliated/registry.json b/affiliated/registry.json new file mode 100644 index 00000000..15070dc5 --- /dev/null +++ b/affiliated/registry.json @@ -0,0 +1,40 @@ +{ + "packages": [ + { + "name": "specutils", + "maintainer": "Wolfgang Kerzendorf", + "stable": false, + "home_url": "https://github.com/astropy/specutils", + "repo_url": "http://github.com/astropy/specutils.git", + }, + { + "name": "pyidlastro", + "maintainer": "Tom Aldcroft", + "stable": false, + "home_url": "https://github.com/astropy/pyidlastro", + "repo_url": "http://github.com/astropy/pyidlastro.git", + }, + { + "name": "photutils", + "maintainer": "Rene Breton", + "stable": false, + "home_url": "https://github.com/astropy/photutils", + "repo_url": "http://github.com/astropy/photutils.git", + } + { + "name": "kcorrect", + "maintainer": "Taro Sato", + "stable": false, + "home_url": "https://github.com/astropy/kcorrect", + "repo_url": "http://github.com/astropy/kcorrect.git", + } + { + "name": "astropysics", + "maintainer": "Erik Tollerud", + "stable": true, + "home_url": "http://packages.python.org/Astropysics/", + "repo_url": "http://github.com/eteq/astropysics.git", + "pypi_name": "astropysics" + } + ] +} From d25012917bada4a54f0d92a012a989257c0ddc44 Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Wed, 13 Jun 2012 13:21:33 -0700 Subject: [PATCH 17/69] updated index page for multiple docs (27c9f3220833b158535be40613c25a69f0520015 in astropy-website) --- _sources/index.txt | 15 ++++++++++----- index.html | 14 +++++++++----- searchindex.js | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/_sources/index.txt b/_sources/index.txt index 0542856d..047e4a42 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -40,11 +40,16 @@ If you are interested in finding out more about the Astropy project, you can rea Documentation ------------- -The documentation for the latest development version of Astropy can be found -at `http://astropy.readthedocs.org `_. This -documentation is automatically updated any time a commit is made to the -Astropy repository. Once a stable version of Astropy is released, we will -provide links to the documentation for that version. +The documentation for the `astropy` core package is available at the +websites listed below. The first is for the most recent released +version. The second is for a version of the documentation that is +automatically updated any time a change is made to the +`astropy source code repository `_. + +* `Stable version (docs.astropy.org) `_ +* `Latest developer version `_ + + Installing ---------- diff --git a/index.html b/index.html index 5bfacbbf..7f1fd097 100644 --- a/index.html +++ b/index.html @@ -160,11 +160,15 @@

        What is Astropy?

        Documentation

        -

        The documentation for the latest development version of Astropy can be found -at http://astropy.readthedocs.org. This -documentation is automatically updated any time a commit is made to the -Astropy repository. Once a stable version of Astropy is released, we will -provide links to the documentation for that version.

        +

        The documentation for the astropy core package is available at the +websites listed below. The first is for the most recent released +version. The second is for a version of the documentation that is +automatically updated any time a change is made to the +astropy source code repository.

        +

        Installing

        diff --git a/searchindex.js b/searchindex.js index 02cbd9e6..ae6b5696 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{all:2,code:[0,2],steve:3,follow:[1,2,3],decid:2,depend:2,send:[0,3],decis:3,ginsburg:3,mechan:2,grollier:3,level:2,gui:2,list:[0,1,2,3],barbari:3,team:[2,3],div:1,readthedoc:1,pleas:[0,1,3],prevent:2,cfa:3,direct:2,nair:3,sign:1,across:[1,2],download:2,further:2,even:0,what:1,abl:2,uniform:2,access:2,version:1,"new":[0,2],ever:2,method:2,ongo:1,berkelei:3,gener:2,never:2,droettboom:3,here:[0,1,3],satisfi:2,layout:2,strong:2,valu:2,wait:2,current:2,prasanth:3,chang:0,via:[0,2],lawrenc:3,transit:2,prefer:0,instal:[1,2],unit:1,from:[1,2],would:2,commun:2,univers:3,websit:0,few:2,criteria:2,crighton:3,until:2,more:[1,2],desir:2,photometr:1,particular:1,effort:1,must:2,irvin:3,join:0,setup:1,work:[0,1,2],dev:[0,3],can:[0,1,2],asciit:1,tar:1,process:2,templat:2,want:[0,1],alwai:2,goal:2,rather:2,nyu:3,how:2,updat:1,astropi:[0,1,2,3],clone:1,pyfit:1,lab:3,befor:2,mai:[1,2],grow:2,github:[0,1],spectra:2,issu:[0,1],maintain:3,allow:2,order:2,help:[1,2],over:[0,2],becaus:2,robitail:3,report:[0,1],ticket:1,greenfield:3,style:2,thank:3,fit:2,fix:0,onc:[1,2],mail:[0,1,3],main:2,them:2,scipi:2,thei:2,handl:1,wolfgang:3,initi:2,nation:3,framework:[1,2],facilit:2,discuss:[1,3],strive:2,choic:2,term:2,eventu:2,name:3,photometri:2,astronom:2,found:1,sato:3,mean:2,neil:3,michael:3,individu:3,idea:0,procedur:2,ensur:2,manifesto:2,http:1,special:2,out:[1,2],matt:3,open:[1,3],perri:3,integr:[0,2],after:0,standard:2,standalon:2,believ:1,releas:[1,2],org:1,promptli:1,could:2,keep:2,outsid:2,adrian:3,first:[1,2],origin:[1,2],major:1,notifi:0,directli:2,christoph:3,demitri:3,independ:2,qualiti:2,number:2,stsci:3,instruct:[0,1],alreadi:[0,1,2],done:2,"long":2,stabl:[1,2],agre:2,miss:3,differ:[0,2],script:2,system:2,tom:3,juli:2,part:2,exactli:2,than:2,whenev:2,provid:[1,2],seamlessli:2,tree:2,project:[0,1,2,3],stall:2,cosmolog:1,mpia:3,rene:3,thereaft:2,mpik:3,ani:[0,1,2],anu:3,have:[0,1,2,3],tabl:2,need:2,seek:2,also:2,build:2,which:2,thoma:3,tool:2,singl:[1,2],simplifi:1,sure:0,unless:2,track:2,price:3,who:2,reach:2,phase:2,"class":[1,2],southampton:3,don:0,adopt:2,request:[0,2,3],pyidlastro:3,salt:3,bring:1,find:1,consolid:2,onli:2,locat:2,activ:[1,2],should:2,contribut:[0,3],get:[0,1],spectroscop:1,pypi:2,muna:3,cannot:2,increas:2,requir:[1,2],organ:[0,2],patch:[0,2],whether:0,common:[1,2],contain:2,where:2,vision:[1,2],set:2,specutil:3,concern:2,correctli:1,someth:1,enough:2,between:2,freder:3,"import":[1,2],email:3,deil:3,tent:1,kei:2,entir:2,matplotlib:2,ipython:1,come:1,addit:[2,3],consensu:2,etc:2,committe:[2,3],mani:[0,1,2,3],brai:3,com:1,schedul:1,summar:2,duplic:2,ultim:2,numpi:[1,2],compon:[1,2],much:2,interest:[0,1],kcorrect:3,crawford:3,imag:1,coordin:[1,2,3],togeth:1,davi:3,"case":2,look:1,packag:[0,1,2,3],aim:2,whelan:3,error:1,everyon:3,almost:1,toolkit:2,itself:2,breton:3,develop:[0,1,2],welcom:1,make:[0,2],python:[1,2],complex:2,document:[0,1,2],higher:2,competit:2,columbia:3,upon:2,user:[1,2],robust:2,implement:2,task:2,discourag:2,thu:2,well:1,kyle:3,exampl:2,thi:[0,1,2],everyth:2,latest:1,pywc:1,identifi:2,easi:2,earli:1,around:1,read:1,world:1,success:1,benefit:2,either:[0,2],page:0,twitter:1,some:2,librari:2,affili:[0,2,3],avoid:2,tracker:[0,1],refer:2,core:[0,1,2,3],encourag:2,repositori:[0,1,2],about:1,central:2,preclud:2,logo_bann:1,kerzendorf:3,commit:1,own:2,colorado:3,primarili:2,automat:1,contributor:3,your:[0,3],merg:1,inclus:2,git:1,wai:0,area:2,support:2,transform:1,submit:[0,2],avail:2,start:[0,1,2],reli:2,aldcroft:3,interfac:2,includ:[1,2],"function":[1,2],head:0,photutil:3,form:2,continu:2,link:1,tollerud:3,bug:1,pull:[0,2,3],made:[1,2],consist:2,possibl:2,"default":2,wish:2,those:2,later:[1,2],creat:0,dure:2,exist:2,erik:3,file:1,check:1,taro:3,detail:1,other:[0,1,2],futur:2,test:2,you:[0,1,3],fork:0,intend:2,astronomi:[0,1,2],intent:0,consid:2,stai:1,reduc:2,adam:3,potenti:2,time:[0,1,2]},objtypes:{},titles:["Contributing to Astropy","Welcome","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","vision","team"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{all:2,code:[0,1,2],steve:3,follow:[1,2,3],decid:2,depend:2,send:[0,3],decis:3,sourc:1,ginsburg:3,mechan:2,grollier:3,level:2,gui:2,list:[0,1,2,3],barbari:3,team:[2,3],div:1,pleas:[0,1,3],prevent:2,direct:2,nair:3,cfa:3,across:[1,2],second:1,download:2,further:2,even:0,what:1,abl:2,uniform:2,access:2,version:1,"new":[0,2],ever:2,method:2,ongo:1,berkelei:3,gener:2,never:2,droettboom:3,here:[0,1,3],satisfi:2,layout:2,strong:2,valu:2,wait:2,current:2,prasanth:3,chang:[0,1],via:[0,2],lawrenc:3,transit:2,prefer:0,instal:[1,2],unit:1,from:[1,2],would:2,commun:2,univers:3,websit:[0,1],few:2,criteria:2,crighton:3,until:2,more:[1,2],desir:2,photometr:1,particular:1,effort:1,must:2,irvin:3,join:0,setup:1,work:[0,1,2],dev:[0,3],can:[0,1,2],asciit:1,tar:1,process:2,templat:2,want:[0,1],alwai:2,goal:2,rather:2,nyu:3,how:2,updat:1,astropi:[0,1,2,3],clone:1,pyfit:1,lab:3,befor:2,mai:[1,2],grow:2,github:[0,1],spectra:2,issu:[0,1],maintain:3,allow:2,order:2,help:[1,2],over:[0,2],becaus:2,robitail:3,report:[0,1],ticket:1,greenfield:3,style:2,thank:3,fit:2,fix:0,onc:[1,2],mail:[0,1,3],main:2,them:2,scipi:2,thei:2,handl:1,wolfgang:3,initi:2,nation:3,framework:[1,2],facilit:2,discuss:[1,3],strive:2,choic:2,term:2,eventu:2,name:3,photometri:2,astronom:2,found:[],sato:3,mean:2,neil:3,michael:3,individu:3,idea:0,procedur:2,ensur:2,manifesto:2,http:1,special:2,out:[1,2],matt:3,open:[1,3],perri:3,common:[1,2],after:0,standard:2,standalon:2,believ:1,releas:[1,2],org:1,promptli:1,could:2,keep:2,outsid:2,adrian:3,first:[1,2],origin:[1,2],major:1,notifi:0,directli:2,christoph:3,demitri:3,independ:2,qualiti:2,number:2,stsci:3,instruct:[0,1],alreadi:[0,1,2],done:2,"long":2,stabl:[1,2],agre:2,miss:3,differ:[0,2],script:2,system:2,tom:3,juli:2,part:2,sign:1,than:2,whenev:2,provid:[1,2],seamlessli:2,tree:2,project:[0,1,2,3],stall:2,cosmolog:1,mpia:3,rene:3,thereaft:2,mpik:3,ani:[0,1,2],anu:3,have:[0,1,2,3],tabl:2,need:2,seek:2,also:2,build:2,which:2,thoma:3,tool:2,singl:[1,2],simplifi:1,sure:0,unless:2,track:2,price:3,who:2,reach:2,most:1,phase:2,"class":[1,2],southampton:3,don:0,doc:1,adopt:2,request:[0,2,3],pyidlastro:3,salt:3,bring:1,find:1,consolid:2,onli:2,exactli:2,locat:2,activ:[1,2],should:2,contribut:[0,3],get:[0,1],spectroscop:1,pypi:2,muna:3,cannot:2,increas:2,requir:[1,2],organ:[0,2],patch:[0,2],whether:0,integr:[0,2],contain:2,where:2,vision:[1,2],set:2,specutil:3,concern:2,correctli:1,someth:1,enough:2,between:2,freder:3,"import":[1,2],email:3,deil:3,tent:1,kei:2,entir:2,matplotlib:2,ipython:1,come:1,addit:[2,3],consensu:2,etc:2,committe:[2,3],mani:[0,1,2,3],brai:3,com:1,schedul:1,summar:2,duplic:2,ultim:2,numpi:[1,2],compon:[1,2],much:2,interest:[0,1],kcorrect:3,crawford:3,imag:1,coordin:[1,2,3],togeth:1,davi:3,"case":2,look:1,packag:[0,1,2,3],aim:2,whelan:3,error:1,everyon:3,almost:1,toolkit:2,itself:2,breton:3,develop:[0,1,2],welcom:1,make:[0,2],python:[1,2],complex:2,document:[0,1,2],higher:2,competit:2,columbia:3,upon:2,user:[1,2],robust:2,implement:2,recent:1,task:2,discourag:2,thu:2,well:1,kyle:3,exampl:2,thi:[0,2],everyth:2,latest:1,pywc:1,identifi:2,web:[],easi:2,earli:1,around:1,read:1,world:1,success:1,benefit:2,either:[0,2],page:0,twitter:1,some:2,librari:2,affili:[0,2,3],avoid:2,tracker:[0,1],refer:2,core:[0,1,2,3],encourag:2,repositori:[0,1,2],about:1,central:2,preclud:2,logo_bann:1,kerzendorf:3,commit:[],own:2,colorado:3,primarili:2,automat:1,contributor:3,your:[0,3],merg:1,inclus:2,git:1,wai:0,area:2,support:2,transform:1,submit:[0,2],avail:[1,2],start:[0,1,2],reli:2,aldcroft:3,interfac:2,includ:[1,2],"function":[1,2],head:0,photutil:3,form:2,continu:2,link:1,tollerud:3,bug:1,pull:[0,2,3],made:[1,2],consist:2,possibl:2,"default":2,wish:2,below:1,those:2,later:[1,2],creat:0,dure:2,exist:2,erik:3,file:1,check:1,taro:3,detail:1,other:[0,1,2],futur:2,test:2,you:[0,1,3],fork:0,intend:2,astronomi:[0,1,2],intent:0,consid:2,stai:1,reduc:2,adam:3,potenti:2,time:[0,1,2]},objtypes:{},titles:["Contributing to Astropy","Welcome","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","vision","team"]}) \ No newline at end of file From d3319b02f04843c05ac176f2876fed9b81657e7c Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Tue, 19 Jun 2012 02:40:15 -0400 Subject: [PATCH 18/69] updated for 0.1 release (8aa04f4eef730cecffabe3a37d6df1c4787cee72 in astropy-website) --- _sources/index.txt | 29 +++++++++++++++++++++-------- index.html | 25 +++++++++++++++++-------- searchindex.js | 2 +- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/_sources/index.txt b/_sources/index.txt index 047e4a42..3999d1f9 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -9,6 +9,9 @@ .. _`documentation`: http://astropy.readthedocs.org/en/latest/install.html .. _`Numpy`: http://numpy.scipy.org .. _`Python`: http://www.python.org +.. _`pip`: http://pypi.python.org/pypi/pip +.. |currentstable| replace:: Astropy 0.1 +.. _currentstable: http://cloud.github.com/downloads/astropy/astropy/astropy-0.1.tar.gz .. raw:: html @@ -30,8 +33,9 @@ Development is actively ongoing, with major packages such as `PyFITS`_, `PyWCS`_, `vo`_, and `asciitable`_ already merged in, and many more components being worked on. In particular, we are developing imaging, photometric, and spectroscopic functionality, as well as frameworks for cosmology, unit -handling, and coordinate transformations. A first stable release is -tentatively scheduled for early May. +handling, and coordinate transformations. + +The current stable version is |currentstable|. Stay updated by following `@astropy `_ on Twitter, or sign up to the `astropy`_ mailing list! @@ -57,14 +61,15 @@ Installing Detailed installation instructions are provided in the `documentation`_, but we have included a simplified version here. -Astropy requires `Python`_ 2.6, 2.7, 3.1, or 3.2, and `Numpy`_ 1.4 or later. -You can install the latest developer version of Astropy using:: +Astropy requires `Python`_ 2.6, 2.7, 3.1, or 3.2, and `Numpy`_ 1.4 or later. The +best way to install astropy is to use `pip`_:: - git clone http://github.com/astropy/astropy.git - cd astropy - python setup.py install + pip install astropy + +Or alternatively, you can download the source from the current version: |currentstable|, +and install the source code in that archive using:: -Once a stable version of Astropy is released, we will provide links to the tar file, and updated installation instructions! + python setup.py install You can check that astropy is correctly installed by starting up ``python`` or ``ipython``, and importing ``astropy``:: @@ -72,6 +77,14 @@ You can check that astropy is correctly installed by starting up ``python`` or ` If you do not get any errors, the installation was successful! +.. note:: + + If you want to install the latest *developer* version of Astropy, use:: + + git clone http://github.com/astropy/astropy.git + cd astropy + python setup.py install + Getting help ------------ diff --git a/index.html b/index.html index 7f1fd097..07a0e9c3 100644 --- a/index.html +++ b/index.html @@ -153,8 +153,8 @@

        What is Astropy?PyWCS, vo, and asciitable already merged in, and many more components being worked on. In particular, we are developing imaging, photometric, and spectroscopic functionality, as well as frameworks for cosmology, unit -handling, and coordinate transformations. A first stable release is -tentatively scheduled for early May.

        +handling, and coordinate transformations.

        +

        The current stable version is Astropy 0.1.

        Stay updated by following @astropy on Twitter, or sign up to the astropy mailing list!

        If you are interested in finding out more about the Astropy project, you can read the original vision for the package.

        @@ -174,18 +174,27 @@

        Documentation

        Detailed installation instructions are provided in the documentation, but we have included a simplified version here.

        -

        Astropy requires Python 2.6, 2.7, 3.1, or 3.2, and Numpy 1.4 or later. -You can install the latest developer version of Astropy using:

        -
        git clone http://github.com/astropy/astropy.git
        -cd astropy
        -python setup.py install
        +

        Astropy requires Python 2.6, 2.7, 3.1, or 3.2, and Numpy 1.4 or later. The +best way to install astropy is to use pip:

        +
        pip install astropy
        +
        +

        Or alternatively, you can download the source from the current version: Astropy 0.1, +and install the source code in that archive using:

        +
        python setup.py install
        -

        Once a stable version of Astropy is released, we will provide links to the tar file, and updated installation instructions!

        You can check that astropy is correctly installed by starting up python or ipython, and importing astropy:

        >>> import astropy
         

        If you do not get any errors, the installation was successful!

        +
        +

        Note

        +

        If you want to install the latest developer version of Astropy, use:

        +
        git clone http://github.com/astropy/astropy.git
        +cd astropy
        +python setup.py install
        +
        +

        Getting help

        diff --git a/searchindex.js b/searchindex.js index ae6b5696..8f113752 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{all:2,code:[0,1,2],steve:3,follow:[1,2,3],decid:2,depend:2,send:[0,3],decis:3,sourc:1,ginsburg:3,mechan:2,grollier:3,level:2,gui:2,list:[0,1,2,3],barbari:3,team:[2,3],div:1,pleas:[0,1,3],prevent:2,direct:2,nair:3,cfa:3,across:[1,2],second:1,download:2,further:2,even:0,what:1,abl:2,uniform:2,access:2,version:1,"new":[0,2],ever:2,method:2,ongo:1,berkelei:3,gener:2,never:2,droettboom:3,here:[0,1,3],satisfi:2,layout:2,strong:2,valu:2,wait:2,current:2,prasanth:3,chang:[0,1],via:[0,2],lawrenc:3,transit:2,prefer:0,instal:[1,2],unit:1,from:[1,2],would:2,commun:2,univers:3,websit:[0,1],few:2,criteria:2,crighton:3,until:2,more:[1,2],desir:2,photometr:1,particular:1,effort:1,must:2,irvin:3,join:0,setup:1,work:[0,1,2],dev:[0,3],can:[0,1,2],asciit:1,tar:1,process:2,templat:2,want:[0,1],alwai:2,goal:2,rather:2,nyu:3,how:2,updat:1,astropi:[0,1,2,3],clone:1,pyfit:1,lab:3,befor:2,mai:[1,2],grow:2,github:[0,1],spectra:2,issu:[0,1],maintain:3,allow:2,order:2,help:[1,2],over:[0,2],becaus:2,robitail:3,report:[0,1],ticket:1,greenfield:3,style:2,thank:3,fit:2,fix:0,onc:[1,2],mail:[0,1,3],main:2,them:2,scipi:2,thei:2,handl:1,wolfgang:3,initi:2,nation:3,framework:[1,2],facilit:2,discuss:[1,3],strive:2,choic:2,term:2,eventu:2,name:3,photometri:2,astronom:2,found:[],sato:3,mean:2,neil:3,michael:3,individu:3,idea:0,procedur:2,ensur:2,manifesto:2,http:1,special:2,out:[1,2],matt:3,open:[1,3],perri:3,common:[1,2],after:0,standard:2,standalon:2,believ:1,releas:[1,2],org:1,promptli:1,could:2,keep:2,outsid:2,adrian:3,first:[1,2],origin:[1,2],major:1,notifi:0,directli:2,christoph:3,demitri:3,independ:2,qualiti:2,number:2,stsci:3,instruct:[0,1],alreadi:[0,1,2],done:2,"long":2,stabl:[1,2],agre:2,miss:3,differ:[0,2],script:2,system:2,tom:3,juli:2,part:2,sign:1,than:2,whenev:2,provid:[1,2],seamlessli:2,tree:2,project:[0,1,2,3],stall:2,cosmolog:1,mpia:3,rene:3,thereaft:2,mpik:3,ani:[0,1,2],anu:3,have:[0,1,2,3],tabl:2,need:2,seek:2,also:2,build:2,which:2,thoma:3,tool:2,singl:[1,2],simplifi:1,sure:0,unless:2,track:2,price:3,who:2,reach:2,most:1,phase:2,"class":[1,2],southampton:3,don:0,doc:1,adopt:2,request:[0,2,3],pyidlastro:3,salt:3,bring:1,find:1,consolid:2,onli:2,exactli:2,locat:2,activ:[1,2],should:2,contribut:[0,3],get:[0,1],spectroscop:1,pypi:2,muna:3,cannot:2,increas:2,requir:[1,2],organ:[0,2],patch:[0,2],whether:0,integr:[0,2],contain:2,where:2,vision:[1,2],set:2,specutil:3,concern:2,correctli:1,someth:1,enough:2,between:2,freder:3,"import":[1,2],email:3,deil:3,tent:1,kei:2,entir:2,matplotlib:2,ipython:1,come:1,addit:[2,3],consensu:2,etc:2,committe:[2,3],mani:[0,1,2,3],brai:3,com:1,schedul:1,summar:2,duplic:2,ultim:2,numpi:[1,2],compon:[1,2],much:2,interest:[0,1],kcorrect:3,crawford:3,imag:1,coordin:[1,2,3],togeth:1,davi:3,"case":2,look:1,packag:[0,1,2,3],aim:2,whelan:3,error:1,everyon:3,almost:1,toolkit:2,itself:2,breton:3,develop:[0,1,2],welcom:1,make:[0,2],python:[1,2],complex:2,document:[0,1,2],higher:2,competit:2,columbia:3,upon:2,user:[1,2],robust:2,implement:2,recent:1,task:2,discourag:2,thu:2,well:1,kyle:3,exampl:2,thi:[0,2],everyth:2,latest:1,pywc:1,identifi:2,web:[],easi:2,earli:1,around:1,read:1,world:1,success:1,benefit:2,either:[0,2],page:0,twitter:1,some:2,librari:2,affili:[0,2,3],avoid:2,tracker:[0,1],refer:2,core:[0,1,2,3],encourag:2,repositori:[0,1,2],about:1,central:2,preclud:2,logo_bann:1,kerzendorf:3,commit:[],own:2,colorado:3,primarili:2,automat:1,contributor:3,your:[0,3],merg:1,inclus:2,git:1,wai:0,area:2,support:2,transform:1,submit:[0,2],avail:[1,2],start:[0,1,2],reli:2,aldcroft:3,interfac:2,includ:[1,2],"function":[1,2],head:0,photutil:3,form:2,continu:2,link:1,tollerud:3,bug:1,pull:[0,2,3],made:[1,2],consist:2,possibl:2,"default":2,wish:2,below:1,those:2,later:[1,2],creat:0,dure:2,exist:2,erik:3,file:1,check:1,taro:3,detail:1,other:[0,1,2],futur:2,test:2,you:[0,1,3],fork:0,intend:2,astronomi:[0,1,2],intent:0,consid:2,stai:1,reduc:2,adam:3,potenti:2,time:[0,1,2]},objtypes:{},titles:["Contributing to Astropy","Welcome","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","vision","team"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{all:2,code:[0,1,2],steve:3,follow:[1,2,3],decid:2,depend:2,send:[0,3],decis:3,sourc:1,ginsburg:3,mechan:2,grollier:3,level:2,gui:2,list:[0,1,2,3],barbari:3,team:[2,3],div:1,pleas:[0,1,3],prevent:2,direct:2,nair:3,cfa:3,across:[1,2],second:1,download:[1,2],further:2,even:0,what:1,abl:2,uniform:2,access:2,version:1,"new":[0,2],ever:2,method:2,ongo:1,berkelei:3,gener:2,never:2,droettboom:3,here:[0,1,3],satisfi:2,layout:2,strong:2,valu:2,wait:2,current:[1,2],prasanth:3,chang:[0,1],via:[0,2],lawrenc:3,transit:2,prefer:0,instal:[1,2],unit:1,from:[1,2],would:2,commun:2,univers:3,websit:[0,1],few:2,criteria:2,crighton:3,until:2,more:[1,2],desir:2,photometr:1,particular:1,effort:1,must:2,irvin:3,join:0,setup:1,work:[0,1,2],dev:[0,3],itself:2,can:[0,1,2],asciit:1,process:2,templat:2,want:[0,1],alwai:2,goal:2,rather:2,nyu:3,how:2,updat:1,astropi:[0,1,2,3],clone:1,pyfit:1,lab:3,befor:2,mai:2,grow:2,github:[0,1],spectra:2,issu:[0,1],maintain:3,allow:2,order:2,help:[1,2],over:[0,2],becaus:2,robitail:3,report:[0,1],ticket:1,greenfield:3,style:2,thank:3,fit:2,fix:0,onc:2,mail:[0,1,3],main:2,them:2,scipi:2,thei:2,handl:1,wolfgang:3,initi:2,nation:3,framework:[1,2],facilit:2,discuss:[1,3],strive:2,choic:2,term:2,eventu:2,name:3,photometri:2,astronom:2,sato:3,mean:2,neil:3,michael:3,individu:3,idea:0,procedur:2,ensur:2,manifesto:2,http:1,special:2,out:[1,2],matt:3,open:[1,3],perri:3,common:[1,2],after:0,standard:2,standalon:2,believ:1,releas:[1,2],org:1,promptli:1,could:2,keep:2,outsid:2,adrian:3,first:[1,2],origin:[1,2],major:1,notifi:0,directli:2,christoph:3,demitri:3,independ:2,qualiti:2,number:2,stsci:3,instruct:[0,1],alreadi:[0,1,2],done:2,"long":2,stabl:[1,2],agre:2,miss:3,differ:[0,2],script:2,system:2,tom:3,juli:2,part:2,exactli:2,than:2,whenev:2,provid:[1,2],seamlessli:2,tree:2,project:[0,1,2,3],stall:2,cosmolog:1,mpia:3,rene:3,thereaft:2,mpik:3,ani:[0,1,2],anu:3,have:[0,1,2,3],tabl:2,need:2,seek:2,note:1,also:2,build:2,which:2,thoma:3,tool:2,singl:[1,2],simplifi:1,sure:0,unless:2,track:2,price:3,who:2,reach:2,most:1,phase:2,"class":[1,2],southampton:3,don:0,doc:1,adopt:2,request:[0,2,3],pyidlastro:3,salt:3,bring:1,find:1,consolid:2,onli:2,locat:2,activ:[1,2],should:2,contribut:[0,3],get:[0,1],spectroscop:1,pypi:2,muna:3,cannot:2,increas:2,requir:[1,2],organ:[0,2],patch:[0,2],whether:0,integr:[0,2],contain:2,where:2,vision:[1,2],set:2,specutil:3,best:1,concern:2,correctli:1,someth:1,enough:2,between:2,freder:3,"import":[1,2],email:3,deil:3,altern:1,kei:2,entir:2,matplotlib:2,ipython:1,come:1,addit:[2,3],consensu:2,etc:2,committe:[2,3],mani:[0,1,2,3],brai:3,com:1,summar:2,duplic:2,ultim:2,numpi:[1,2],compon:[1,2],much:2,interest:[0,1],kcorrect:3,crawford:3,imag:1,coordin:[1,2,3],togeth:1,davi:3,"case":2,look:1,packag:[0,1,2,3],aim:2,whelan:3,error:1,everyon:3,almost:1,toolkit:2,archiv:1,breton:3,develop:[0,1,2],welcom:1,make:[0,2],python:[1,2],complex:2,document:[0,1,2],higher:2,competit:2,columbia:3,upon:2,user:[1,2],robust:2,implement:2,recent:1,task:2,discourag:2,thu:2,well:1,kyle:3,exampl:2,thi:[0,2],everyth:2,latest:1,pywc:1,identifi:2,easi:2,around:1,read:1,world:1,success:1,benefit:2,either:[0,2],page:0,sign:1,twitter:1,some:2,librari:2,affili:[0,2,3],avoid:2,tracker:[0,1],refer:2,core:[0,1,2,3],encourag:2,repositori:[0,1,2],about:1,central:2,preclud:2,logo_bann:1,kerzendorf:3,own:2,colorado:3,primarili:2,automat:1,contributor:3,your:[0,3],merg:1,inclus:2,git:1,wai:[0,1],area:2,support:2,transform:1,submit:[0,2],avail:[1,2],start:[0,1,2],reli:2,aldcroft:3,interfac:2,includ:[1,2],"function":[1,2],head:0,photutil:3,form:2,continu:2,tollerud:3,bug:1,pull:[0,2,3],made:[1,2],consist:2,possibl:2,"default":2,wish:2,below:1,those:2,later:[1,2],creat:0,dure:2,exist:2,erik:3,pip:1,check:1,taro:3,detail:1,other:[0,1,2],futur:2,test:2,you:[0,1,3],fork:0,intend:2,astronomi:[0,1,2],intent:0,consid:2,stai:1,reduc:2,adam:3,potenti:2,time:[0,1,2]},objtypes:{},titles:["Contributing to Astropy","Welcome","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","vision","team"]}) \ No newline at end of file From 32ec0933f83704efb0da9271679d774c7ebce70b Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Tue, 19 Jun 2012 02:52:06 -0400 Subject: [PATCH 19/69] quick fix for incorrectly-made links --- index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 07a0e9c3..edc20b0f 100644 --- a/index.html +++ b/index.html @@ -154,7 +154,7 @@

        What is Astropy?Astropy 0.1.

        Stay updated by following @astropy on Twitter, or sign up to the astropy mailing list!

        If you are interested in finding out more about the Astropy project, you can read the original vision for the package.

        @@ -178,7 +178,7 @@

        Installingpip:

        pip install astropy
        -

        Or alternatively, you can download the source from the current version: Astropy 0.1, +

        Or alternatively, you can download the source from the current version: Astropy 0.1, and install the source code in that archive using:

        python setup.py install
        @@ -226,4 +226,4 @@

        Reporting issues`_ entry (if it has one). + +Registering Packages +^^^^^^^^^^^^^^^^^^^^ + +To include your python astronomy package in this registry, contact the +coordination committe by e-mailing `astropy.team@gmail.com +`_. + + +Currently Registered Packages +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. The javascript at the bottom does the actual table populating + ++--------------+---------+-----------+----------+-----------------+------------+ +| Package Name | Stable? | PyPI Name | Web Page | Code Repository | Maintainer | ++==============+=========+===========+==========+=================+============+ +| Loading... | + + + | | ++--------------+---------+-----------+----------+-----------------+------------+ + +.. raw:: html + + diff --git a/_sources/index.txt b/_sources/index.txt index 3999d1f9..c79473cd 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -5,6 +5,7 @@ .. _`vo`: https://trac.assembla.com/astrolib .. _`asciitable`: http://cxc.harvard.edu/contrib/asciitable/ .. _`astropy`: http://mail.scipy.org/mailman/listinfo/astropy +.. _`astropy-dev`: http://groups.google.com/group/astropy-dev .. _`issue tracker`: http://github.com/astropy/astropy/issues .. _`documentation`: http://astropy.readthedocs.org/en/latest/install.html .. _`Numpy`: http://numpy.scipy.org @@ -23,9 +24,6 @@

        -What is Astropy? ----------------- - The Astropy project is a common effort to develop a single core package for Astronomy that brings together almost 100 developers from around the world. @@ -35,11 +33,16 @@ being worked on. In particular, we are developing imaging, photometric, and spectroscopic functionality, as well as frameworks for cosmology, unit handling, and coordinate transformations. -The current stable version is |currentstable|. +The current stable version is |currentstable|_. -Stay updated by following `@astropy `_ on Twitter, or sign up to the `astropy`_ mailing list! +Stay updated by following `@astropy `_ on Twitter, and sign up for the `astropy`_ mailing list, where you can ask python astronomy +questions of all sorts! If you want to get involved in Astropy development +efforts, or other more technical discussions of Astropy, join the +`astropy-dev`_ list. -If you are interested in finding out more about the Astropy project, you can read the :doc:`original vision ` for the package. +If you are interested in a detailed description of the plan for the Astropy +project, you can read the :doc:`original vision `, or the +`documentation overview `_. Documentation ------------- @@ -66,7 +69,7 @@ best way to install astropy is to use `pip`_:: pip install astropy -Or alternatively, you can download the source from the current version: |currentstable|, +Or alternatively, you can download the source from the current version (|currentstable|_), and install the source code in that archive using:: python setup.py install @@ -88,8 +91,9 @@ If you do not get any errors, the installation was successful! Getting help ------------ -If you want to discuss issues with other Astropy users and with the -developers, you can sign up to the `astropy`_ mailing list! +If you want to discuss issues with other Astropy users, you can sign up +to the `astropy`_ mailing list. Alternatively, the `astropy-dev`_ list +is where you should go to discuss more technical aspects of Astropy. Reporting issues ---------------- diff --git a/affiliated/index.html b/affiliated/index.html new file mode 100644 index 00000000..86a823f5 --- /dev/null +++ b/affiliated/index.html @@ -0,0 +1,314 @@ + + + + + + + + + + + Astropy Affilated Package Registry — Astropy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        + +
        +

        Astropy Affilated Package Registry

        +

        A major part of the Astropy project is the existence of “Affiliated +Packages”. An affiliated package is an astronomy-related python package +that is not part of the astropy core source code, but has requested to +be included in the Astropy project. The projects are expressing an +interest in Astropy’s goals of improving reuse, interoperability, and +interface standards for python astronomy and astrophysics packages.

        +

        This page houses the official registry for affiliated packages. The +table below lists these packages, as determined from the +http://affiliated.astropy.org/registry.json file that contains the actual +registry. The following information is included for each package:

        +
          +
        • The name of the package.
        • +
        • The name of the author/maintainer of the package.
        • +
        • It’s “stability” status. The exact meaning of this is not fully defined, +but it should be used as a guide for whether or not the package maintainer +wants you to consider the package as “working,” and not under heavy +development or similar.
        • +
        • The web page of the package.
        • +
        • The source code repository for the package.
        • +
        • The package’s PyPI entry (if it has one).
        • +
        +
        +

        Registering Packages

        +

        To include your python astronomy package in this registry, contact the +coordination committe by e-mailing astropy.team@gmail.com.

        +
        +
        +

        Currently Registered Packages

        + ++++++++ + + + + + + + + + + + + + + + + + + + +
        Package NameStable?PyPI NameWeb PageCode RepositoryMaintainer
        Loading...     
        +
        +
        + + +
        +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +
        +
        + + \ No newline at end of file diff --git a/affiliated/registry.json b/affiliated/registry.json index 15070dc5..72586127 100644 --- a/affiliated/registry.json +++ b/affiliated/registry.json @@ -5,36 +5,36 @@ "maintainer": "Wolfgang Kerzendorf", "stable": false, "home_url": "https://github.com/astropy/specutils", - "repo_url": "http://github.com/astropy/specutils.git", + "repo_url": "http://github.com/astropy/specutils.git" }, { "name": "pyidlastro", "maintainer": "Tom Aldcroft", "stable": false, "home_url": "https://github.com/astropy/pyidlastro", - "repo_url": "http://github.com/astropy/pyidlastro.git", + "repo_url": "http://github.com/astropy/pyidlastro.git" }, { "name": "photutils", "maintainer": "Rene Breton", "stable": false, "home_url": "https://github.com/astropy/photutils", - "repo_url": "http://github.com/astropy/photutils.git", - } + "repo_url": "http://github.com/astropy/photutils.git" + }, { "name": "kcorrect", "maintainer": "Taro Sato", "stable": false, "home_url": "https://github.com/astropy/kcorrect", - "repo_url": "http://github.com/astropy/kcorrect.git", - } + "repo_url": "http://github.com/astropy/kcorrect.git" + }, { "name": "astropysics", - "maintainer": "Erik Tollerud", + "maintainer": "Erik Tollerud ", "stable": true, "home_url": "http://packages.python.org/Astropysics/", "repo_url": "http://github.com/eteq/astropysics.git", - "pypi_name": "astropysics" + "pypi_name": "Astropysics" } ] } diff --git a/index.html b/index.html index edc20b0f..151ffeba 100644 --- a/index.html +++ b/index.html @@ -145,19 +145,21 @@
        _images/astropy_banner_96.png -
        -

        What is Astropy?

        -

        The Astropy project is a common effort to develop a single core package for +

        The Astropy project is a common effort to develop a single core package for Astronomy that brings together almost 100 developers from around the world.

        Development is actively ongoing, with major packages such as PyFITS, PyWCS, vo, and asciitable already merged in, and many more components being worked on. In particular, we are developing imaging, photometric, and spectroscopic functionality, as well as frameworks for cosmology, unit handling, and coordinate transformations.

        -

        The current stable version is Astropy 0.1.

        -

        Stay updated by following @astropy on Twitter, or sign up to the astropy mailing list!

        -

        If you are interested in finding out more about the Astropy project, you can read the original vision for the package.

        -
        +

        The current stable version is Astropy 0.1.

        +

        Stay updated by following @astropy on Twitter, and sign up for the astropy mailing list, where you can ask python astronomy +questions of all sorts! If you want to get involved in Astropy development +efforts, or other more technical discussions of Astropy, join the +astropy-dev list.

        +

        If you are interested in a detailed description of the plan for the Astropy +project, you can read the original vision, or the +documentation overview.

        Documentation

        The documentation for the astropy core package is available at the @@ -178,7 +180,7 @@

        Installingpip:

        pip install astropy
        -

        Or alternatively, you can download the source from the current version: Astropy 0.1, +

        Or alternatively, you can download the source from the current version (Astropy 0.1), and install the source code in that archive using:

        python setup.py install
        @@ -198,8 +200,9 @@

        Installing

        Getting help

        -

        If you want to discuss issues with other Astropy users and with the -developers, you can sign up to the astropy mailing list!

        +

        If you want to discuss issues with other Astropy users, you can sign up +to the astropy mailing list. Alternatively, the astropy-dev list +is where you should go to discuss more technical aspects of Astropy.

        diff --git a/searchindex.js b/searchindex.js index a1f4b174..a2b22d9c 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{all:[1,3],code:[0,1,2,3],steve:4,follow:[1,2,3,4],row:2,decid:3,depend:3,send:[0,4],decis:4,under:2,sourc:[1,2],than:3,ginsburg:4,insertrow:2,mechan:3,grollier:4,exact:2,nmcell:2,pypinam:2,level:3,gui:3,list:[0,1,2,3,4],barbari:4,team:[2,3,4],div:1,pleas:[0,1,4],prevent:3,cfa:4,direct:3,nair:4,sign:1,second:1,pypi_transl:2,download:[1,3],further:3,even:[0,2],url_transl:2,abl:3,uniform:3,current:[1,2,3],version:1,"new":[0,2,3],ever:3,method:3,ongo:1,consolid:3,gener:3,never:3,droettboom:4,here:[0,1,4],satisfi:3,layout:3,strong:3,valu:3,wait:3,urlcel:2,prasanth:4,stablecel:2,via:[0,3],lawrenc:4,transit:3,pypicel:2,prefer:0,ask:1,href:2,instal:[1,3],unit:1,from:[1,2,3],would:3,commun:3,univers:4,regist:2,websit:[0,1],almost:1,criteria:3,type:2,until:3,more:[1,3],sort:1,desir:3,relat:2,photometr:1,particular:1,actual:2,effort:1,must:3,irvin:4,none:2,join:[0,1],hous:2,setup:1,work:[0,1,2,3],dev:[0,1,4],xhr:2,archiv:1,can:[0,1,3],asciit:1,want:[0,1,2],process:3,templat:3,tab:2,alwai:3,goal:[2,3],rather:3,nyu:4,how:3,updat:1,astropi:[0,1,2,3,4],clone:1,after:0,lab:4,"20affili":2,befor:[2,3],crighton:4,mai:3,data:2,grow:3,stabil:2,github:[0,1],spectra:3,issu:[0,1],inform:2,maintain:[2,4],allow:3,order:3,help:[1,3],offici:2,becaus:[2,3],robitail:4,report:[0,1],ticket:1,greenfield:4,style:3,thank:4,fit:3,fix:0,urltext:2,onc:3,mail:[0,1,2,4],main:3,them:3,scipi:3,"return":2,thei:3,python:[1,2,3],wolfgang:4,initi:3,nation:4,framework:[1,3],facilit:3,discuss:[1,4],strive:3,choic:3,term:3,home_url:2,name:[2,4],anyth:2,photometri:3,tstat:2,astronom:3,each:2,fulli:2,sato:4,mean:[2,3],few:3,neil:4,michael:4,individu:4,idea:0,procedur:3,heavi:2,contributor:4,maintcel:2,populatet:2,columbia:4,special:3,out:3,matt:4,miss:4,perri:4,"_email_with_name_regex":2,common:[1,3],pyfit:1,stable_transl:2,committ:2,standard:[2,3],standalon:3,reason:2,believ:1,releas:[1,3],org:[1,2],promptli:1,could:[2,3],keep:3,length:2,outsid:3,adrian:4,getelementsbytagnam:2,think:2,first:[1,3],origin:[1,3],major:[1,2],notifi:0,directli:3,christoph:4,demitri:4,independ:3,qualiti:3,number:3,stsci:4,instruct:[0,1],alreadi:[0,1,3],done:3,submit:[0,3],stabl:[1,2,3],agre:3,open:[1,2,4],differ:[0,3],script:[2,3],system:3,tom:4,juli:3,insertcel:2,part:[2,3],exactli:3,technic:1,"20packag":2,whenev:3,provid:[1,3],seamlessli:3,tree:3,jqueri:2,stall:3,cosmolog:1,browser:2,mpia:4,rene:4,thereaft:3,modern:2,ani:[0,1,2,3],anu:4,have:[0,1,3,4],tabl:[2,3],need:[2,3],"null":2,seek:3,note:[1,2],also:3,contact:2,best:1,which:3,thoma:4,concern:3,tool:3,singl:[1,3],simplifi:1,sure:[0,2],unless:3,exec:2,track:3,price:4,who:3,reach:3,most:1,plan:1,phase:3,"class":[1,3],southampton:4,don:0,url:2,doc:[1,2],later:[1,3],request:[0,2,3,4],pyidlastro:4,determin:2,salt:4,text:2,maint:2,bring:1,pkg:2,astrophys:2,fine:2,affil:2,involv:1,cell:2,onli:3,locat:3,activ:[1,3],should:[1,2,3],local:2,over:[0,3],contribut:[0,4],get:[0,1],spectroscop:1,express:2,pypi:[2,3],muna:4,cannot:3,increas:3,requir:[1,3],organ:[0,3],pkgnm:2,patch:[0,3],whether:[0,2],integr:[0,3],contain:[2,3],where:[1,3],vision:[1,3],set:3,specutil:4,fail:2,maintainer_transl:2,gmail:2,project:[0,1,2,3,4],statu:2,correctli:1,someth:1,berkelei:4,enough:3,reus:2,between:3,freder:4,"import":[1,3],across:[1,3],deil:4,altern:1,kei:3,javascript:2,subject:2,entir:3,matplotlib:3,ipython:1,"_email_regex":2,come:1,addit:[3,4],consensu:3,etc:3,committe:[3,4],mani:[0,1,3,4],brai:4,com:[1,2],load:2,overview:1,innerhtml:2,guid:2,summar:3,duplic:3,mailto:2,ultim:3,chrome:2,numpi:[1,3],compon:[1,3],json:2,much:3,interest:[0,1,2],kcorrect:4,crawford:4,mpik:4,imag:1,coordin:[1,2,3,4],togeth:1,davi:4,"case":3,interoper:2,look:1,packag:[0,1,2,3,4],aim:3,defin:2,whelan:4,error:1,everyon:4,readi:2,toolkit:3,itself:3,breton:4,"_email_regex_str":2,develop:[0,1,2,3],welcom:1,author:2,make:[0,2,3],pkgi:2,handl:1,complex:3,document:[0,1,2,3],higher:3,competit:3,http:[1,2],upon:3,user:[1,3],improv:2,robust:3,implement:3,recent:1,task:3,discourag:3,entri:2,thu:3,well:1,kyle:4,exampl:3,thi:[0,2,3],undefin:2,everyth:3,latest:1,pywc:1,identifi:3,aspect:1,web:2,easi:3,els:2,match:2,build:3,around:1,quirk:2,read:1,pypi_nam:2,repo_url:2,world:1,success:1,server:2,benefit:3,either:[0,3],page:[0,2],repocel:2,twitter:1,some:[2,3],deleterow:2,ncol:2,librari:3,affili:[0,2,3,4],avoid:3,tracker:[0,1],refer:3,core:[0,1,2,3,4],encourag:3,repositori:[0,1,2,3],eventu:3,regexp:2,unsaf:2,central:3,preclud:3,logo_bann:1,kerzendorf:4,rpocel:2,own:3,colorado:4,primarili:3,automat:1,ensur:3,chang:[0,1],your:[0,2,4],merg:1,inclus:3,git:1,wai:[0,1],area:3,support:3,question:1,transform:1,"long":3,avail:[1,3],start:[0,1,3],reli:3,aldcroft:4,interfac:[2,3],includ:[1,2,3],"var":2,"function":[1,2,3],head:0,photutil:4,form:3,bundl:2,basic:2,continu:3,tollerud:4,bug:1,pull:[0,3,4],made:[1,3],consist:3,possibl:3,"default":3,wish:3,access:3,below:[1,2],manifesto:3,those:3,similar:2,email:4,adopt:3,creat:0,dure:3,exist:[2,3],erik:4,file:2,pip:1,check:1,taro:4,detail:1,other:[0,1,2,3],futur:3,test:[2,3],you:[0,1,2,4],fork:0,intend:3,registri:2,astronomi:[0,1,2,3],intent:0,consid:[2,3],stai:1,reduc:3,sphinx:2,descript:1,getjson:2,adam:4,potenti:3,time:[0,1,3]},objtypes:{},titles:["Contributing to Astropy","Welcome","Astropy Affilated Package Registry","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","affiliated/index","vision","team"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{all:[1,3],code:[0,1,2,3],steve:4,follow:[1,2,3,4],row:2,decid:3,depend:3,send:[0,4],decis:4,under:2,sourc:[1,2],than:3,ginsburg:4,insertrow:2,mechan:3,grollier:4,exact:2,nmcell:2,pypinam:2,level:3,gui:3,list:[0,1,2,3,4],barbari:4,team:[2,3,4],div:1,pleas:[0,1,4],prevent:3,cfa:4,direct:3,nair:4,sign:1,second:1,pypi_transl:2,download:[1,3],further:3,even:[0,2],url_transl:2,abl:3,uniform:3,current:[1,2,3],version:1,"new":[0,2,3],ever:3,method:3,ongo:1,consolid:3,gener:3,never:3,droettboom:4,here:[0,1,4],satisfi:3,layout:3,strong:3,valu:3,wait:3,urlcel:2,prasanth:4,stablecel:2,via:[0,3],lawrenc:4,transit:3,pypicel:2,prefer:0,ask:1,href:2,instal:[1,3],unit:1,from:[1,2,3],would:3,commun:3,univers:4,regist:2,websit:[0,1],almost:1,criteria:3,type:2,until:3,more:[1,3],sort:1,desir:3,relat:2,photometr:1,particular:1,actual:2,effort:1,must:3,irvin:4,none:2,join:[0,1],hous:2,setup:1,work:[0,1,2,3],dev:[0,1,4],xhr:2,archiv:1,can:[0,1,3],asciit:1,want:[0,1,2],process:3,templat:3,tab:2,alwai:3,goal:[2,3],rather:3,nyu:4,how:3,updat:1,astropi:[0,1,2,3,4],clone:1,after:0,lab:4,"20affili":2,befor:[2,3],crighton:4,mai:3,data:2,grow:3,stabil:2,github:[0,1],spectra:3,issu:[0,1],inform:2,maintain:[2,4],allow:3,devdoc:1,order:3,help:[1,3],offici:2,becaus:[2,3],robitail:4,report:[0,1],ticket:1,greenfield:4,style:3,thank:4,fit:3,fix:0,urltext:2,onc:3,mail:[0,1,2,4],main:3,them:3,scipi:3,"return":2,thei:3,python:[1,2,3],wolfgang:4,initi:3,nation:4,framework:[1,3],facilit:3,discuss:[1,4],strive:3,choic:3,term:3,home_url:2,name:[2,4],anyth:2,photometri:3,tstat:2,astronom:3,each:2,fulli:2,sato:4,mean:[2,3],few:3,neil:4,michael:4,individu:4,idea:0,procedur:3,heavi:2,contributor:4,maintcel:2,populatet:2,http:[1,2],special:3,out:3,matt:4,miss:4,perri:4,"_email_with_name_regex":2,common:[1,3],pyfit:1,stable_transl:2,committ:2,standard:[2,3],standalon:3,reason:2,believ:1,releas:[1,3],org:[1,2],promptli:1,could:[2,3],keep:3,length:2,outsid:3,adrian:4,getelementsbytagnam:2,think:2,first:[1,3],origin:[1,3],major:[1,2],notifi:0,directli:3,christoph:4,demitri:4,independ:3,qualiti:3,number:3,stsci:4,instruct:[0,1],alreadi:[0,1,3],done:3,submit:[0,3],stabl:[1,2,3],agre:3,open:[1,2,4],differ:[0,3],script:[2,3],system:3,tom:4,juli:3,insertcel:2,part:[2,3],exactli:3,technic:1,"20packag":2,whenev:3,provid:[1,3],seamlessli:3,tree:3,jqueri:2,stall:3,cosmolog:1,browser:2,mpia:4,rene:4,thereaft:3,modern:2,ani:[0,1,2,3],anu:4,have:[0,1,3,4],tabl:[2,3],need:[2,3],"null":2,seek:3,note:[1,2],also:3,contact:2,best:1,which:3,thoma:4,concern:3,tool:3,singl:[1,3],simplifi:1,sure:[0,2],unless:3,exec:2,track:3,price:4,who:3,reach:3,most:1,plan:1,phase:3,"class":[1,3],southampton:4,don:0,url:2,doc:[1,2],later:[1,3],request:[0,2,3,4],pyidlastro:4,determin:2,salt:4,text:2,maint:2,bring:1,pkg:2,astrophys:2,fine:2,affil:2,involv:1,cell:2,onli:3,locat:3,activ:[1,3],should:[1,2,3],local:2,over:[0,3],contribut:[0,4],get:[0,1],spectroscop:1,express:2,pypi:[2,3],muna:4,cannot:3,increas:3,requir:[1,3],organ:[0,3],pkgnm:2,patch:[0,3],whether:[0,2],integr:[0,3],contain:[2,3],where:[1,3],vision:[1,3],set:3,specutil:4,fail:2,maintainer_transl:2,gmail:2,project:[0,1,2,3,4],statu:2,correctli:1,someth:1,berkelei:4,enough:3,reus:2,between:3,freder:4,"import":[1,3],across:[1,3],deil:4,altern:1,kei:3,javascript:2,subject:2,entir:3,matplotlib:3,ipython:1,"_email_regex":2,come:1,addit:[3,4],consensu:3,etc:3,committe:[3,4],mani:[0,1,3,4],brai:4,com:[1,2],load:2,overview:1,innerhtml:2,guid:2,summar:3,duplic:3,mailto:2,ultim:3,chrome:2,numpi:[1,3],compon:[1,3],json:2,much:3,interest:[0,1,2],kcorrect:4,crawford:4,mpik:4,imag:1,coordin:[1,2,3,4],togeth:1,davi:4,"case":3,interoper:2,look:1,packag:[0,1,2,3,4],aim:3,defin:2,whelan:4,error:1,everyon:4,readi:2,toolkit:3,itself:3,breton:4,"_email_regex_str":2,develop:[0,1,2,3],welcom:1,author:2,make:[0,2,3],pkgi:2,handl:1,complex:3,document:[0,1,2,3],higher:3,competit:3,columbia:4,upon:3,user:[1,3],improv:2,robust:3,implement:3,recent:1,task:3,discourag:3,entri:2,thu:3,well:1,kyle:4,exampl:3,thi:[0,2,3],undefin:2,everyth:3,latest:1,pywc:1,identifi:3,aspect:1,web:2,easi:3,els:2,match:2,build:3,around:1,quirk:2,read:1,pypi_nam:2,repo_url:2,world:1,success:1,server:2,benefit:3,either:[0,3],page:[0,2],repocel:2,twitter:1,some:[2,3],deleterow:2,ncol:2,librari:3,affili:[0,2,3,4],avoid:3,tracker:[0,1],refer:3,core:[0,1,2,3,4],encourag:3,repositori:[0,1,2,3],eventu:3,regexp:2,unsaf:2,central:3,preclud:3,logo_bann:1,kerzendorf:4,rpocel:2,own:3,colorado:4,primarili:3,automat:1,ensur:3,chang:[0,1],your:[0,2,4],merg:1,inclus:3,git:1,wai:[0,1],area:3,support:3,question:1,transform:1,"long":3,avail:[1,3],start:[0,1,3],reli:3,aldcroft:4,interfac:[2,3],includ:[1,2,3],"var":2,"function":[1,2,3],head:0,photutil:4,form:3,bundl:2,basic:2,continu:3,tollerud:4,bug:1,pull:[0,3,4],made:[1,3],consist:3,possibl:3,"default":3,wish:3,access:3,below:[1,2],manifesto:3,those:3,similar:2,email:4,adopt:3,creat:0,dure:3,exist:[2,3],erik:4,file:2,pip:1,check:1,taro:4,detail:1,other:[0,1,2,3],futur:3,test:[2,3],you:[0,1,2,4],fork:0,intend:3,registri:2,astronomi:[0,1,2,3],intent:0,consid:[2,3],stai:1,reduc:3,sphinx:2,descript:1,getjson:2,adam:4,potenti:3,time:[0,1,3]},objtypes:{},titles:["Contributing to Astropy","Welcome","Astropy Affilated Package Registry","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","affiliated/index","vision","team"]}) \ No newline at end of file From 7fcaf3e5459e42db476f81428dca224195138b25 Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 11 Oct 2012 00:36:17 -0400 Subject: [PATCH 22/69] Updated page (commit 95e2bad7ef10dc5d4e675d724ea6981b8c3a1b45 in astropy-website) --- _sources/affiliated/index.txt | 2 +- _sources/index.txt | 3 +++ affiliated/index.html | 6 +++--- index.html | 3 ++- searchindex.js | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/_sources/affiliated/index.txt b/_sources/affiliated/index.txt index b2601167..57baa43f 100644 --- a/_sources/affiliated/index.txt +++ b/_sources/affiliated/index.txt @@ -1,7 +1,7 @@ :orphan: -Astropy Affilated Package Registry +Astropy Affiliated Package Registry ---------------------------------- A major part of the Astropy project is the existence of "Affiliated diff --git a/_sources/index.txt b/_sources/index.txt index c6be82b8..9edca646 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -11,6 +11,7 @@ .. _`Numpy`: http://numpy.scipy.org .. _`Python`: http://www.python.org .. _`pip`: http://pypi.python.org/pypi/pip +.. _`Cython`: http://cython.org/ .. |currentstable| replace:: Astropy 0.1 .. _currentstable: http://cloud.github.com/downloads/astropy/astropy/astropy-0.1.tar.gz @@ -88,6 +89,8 @@ If you do not get any errors, the installation was successful! cd astropy python setup.py install + Be aware that the developer build requires `Cython`_ (in addition to `Numpy`_). + Getting help ------------ diff --git a/affiliated/index.html b/affiliated/index.html index 86a823f5..48a52078 100644 --- a/affiliated/index.html +++ b/affiliated/index.html @@ -8,7 +8,7 @@ - Astropy Affilated Package Registry — Astropy + Astropy Affiliated Package Registry — Astropy @@ -144,8 +144,8 @@
        -
        -

        Astropy Affilated Package Registry

        +
        +

        Astropy Affiliated Package Registry

        A major part of the Astropy project is the existence of “Affiliated Packages”. An affiliated package is an astronomy-related python package that is not part of the astropy core source code, but has requested to diff --git a/index.html b/index.html index feb4b65d..1465f608 100644 --- a/index.html +++ b/index.html @@ -192,10 +192,11 @@

        Installing

        Note

        If you want to install the latest developer version of Astropy, use:

        -

        diff --git a/searchindex.js b/searchindex.js index a2b22d9c..663870f3 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{all:[1,3],code:[0,1,2,3],steve:4,follow:[1,2,3,4],row:2,decid:3,depend:3,send:[0,4],decis:4,under:2,sourc:[1,2],than:3,ginsburg:4,insertrow:2,mechan:3,grollier:4,exact:2,nmcell:2,pypinam:2,level:3,gui:3,list:[0,1,2,3,4],barbari:4,team:[2,3,4],div:1,pleas:[0,1,4],prevent:3,cfa:4,direct:3,nair:4,sign:1,second:1,pypi_transl:2,download:[1,3],further:3,even:[0,2],url_transl:2,abl:3,uniform:3,current:[1,2,3],version:1,"new":[0,2,3],ever:3,method:3,ongo:1,consolid:3,gener:3,never:3,droettboom:4,here:[0,1,4],satisfi:3,layout:3,strong:3,valu:3,wait:3,urlcel:2,prasanth:4,stablecel:2,via:[0,3],lawrenc:4,transit:3,pypicel:2,prefer:0,ask:1,href:2,instal:[1,3],unit:1,from:[1,2,3],would:3,commun:3,univers:4,regist:2,websit:[0,1],almost:1,criteria:3,type:2,until:3,more:[1,3],sort:1,desir:3,relat:2,photometr:1,particular:1,actual:2,effort:1,must:3,irvin:4,none:2,join:[0,1],hous:2,setup:1,work:[0,1,2,3],dev:[0,1,4],xhr:2,archiv:1,can:[0,1,3],asciit:1,want:[0,1,2],process:3,templat:3,tab:2,alwai:3,goal:[2,3],rather:3,nyu:4,how:3,updat:1,astropi:[0,1,2,3,4],clone:1,after:0,lab:4,"20affili":2,befor:[2,3],crighton:4,mai:3,data:2,grow:3,stabil:2,github:[0,1],spectra:3,issu:[0,1],inform:2,maintain:[2,4],allow:3,devdoc:1,order:3,help:[1,3],offici:2,becaus:[2,3],robitail:4,report:[0,1],ticket:1,greenfield:4,style:3,thank:4,fit:3,fix:0,urltext:2,onc:3,mail:[0,1,2,4],main:3,them:3,scipi:3,"return":2,thei:3,python:[1,2,3],wolfgang:4,initi:3,nation:4,framework:[1,3],facilit:3,discuss:[1,4],strive:3,choic:3,term:3,home_url:2,name:[2,4],anyth:2,photometri:3,tstat:2,astronom:3,each:2,fulli:2,sato:4,mean:[2,3],few:3,neil:4,michael:4,individu:4,idea:0,procedur:3,heavi:2,contributor:4,maintcel:2,populatet:2,http:[1,2],special:3,out:3,matt:4,miss:4,perri:4,"_email_with_name_regex":2,common:[1,3],pyfit:1,stable_transl:2,committ:2,standard:[2,3],standalon:3,reason:2,believ:1,releas:[1,3],org:[1,2],promptli:1,could:[2,3],keep:3,length:2,outsid:3,adrian:4,getelementsbytagnam:2,think:2,first:[1,3],origin:[1,3],major:[1,2],notifi:0,directli:3,christoph:4,demitri:4,independ:3,qualiti:3,number:3,stsci:4,instruct:[0,1],alreadi:[0,1,3],done:3,submit:[0,3],stabl:[1,2,3],agre:3,open:[1,2,4],differ:[0,3],script:[2,3],system:3,tom:4,juli:3,insertcel:2,part:[2,3],exactli:3,technic:1,"20packag":2,whenev:3,provid:[1,3],seamlessli:3,tree:3,jqueri:2,stall:3,cosmolog:1,browser:2,mpia:4,rene:4,thereaft:3,modern:2,ani:[0,1,2,3],anu:4,have:[0,1,3,4],tabl:[2,3],need:[2,3],"null":2,seek:3,note:[1,2],also:3,contact:2,best:1,which:3,thoma:4,concern:3,tool:3,singl:[1,3],simplifi:1,sure:[0,2],unless:3,exec:2,track:3,price:4,who:3,reach:3,most:1,plan:1,phase:3,"class":[1,3],southampton:4,don:0,url:2,doc:[1,2],later:[1,3],request:[0,2,3,4],pyidlastro:4,determin:2,salt:4,text:2,maint:2,bring:1,pkg:2,astrophys:2,fine:2,affil:2,involv:1,cell:2,onli:3,locat:3,activ:[1,3],should:[1,2,3],local:2,over:[0,3],contribut:[0,4],get:[0,1],spectroscop:1,express:2,pypi:[2,3],muna:4,cannot:3,increas:3,requir:[1,3],organ:[0,3],pkgnm:2,patch:[0,3],whether:[0,2],integr:[0,3],contain:[2,3],where:[1,3],vision:[1,3],set:3,specutil:4,fail:2,maintainer_transl:2,gmail:2,project:[0,1,2,3,4],statu:2,correctli:1,someth:1,berkelei:4,enough:3,reus:2,between:3,freder:4,"import":[1,3],across:[1,3],deil:4,altern:1,kei:3,javascript:2,subject:2,entir:3,matplotlib:3,ipython:1,"_email_regex":2,come:1,addit:[3,4],consensu:3,etc:3,committe:[3,4],mani:[0,1,3,4],brai:4,com:[1,2],load:2,overview:1,innerhtml:2,guid:2,summar:3,duplic:3,mailto:2,ultim:3,chrome:2,numpi:[1,3],compon:[1,3],json:2,much:3,interest:[0,1,2],kcorrect:4,crawford:4,mpik:4,imag:1,coordin:[1,2,3,4],togeth:1,davi:4,"case":3,interoper:2,look:1,packag:[0,1,2,3,4],aim:3,defin:2,whelan:4,error:1,everyon:4,readi:2,toolkit:3,itself:3,breton:4,"_email_regex_str":2,develop:[0,1,2,3],welcom:1,author:2,make:[0,2,3],pkgi:2,handl:1,complex:3,document:[0,1,2,3],higher:3,competit:3,columbia:4,upon:3,user:[1,3],improv:2,robust:3,implement:3,recent:1,task:3,discourag:3,entri:2,thu:3,well:1,kyle:4,exampl:3,thi:[0,2,3],undefin:2,everyth:3,latest:1,pywc:1,identifi:3,aspect:1,web:2,easi:3,els:2,match:2,build:3,around:1,quirk:2,read:1,pypi_nam:2,repo_url:2,world:1,success:1,server:2,benefit:3,either:[0,3],page:[0,2],repocel:2,twitter:1,some:[2,3],deleterow:2,ncol:2,librari:3,affili:[0,2,3,4],avoid:3,tracker:[0,1],refer:3,core:[0,1,2,3,4],encourag:3,repositori:[0,1,2,3],eventu:3,regexp:2,unsaf:2,central:3,preclud:3,logo_bann:1,kerzendorf:4,rpocel:2,own:3,colorado:4,primarili:3,automat:1,ensur:3,chang:[0,1],your:[0,2,4],merg:1,inclus:3,git:1,wai:[0,1],area:3,support:3,question:1,transform:1,"long":3,avail:[1,3],start:[0,1,3],reli:3,aldcroft:4,interfac:[2,3],includ:[1,2,3],"var":2,"function":[1,2,3],head:0,photutil:4,form:3,bundl:2,basic:2,continu:3,tollerud:4,bug:1,pull:[0,3,4],made:[1,3],consist:3,possibl:3,"default":3,wish:3,access:3,below:[1,2],manifesto:3,those:3,similar:2,email:4,adopt:3,creat:0,dure:3,exist:[2,3],erik:4,file:2,pip:1,check:1,taro:4,detail:1,other:[0,1,2,3],futur:3,test:[2,3],you:[0,1,2,4],fork:0,intend:3,registri:2,astronomi:[0,1,2,3],intent:0,consid:[2,3],stai:1,reduc:3,sphinx:2,descript:1,getjson:2,adam:4,potenti:3,time:[0,1,3]},objtypes:{},titles:["Contributing to Astropy","Welcome","Astropy Affilated Package Registry","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","affiliated/index","vision","team"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{all:[1,3],code:[0,1,2,3],steve:4,follow:[1,2,3,4],row:2,cython:1,decid:3,depend:3,send:[0,4],decis:4,under:2,sourc:[1,2],than:3,ginsburg:4,insertrow:2,mechan:3,grollier:4,exact:2,nmcell:2,pypinam:2,level:3,gui:3,list:[0,1,2,3,4],barbari:4,team:[2,3,4],div:1,pleas:[0,1,4],prevent:3,cfa:4,direct:3,nair:4,sign:1,second:1,pypi_transl:2,download:[1,3],further:3,even:[0,2],url_transl:2,abl:3,uniform:3,cell:2,version:1,"new":[0,2,3],ever:3,method:3,ongo:1,berkelei:4,gener:3,never:3,droettboom:4,here:[0,1,4],satisfi:3,layout:3,strong:3,valu:3,wait:3,urlcel:2,current:[1,2,3],prasanth:4,stablecel:2,via:[0,3],lawrenc:4,transit:3,pypicel:2,prefer:0,ask:1,href:2,instal:[1,3],unit:1,from:[1,2,3],would:3,commun:3,univers:4,regist:2,websit:[0,1],almost:1,criteria:3,type:2,until:3,more:[1,3],sort:1,desir:3,relat:2,photometr:1,particular:1,actual:2,effort:1,must:3,irvin:4,none:2,join:[0,1],hous:2,setup:1,work:[0,1,2,3],dev:[0,1,4],xhr:2,archiv:1,can:[0,1,3],asciit:1,want:[0,1,2],process:3,templat:3,tab:2,alwai:3,goal:[2,3],rather:3,nyu:4,how:3,updat:1,astropi:[0,1,2,3,4],clone:1,after:0,lab:4,"20affili":2,befor:[2,3],crighton:4,mai:3,data:2,grow:3,stabil:2,github:[0,1],spectra:3,issu:[0,1],inform:2,maintain:[2,4],allow:3,devdoc:1,order:3,help:[1,3],offici:2,becaus:[2,3],robitail:4,report:[0,1],ticket:1,greenfield:4,style:3,thank:4,fit:3,fix:0,urltext:2,onc:3,mail:[0,1,2,4],main:3,them:3,scipi:3,"return":2,thei:3,python:[1,2,3],wolfgang:4,initi:3,nation:4,framework:[1,3],facilit:3,discuss:[1,4],strive:3,choic:3,term:3,home_url:2,name:[2,4],anyth:2,photometri:3,tstat:2,astronom:3,each:2,fulli:2,sato:4,mean:[2,3],few:3,neil:4,michael:4,individu:4,idea:0,procedur:3,heavi:2,contributor:4,maintcel:2,populatet:2,http:[1,2],special:3,out:3,matt:4,miss:4,perri:4,"_email_with_name_regex":2,common:[1,3],pyfit:1,stable_transl:2,committ:2,standard:[2,3],standalon:3,reason:2,believ:1,releas:[1,3],org:[1,2],promptli:1,could:[2,3],keep:3,length:2,outsid:3,adrian:4,getelementsbytagnam:2,think:2,first:[1,3],origin:[1,3],major:[1,2],notifi:0,directli:3,christoph:4,demitri:4,independ:3,qualiti:3,number:3,stsci:4,instruct:[0,1],alreadi:[0,1,3],done:3,submit:[0,3],stabl:[1,2,3],agre:3,open:[1,2,4],differ:[0,3],script:[2,3],system:3,tom:4,juli:3,insertcel:2,part:[2,3],exactli:3,technic:1,"20packag":2,whenev:3,provid:[1,3],seamlessli:3,tree:3,project:[0,1,2,3,4],stall:3,cosmolog:1,browser:2,mpia:4,rene:4,thereaft:3,modern:2,ani:[0,1,2,3],anu:4,have:[0,1,3,4],tabl:[2,3],need:[2,3],"null":2,seek:3,note:[1,2],also:3,contact:2,build:[1,3],which:3,thoma:4,concern:3,tool:3,singl:[1,3],simplifi:1,sure:[0,2],unless:3,exec:2,track:3,price:4,who:3,reach:3,most:1,plan:1,phase:3,"class":[1,3],southampton:4,don:0,url:2,doc:[1,2],later:[1,3],request:[0,2,3,4],pyidlastro:4,determin:2,salt:4,text:2,maint:2,bring:1,pkg:2,astrophys:2,fine:2,involv:1,consolid:3,onli:3,locat:3,activ:[1,3],should:[1,2,3],local:2,over:[0,3],contribut:[0,4],get:[0,1],spectroscop:1,express:2,pypi:[2,3],muna:4,cannot:3,increas:3,requir:[1,3],organ:[0,3],pkgnm:2,patch:[0,3],whether:[0,2],integr:[0,3],contain:[2,3],where:[1,3],vision:[1,3],set:3,specutil:4,fail:2,maintainer_transl:2,gmail:2,awar:1,statu:2,correctli:1,someth:1,enough:3,reus:2,between:3,freder:4,"import":[1,3],across:[1,3],deil:4,altern:1,kei:3,javascript:2,subject:2,entir:3,matplotlib:3,ipython:1,"_email_regex":2,come:1,addit:[1,3,4],consensu:3,etc:3,committe:[3,4],mani:[0,1,3,4],brai:4,com:[1,2],load:2,overview:1,innerhtml:2,guid:2,summar:3,duplic:3,mailto:2,ultim:3,chrome:2,numpi:[1,3],compon:[1,3],json:2,much:3,interest:[0,1,2],kcorrect:4,crawford:4,mpik:4,imag:1,coordin:[1,2,3,4],togeth:1,davi:4,"case":3,interoper:2,look:1,packag:[0,1,2,3,4],aim:3,defin:2,whelan:4,error:1,everyon:4,readi:2,toolkit:3,itself:3,breton:4,"_email_regex_str":2,develop:[0,1,2,3],welcom:1,author:2,make:[0,2,3],pkgi:2,handl:1,complex:3,document:[0,1,2,3],higher:3,competit:3,columbia:4,upon:3,jqueri:2,user:[1,3],improv:2,robust:3,implement:3,recent:1,task:3,discourag:3,entri:2,thu:3,well:1,kyle:4,exampl:3,thi:[0,2,3],undefin:2,everyth:3,latest:1,pywc:1,identifi:3,aspect:1,web:2,easi:3,els:2,match:2,around:1,quirk:2,read:1,pypi_nam:2,repo_url:2,world:1,success:1,server:2,benefit:3,either:[0,3],page:[0,2],repocel:2,twitter:1,some:[2,3],deleterow:2,ncol:2,librari:3,affili:[0,2,3,4],avoid:3,best:1,tracker:[0,1],refer:3,core:[0,1,2,3,4],encourag:3,repositori:[0,1,2,3],eventu:3,regexp:2,unsaf:2,central:3,preclud:3,logo_bann:1,kerzendorf:4,rpocel:2,own:3,colorado:4,primarili:3,automat:1,ensur:3,chang:[0,1],your:[0,2,4],merg:1,inclus:3,git:1,wai:[0,1],area:3,support:3,question:1,transform:1,"long":3,avail:[1,3],start:[0,1,3],reli:3,aldcroft:4,interfac:[2,3],includ:[1,2,3],"var":2,"function":[1,2,3],head:0,photutil:4,form:3,bundl:2,basic:2,continu:3,tollerud:4,bug:1,pull:[0,3,4],made:[1,3],consist:3,possibl:3,"default":3,wish:3,access:3,below:[1,2],manifesto:3,those:3,similar:2,email:4,adopt:3,creat:0,dure:3,exist:[2,3],erik:4,file:2,pip:1,check:1,taro:4,detail:1,other:[0,1,2,3],futur:3,test:[2,3],you:[0,1,2,4],fork:0,intend:3,registri:2,astronomi:[0,1,2,3],intent:0,consid:[2,3],stai:1,reduc:3,sphinx:2,descript:1,getjson:2,adam:4,potenti:3,time:[0,1,3]},objtypes:{},titles:["Contributing to Astropy","Welcome","Astropy Affiliated Package Registry","Vision for a Common Astronomy Python Package","The Astropy team"],objnames:{},filenames:["contributing","index","affiliated/index","vision","team"]}) \ No newline at end of file From ea4eed6a63a13581125e441593c9d90facd2f13f Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 11 Oct 2012 00:53:04 -0400 Subject: [PATCH 23/69] Updated page (commit ee217e9caf3b7bc659c74b252b3a23a39c890fb4 in astropy-website) --- affiliated/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/affiliated/index.html b/affiliated/index.html index 48a52078..345cb998 100644 --- a/affiliated/index.html +++ b/affiliated/index.html @@ -140,7 +140,7 @@
        - Fork me on GitHub + Fork me on GitHub
        From 4adb5eb8aeda9c827d60031ff90a8c07ba7b844b Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Fri, 19 Oct 2012 23:47:35 +0200 Subject: [PATCH 24/69] Updated for updated logos to latest version (commit 68f6c3a1cdd62364809efe9bb18dba676c6f501c in astropy-website) --- _images/astropy_banner_96.png | Bin 29833 -> 26836 bytes _sources/affiliated/index.txt | 2 +- _static/astropy_logo.ico | Bin 0 -> 1150 bytes _static/astropy_word_32.png | Bin 0 -> 1927 bytes _static/bootstrap-sphinx.css | 2 +- affiliated/index.html | 2 +- contributing.html | 2 +- genindex.html | 2 +- index.html | 2 +- search.html | 2 +- team.html | 2 +- vision.html | 2 +- 12 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 _static/astropy_logo.ico create mode 100644 _static/astropy_word_32.png diff --git a/_images/astropy_banner_96.png b/_images/astropy_banner_96.png index 89ca2cef2f2d8a46272272f1f2b561c01477af57..3bd96747946b96391a2c609fadb49693677432d7 100644 GIT binary patch literal 26836 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 To9;Xs00000NkvXXu0mjf0T=xY literal 29833 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 vz5(+>=_q85E_ty8+owyF(p8rKz|?`mh+; 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 diff --git a/_sources/affiliated/index.txt b/_sources/affiliated/index.txt index 57baa43f..1e4faa5f 100644 --- a/_sources/affiliated/index.txt +++ b/_sources/affiliated/index.txt @@ -2,7 +2,7 @@ Astropy Affiliated Package Registry ----------------------------------- +----------------------------------- A major part of the Astropy project is the existence of "Affiliated Packages". An affiliated package is an astronomy-related python package diff --git a/_static/astropy_logo.ico b/_static/astropy_logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..c2bca3af116dc3c3f50313c7f5620c74ff255837 GIT binary patch literal 1150 zcmYjRZ)lZe6#u>N-Q7R6E-U8TgkAN{l{Nb_i%5*+3N>Sn)tb~mf_+HvGNNs1lDp29 zTQzrwnKJfajXsPOA|XSVAO&VaaKjc8BiJfGlx!umd3Wz~ey4Nq{nGpLd(LzI{GM~3 z^E~ehc=m=uurZ8xa)4q0j~L8kmaN?bV7}QkS!DF|5E0~5iU&BuiW%IN`~nwU{F|p+ zqH@CY#W24PC7%GgrQM}Mo4xy)|6sz4>;W|kT3{vgkwwHx?z-jJ! zSqzrRnLwG81j`(}N(o>qfht3V!|G~RjuJOt{;cTSAC#p8-L7UyA?Q+G$O+asqR6Qq zb_>DHZg;_>g23ap#t!2n1yss-?qj0A{>H?$pUAvTqInyHhq{HM7s;V9%HD&Lw3_Kf zL;_Dpea=>aUnPMDYglVN(D&n%`$=+DwJ`h=_0C;tGNt<64eIo5W;S$nnyzR&6;*OC zZwD(-P53Xc2irt%&C{LvnoO@Xb(=alOZCley~-fmK+gX~y?T>L*gmnHqp%vVQ$}-N zp(c`a4V~n}uV+%}lW$Y^9Hw5j{6m+hg*!#VjhQ;w)MYh1C(9OFg;!-br-8b(Lbtz{ zEIB}3PEapi&#selSvfReoM%L@Op_NT>F}ax{%dRtHnR=;M1TB+?);?HUn@FsGs{UI z;`kKx%kQlRbH=wC&Rrs>=8Rt_8hDe#MNz9^zbx0qGaT;ivo)GTo9qtk>Nifa=*;ib zksoZnNA&!4^2)67-w+M9SPxq59HJ&$L_e8eGM#he8d-CSTK5HY<_>jXiCWffe2e+# zK6&JV@ekM;w_5Mp?GC)h3csEA5EX40q5JtyYKr8FSRZatOFOCSj#4M=9Pj>179SJA zyOzI$wcb$%{Nsf8A?y7Z1szs@2a^R|l-wBUwVB>ZelwHZU*}~e&_)f$IF3FA4oaFE z@Oo_Ct-Axgy5RMy;$x-hQuvvs>c%v6_6FTs-%|2F&G_d1ZkC%LIAV9;up!0(`b|H@ z67=(PZ-9#!ussiu&)dCPmG0$9O`?xuh_e)f7JHH&j%V@$ADKL%K6=%|X`7$ZVw}}R zLkw~4$sg21YroPh_`rO}=vjUbT|_(r)D&9!puxA#$^HTvnE3w_GbN20^A8*9EjCgB F{0C|Ra})po literal 0 HcmV?d00001 diff --git a/_static/astropy_word_32.png b/_static/astropy_word_32.png new file mode 100644 index 0000000000000000000000000000000000000000..7fd42f9feb15a52e077616e6fdd249b3d1a4a07a GIT binary patch literal 1927 zcmZ{lS5y<&7KT$Ggf1`?u`oaoQA#LM5*%89lm$qY5-9>n=%J&4Bu=;t3YRiS5~?K# zjsy_|B7IOg1Vy^kg(DzUktS`z-1~AL?pf{&D<@gNvxWfjRI?8F1;!`RXjLq@ytilU<@0-9gU zk2@*Gkj;oZ*71Y@7`!rV;=LDxL76#`rdOHq<<9NW9ZABRhvXMRZ>>?nHTTx#EcyOm z|7!#-(yq~Q_fG@+R~>aA(i0GEJ@f-^1U%g!epS`OZ&gxV;y2wG&5gSy(QrFso5@=FV~E0Qxj@m2N$&* zn>jS}B4DeMOGl=IZ?g42AFwm^-l!Vd1)HcOJf#sIyt5X(zT0px`iOQ5yX(WP7~Z-N zs~sTA;j;JYJ*Vf2f$Y|9(-x3|HDEKLy&Y8yJdo~!w1~MXj8D!zAEn61n`EY->xCG$ zA+nlRs`bN;y}cFT5{re^=b(52V^5S}(F85ZQoioG0@urmct;2$e?_CQ|N4Y}1L2V4`F#S$9Kt)_GP>*JECaj37Jv z?U(dc&Gho0n-OOK%Rv=8)B|p6DCj&OCVGlU^`*?UI_+fq?vlHux6kSD=t1L*1{^L( zR+ZR6AAO%dABTE_;Vyy}-?%xINV49>6?k0~0wziysxv*xCj}iLuh;eb^?VTmJ14W} zK9cO|!K(8d%;HBZSRoW-SL&sn{CIJQ??x}lCa2jaC!#s;mRlSgaIhSB=U;T0v4Z*N z9htqAsGEfKpUxsQhFqYu2Qu@%S{|_e96b(_W$;@IW4sNtxAcCqkg#oo4TKj}-^!gf5#r@W6Zq*ktiyAbLI}7D`3;0Y#(A7}$r-yNeRaJ` zI^@Mxl`fwf7D=W@h7(vw?tYFt)~AQ*uS^71H(CTyO+fpMarkU@#cf}LxFq3@u88pgv_aHrpc7uX0=C{icB)Kt)dR08rlTJo9=uh85SIH_fVxO(W_RPdvjx>r$+?}7F7nH$r+{L74;hsjsGd~)Cqax=8=pH=Q~V7G zSCD&3v&SylxQ=@P>>e2Pb#cX-W4z65i5WV+7>fj4CrTX@s`=9E%vJI1p%iwf$>W7* z*IE3+XEEqOEdis;rf1MnzXUOj-pG84_#7LFS&P620Nn^$)c2rP8iUjs_Ke*nmrTE3;Z0!ET-`p|(eQf<+VA-}Ihk?? z%*y*(F^?C(s&t7}hE0gi(;E_nS@O4KDq5r{7E~KrPFOQDde^#)YHEFScg~>tWve3X zLp=Y6(z`%Ha(aA$iJ)N@a{rf&G-l%BmU3C*a@@y0m)I*%OcQmU@&uYPVZ9cHd35Kn z=RB4(2BY=%x_eVgN?ymWlnRnI^)qUssy8bbE9+7be(OPMxVpiCxY_VF?nDyqa)auT z@vd#F`0&!vk5UZ@QU0X!P8U;B(wm@-H|(GuS`wjC9w^HgUpbq@tA1)5y&7j97w$G^ zH>FMl;-@Hu(7kA_HtPyz?jU=h_n$HU$o#+a{y!$z;6Qw7%TT$!O^MB0MJiF2u2FtI zQT_`I&f_r4Q;rFwxN@b4noHWp{H{hu7iNX-Gcio|0fU<<`+P?_5TAGwWCFN wfzu~HIEE3TVtpd~0kN^MngO9fk-k1;f6cH6V*Z-3Jg*6Wv9v{1n0w#-8{W2TkN^Mx literal 0 HcmV?d00001 diff --git a/_static/bootstrap-sphinx.css b/_static/bootstrap-sphinx.css index 89b93c13..f082e0fd 100644 --- a/_static/bootstrap-sphinx.css +++ b/_static/bootstrap-sphinx.css @@ -14,6 +14,6 @@ div.documentwrapper { width: 100%; } .topbar h3 a, .topbar .brand { - background: transparent url("astropy_word_26.png") no-repeat 22px 4px; + background: transparent url("astropy_word_32.png") no-repeat 22px 4px; padding-left: 62px; } \ No newline at end of file diff --git a/affiliated/index.html b/affiliated/index.html index 345cb998..707a13d1 100644 --- a/affiliated/index.html +++ b/affiliated/index.html @@ -29,7 +29,7 @@ - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        + +
        +

        Astropy Documentation

        +

        Below are links to the documentation for all versions of Astropy.

        + +
        + + +
        +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +
        +
        + + \ No newline at end of file diff --git a/genindex.html b/genindex.html index 805465c6..8f7db798 100644 --- a/genindex.html +++ b/genindex.html @@ -121,7 +121,7 @@

        Installing

        @@ -180,7 +179,7 @@

        Installingpip:

        pip install astropy
        -

        Or alternatively, you can download the source from the current version (Astropy 0.1), +

        Or alternatively, you can download the source from the current version (Astropy 0.2), and install the source code in that archive using:

        python setup.py install
        @@ -221,12 +220,6 @@

        Reporting issuesSphinx 1.1.3.

        -

        - - - -

        -

        diff --git a/search.html b/search.html index 10cb004d..59187eca 100644 --- a/search.html +++ b/search.html @@ -125,7 +125,7 @@
        +
        +

        How to start working with Astropy

        +

        Take a look at the Getting Started +guide in the documentation for an initial look at how to work with Astropy. +To drill deeper, explore the Astropy Documentation.

        +

        Getting help

        If you want to discuss issues with other Astropy users, you can sign up diff --git a/searchindex.js b/searchindex.js index d178c6d2..acdc234c 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{all:[0,3,5,1],code:[2,0,3,5,4],queri:3,lian:4,follow:[2,0,3,5],astroml:3,row:3,cython:0,decid:5,simon:4,depend:[0,5],send:[2,4],foster:0,decis:4,under:[0,3],sourc:0,ginsburg:[3,4],util:3,mechan:5,whether:[2,0,3],veri:3,ticket:0,nmcell:3,pypinam:3,level:[3,5],gui:5,henri:4,list:[2,0,3,5,4],ryan:4,"try":3,barbari:4,team:[3,5,4],div:0,pleas:[2,0,3,4],prevent:5,kowalik:4,direct:5,nair:4,sign:0,second:0,pypi_transl:3,download:[0,5],further:5,gustavo:4,victor:4,even:[2,3],url_transl:3,compar:3,han:4,abl:5,uniform:5,current:[0,3,5,1],version:[0,1],axel:4,conduct:2,"new":[2,3,5],ever:5,method:5,ongo:0,widget:3,zach:4,gener:5,never:5,barentsen:4,here:[2,0],leo:4,satisfi:5,layout:5,becom:3,valu:5,madhura:4,convert:3,urlcel:3,jame:4,prasanth:4,chang:[2,0,3],woillez:4,via:[2,5],modul:3,pypicel:3,foundat:2,ask:0,href:3,instal:[0,3,5],should:[0,5],unit:4,plot:3,from:[0,3,5],would:[0,3,5],commun:[2,0,5],conlei:4,regist:3,websit:[2,0],few:[3,5],edward:4,criteria:5,type:3,until:5,oprescu:4,more:[0,5],sort:[0,3],"fr\u00e9d\u00e9ric":4,desir:5,relat:3,templat:5,actual:3,effort:0,must:5,none:3,graphic:3,join:[2,0],scalabl:3,regdiv:3,setup:0,work:[2,0,3,5],dev:[2,0,3,4],xhr:3,archiv:0,can:[2,0,5],learn:3,asciit:0,want:[2,0],give:0,process:5,indic:3,high:3,tab:3,onlin:3,david:4,alwai:5,goal:[3,5],rather:5,anoth:0,write:3,how:5,anyon:2,pure:3,stablecel:3,chri:4,updat:0,map:3,astropi:[0,1,2,3,4,5],dencheva:4,rudi:4,pyfit:0,"20affili":3,befor:[3,5],date:0,data:3,grow:5,insertrow:3,github:[2,0],bind:3,spectra:5,issu:[2,0,3],maintain:3,allow:[0,5],devdoc:0,order:[3,5],talk:0,help:[0,5],astropys:3,over:[2,5],beaumont:4,becaus:[3,5],barrett:4,robitail:[3,4],report:[2,0,3],paper:0,flexibl:3,grollier:4,style:5,fit:[3,5],fix:2,urltext:3,onc:5,mail:[2,0,3,4],main:5,them:5,scipi:5,"return":3,thei:5,python:[2,0,3,5],wolfgang:4,initi:5,framework:5,getelementbyid:3,facilit:[3,5],geert:4,discuss:[0,4],strive:5,choic:[3,5],term:5,home_url:3,alex:4,name:[3,4],anyth:3,drop:3,tstat:3,astronom:[3,5],slide:0,mean:5,zabalza:4,neil:4,citat:0,michael:4,individu:3,idea:2,procedur:5,heavi:3,contributor:4,maintcel:3,significantli:3,populatet:3,logo:0,patch:[2,5],rpocel:3,special:5,out:[3,5],canvas:3,miss:4,astroqueri:3,research:0,daniel:4,"_email_with_name_regex":3,correct:3,hogan:4,shiga:4,benjamin:4,after:2,stable_transl:3,standard:[3,5],standalon:5,reason:3,believ:0,releas:[0,5],org:[0,3],nmarr:3,featur:[0,3],promptli:0,wai:[2,0],could:[0,3,5],keep:5,length:3,outsid:5,adrian:4,getelementsbytagnam:3,think:3,first:[0,3,5],origin:[0,5],softwar:2,major:[0,3],notifi:2,directli:[0,5],christoph:4,demitri:4,arrai:3,independ:5,qualiti:[3,5],number:5,moritz:4,mai:[3,5],instruct:[2,0],alreadi:[2,0,5],done:5,submit:[2,5],stabl:[0,3,5,1],agre:5,open:[0,3,4],differ:[2,5],script:[3,5],interact:3,system:[3,5],wrapper:3,sortord:3,aldcroft:4,tom:4,white:0,tool:[3,5],alan:4,insertcel:3,part:[3,5],exactli:5,technic:0,png:3,"20packag":3,grew:4,whenev:5,provid:[0,3,5],seamlessli:5,tree:5,"g\u00fcnther":4,project:[2,0,3,5,4],reus:3,transport:3,browser:3,analysi:3,viewer:3,thereaft:5,modern:3,ani:[2,0,3,5],packag:[2,0,3,5,4],perri:4,have:[2,0,5,4],tabl:[3,5],need:[3,5],turner:4,"null":3,seek:5,photutil:3,connelli:4,engin:3,lim:4,note:[0,3],also:[0,5],contact:3,maintainer_transl:3,which:[3,5],thoma:[3,4],concern:5,juli:5,singl:[0,5],pontzen:4,simplifi:0,sure:[2,3],unless:5,exec:3,track:5,price:4,who:[2,5],reach:5,most:0,plan:0,phase:5,"class":[0,5],singer:4,don:2,correctli:0,url:3,doc:[0,3],adopt:5,request:[2,3,5,4],bibtex:0,determin:3,latest:[0,1],text:[0,3],maint:3,pkg:3,astrophys:3,fine:3,involv:0,consolid:5,onli:5,locat:5,hanlei:4,activ:[0,5],figur:3,than:5,nadia:4,local:3,conseil:4,contribut:[2,4],get:[2,0],spectroscop:3,express:3,pypi:[3,5],muna:4,cannot:5,increas:5,requir:[0,5],"terr\u00f3n":4,organ:[2,5],pkgnm:3,"public":[0,3],blanton:3,common:5,contain:[3,5],jeschke:3,weaver:4,where:[0,5],vision:[0,5],set:5,julien:4,pynbodi:4,specutil:3,fail:3,best:0,subject:3,awar:0,still:3,shupe:4,databas:3,someth:0,enough:5,stall:5,donath:4,between:[0,5],"import":[0,5],across:[0,5],deil:4,altern:0,kei:5,javascript:3,droettboom:4,entir:5,matplotlib:[3,5],ipython:0,"_email_regex":3,come:0,addit:[0,3,5],both:3,consensu:5,etc:5,present:0,committe:[3,5],pdf:3,brai:4,com:[0,3],clone:0,bell:4,color:3,overview:0,innerhtml:3,taylor:4,summar:5,duplic:5,mailto:3,ultim:5,strong:5,chrome:3,numpi:[0,5],mark:3,compon:[0,5],hagen:4,json:3,much:[3,5],interest:[2,3],basic:3,futur:[3,5],wait:5,crawford:4,wish:[0,5],imag:3,andrew:4,mine:3,coordin:[3,5,4],"bragan\u00e7a":4,davi:4,"case":5,interoper:[0,3],look:0,aim:[3,5],whelan:4,abov:0,error:0,everyon:4,ginga:3,cell:3,readi:3,toolkit:5,itself:5,sever:3,around:3,develop:[2,0,3,5,1],welcom:2,credit:4,suggest:0,make:[2,0,3,5],format:3,pkgi:3,complex:5,document:[2,0,3,5,1],pan:3,higher:5,competit:5,http:[0,3],upon:5,capabl:3,jqueri:3,user:[0,3,5],mani:[2,0,5,4],robust:5,implement:5,mosaic:3,recent:0,task:5,center:3,discourag:5,thu:5,kyle:4,exampl:5,command:3,thi:[2,0,3,5,4],undefin:3,everyth:5,ferguson:4,load:3,pywc:0,identifi:5,erben:4,eventu:5,kramer:4,obtain:0,collabor:0,aspect:0,bressert:[3,4],paul:4,web:3,eli:[3,4],easi:5,parikh:4,jeff:4,els:3,transit:5,match:3,build:[0,5],"_email_regex_str":3,quirk:3,read:[0,3],prefer:2,pypi_nam:3,repo_url:3,emma:4,like:[0,3],success:0,eric:3,zoom:3,server:3,benefit:5,api:3,either:[2,5],output:3,page:[2,3,4],jean:4,www:0,photometri:[3,5],acknowledg:0,twitter:0,gmail:3,"v\u00edctor":4,deleterow:3,ncol:3,home:3,librari:[3,5],affili:[2,3,5],kerkwijk:4,montag:3,avoid:5,cut:3,tracker:[2,0],pei:4,refer:5,machin:3,core:[2,0,3,5,4],encourag:5,power:3,journal:0,pascual:4,repositori:[2,0,3,5,4],hsu:4,regexp:3,sphinx:3,unsaf:3,about:3,central:5,column:3,preclud:5,logo_bann:0,idl:3,integr:[2,5],kerzendorf:4,produc:3,routin:3,own:5,greenfield:4,primarili:5,sergio:4,automat:[0,3],repocel:3,steven:4,ensur:5,your:[2,0,3,4],merg:0,inclus:5,git:0,van:4,val:4,area:5,support:[3,5],question:0,"long":5,avail:[0,5],start:[2,0,5],reli:5,joseph:4,interfac:[3,5],includ:[0,3,5],"var":3,"function":[3,5],head:2,marten:4,roban:4,form:[3,5],some:[3,5],bundl:3,kcorrect:3,continu:5,link:[0,1],grate:0,tollerud:4,line:3,bug:0,pull:[2,5,4],made:[0,5],consist:5,possibl:5,"default":5,crighton:4,access:[3,5],displai:3,below:[0,3,1],miguel:4,those:5,email:4,aplpi:3,later:[0,5],creat:[2,3],dure:5,miruna:4,indeci:3,exist:[3,5],erik:4,file:3,pip:0,improv:3,check:0,titl:0,detail:0,borro:4,other:[2,0,3,5,4],kacper:4,test:[3,5],you:[2,0,3,4],fork:2,intend:5,registri:3,astronomi:[2,0,3,5],matt:4,intens:3,intent:2,consid:[3,5],stai:0,reduc:5,mosaick:3,algorithm:3,svg:[0,3],getjson:3,geometr:3,adam:[3,4],potenti:5,time:[2,0,5],manifesto:5},objtypes:{},titles:["Documentation","Astropy Documentation","Contributing to Astropy","About affiliated packages","The Astropy Team","Vision for a Common Astronomy Python Package"],objnames:{},filenames:["index","docs","contributing","affiliated/index","team","vision"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{all:[0,3,5,1],code:[2,0,3,5,4],queri:3,lian:4,follow:[2,0,3,5],astroml:3,row:3,cython:0,decid:5,simon:4,depend:[0,5],send:[2,4],foster:0,decis:4,under:[0,3],sourc:0,ginsburg:[3,4],util:3,mechan:5,whether:[2,0,3],veri:3,ticket:0,nmcell:3,pypinam:3,level:[3,5],gui:5,henri:4,list:[2,0,3,5,4],ryan:4,"try":3,barbari:4,team:[3,5,4],div:0,pleas:[2,0,3,4],prevent:5,kowalik:4,direct:5,nair:4,sign:0,second:0,pypi_transl:3,download:[0,5],further:5,gustavo:4,victor:4,even:[2,3],url_transl:3,compar:3,han:4,abl:5,uniform:5,current:[0,3,5,1],version:[0,1],axel:4,conduct:2,"new":[2,3,5],ever:5,method:5,ongo:0,widget:3,zach:4,gener:5,never:5,barentsen:4,here:[2,0],leo:4,satisfi:5,layout:5,becom:3,valu:5,madhura:4,convert:3,urlcel:3,jame:4,prasanth:4,chang:[2,0,3],woillez:4,via:[2,5],modul:3,pypicel:3,foundat:2,ask:0,href:3,instal:[0,3,5],should:[0,5],unit:4,plot:3,from:[0,3,5],would:[0,3,5],commun:[2,0,5],conlei:4,regist:3,websit:[2,0],few:[3,5],edward:4,criteria:5,type:3,until:5,oprescu:4,more:[0,5],sort:[0,3],"fr\u00e9d\u00e9ric":4,desir:5,relat:3,templat:5,actual:3,effort:0,must:5,none:3,graphic:3,join:[2,0],scalabl:3,regdiv:3,setup:0,work:[2,0,3,5],dev:[2,0,3,4],xhr:3,archiv:0,can:[2,0,5],drill:0,learn:3,asciit:0,want:[2,0],give:0,process:5,indic:3,high:3,tab:3,onlin:3,david:4,alwai:5,goal:[3,5],rather:5,anoth:0,write:3,how:[0,5],anyon:2,pure:3,stablecel:3,chri:4,updat:0,map:3,astropi:[0,1,2,3,4,5],dencheva:4,rudi:4,pyfit:0,"20affili":3,befor:[3,5],date:0,data:3,grow:5,insertrow:3,github:[2,0],bind:3,spectra:5,issu:[2,0,3],maintain:3,allow:[0,5],devdoc:0,order:[3,5],talk:0,help:[0,5],astropys:3,over:[2,5],beaumont:4,becaus:[3,5],barrett:4,robitail:[3,4],report:[2,0,3],paper:0,flexibl:3,grollier:4,style:5,fit:[3,5],fix:2,urltext:3,onc:5,mail:[2,0,3,4],main:5,them:5,scipi:5,"return":3,thei:5,python:[2,0,3,5],wolfgang:4,initi:[0,5],framework:5,getelementbyid:3,facilit:[3,5],geert:4,discuss:[0,4],strive:5,choic:[3,5],term:5,home_url:3,alex:4,name:[3,4],anyth:3,drop:3,tstat:3,astronom:[3,5],slide:0,mean:5,zabalza:4,neil:4,citat:0,michael:4,individu:3,idea:2,procedur:5,heavi:3,contributor:4,maintcel:3,significantli:3,populatet:3,logo:0,patch:[2,5],rpocel:3,special:5,out:[3,5],canvas:3,miss:4,astroqueri:3,research:0,daniel:4,"_email_with_name_regex":3,correct:3,hogan:4,shiga:4,benjamin:4,after:2,stable_transl:3,standard:[3,5],standalon:5,reason:3,believ:0,releas:[0,5],org:[0,3],nmarr:3,featur:[0,3],promptli:0,wai:[2,0],could:[0,3,5],keep:5,length:3,outsid:5,adrian:4,getelementsbytagnam:3,think:3,first:[0,3,5],origin:[0,5],softwar:2,major:[0,3],notifi:2,directli:[0,5],christoph:4,demitri:4,arrai:3,independ:5,qualiti:[3,5],number:5,moritz:4,mai:[3,5],instruct:[2,0],alreadi:[2,0,5],done:5,submit:[2,5],stabl:[0,3,5,1],agre:5,open:[0,3,4],differ:[2,5],script:[3,5],interact:3,system:[3,5],wrapper:3,sortord:3,aldcroft:4,tom:4,white:0,tool:[3,5],alan:4,insertcel:3,part:[3,5],exactli:5,technic:0,png:3,"20packag":3,grew:4,whenev:5,provid:[0,3,5],seamlessli:5,tree:5,"g\u00fcnther":4,project:[2,0,3,5,4],reus:3,transport:3,browser:3,analysi:3,viewer:3,thereaft:5,modern:3,ani:[2,0,3,5],packag:[2,0,3,5,4],perri:4,have:[2,0,5,4],tabl:[3,5],need:[3,5],turner:4,"null":3,seek:5,photutil:3,connelli:4,engin:3,lim:4,note:[0,3],also:[0,5],contact:3,take:0,which:[3,5],thoma:[3,4],concern:5,juli:5,singl:[0,5],pontzen:4,simplifi:0,sure:[2,3],unless:5,exec:3,track:5,price:4,who:[2,5],reach:5,most:0,plan:0,phase:5,"class":[0,5],singer:4,don:2,correctli:0,url:3,doc:[0,3],adopt:5,request:[2,3,5,4],bibtex:0,determin:3,latest:[0,1],text:[0,3],maint:3,pkg:3,astrophys:3,fine:3,involv:0,consolid:5,onli:5,locat:5,hanlei:4,activ:[0,5],figur:3,than:5,nadia:4,local:3,conseil:4,contribut:[2,4],get:[2,0],spectroscop:3,express:3,pypi:[3,5],muna:4,cannot:5,increas:5,requir:[0,5],"terr\u00f3n":4,organ:[2,5],pkgnm:3,"public":[0,3],blanton:3,common:5,contain:[3,5],jeschke:3,weaver:4,where:[0,5],vision:[0,5],set:5,julien:4,pynbodi:4,specutil:3,fail:3,best:0,subject:3,awar:0,still:3,shupe:4,databas:3,someth:0,enough:5,stall:5,donath:4,between:[0,5],"import":[0,5],across:[0,5],deil:4,altern:0,kei:5,javascript:3,droettboom:4,entir:5,matplotlib:[3,5],ipython:0,"_email_regex":3,come:0,addit:[0,3,5],both:3,consensu:5,etc:5,present:0,committe:[3,5],pdf:3,brai:4,com:[0,3],clone:0,bell:4,color:3,overview:0,innerhtml:3,taylor:4,guid:0,summar:5,duplic:5,mailto:3,ultim:5,strong:5,chrome:3,numpi:[0,5],mark:3,compon:[0,5],hagen:4,json:3,much:[3,5],interest:[2,3],basic:3,futur:[3,5],wait:5,crawford:4,wish:[0,5],deeper:0,imag:3,andrew:4,mine:3,coordin:[3,5,4],"bragan\u00e7a":4,davi:4,"case":5,interoper:[0,3],look:0,aim:[3,5],whelan:4,abov:0,error:0,everyon:4,ginga:3,cell:3,readi:3,toolkit:5,itself:5,sever:3,around:3,develop:[2,0,3,5,1],welcom:2,credit:4,suggest:0,make:[2,0,3,5],format:3,pkgi:3,complex:5,document:[2,0,3,5,1],pan:3,higher:5,competit:5,http:[0,3],upon:5,capabl:3,jqueri:3,user:[0,3,5],mani:[2,0,5,4],robust:5,implement:5,mosaic:3,recent:0,task:5,center:3,discourag:5,thu:5,kyle:4,exampl:5,command:3,thi:[2,0,3,5,4],undefin:3,everyth:5,ferguson:4,load:3,pywc:0,identifi:5,erben:4,eventu:5,kramer:4,obtain:0,collabor:0,aspect:0,bressert:[3,4],paul:4,web:3,eli:[3,4],easi:5,parikh:4,jeff:4,els:3,transit:5,match:3,build:[0,5],"_email_regex_str":3,quirk:3,read:[0,3],prefer:2,pypi_nam:3,repo_url:3,emma:4,like:[0,3],success:0,eric:3,zoom:3,server:3,benefit:5,api:3,either:[2,5],output:3,page:[2,3,4],jean:4,www:0,photometri:[3,5],acknowledg:0,twitter:0,gmail:3,"v\u00edctor":4,deleterow:3,ncol:3,home:3,librari:[3,5],affili:[2,3,5],kerkwijk:4,montag:3,avoid:5,cut:3,tracker:[2,0],pei:4,refer:5,machin:3,core:[2,0,3,5,4],encourag:5,power:3,journal:0,explor:0,pascual:4,repositori:[2,0,3,5,4],hsu:4,regexp:3,sphinx:3,unsaf:3,about:3,central:5,column:3,preclud:5,logo_bann:0,idl:3,integr:[2,5],kerzendorf:4,produc:3,routin:3,own:5,greenfield:4,primarili:5,sergio:4,automat:[0,3],repocel:3,steven:4,ensur:5,your:[2,0,3,4],merg:0,inclus:5,git:0,van:4,val:4,area:5,support:[3,5],question:0,"long":5,avail:[0,5],start:[2,0,5],reli:5,joseph:4,interfac:[3,5],includ:[0,3,5],"var":3,"function":[3,5],head:2,marten:4,roban:4,form:[3,5],some:[3,5],bundl:3,kcorrect:3,continu:5,link:[0,1],grate:0,tollerud:4,line:3,bug:0,pull:[2,5,4],made:[0,5],consist:5,possibl:5,"default":5,crighton:4,access:[3,5],displai:3,maintainer_transl:3,below:[0,3,1],miguel:4,those:5,email:4,aplpi:3,later:[0,5],creat:[2,3],dure:5,miruna:4,indeci:3,exist:[3,5],erik:4,file:3,pip:0,improv:3,check:0,titl:0,detail:0,borro:4,other:[2,0,3,5,4],kacper:4,test:[3,5],you:[2,0,3,4],fork:2,intend:5,registri:3,astronomi:[2,0,3,5],matt:4,intens:3,intent:2,consid:[3,5],stai:0,reduc:5,mosaick:3,algorithm:3,svg:[0,3],getjson:3,geometr:3,adam:[3,4],potenti:5,time:[2,0,5],manifesto:5},objtypes:{},titles:["Documentation","Astropy Documentation","Contributing to Astropy","About affiliated packages","The Astropy Team","Vision for a Common Astronomy Python Package"],objnames:{},filenames:["index","docs","contributing","affiliated/index","team","vision"]}) \ No newline at end of file From 77790ec39a6a9a3e815fd363e3c97290482bc28b Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Wed, 18 Sep 2013 16:49:56 -0400 Subject: [PATCH 56/69] Updated page (commit c380be14d07c8b1c86abb2d3ad430afd9dd884bf in astropy-website) --- _sources/index.txt | 13 +++++++------ index.html | 11 +++++------ searchindex.js | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/_sources/index.txt b/_sources/index.txt index 7e853885..fcdce58b 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -41,6 +41,13 @@ efforts, or other more technical discussions of Astropy, join the **Please note:** If you use Astropy for work/research presented in a publication, please read `Acknowledging the use of Astropy`_. +How to start working with Astropy +--------------------------------- + +Take a look at the `Getting Started `_ +guide in the documentation for an initial look at how to work with Astropy. + + Documentation ------------- @@ -88,12 +95,6 @@ If you do not get any errors, the installation was successful! Be aware that the developer build requires `Cython`_ (in addition to `Numpy`_). -How to start working with Astropy ---------------------------------- - -Take a look at the `Getting Started `_ -guide in the documentation for an initial look at how to work with Astropy. -To drill deeper, explore the :doc:`docs`. Getting help ------------ diff --git a/index.html b/index.html index dc1cc6c7..a4a8f9c4 100644 --- a/index.html +++ b/index.html @@ -162,6 +162,11 @@ astropy-dev list.

        Please note: If you use Astropy for work/research presented in a publication, please read Acknowledging the use of Astropy.

        +
        +

        How to start working with Astropy

        +

        Take a look at the Getting Started +guide in the documentation for an initial look at how to work with Astropy.

        +

        Documentation

        The documentation for the astropy core package is available at the @@ -202,12 +207,6 @@

        InstallingBe aware that the developer build requires Cython (in addition to Numpy).

        -
        -

        How to start working with Astropy

        -

        Take a look at the Getting Started -guide in the documentation for an initial look at how to work with Astropy. -To drill deeper, explore the Astropy Documentation.

        -

        Getting help

        If you want to discuss issues with other Astropy users, you can sign up diff --git a/searchindex.js b/searchindex.js index acdc234c..6e7d829b 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{all:[0,3,5,1],code:[2,0,3,5,4],queri:3,lian:4,follow:[2,0,3,5],astroml:3,row:3,cython:0,decid:5,simon:4,depend:[0,5],send:[2,4],foster:0,decis:4,under:[0,3],sourc:0,ginsburg:[3,4],util:3,mechan:5,whether:[2,0,3],veri:3,ticket:0,nmcell:3,pypinam:3,level:[3,5],gui:5,henri:4,list:[2,0,3,5,4],ryan:4,"try":3,barbari:4,team:[3,5,4],div:0,pleas:[2,0,3,4],prevent:5,kowalik:4,direct:5,nair:4,sign:0,second:0,pypi_transl:3,download:[0,5],further:5,gustavo:4,victor:4,even:[2,3],url_transl:3,compar:3,han:4,abl:5,uniform:5,current:[0,3,5,1],version:[0,1],axel:4,conduct:2,"new":[2,3,5],ever:5,method:5,ongo:0,widget:3,zach:4,gener:5,never:5,barentsen:4,here:[2,0],leo:4,satisfi:5,layout:5,becom:3,valu:5,madhura:4,convert:3,urlcel:3,jame:4,prasanth:4,chang:[2,0,3],woillez:4,via:[2,5],modul:3,pypicel:3,foundat:2,ask:0,href:3,instal:[0,3,5],should:[0,5],unit:4,plot:3,from:[0,3,5],would:[0,3,5],commun:[2,0,5],conlei:4,regist:3,websit:[2,0],few:[3,5],edward:4,criteria:5,type:3,until:5,oprescu:4,more:[0,5],sort:[0,3],"fr\u00e9d\u00e9ric":4,desir:5,relat:3,templat:5,actual:3,effort:0,must:5,none:3,graphic:3,join:[2,0],scalabl:3,regdiv:3,setup:0,work:[2,0,3,5],dev:[2,0,3,4],xhr:3,archiv:0,can:[2,0,5],drill:0,learn:3,asciit:0,want:[2,0],give:0,process:5,indic:3,high:3,tab:3,onlin:3,david:4,alwai:5,goal:[3,5],rather:5,anoth:0,write:3,how:[0,5],anyon:2,pure:3,stablecel:3,chri:4,updat:0,map:3,astropi:[0,1,2,3,4,5],dencheva:4,rudi:4,pyfit:0,"20affili":3,befor:[3,5],date:0,data:3,grow:5,insertrow:3,github:[2,0],bind:3,spectra:5,issu:[2,0,3],maintain:3,allow:[0,5],devdoc:0,order:[3,5],talk:0,help:[0,5],astropys:3,over:[2,5],beaumont:4,becaus:[3,5],barrett:4,robitail:[3,4],report:[2,0,3],paper:0,flexibl:3,grollier:4,style:5,fit:[3,5],fix:2,urltext:3,onc:5,mail:[2,0,3,4],main:5,them:5,scipi:5,"return":3,thei:5,python:[2,0,3,5],wolfgang:4,initi:[0,5],framework:5,getelementbyid:3,facilit:[3,5],geert:4,discuss:[0,4],strive:5,choic:[3,5],term:5,home_url:3,alex:4,name:[3,4],anyth:3,drop:3,tstat:3,astronom:[3,5],slide:0,mean:5,zabalza:4,neil:4,citat:0,michael:4,individu:3,idea:2,procedur:5,heavi:3,contributor:4,maintcel:3,significantli:3,populatet:3,logo:0,patch:[2,5],rpocel:3,special:5,out:[3,5],canvas:3,miss:4,astroqueri:3,research:0,daniel:4,"_email_with_name_regex":3,correct:3,hogan:4,shiga:4,benjamin:4,after:2,stable_transl:3,standard:[3,5],standalon:5,reason:3,believ:0,releas:[0,5],org:[0,3],nmarr:3,featur:[0,3],promptli:0,wai:[2,0],could:[0,3,5],keep:5,length:3,outsid:5,adrian:4,getelementsbytagnam:3,think:3,first:[0,3,5],origin:[0,5],softwar:2,major:[0,3],notifi:2,directli:[0,5],christoph:4,demitri:4,arrai:3,independ:5,qualiti:[3,5],number:5,moritz:4,mai:[3,5],instruct:[2,0],alreadi:[2,0,5],done:5,submit:[2,5],stabl:[0,3,5,1],agre:5,open:[0,3,4],differ:[2,5],script:[3,5],interact:3,system:[3,5],wrapper:3,sortord:3,aldcroft:4,tom:4,white:0,tool:[3,5],alan:4,insertcel:3,part:[3,5],exactli:5,technic:0,png:3,"20packag":3,grew:4,whenev:5,provid:[0,3,5],seamlessli:5,tree:5,"g\u00fcnther":4,project:[2,0,3,5,4],reus:3,transport:3,browser:3,analysi:3,viewer:3,thereaft:5,modern:3,ani:[2,0,3,5],packag:[2,0,3,5,4],perri:4,have:[2,0,5,4],tabl:[3,5],need:[3,5],turner:4,"null":3,seek:5,photutil:3,connelli:4,engin:3,lim:4,note:[0,3],also:[0,5],contact:3,take:0,which:[3,5],thoma:[3,4],concern:5,juli:5,singl:[0,5],pontzen:4,simplifi:0,sure:[2,3],unless:5,exec:3,track:5,price:4,who:[2,5],reach:5,most:0,plan:0,phase:5,"class":[0,5],singer:4,don:2,correctli:0,url:3,doc:[0,3],adopt:5,request:[2,3,5,4],bibtex:0,determin:3,latest:[0,1],text:[0,3],maint:3,pkg:3,astrophys:3,fine:3,involv:0,consolid:5,onli:5,locat:5,hanlei:4,activ:[0,5],figur:3,than:5,nadia:4,local:3,conseil:4,contribut:[2,4],get:[2,0],spectroscop:3,express:3,pypi:[3,5],muna:4,cannot:5,increas:5,requir:[0,5],"terr\u00f3n":4,organ:[2,5],pkgnm:3,"public":[0,3],blanton:3,common:5,contain:[3,5],jeschke:3,weaver:4,where:[0,5],vision:[0,5],set:5,julien:4,pynbodi:4,specutil:3,fail:3,best:0,subject:3,awar:0,still:3,shupe:4,databas:3,someth:0,enough:5,stall:5,donath:4,between:[0,5],"import":[0,5],across:[0,5],deil:4,altern:0,kei:5,javascript:3,droettboom:4,entir:5,matplotlib:[3,5],ipython:0,"_email_regex":3,come:0,addit:[0,3,5],both:3,consensu:5,etc:5,present:0,committe:[3,5],pdf:3,brai:4,com:[0,3],clone:0,bell:4,color:3,overview:0,innerhtml:3,taylor:4,guid:0,summar:5,duplic:5,mailto:3,ultim:5,strong:5,chrome:3,numpi:[0,5],mark:3,compon:[0,5],hagen:4,json:3,much:[3,5],interest:[2,3],basic:3,futur:[3,5],wait:5,crawford:4,wish:[0,5],deeper:0,imag:3,andrew:4,mine:3,coordin:[3,5,4],"bragan\u00e7a":4,davi:4,"case":5,interoper:[0,3],look:0,aim:[3,5],whelan:4,abov:0,error:0,everyon:4,ginga:3,cell:3,readi:3,toolkit:5,itself:5,sever:3,around:3,develop:[2,0,3,5,1],welcom:2,credit:4,suggest:0,make:[2,0,3,5],format:3,pkgi:3,complex:5,document:[2,0,3,5,1],pan:3,higher:5,competit:5,http:[0,3],upon:5,capabl:3,jqueri:3,user:[0,3,5],mani:[2,0,5,4],robust:5,implement:5,mosaic:3,recent:0,task:5,center:3,discourag:5,thu:5,kyle:4,exampl:5,command:3,thi:[2,0,3,5,4],undefin:3,everyth:5,ferguson:4,load:3,pywc:0,identifi:5,erben:4,eventu:5,kramer:4,obtain:0,collabor:0,aspect:0,bressert:[3,4],paul:4,web:3,eli:[3,4],easi:5,parikh:4,jeff:4,els:3,transit:5,match:3,build:[0,5],"_email_regex_str":3,quirk:3,read:[0,3],prefer:2,pypi_nam:3,repo_url:3,emma:4,like:[0,3],success:0,eric:3,zoom:3,server:3,benefit:5,api:3,either:[2,5],output:3,page:[2,3,4],jean:4,www:0,photometri:[3,5],acknowledg:0,twitter:0,gmail:3,"v\u00edctor":4,deleterow:3,ncol:3,home:3,librari:[3,5],affili:[2,3,5],kerkwijk:4,montag:3,avoid:5,cut:3,tracker:[2,0],pei:4,refer:5,machin:3,core:[2,0,3,5,4],encourag:5,power:3,journal:0,explor:0,pascual:4,repositori:[2,0,3,5,4],hsu:4,regexp:3,sphinx:3,unsaf:3,about:3,central:5,column:3,preclud:5,logo_bann:0,idl:3,integr:[2,5],kerzendorf:4,produc:3,routin:3,own:5,greenfield:4,primarili:5,sergio:4,automat:[0,3],repocel:3,steven:4,ensur:5,your:[2,0,3,4],merg:0,inclus:5,git:0,van:4,val:4,area:5,support:[3,5],question:0,"long":5,avail:[0,5],start:[2,0,5],reli:5,joseph:4,interfac:[3,5],includ:[0,3,5],"var":3,"function":[3,5],head:2,marten:4,roban:4,form:[3,5],some:[3,5],bundl:3,kcorrect:3,continu:5,link:[0,1],grate:0,tollerud:4,line:3,bug:0,pull:[2,5,4],made:[0,5],consist:5,possibl:5,"default":5,crighton:4,access:[3,5],displai:3,maintainer_transl:3,below:[0,3,1],miguel:4,those:5,email:4,aplpi:3,later:[0,5],creat:[2,3],dure:5,miruna:4,indeci:3,exist:[3,5],erik:4,file:3,pip:0,improv:3,check:0,titl:0,detail:0,borro:4,other:[2,0,3,5,4],kacper:4,test:[3,5],you:[2,0,3,4],fork:2,intend:5,registri:3,astronomi:[2,0,3,5],matt:4,intens:3,intent:2,consid:[3,5],stai:0,reduc:5,mosaick:3,algorithm:3,svg:[0,3],getjson:3,geometr:3,adam:[3,4],potenti:5,time:[2,0,5],manifesto:5},objtypes:{},titles:["Documentation","Astropy Documentation","Contributing to Astropy","About affiliated packages","The Astropy Team","Vision for a Common Astronomy Python Package"],objnames:{},filenames:["index","docs","contributing","affiliated/index","team","vision"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{all:[0,3,5,1],code:[2,0,3,5,4],queri:3,lian:4,follow:[2,0,3,5],astroml:3,row:3,cython:0,decid:5,simon:4,depend:[0,5],send:[2,4],foster:0,decis:4,under:[0,3],sourc:0,ginsburg:[3,4],util:3,mechan:5,whether:[2,0,3],veri:3,ticket:0,nmcell:3,pypinam:3,level:[3,5],gui:5,henri:4,list:[2,0,3,5,4],ryan:4,"try":3,barbari:4,team:[3,5,4],div:0,pleas:[2,0,3,4],prevent:5,kowalik:4,direct:5,nair:4,sign:0,second:0,pypi_transl:3,download:[0,5],further:5,gustavo:4,victor:4,even:[2,3],url_transl:3,compar:3,han:4,abl:5,uniform:5,current:[0,3,5,1],version:[0,1],axel:4,conduct:2,"new":[2,3,5],ever:5,method:5,ongo:0,widget:3,zach:4,gener:5,never:5,barentsen:4,here:[2,0],leo:4,satisfi:5,layout:5,becom:3,valu:5,madhura:4,convert:3,urlcel:3,jame:4,prasanth:4,chang:[2,0,3],woillez:4,via:[2,5],modul:3,pypicel:3,foundat:2,ask:0,href:3,instal:[0,3,5],should:[0,5],unit:4,plot:3,from:[0,3,5],would:[0,3,5],commun:[2,0,5],conlei:4,regist:3,websit:[2,0],few:[3,5],edward:4,criteria:5,type:3,until:5,oprescu:4,more:[0,5],sort:[0,3],"fr\u00e9d\u00e9ric":4,desir:5,relat:3,templat:5,actual:3,effort:0,must:5,none:3,graphic:3,join:[2,0],scalabl:3,regdiv:3,setup:0,work:[2,0,3,5],dev:[2,0,3,4],xhr:3,archiv:0,can:[2,0,5],learn:3,asciit:0,want:[2,0],give:0,process:5,indic:3,high:3,tab:3,onlin:3,david:4,alwai:5,goal:[3,5],rather:5,anoth:0,write:3,how:[0,5],anyon:2,pure:3,stablecel:3,chri:4,updat:0,map:3,astropi:[0,1,2,3,4,5],dencheva:4,rudi:4,pyfit:0,"20affili":3,befor:[3,5],date:0,data:3,grow:5,insertrow:3,github:[2,0],bind:3,spectra:5,issu:[2,0,3],maintain:3,allow:[0,5],devdoc:0,order:[3,5],talk:0,help:[0,5],astropys:3,over:[2,5],beaumont:4,becaus:[3,5],barrett:4,robitail:[3,4],report:[2,0,3],paper:0,flexibl:3,grollier:4,style:5,fit:[3,5],fix:2,urltext:3,onc:5,mail:[2,0,3,4],main:5,them:5,scipi:5,"return":3,thei:5,python:[2,0,3,5],wolfgang:4,initi:[0,5],framework:5,getelementbyid:3,facilit:[3,5],geert:4,discuss:[0,4],strive:5,choic:[3,5],term:5,home_url:3,alex:4,name:[3,4],anyth:3,drop:3,tstat:3,astronom:[3,5],slide:0,mean:5,zabalza:4,neil:4,citat:0,michael:4,individu:3,idea:2,procedur:5,heavi:3,contributor:4,maintcel:3,significantli:3,populatet:3,logo:0,patch:[2,5],rpocel:3,special:5,out:[3,5],canvas:3,miss:4,astroqueri:3,research:0,daniel:4,"_email_with_name_regex":3,correct:3,hogan:4,shiga:4,benjamin:4,after:2,stable_transl:3,standard:[3,5],standalon:5,reason:3,believ:0,releas:[0,5],org:[0,3],nmarr:3,featur:[0,3],promptli:0,wai:[2,0],could:[0,3,5],keep:5,length:3,outsid:5,adrian:4,getelementsbytagnam:3,think:3,first:[0,3,5],origin:[0,5],softwar:2,major:[0,3],notifi:2,directli:[0,5],christoph:4,demitri:4,arrai:3,independ:5,qualiti:[3,5],number:5,moritz:4,mai:[3,5],instruct:[2,0],alreadi:[2,0,5],done:5,submit:[2,5],stabl:[0,3,5,1],agre:5,open:[0,3,4],differ:[2,5],script:[3,5],interact:3,system:[3,5],wrapper:3,sortord:3,aldcroft:4,tom:4,white:0,tool:[3,5],alan:4,insertcel:3,part:[3,5],exactli:5,technic:0,png:3,"20packag":3,grew:4,whenev:5,provid:[0,3,5],seamlessli:5,tree:5,"g\u00fcnther":4,project:[2,0,3,5,4],reus:3,transport:3,browser:3,analysi:3,viewer:3,thereaft:5,modern:3,ani:[2,0,3,5],packag:[2,0,3,5,4],perri:4,have:[2,0,5,4],tabl:[3,5],need:[3,5],turner:4,"null":3,seek:5,photutil:3,connelli:4,engin:3,lim:4,note:[0,3],also:[0,5],contact:3,take:0,which:[3,5],thoma:[3,4],concern:5,juli:5,singl:[0,5],pontzen:4,simplifi:0,sure:[2,3],unless:5,exec:3,track:5,price:4,who:[2,5],reach:5,most:0,plan:0,phase:5,"class":[0,5],singer:4,don:2,correctli:0,url:3,doc:[0,3],adopt:5,request:[2,3,5,4],bibtex:0,determin:3,latest:[0,1],text:[0,3],maint:3,pkg:3,astrophys:3,fine:3,involv:0,consolid:5,onli:5,locat:5,hanlei:4,activ:[0,5],figur:3,than:5,nadia:4,local:3,conseil:4,contribut:[2,4],get:[2,0],spectroscop:3,express:3,pypi:[3,5],muna:4,cannot:5,increas:5,requir:[0,5],"terr\u00f3n":4,organ:[2,5],pkgnm:3,"public":[0,3],blanton:3,common:5,contain:[3,5],jeschke:3,weaver:4,where:[0,5],vision:[0,5],set:5,julien:4,pynbodi:4,specutil:3,fail:3,maintainer_transl:3,subject:3,awar:0,still:3,shupe:4,databas:3,someth:0,enough:5,stall:5,donath:4,between:[0,5],"import":[0,5],across:[0,5],deil:4,altern:0,kei:5,javascript:3,droettboom:4,entir:5,matplotlib:[3,5],ipython:0,"_email_regex":3,come:0,addit:[0,3,5],both:3,consensu:5,etc:5,present:0,committe:[3,5],pdf:3,brai:4,com:[0,3],clone:0,bell:4,color:3,overview:0,innerhtml:3,taylor:4,guid:0,summar:5,duplic:5,mailto:3,ultim:5,strong:5,chrome:3,numpi:[0,5],mark:3,compon:[0,5],hagen:4,json:3,much:[3,5],interest:[2,3],basic:3,futur:[3,5],wait:5,crawford:4,wish:[0,5],imag:3,andrew:4,mine:3,coordin:[3,5,4],"bragan\u00e7a":4,davi:4,"case":5,interoper:[0,3],look:0,aim:[3,5],whelan:4,abov:0,error:0,everyon:4,ginga:3,cell:3,readi:3,toolkit:5,itself:5,sever:3,around:3,develop:[2,0,3,5,1],welcom:2,credit:4,suggest:0,make:[2,0,3,5],format:3,pkgi:3,complex:5,document:[2,0,3,5,1],pan:3,higher:5,competit:5,http:[0,3],upon:5,capabl:3,jqueri:3,user:[0,3,5],mani:[2,0,5,4],robust:5,implement:5,mosaic:3,recent:0,task:5,center:3,discourag:5,thu:5,kyle:4,exampl:5,command:3,thi:[2,0,3,5,4],undefin:3,everyth:5,ferguson:4,load:3,pywc:0,identifi:5,erben:4,eventu:5,kramer:4,obtain:0,collabor:0,aspect:0,bressert:[3,4],paul:4,web:3,eli:[3,4],easi:5,parikh:4,jeff:4,els:3,transit:5,match:3,build:[0,5],"_email_regex_str":3,quirk:3,read:[0,3],prefer:2,pypi_nam:3,repo_url:3,emma:4,like:[0,3],success:0,eric:3,zoom:3,server:3,benefit:5,api:3,either:[2,5],output:3,page:[2,3,4],jean:4,www:0,photometri:[3,5],acknowledg:0,twitter:0,gmail:3,"v\u00edctor":4,deleterow:3,ncol:3,home:3,librari:[3,5],affili:[2,3,5],kerkwijk:4,montag:3,avoid:5,cut:3,best:0,tracker:[2,0],pei:4,refer:5,machin:3,core:[2,0,3,5,4],encourag:5,power:3,journal:0,pascual:4,repositori:[2,0,3,5,4],hsu:4,regexp:3,sphinx:3,unsaf:3,about:3,central:5,column:3,preclud:5,logo_bann:0,idl:3,integr:[2,5],kerzendorf:4,produc:3,routin:3,own:5,greenfield:4,primarili:5,sergio:4,automat:[0,3],repocel:3,steven:4,ensur:5,your:[2,0,3,4],merg:0,inclus:5,git:0,van:4,val:4,area:5,support:[3,5],question:0,"long":5,avail:[0,5],start:[2,0,5],reli:5,joseph:4,interfac:[3,5],includ:[0,3,5],"var":3,"function":[3,5],head:2,marten:4,roban:4,form:[3,5],some:[3,5],bundl:3,kcorrect:3,continu:5,link:[0,1],grate:0,tollerud:4,line:3,bug:0,pull:[2,5,4],made:[0,5],consist:5,possibl:5,"default":5,crighton:4,access:[3,5],displai:3,below:[0,3,1],miguel:4,those:5,email:4,aplpi:3,later:[0,5],creat:[2,3],dure:5,miruna:4,indeci:3,exist:[3,5],erik:4,file:3,pip:0,improv:3,check:0,titl:0,detail:0,borro:4,other:[2,0,3,5,4],kacper:4,test:[3,5],you:[2,0,3,4],fork:2,intend:5,registri:3,astronomi:[2,0,3,5],matt:4,intens:3,intent:2,consid:[3,5],stai:0,reduc:5,mosaick:3,algorithm:3,svg:[0,3],getjson:3,geometr:3,adam:[3,4],potenti:5,time:[2,0,5],manifesto:5},objtypes:{},titles:["How to start working with Astropy","Astropy Documentation","Contributing to Astropy","About affiliated packages","The Astropy Team","Vision for a Common Astronomy Python Package"],objnames:{},filenames:["index","docs","contributing","affiliated/index","team","vision"]}) \ No newline at end of file From 6310640db59416e09c0262f1b8ca1aca6863794c Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Thu, 19 Sep 2013 16:33:13 -0400 Subject: [PATCH 57/69] Updated page (commit c8b3967ffbc93072949ba068d55984de67c29074 in astropy-website) --- _sources/docs.txt | 3 ++- docs.html | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/_sources/docs.txt b/_sources/docs.txt index e13fd4d3..622560ea 100644 --- a/_sources/docs.txt +++ b/_sources/docs.txt @@ -6,7 +6,8 @@ Astropy Documentation Below are links to the documentation for all versions of Astropy. * `Latest developer version `_ -* `v0.2.3 (Current Stable Version) `_ +* `v0.2.4 (Current Stable Version) `_ +* `v0.2.3 `_ * `v0.2.2 `_ * `v0.2.1 `_ * `v0.2 `_ diff --git a/docs.html b/docs.html index fc8af83f..94a92062 100644 --- a/docs.html +++ b/docs.html @@ -152,7 +152,8 @@

        Astropy DocumentationBelow are links to the documentation for all versions of Astropy.

        • Latest developer version
        • -
        • v0.2.3 (Current Stable Version)
        • +
        • v0.2.4 (Current Stable Version)
        • +
        • v0.2.3
        • v0.2.2
        • v0.2.1
        • v0.2
        • From f5c7093f92fffccb7de0108d0f23635ee39e9b73 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 2 Oct 2013 12:30:12 +0200 Subject: [PATCH 58/69] Updated page (commit fdbdde1530a8ec92f99f218fae68453dab142bae in astropy-website) --- _sources/index.txt | 2 +- index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_sources/index.txt b/_sources/index.txt index fcdce58b..408a6ff4 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -123,7 +123,7 @@ could include the following acknowledgment: for Astronomy (Astropy Collaboration, 2013).* where *(Astropy Collaboration, 2013)* is a citation to `this paper -`_ (`ADS `_ - `BibTeX `_). +`_ (`ADS `_ - `BibTeX `_). If you wish, you can also include a link to ``_ (if the journal allows this) in addition to the above text. diff --git a/index.html b/index.html index a4a8f9c4..6cc5c958 100644 --- a/index.html +++ b/index.html @@ -227,7 +227,7 @@

          Publicationsthis paper (ADS - BibTeX).

          +

          where (Astropy Collaboration, 2013) is a citation to this paper (ADS - BibTeX).

          If you wish, you can also include a link to http://www.astropy.org (if the journal allows this) in addition to the above text.

        From 8111280e3f228f06c5b9d7dd71f66e8f22d1a3ea Mon Sep 17 00:00:00 2001 From: Erik Tollerud Date: Mon, 7 Oct 2013 01:39:09 -0400 Subject: [PATCH 59/69] Updated page (commit 839fd82912a07c7c3ee575783fe0688b97b014db in astropy-website) --- _sources/affiliated/index.txt | 64 +- _static/jquery.js | 9536 ++++++++++++++++++++++++++++++++- _static/searchtools.js | 33 +- _static/underscore.js | 1244 ++++- affiliated/index.html | 60 +- search.html | 2 + searchindex.js | 2 +- 7 files changed, 10734 insertions(+), 207 deletions(-) diff --git a/_sources/affiliated/index.txt b/_sources/affiliated/index.txt index 2177c92e..eaf4f0cc 100644 --- a/_sources/affiliated/index.txt +++ b/_sources/affiliated/index.txt @@ -3,15 +3,17 @@ About affiliated packages ========================= -A major part of the Astropy project is the existence of "Affiliated +A major part of the Astropy project is the concept of "Affiliated Packages". An affiliated package is an astronomy-related Python package that is not part of the astropy core package, but has requested to -be included in the Astropy project. These packages are expressing an -interest in Astropy's goals of improving reuse, interoperability, and -interface standards for python astronomy and astrophysics packages. +be included as part of the Astropy project's community. These packages +are expressing an interest in Astropy's goals of improving reuse, +interoperability, and interface standards for python astronomy and +astrophysics packages. + +If you are developer interested in signing up as an affiliated package, +details are at the end of this page. -If you are the developer of an astronomy package, and would like to become -affiliated with the Astropy project, please drop us a line on the `astropy-dev `_ mailing list! Featured packages ================= @@ -118,12 +120,12 @@ These packages are still very much in development, and the user interface (API) Affiliated Package Registry =========================== -The following table below lists all currently registered affiliated packages. +The following table lists all currently registered affiliated packages. This table is determined from the http://affiliated.astropy.org/registry.json -file that contains the actual registry. The *Stable* column indicates whether -the package maintainer consider the package to be ready for use. Packages that -are under heavy development and for which the user interface is likely to -change significantly in the near future are marked as *No*. +file, which is the authoritative ctual registry. The *Stable* column indicates +whether the package maintainer consider the package to be ready for use. +Packages that are under heavy development and for which the user interface +is likely to change significantly in the near future are marked as *No*. .. The javascript at the bottom does the actual table populating @@ -134,10 +136,44 @@ change significantly in the near future are marked as *No*. +--------------+---------+-----------+----------+-----------------+------------+ -To include your python astronomy package in this registry, contact the -coordination committee by e-mailing `astropy.team@gmail.com -`_. +Becoming an affiliated package +============================== + +If you are the developer of an astronomy package and would like to become +affiliated with the Astropy project, contact the Astropy coordination commitee +by leaving a message on the `astropy-dev `_ +group, or by contacting one of the coordination committee members directly. + +A candiate affilated package will be judged by the coordination committee on the following +standards: + +* It should use `classes and functions from the astropy package `_ + wherever possible and appropriate. This facilitates re-use of code and + sharing of resources. +* The package should have documentation that adequately explains the use of the + package, at standards comparable to `astropy`. Additionally, user-facing + classes and functions should all have docstrings. We suggest using `sphinx`, + with the `numpydoc`-like `docstring standards used by astropy `_, + but this is not a strict requirement as long as the documentation is of + comparable quality. +* The package should make a best-effort to include an easy-to-run test suite + that covers its intended functionality. We realize this is not possible + always possible, but when possible, a test suite is a crucial element of + stable software and reproducible science. +* The package developer(s) should make an effort to connect with the Astropy + developer community, including both relevant parts of the core `astropy` + package and any related affiliated packages. + + +If you are considering creating a new astronomy package and would like it to be +an Astropy affiliated package, we provides a package template to make it much +easier to meet these standards. It provides the necessary structure to +generate documentation like that used in the `astropy` package, a ready-to-use +testing framework, and a variety of tools that streamline tasks like user +configuration, caching downloaded files, or linking C-compiled extensions. More +details on this template are available in the `usage instructions for the +template `_. diff --git a/_static/jquery.js b/_static/jquery.js index 7c243080..981a8a0f 100644 --- a/_static/jquery.js +++ b/_static/jquery.js @@ -1,154 +1,9404 @@ /*! - * jQuery JavaScript Library v1.4.2 + * jQuery JavaScript Library v1.7.2 * http://jquery.com/ * - * Copyright 2010, John Resig + * Copyright 2011, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation + * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * - * Date: Sat Feb 13 22:33:48 2010 -0500 + * Date: Mon Jun 4 13:11:32 UTC 2012 */ -(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
        a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

        ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
        ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
        ","
        "],thead:[1,"","
        "],tr:[2,"","
        "],td:[3,"","
        "],col:[2,"","
        "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
        ","
        "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
        ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
        "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.7.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, pass ) { + var exec, + bulk = key == null, + i = 0, + length = elems.length; + + // Sets many values + if ( key && typeof key === "object" ) { + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); + } + chainable = 1; + + // Sets one value + } else if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = pass === undefined && jQuery.isFunction( value ); + + if ( bulk ) { + // Bulk operations only iterate when executing function values + if ( exec ) { + exec = fn; + fn = function( elem, key, value ) { + return exec.call( jQuery( elem ), value ); + }; + + // Otherwise they run against the entire set + } else { + fn.call( elems, value ); + fn = null; + } + } + + if ( fn ) { + for (; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + } + + chainable = 1; + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + fired = true; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
        a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + pixelMargin: true + }; + + // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead + jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat"); + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for ( i in { + submit: 1, + change: 1, + focusin: 1 + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight, + paddingMarginBorderVisibility, paddingMarginBorder, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + paddingMarginBorder = "padding:0;margin:0;border:"; + positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;"; + paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;"; + style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;"; + html = "
        " + + "" + + "
        "; + + container = document.createElement("div"); + container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "
        t
        "; + tds = div.getElementsByTagName( "td" ); + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( window.getComputedStyle ) { + div.innerHTML = ""; + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.innerHTML = ""; + div.style.width = div.style.padding = "1px"; + div.style.border = 0; + div.style.overflow = "hidden"; + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = "block"; + div.style.overflow = "visible"; + div.innerHTML = "
        "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + } + + div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + if ( window.getComputedStyle ) { + div.style.marginTop = "1%"; + support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%"; + } + + if ( typeof container.style.zoom !== "undefined" ) { + container.style.zoom = 1; + } + + body.removeChild( container ); + marginDiv = div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, part, attr, name, l, + elem = this[0], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attr = elem.attributes; + for ( l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split( ".", 2 ); + parts[1] = parts[1] ? "." + parts[1] : ""; + part = parts[1] + "!"; + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + data = this.triggerHandler( "getData" + part, [ parts[0] ] ); + + // Try to fetch any internally stored data first + if ( data === undefined && elem ) { + data = jQuery.data( elem, key ); + data = dataAttr( elem, key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } + + parts[1] = value; + this.each(function() { + var self = jQuery( this ); + + self.triggerHandler( "setData" + part, parts ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + part, parts ); + }); + }, null, value, arguments.length > 1, null, false ); + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery._data( elem, deferDataKey ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery._data( elem, queueDataKey ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise( object ); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, i, max, option, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, l, isBool, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + isBool = rboolean.test( name ); + + // See #9699 for explanation of this approach (setting first, then removal) + // Do not do this for boolean attributes (see #10870) + if ( !isBool ) { + jQuery.attr( elem, name, "" ); + } + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( isBool && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true, + coords: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = "" + value ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); + + + + +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /(?:^|\s)hover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: selector && quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + special = jQuery.event.special[ event.type ] || {}, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers that should run if there are delegated events + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + + // Don't process events on disabled elements (#6911, #8165) + if ( cur.disabled !== true ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { // && selector != null + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context, seed ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set, seed ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + filter = Expr.filter[ type ]; + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + pass = not ^ found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var first, last, + doneName, parent, cache, + count, diff, + type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Sizzle.attr ? + Sizzle.attr( elem, name ) : + Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + !type && Sizzle.attr ? + result != null : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} +// Expose origPOS +// "global" as in regardless of relation to brackets/parens +Expr.match.globalPOS = origPOS; + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

        "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
        "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context, seed ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.globalPOS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /]", "i"), + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /\/(java|ecma)script/i, + rcleanScript = /^\s*", "" ], + legend: [ 1, "
        ", "
        " ], + thead: [ 1, "", "
        " ], + tr: [ 2, "", "
        " ], + td: [ 3, "", "
        " ], + col: [ 2, "", "
        " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + + +
        +
        +
        + + Fork me on GitHub + +
        + +
        +

        Astropy Feedback (and getting help)

        +

        Astropy is a package for the community, and the developers depend on the +feedback from users to understand how we can improve Astropy.

        +

        There are several ways in which you can give us feedback:

        +
          +
        • If you would like to give us feedback and participate in discussions, we +encourage you to join the astropy mailing list and post +there. This should be the preferred way if you are interested in having a +discussion with the developers and other users.
        • +
        • If you have feedback you would prefer to keep private, you can e-mail +`astropy-feedback@googlegroups.com`_. This address points to a private mailing list that +includes the astropy core developers. If you would like a reply (e.g., an +acknowledgement of your comment), please request it.
        • +
        • For the extremely impatient, astropy developers often hang out in the +#astropy freenode.net IRC channel, which can be accessed for free without +registration from any IRC client (e.g., http://webchat.freenode.net/).
        • +
        • We also welcome code posts as issues (or pull requests) on github and +as posts to the astropy-dev google group.
        • +
        +
        + + +
        +
        +
        +

        Back to top

        +

        + © Copyright 2012, The Astropy Collaboration.
        + Created using Sphinx 1.1.3.
        +

        + +
        +
        + + \ No newline at end of file diff --git a/search.html b/search.html index d47c4f3c..86f04c12 100644 --- a/search.html +++ b/search.html @@ -38,8 +38,6 @@ jQuery(function() { Search.loadIndex("searchindex.js"); }); - - + + - -