diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..18969fbd --- /dev/null +++ b/.gitignore @@ -0,0 +1,56 @@ +# Compiled files +*.py[cod] +*.a +*.o +*.so +__pycache__ + +# Ignore .c files by default to avoid including generated code. If you want to +# add a non-generated .c extension, use `git add -f filename.c`. +*.c + +# Other generated files +*/version.py +*/cython_version.py +htmlcov +.coverage +MANIFEST +.ipynb_checkpoints + +# Sphinx +docs/api +docs/_build + +# Eclipse editor project files +.project +.pydevproject +.settings + +# Pycharm editor project files +.idea + +# Packages/installer info +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg +distribute-*.tar.gz + +# Other +.cache +.tox +.*.sw[op] +*~ +.project +.pydevproject +.settings + +# Mac OSX +.DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..6a20fa6e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "astropy_helpers"] + path = astropy_helpers + url = https://github.com/astropy/astropy-helpers.git diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..70a10b1f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,135 @@ +language: python + +python: + - 2.7 + # - 3.4 + #- 3.5 #TODO fix it + +# Setting sudo to false opts in to Travis-CI container-based builds. +sudo: false + +# The apt packages below are needed for sphinx builds. A full list of packages +# that can be included can be found here: +# +# https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise + +#addons: +# apt: +# packages: +# - graphviz +# - texlive-latex-extra +# - dvipng + +env: + global: + + # The following versions are the 'default' for tests, unless + # overridden underneath. They are defined here in order to save having + # to repeat them for all configurations. + - NUMPY_VERSION=stable + - ASTROPY_VERSION=stable + - SETUP_CMD='test' + - PIP_DEPENDENCIES='cadcutils lxml xml-compare requests enum34 mock coverage' + + # For this package-template, we include examples of Cython modules, + # so Cython is required for testing. If your package does not include + # Cython code, you can set CONDA_DEPENDENCIES='' + - CONDA_DEPENDENCIES='' + + # Conda packages for affiliated packages are hosted in channel + # "astropy" while builds for astropy LTS with recent numpy versions + # are in astropy-ci-extras. If your package uses either of these, + # add the channels to CONDA_CHANNELS along with any other channels + # you want to use. + # - CONDA_CHANNELS='astopy-ci-extras astropy' + + # If there are matplotlib or other GUI tests, uncomment the following + # line to use the X virtual framebuffer. + # - SETUP_XVFB=True + + matrix: + # Make sure that egg_info works without dependencies + - SETUP_CMD='egg_info' + # Try all python versions with the latest numpy + - SETUP_CMD='test' + +matrix: + include: + + # Do a coverage test in Python 2. + - python: 2.7 + env: SETUP_CMD='test --coverage' + + # Check for sphinx doc build warnings - we do this first because it + # may run for a long time + #- python: 2.7 + # env: SETUP_CMD='build_sphinx -w' + + # Try Astropy development version + #- python: 2.7 + # env: ASTROPY_VERSION=development + #- python: 3.5 + # env: ASTROPY_VERSION=development + #- python: 2.7 + # env: ASTROPY_VERSION=lts + #- python: 3.5 + # env: ASTROPY_VERSION=lts + + # Python 3.3 doesn't have numpy 1.10 in conda, but can be put + # back into the main matrix once the numpy build is available in the + # astropy-ci-extras channel (or in the one provided in the + # CONDA_CHANNELS environmental variable). + + #- python: 3.3 + # env: SETUP_CMD='egg_info' + #- python: 3.3 + # env: SETUP_CMD='test' NUMPY_VERSION=1.9 + + # Try older numpy versions + #- python: 2.7 + # env: NUMPY_VERSION=1.10 + #- python: 2.7 + # env: NUMPY_VERSION=1.9 + #- python: 2.7 + # env: NUMPY_VERSION=1.8 + #- python: 2.7 + # env: NUMPY_VERSION=1.7 + + # Try numpy pre-release + #- python: 3.5 + # env: NUMPY_VERSION=prerelease + +install: + + # We now use the ci-helpers package to set up our testing environment. + # This is done by using Miniconda and then using conda and pip to install + # dependencies. Which dependencies are installed using conda and pip is + # determined by the CONDA_DEPENDENCIES and PIP_DEPENDENCIES variables, + # which should be space-delimited lists of package names. See the README + # in https://github.com/astropy/ci-helpers for information about the full + # list of environment variables that can be used to customize your + # environment. In some cases, ci-helpers may not offer enough flexibility + # in how to install a package, in which case you can have additional + # commands in the install: section below. + + - git clone git://github.com/astropy/ci-helpers.git + - source ci-helpers/travis/setup_conda_$TRAVIS_OS_NAME.sh + + # As described above, using ci-helpers, you should be able to set up an + # environment with dependencies installed using conda and pip, but in some + # cases this may not provide enough flexibility in how to install a + # specific dependency (and it will not be able to install non-Python + # dependencies). Therefore, you can also include commands below (as + # well as at the start of the install section or in the before_install + # section if they are needed before setting up conda) to install any + # other dependencies. + +script: + - cd caom2; python setup.py $SETUP_CMD || break -1;cd .. + - cd caom2repo; pip install ../caom2; python setup.py $SETUP_CMD || break -1 + +after_success: + # If coveralls.io is set up for this package, uncomment the line + # below and replace "packagename" with the name of your package. + # The coveragerc file may be customized as needed for your package. + # - if [[ $SETUP_CMD == 'test --coverage' ]]; then coveralls --rcfile='packagename/tests/coveragerc'; fi diff --git a/README.md b/README.md deleted file mode 100644 index ad442c2a..00000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# caom2tools -Common Archive Observation Model - data engineering tools diff --git a/LICENSE b/caom2/LICENSE similarity index 100% rename from LICENSE rename to caom2/LICENSE diff --git a/caom2/MANIFEST.in b/caom2/MANIFEST.in new file mode 100644 index 00000000..c3bf88f0 --- /dev/null +++ b/caom2/MANIFEST.in @@ -0,0 +1,40 @@ +include README.rst +include CHANGES.rst + +include ez_setup.py +include ah_bootstrap.py +include setup.cfg + +recursive-include packagename *.pyx *.c *.pxd +recursive-include docs * +recursive-include licenses * +recursive-include cextern * +recursive-include scripts * + +prune build +prune docs/_build +prune docs/api + + +# the next few stanzas are for astropy_helpers. It's derived from the +# astropy_helpers/MANIFEST.in, but requires additional includes for the actual +# package directory and egg-info. + +include astropy_helpers/README.rst +include astropy_helpers/CHANGES.rst +include astropy_helpers/LICENSE.rst +recursive-include astropy_helpers/licenses * + +include astropy_helpers/ez_setup.py +include astropy_helpers/ah_bootstrap.py + +recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h +recursive-include astropy_helpers/astropy_helpers.egg-info * +# include the sphinx stuff with "*" because there are css/html/rst/etc. +recursive-include astropy_helpers/astropy_helpers/sphinx * + +prune astropy_helpers/build +prune astropy_helpers/astropy_helpers/tests + + +global-exclude *.pyc *.o diff --git a/caom2/README.md b/caom2/README.md new file mode 100644 index 00000000..d3fc044c --- /dev/null +++ b/caom2/README.md @@ -0,0 +1,363 @@ +# caom2tools +Common Archive Observation Model - data engineering tools + +caom2 module + +The caom2 module is a library implementing the Common Archive Observation Model (CAOM-2.2) for manipulating CAOM observations and reading and writing XML documents. + + + + +## To create a minimal Simple Observation +```python + observation = SimpleObservation('collection', 'observationID') + + observation.planes = TypedOrderedDict(Plane) + plane = Plane('productID') + observation.planes['productID'] = plane + + plane.artifacts = TypedOrderedDict(Artifact) + artifact = Artifact('uri:foo/bar', ProductType.SCIENCE, ReleaseType.META) + plane.artifacts['uri:foo/bar'] = artifact + + artifact.parts = TypedOrderedDict(Part) + part = Part('name') + artifact.parts['name'] = part + + part.chunks = TypedList(Chunk) + chunk = Chunk() + part.chunks.append(chunk) + + writer = ObservationWriter() + writer.write(observation, sys.stdout) +``` +```xml + + + collection + observationID + + exposure + + + + productID + + + uri:foo/bar + science + meta + + + name + + + + + + + + + + +``` +## To create a complete SimpleObservation + +```python + observation = SimpleObservation('collection', 'observationID') + observation.obs_type = 'flat' + observation.intent = ObservationIntentType.SCIENCE + observation.meta_release = datetime(2016, 11, 22, 11, 53, 44, 0) + + observation.proposal = Proposal('proposal id') + observation.proposal.pi_name = 'pi name' + observation.proposal.project = 'proposal project' + observation.proposal.title = 'proposal title' + observation.proposal.keywords.update({'proposal', 'key', 'words'}) + + observation.target = Target('target name') + observation.target.target_type = TargetType.OBJECT + observation.target.standard = False + observation.target.redshift = 1.5 + observation.target.keywords.update({'target', 'key', 'words'}) + + point = Point(1.0, 2.0) + observation.target_position = TargetPosition(point, 'coordsys') + observation.target_position.equinox = 3.0 + + observation.telescope = Telescope('telescope name') + observation.telescope.geo_location_x = 1.0 + observation.telescope.geo_location_y = 2.0 + observation.telescope.geo_location_z = 3.0 + observation.telescope.keywords.update({'telescope', 'key', 'words'}) + + observation.instrument = Instrument('instrument name') + observation.instrument.keywords.update({'instrument', 'key', 'words'}) + + observation.env = Environment() + observation.env.seeing = 0.08 + observation.env.humidity = 0.35 + observation.env.elevation = 2.7 + observation.env.tau = 0.7 + observation.env.wavelength_tau = 450e-6 + observation.env.ambient_temp = 20.0 + observation.env.photometric = True + + observation.planes = TypedOrderedDict(Plane) + plane = Plane('productID') + observation.planes['productID'] = plane + + plane.meta_release = datetime(2016, 11, 22, 12, 26, 21, 0) + plane.data_release = datetime(2018, 01, 01, 00, 00, 00, 0) + plane.data_product_type = DataProductType.IMAGE + plane.calibration_level = CalibrationLevel.PRODUCT + + plane.provenance = provenance = Provenance('name') + plane.provenance.version = 'version' + plane.provenance.product = 'product' + plane.provenance.producer = 'producer' + plane.provenance.run_id = 'run_id' + plane.provenance.reference = 'http://foo/bar' + plane.provenance.last_executed = datetime(2016, 11, 22, 12, 28, 16, 0) + plane.provenance.keywords.update({'provenance', 'key', 'words'}) + + plane.metrics = Metrics() + plane.metrics.source_number_density = 1.0 + plane.metrics.background = 2.0 + plane.metrics.background_std_dev = 3.0 + plane.metrics.flux_density_limit = 4.0 + plane.metrics.mag_limit = 5.0 + + plane.artifacts = TypedOrderedDict(Artifact) + artifact = Artifact('uri:foo/bar', ProductType.SCIENCE, ReleaseType.META) + plane.artifacts['uri:foo/bar'] = artifact + + artifact.content_type = 'application/fits' + artifact.content_length = 12345L + + artifact.parts = TypedOrderedDict(Part) + part = Part('name') + artifact.parts['name'] = part + part.product_type = ProductType.SCIENCE + + part.chunks = TypedList(Chunk) + chunk = Chunk() + part.chunks.append(chunk) + + chunk.product_type = ProductType.SCIENCE + chunk.naxis = 5 + chunk.observable_axis = 1 + chunk.position_axis_1 = 1 + chunk.position_axis_2 = 2 + chunk.energy_axis = 3 + chunk.time_axis = 4 + chunk.polarization_axis = 5 + + observable_axis = Slice(Axis('observable_ctype', 'observable_cunit'), 1L) + chunk.observable = ObservableAxis(observable_axis) + + position_axis = CoordAxis2D(Axis('position_ctype_1', 'position_cunit_1'), + Axis('position_ctype_2', 'position_cunit_2')) + chunk.position = SpatialWCS(position_axis) + chunk.position.coordsys = 'position coordsys' + chunk.position.equinox = 2000.0 + chunk.position.resolution = 0.5 + + energy_axis = CoordAxis1D(Axis('energy_ctype', 'energy_cunit')) + chunk.energy = SpectralWCS(energy_axis, 'specsys') + chunk.energy.ssysobs = 'ssysobs' + chunk.energy.ssyssrc = 'ssyssrc' + chunk.energy.restfrq = 1.0 + chunk.energy.restwav = 2.0 + chunk.energy.velosys = 3.0 + chunk.energy.zsource = 4.0 + chunk.energy.velang = 5.0 + chunk.energy.bandpassName = 'bandpass name' + chunk.energy.resolvingPower = 6.0 + chunk.energy.transition = EnergyTransition('H', '21cm') + + time_axis = CoordAxis1D(Axis('time_ctype', 'time_cunit')) + chunk.time = TemporalWCS(time_axis) + chunk.time.exposure = 1.0 + chunk.time.resolution = 2.0 + chunk.time.timesys = 'UTC' + chunk.time.trefpos = 'TOPOCENTER' + chunk.time.mjdref = 3.0 + + polarization_axis = CoordAxis1D(Axis('STOKES')) + polarization_axis.function = CoordFunction1D(4L, 1.0, RefCoord(1.0, 1.0)) + chunk.polarization = PolarizationWCS(polarization_axis) + + writer = ObservationWriter() + writer.write(observation, sys.stdout) +``` +```xml + + + collection + observationID + 2016-11-22T11:53:44.000 + + exposure + + flat + science + + proposal id + pi name + proposal project + proposal title + proposal words key + + + target name + object + false + 1.5 + words key target + + + coordsys + 3.0 + + 1.0 + 2.0 + + + + telescope name + 1.0 + 2.0 + 3.0 + words key telescope + + + instrument name + instrument words key + + + + productID + 2016-11-22T12:26:21.000 + 2018-01-01T00:00:00.000 + image + 3 + + name + version + producer + run_id + http://foo/bar + 2016-11-22T12:28:16.000 + provenance words key + + + 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + + + + uri:foo/bar + science + meta + application/fits + 12345 + + + name + science + + + science + 5 + 1 + 1 + 2 + 3 + 4 + 5 + + + + observable_ctype + observable_cunit + + 1 + + + + + + position_ctype_1 + position_cunit_1 + + + position_ctype_2 + position_cunit_2 + + + position coordsys + 2000.0 + 0.5 + + + + + energy_ctype + energy_cunit + + + specsys + ssysobs + ssyssrc + 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + + H + 21cm + + + + + + time_ctype + time_cunit + + + UTC + TOPOCENTER + 3.0 + 1.0 + 2.0 + + + + + STOKES + + + 4 + 1.0 + + 1.0 + 1.0 + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/caom2/ah_bootstrap.py b/caom2/ah_bootstrap.py new file mode 100644 index 00000000..0dc50071 --- /dev/null +++ b/caom2/ah_bootstrap.py @@ -0,0 +1,987 @@ +""" +This bootstrap module contains code for ensuring that the astropy_helpers +package will be importable by the time the setup.py script runs. It also +includes some workarounds to ensure that a recent-enough version of setuptools +is being used for the installation. + +This module should be the first thing imported in the setup.py of distributions +that make use of the utilities in astropy_helpers. If the distribution ships +with its own copy of astropy_helpers, this module will first attempt to import +from the shipped copy. However, it will also check PyPI to see if there are +any bug-fix releases on top of the current version that may be useful to get +past platform-specific bugs that have been fixed. When running setup.py, use +the ``--offline`` command-line option to disable the auto-upgrade checks. + +When this module is imported or otherwise executed it automatically calls a +main function that attempts to read the project's setup.cfg file, which it +checks for a configuration section called ``[ah_bootstrap]`` the presences of +that section, and options therein, determine the next step taken: If it +contains an option called ``auto_use`` with a value of ``True``, it will +automatically call the main function of this module called +`use_astropy_helpers` (see that function's docstring for full details). +Otherwise no further action is taken (however, +``ah_bootstrap.use_astropy_helpers`` may be called manually from within the +setup.py script). + +Additional options in the ``[ah_boostrap]`` section of setup.cfg have the same +names as the arguments to `use_astropy_helpers`, and can be used to configure +the bootstrap script when ``auto_use = True``. + +See https://github.com/astropy/astropy-helpers for more details, and for the +latest version of this module. +""" + +import contextlib +import errno +import imp +import io +import locale +import os +import re +import subprocess as sp +import sys + +try: + from ConfigParser import ConfigParser, RawConfigParser +except ImportError: + from configparser import ConfigParser, RawConfigParser + + +if sys.version_info[0] < 3: + _str_types = (str, unicode) + _text_type = unicode + PY3 = False +else: + _str_types = (str, bytes) + _text_type = str + PY3 = True + + +# What follows are several import statements meant to deal with install-time +# issues with either missing or misbehaving pacakges (including making sure +# setuptools itself is installed): + + +# Some pre-setuptools checks to ensure that either distribute or setuptools >= +# 0.7 is used (over pre-distribute setuptools) if it is available on the path; +# otherwise the latest setuptools will be downloaded and bootstrapped with +# ``ez_setup.py``. This used to be included in a separate file called +# setuptools_bootstrap.py; but it was combined into ah_bootstrap.py +try: + import pkg_resources + _setuptools_req = pkg_resources.Requirement.parse('setuptools>=0.7') + # This may raise a DistributionNotFound in which case no version of + # setuptools or distribute is properly installed + _setuptools = pkg_resources.get_distribution('setuptools') + if _setuptools not in _setuptools_req: + # Older version of setuptools; check if we have distribute; again if + # this results in DistributionNotFound we want to give up + _distribute = pkg_resources.get_distribution('distribute') + if _setuptools != _distribute: + # It's possible on some pathological systems to have an old version + # of setuptools and distribute on sys.path simultaneously; make + # sure distribute is the one that's used + sys.path.insert(1, _distribute.location) + _distribute.activate() + imp.reload(pkg_resources) +except: + # There are several types of exceptions that can occur here; if all else + # fails bootstrap and use the bootstrapped version + from ez_setup import use_setuptools + use_setuptools() + + +# Note: The following import is required as a workaround to +# https://github.com/astropy/astropy-helpers/issues/89; if we don't import this +# module now, it will get cleaned up after `run_setup` is called, but that will +# later cause the TemporaryDirectory class defined in it to stop working when +# used later on by setuptools +try: + import setuptools.py31compat +except ImportError: + pass + + +# matplotlib can cause problems if it is imported from within a call of +# run_setup(), because in some circumstances it will try to write to the user's +# home directory, resulting in a SandboxViolation. See +# https://github.com/matplotlib/matplotlib/pull/4165 +# Making sure matplotlib, if it is available, is imported early in the setup +# process can mitigate this (note importing matplotlib.pyplot has the same +# issue) +try: + import matplotlib + matplotlib.use('Agg') + import matplotlib.pyplot +except: + # Ignore if this fails for *any* reason* + pass + + +# End compatibility imports... + + +# In case it didn't successfully import before the ez_setup checks +import pkg_resources + +from setuptools import Distribution +from setuptools.package_index import PackageIndex +from setuptools.sandbox import run_setup + +from distutils import log +from distutils.debug import DEBUG + + +# TODO: Maybe enable checking for a specific version of astropy_helpers? +DIST_NAME = 'astropy-helpers' +PACKAGE_NAME = 'astropy_helpers' + +# Defaults for other options +DOWNLOAD_IF_NEEDED = True +INDEX_URL = 'https://pypi.python.org/simple' +USE_GIT = True +OFFLINE = False +AUTO_UPGRADE = True + +# A list of all the configuration options and their required types +CFG_OPTIONS = [ + ('auto_use', bool), ('path', str), ('download_if_needed', bool), + ('index_url', str), ('use_git', bool), ('offline', bool), + ('auto_upgrade', bool) +] + + +class _Bootstrapper(object): + """ + Bootstrapper implementation. See ``use_astropy_helpers`` for parameter + documentation. + """ + + def __init__(self, path=None, index_url=None, use_git=None, offline=None, + download_if_needed=None, auto_upgrade=None): + + if path is None: + path = PACKAGE_NAME + + if not (isinstance(path, _str_types) or path is False): + raise TypeError('path must be a string or False') + + if PY3 and not isinstance(path, _text_type): + fs_encoding = sys.getfilesystemencoding() + path = path.decode(fs_encoding) # path to unicode + + self.path = path + + # Set other option attributes, using defaults where necessary + self.index_url = index_url if index_url is not None else INDEX_URL + self.offline = offline if offline is not None else OFFLINE + + # If offline=True, override download and auto-upgrade + if self.offline: + download_if_needed = False + auto_upgrade = False + + self.download = (download_if_needed + if download_if_needed is not None + else DOWNLOAD_IF_NEEDED) + self.auto_upgrade = (auto_upgrade + if auto_upgrade is not None else AUTO_UPGRADE) + + # If this is a release then the .git directory will not exist so we + # should not use git. + git_dir_exists = os.path.exists(os.path.join(os.path.dirname(__file__), '.git')) + if use_git is None and not git_dir_exists: + use_git = False + + self.use_git = use_git if use_git is not None else USE_GIT + # Declared as False by default--later we check if astropy-helpers can be + # upgraded from PyPI, but only if not using a source distribution (as in + # the case of import from a git submodule) + self.is_submodule = False + + @classmethod + def main(cls, argv=None): + if argv is None: + argv = sys.argv + + config = cls.parse_config() + config.update(cls.parse_command_line(argv)) + + auto_use = config.pop('auto_use', False) + bootstrapper = cls(**config) + + if auto_use: + # Run the bootstrapper, otherwise the setup.py is using the old + # use_astropy_helpers() interface, in which case it will run the + # bootstrapper manually after reconfiguring it. + bootstrapper.run() + + return bootstrapper + + @classmethod + def parse_config(cls): + if not os.path.exists('setup.cfg'): + return {} + + cfg = ConfigParser() + + try: + cfg.read('setup.cfg') + except Exception as e: + if DEBUG: + raise + + log.error( + "Error reading setup.cfg: {0!r}\n{1} will not be " + "automatically bootstrapped and package installation may fail." + "\n{2}".format(e, PACKAGE_NAME, _err_help_msg)) + return {} + + if not cfg.has_section('ah_bootstrap'): + return {} + + config = {} + + for option, type_ in CFG_OPTIONS: + if not cfg.has_option('ah_bootstrap', option): + continue + + if type_ is bool: + value = cfg.getboolean('ah_bootstrap', option) + else: + value = cfg.get('ah_bootstrap', option) + + config[option] = value + + return config + + @classmethod + def parse_command_line(cls, argv=None): + if argv is None: + argv = sys.argv + + config = {} + + # For now we just pop recognized ah_bootstrap options out of the + # arg list. This is imperfect; in the unlikely case that a setup.py + # custom command or even custom Distribution class defines an argument + # of the same name then we will break that. However there's a catch22 + # here that we can't just do full argument parsing right here, because + # we don't yet know *how* to parse all possible command-line arguments. + if '--no-git' in argv: + config['use_git'] = False + argv.remove('--no-git') + + if '--offline' in argv: + config['offline'] = True + argv.remove('--offline') + + return config + + def run(self): + strategies = ['local_directory', 'local_file', 'index'] + dist = None + + # First, remove any previously imported versions of astropy_helpers; + # this is necessary for nested installs where one package's installer + # is installing another package via setuptools.sandbox.run_setup, as in + # the case of setup_requires + for key in list(sys.modules): + try: + if key == PACKAGE_NAME or key.startswith(PACKAGE_NAME + '.'): + del sys.modules[key] + except AttributeError: + # Sometimes mysterious non-string things can turn up in + # sys.modules + continue + + # Check to see if the path is a submodule + self.is_submodule = self._check_submodule() + + for strategy in strategies: + method = getattr(self, 'get_{0}_dist'.format(strategy)) + dist = method() + if dist is not None: + break + else: + raise _AHBootstrapSystemExit( + "No source found for the {0!r} package; {0} must be " + "available and importable as a prerequisite to building " + "or installing this package.".format(PACKAGE_NAME)) + + # This is a bit hacky, but if astropy_helpers was loaded from a + # directory/submodule its Distribution object gets a "precedence" of + # "DEVELOP_DIST". However, in other cases it gets a precedence of + # "EGG_DIST". However, when activing the distribution it will only be + # placed early on sys.path if it is treated as an EGG_DIST, so always + # do that + dist = dist.clone(precedence=pkg_resources.EGG_DIST) + + # Otherwise we found a version of astropy-helpers, so we're done + # Just active the found distribution on sys.path--if we did a + # download this usually happens automatically but it doesn't hurt to + # do it again + # Note: Adding the dist to the global working set also activates it + # (makes it importable on sys.path) by default. + + try: + pkg_resources.working_set.add(dist, replace=True) + except TypeError: + # Some (much) older versions of setuptools do not have the + # replace=True option here. These versions are old enough that all + # bets may be off anyways, but it's easy enough to work around just + # in case... + if dist.key in pkg_resources.working_set.by_key: + del pkg_resources.working_set.by_key[dist.key] + pkg_resources.working_set.add(dist) + + @property + def config(self): + """ + A `dict` containing the options this `_Bootstrapper` was configured + with. + """ + + return dict((optname, getattr(self, optname)) + for optname, _ in CFG_OPTIONS if hasattr(self, optname)) + + def get_local_directory_dist(self): + """ + Handle importing a vendored package from a subdirectory of the source + distribution. + """ + + if not os.path.isdir(self.path): + return + + log.info('Attempting to import astropy_helpers from {0} {1!r}'.format( + 'submodule' if self.is_submodule else 'directory', + self.path)) + + dist = self._directory_import() + + if dist is None: + log.warn( + 'The requested path {0!r} for importing {1} does not ' + 'exist, or does not contain a copy of the {1} ' + 'package.'.format(self.path, PACKAGE_NAME)) + elif self.auto_upgrade and not self.is_submodule: + # A version of astropy-helpers was found on the available path, but + # check to see if a bugfix release is available on PyPI + upgrade = self._do_upgrade(dist) + if upgrade is not None: + dist = upgrade + + return dist + + def get_local_file_dist(self): + """ + Handle importing from a source archive; this also uses setup_requires + but points easy_install directly to the source archive. + """ + + if not os.path.isfile(self.path): + return + + log.info('Attempting to unpack and import astropy_helpers from ' + '{0!r}'.format(self.path)) + + try: + dist = self._do_download(find_links=[self.path]) + except Exception as e: + if DEBUG: + raise + + log.warn( + 'Failed to import {0} from the specified archive {1!r}: ' + '{2}'.format(PACKAGE_NAME, self.path, str(e))) + dist = None + + if dist is not None and self.auto_upgrade: + # A version of astropy-helpers was found on the available path, but + # check to see if a bugfix release is available on PyPI + upgrade = self._do_upgrade(dist) + if upgrade is not None: + dist = upgrade + + return dist + + def get_index_dist(self): + if not self.download: + log.warn('Downloading {0!r} disabled.'.format(DIST_NAME)) + return None + + log.warn( + "Downloading {0!r}; run setup.py with the --offline option to " + "force offline installation.".format(DIST_NAME)) + + try: + dist = self._do_download() + except Exception as e: + if DEBUG: + raise + log.warn( + 'Failed to download and/or install {0!r} from {1!r}:\n' + '{2}'.format(DIST_NAME, self.index_url, str(e))) + dist = None + + # No need to run auto-upgrade here since we've already presumably + # gotten the most up-to-date version from the package index + return dist + + def _directory_import(self): + """ + Import astropy_helpers from the given path, which will be added to + sys.path. + + Must return True if the import succeeded, and False otherwise. + """ + + # Return True on success, False on failure but download is allowed, and + # otherwise raise SystemExit + path = os.path.abspath(self.path) + + # Use an empty WorkingSet rather than the man + # pkg_resources.working_set, since on older versions of setuptools this + # will invoke a VersionConflict when trying to install an upgrade + ws = pkg_resources.WorkingSet([]) + ws.add_entry(path) + dist = ws.by_key.get(DIST_NAME) + + if dist is None: + # We didn't find an egg-info/dist-info in the given path, but if a + # setup.py exists we can generate it + setup_py = os.path.join(path, 'setup.py') + if os.path.isfile(setup_py): + with _silence(): + run_setup(os.path.join(path, 'setup.py'), + ['egg_info']) + + for dist in pkg_resources.find_distributions(path, True): + # There should be only one... + return dist + + return dist + + def _do_download(self, version='', find_links=None): + if find_links: + allow_hosts = '' + index_url = None + else: + allow_hosts = None + index_url = self.index_url + + # Annoyingly, setuptools will not handle other arguments to + # Distribution (such as options) before handling setup_requires, so it + # is not straightforward to programmatically augment the arguments which + # are passed to easy_install + class _Distribution(Distribution): + def get_option_dict(self, command_name): + opts = Distribution.get_option_dict(self, command_name) + if command_name == 'easy_install': + if find_links is not None: + opts['find_links'] = ('setup script', find_links) + if index_url is not None: + opts['index_url'] = ('setup script', index_url) + if allow_hosts is not None: + opts['allow_hosts'] = ('setup script', allow_hosts) + return opts + + if version: + req = '{0}=={1}'.format(DIST_NAME, version) + else: + req = DIST_NAME + + attrs = {'setup_requires': [req]} + + try: + if DEBUG: + _Distribution(attrs=attrs) + else: + with _silence(): + _Distribution(attrs=attrs) + + # If the setup_requires succeeded it will have added the new dist to + # the main working_set + return pkg_resources.working_set.by_key.get(DIST_NAME) + except Exception as e: + if DEBUG: + raise + + msg = 'Error retrieving {0} from {1}:\n{2}' + if find_links: + source = find_links[0] + elif index_url != INDEX_URL: + source = index_url + else: + source = 'PyPI' + + raise Exception(msg.format(DIST_NAME, source, repr(e))) + + def _do_upgrade(self, dist): + # Build up a requirement for a higher bugfix release but a lower minor + # release (so API compatibility is guaranteed) + next_version = _next_version(dist.parsed_version) + + req = pkg_resources.Requirement.parse( + '{0}>{1},<{2}'.format(DIST_NAME, dist.version, next_version)) + + package_index = PackageIndex(index_url=self.index_url) + + upgrade = package_index.obtain(req) + + if upgrade is not None: + return self._do_download(version=upgrade.version) + + def _check_submodule(self): + """ + Check if the given path is a git submodule. + + See the docstrings for ``_check_submodule_using_git`` and + ``_check_submodule_no_git`` for further details. + """ + + if (self.path is None or + (os.path.exists(self.path) and not os.path.isdir(self.path))): + return False + + if self.use_git: + return self._check_submodule_using_git() + else: + return self._check_submodule_no_git() + + def _check_submodule_using_git(self): + """ + Check if the given path is a git submodule. If so, attempt to initialize + and/or update the submodule if needed. + + This function makes calls to the ``git`` command in subprocesses. The + ``_check_submodule_no_git`` option uses pure Python to check if the given + path looks like a git submodule, but it cannot perform updates. + """ + + cmd = ['git', 'submodule', 'status', '--', self.path] + + try: + log.info('Running `{0}`; use the --no-git option to disable git ' + 'commands'.format(' '.join(cmd))) + returncode, stdout, stderr = run_cmd(cmd) + except _CommandNotFound: + # The git command simply wasn't found; this is most likely the + # case on user systems that don't have git and are simply + # trying to install the package from PyPI or a source + # distribution. Silently ignore this case and simply don't try + # to use submodules + return False + + stderr = stderr.strip() + + if returncode != 0 and stderr: + # Unfortunately the return code alone cannot be relied on, as + # earlier versions of git returned 0 even if the requested submodule + # does not exist + + # This is a warning that occurs in perl (from running git submodule) + # which only occurs with a malformatted locale setting which can + # happen sometimes on OSX. See again + # https://github.com/astropy/astropy/issues/2749 + perl_warning = ('perl: warning: Falling back to the standard locale ' + '("C").') + if not stderr.strip().endswith(perl_warning): + # Some other unknown error condition occurred + log.warn('git submodule command failed ' + 'unexpectedly:\n{0}'.format(stderr)) + return False + + # Output of `git submodule status` is as follows: + # + # 1: Status indicator: '-' for submodule is uninitialized, '+' if + # submodule is initialized but is not at the commit currently indicated + # in .gitmodules (and thus needs to be updated), or 'U' if the + # submodule is in an unstable state (i.e. has merge conflicts) + # + # 2. SHA-1 hash of the current commit of the submodule (we don't really + # need this information but it's useful for checking that the output is + # correct) + # + # 3. The output of `git describe` for the submodule's current commit + # hash (this includes for example what branches the commit is on) but + # only if the submodule is initialized. We ignore this information for + # now + _git_submodule_status_re = re.compile( + '^(?P[+-U ])(?P[0-9a-f]{40}) ' + '(?P\S+)( .*)?$') + + # The stdout should only contain one line--the status of the + # requested submodule + m = _git_submodule_status_re.match(stdout) + if m: + # Yes, the path *is* a git submodule + self._update_submodule(m.group('submodule'), m.group('status')) + return True + else: + log.warn( + 'Unexpected output from `git submodule status`:\n{0}\n' + 'Will attempt import from {1!r} regardless.'.format( + stdout, self.path)) + return False + + def _check_submodule_no_git(self): + """ + Like ``_check_submodule_using_git``, but simply parses the .gitmodules file + to determine if the supplied path is a git submodule, and does not exec any + subprocesses. + + This can only determine if a path is a submodule--it does not perform + updates, etc. This function may need to be updated if the format of the + .gitmodules file is changed between git versions. + """ + + gitmodules_path = os.path.abspath('.gitmodules') + + if not os.path.isfile(gitmodules_path): + return False + + # This is a minimal reader for gitconfig-style files. It handles a few of + # the quirks that make gitconfig files incompatible with ConfigParser-style + # files, but does not support the full gitconfig syntax (just enough + # needed to read a .gitmodules file). + gitmodules_fileobj = io.StringIO() + + # Must use io.open for cross-Python-compatible behavior wrt unicode + with io.open(gitmodules_path) as f: + for line in f: + # gitconfig files are more flexible with leading whitespace; just + # go ahead and remove it + line = line.lstrip() + + # comments can start with either # or ; + if line and line[0] in (':', ';'): + continue + + gitmodules_fileobj.write(line) + + gitmodules_fileobj.seek(0) + + cfg = RawConfigParser() + + try: + cfg.readfp(gitmodules_fileobj) + except Exception as exc: + log.warn('Malformatted .gitmodules file: {0}\n' + '{1} cannot be assumed to be a git submodule.'.format( + exc, self.path)) + return False + + for section in cfg.sections(): + if not cfg.has_option(section, 'path'): + continue + + submodule_path = cfg.get(section, 'path').rstrip(os.sep) + + if submodule_path == self.path.rstrip(os.sep): + return True + + return False + + def _update_submodule(self, submodule, status): + if status == ' ': + # The submodule is up to date; no action necessary + return + elif status == '-': + if self.offline: + raise _AHBootstrapSystemExit( + "Cannot initialize the {0} submodule in --offline mode; " + "this requires being able to clone the submodule from an " + "online repository.".format(submodule)) + cmd = ['update', '--init'] + action = 'Initializing' + elif status == '+': + cmd = ['update'] + action = 'Updating' + if self.offline: + cmd.append('--no-fetch') + elif status == 'U': + raise _AHBoostrapSystemExit( + 'Error: Submodule {0} contains unresolved merge conflicts. ' + 'Please complete or abandon any changes in the submodule so that ' + 'it is in a usable state, then try again.'.format(submodule)) + else: + log.warn('Unknown status {0!r} for git submodule {1!r}. Will ' + 'attempt to use the submodule as-is, but try to ensure ' + 'that the submodule is in a clean state and contains no ' + 'conflicts or errors.\n{2}'.format(status, submodule, + _err_help_msg)) + return + + err_msg = None + cmd = ['git', 'submodule'] + cmd + ['--', submodule] + log.warn('{0} {1} submodule with: `{2}`'.format( + action, submodule, ' '.join(cmd))) + + try: + log.info('Running `{0}`; use the --no-git option to disable git ' + 'commands'.format(' '.join(cmd))) + returncode, stdout, stderr = run_cmd(cmd) + except OSError as e: + err_msg = str(e) + else: + if returncode != 0: + err_msg = stderr + + if err_msg is not None: + log.warn('An unexpected error occurred updating the git submodule ' + '{0!r}:\n{1}\n{2}'.format(submodule, err_msg, + _err_help_msg)) + +class _CommandNotFound(OSError): + """ + An exception raised when a command run with run_cmd is not found on the + system. + """ + + +def run_cmd(cmd): + """ + Run a command in a subprocess, given as a list of command-line + arguments. + + Returns a ``(returncode, stdout, stderr)`` tuple. + """ + + try: + p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) + # XXX: May block if either stdout or stderr fill their buffers; + # however for the commands this is currently used for that is + # unlikely (they should have very brief output) + stdout, stderr = p.communicate() + except OSError as e: + if DEBUG: + raise + + if e.errno == errno.ENOENT: + msg = 'Command not found: `{0}`'.format(' '.join(cmd)) + raise _CommandNotFound(msg, cmd) + else: + raise _AHBoostrapSystemExit( + 'An unexpected error occurred when running the ' + '`{0}` command:\n{1}'.format(' '.join(cmd), str(e))) + + + # Can fail of the default locale is not configured properly. See + # https://github.com/astropy/astropy/issues/2749. For the purposes under + # consideration 'latin1' is an acceptable fallback. + try: + stdio_encoding = locale.getdefaultlocale()[1] or 'latin1' + except ValueError: + # Due to an OSX oddity locale.getdefaultlocale() can also crash + # depending on the user's locale/language settings. See: + # http://bugs.python.org/issue18378 + stdio_encoding = 'latin1' + + # Unlikely to fail at this point but even then let's be flexible + if not isinstance(stdout, _text_type): + stdout = stdout.decode(stdio_encoding, 'replace') + if not isinstance(stderr, _text_type): + stderr = stderr.decode(stdio_encoding, 'replace') + + return (p.returncode, stdout, stderr) + + +def _next_version(version): + """ + Given a parsed version from pkg_resources.parse_version, returns a new + version string with the next minor version. + + Examples + ======== + >>> _next_version(pkg_resources.parse_version('1.2.3')) + '1.3.0' + """ + + if hasattr(version, 'base_version'): + # New version parsing from setuptools >= 8.0 + if version.base_version: + parts = version.base_version.split('.') + else: + parts = [] + else: + parts = [] + for part in version: + if part.startswith('*'): + break + parts.append(part) + + parts = [int(p) for p in parts] + + if len(parts) < 3: + parts += [0] * (3 - len(parts)) + + major, minor, micro = parts[:3] + + return '{0}.{1}.{2}'.format(major, minor + 1, 0) + + +class _DummyFile(object): + """A noop writeable object.""" + + errors = '' # Required for Python 3.x + encoding = 'utf-8' + + def write(self, s): + pass + + def flush(self): + pass + + +@contextlib.contextmanager +def _silence(): + """A context manager that silences sys.stdout and sys.stderr.""" + + old_stdout = sys.stdout + old_stderr = sys.stderr + sys.stdout = _DummyFile() + sys.stderr = _DummyFile() + exception_occurred = False + try: + yield + except: + exception_occurred = True + # Go ahead and clean up so that exception handling can work normally + sys.stdout = old_stdout + sys.stderr = old_stderr + raise + + if not exception_occurred: + sys.stdout = old_stdout + sys.stderr = old_stderr + + +_err_help_msg = """ +If the problem persists consider installing astropy_helpers manually using pip +(`pip install astropy_helpers`) or by manually downloading the source archive, +extracting it, and installing by running `python setup.py install` from the +root of the extracted source code. +""" + + +class _AHBootstrapSystemExit(SystemExit): + def __init__(self, *args): + if not args: + msg = 'An unknown problem occurred bootstrapping astropy_helpers.' + else: + msg = args[0] + + msg += '\n' + _err_help_msg + + super(_AHBootstrapSystemExit, self).__init__(msg, *args[1:]) + + +if sys.version_info[:2] < (2, 7): + # In Python 2.6 the distutils log does not log warnings, errors, etc. to + # stderr so we have to wrap it to ensure consistency at least in this + # module + import distutils + + class log(object): + def __getattr__(self, attr): + return getattr(distutils.log, attr) + + def warn(self, msg, *args): + self._log_to_stderr(distutils.log.WARN, msg, *args) + + def error(self, msg): + self._log_to_stderr(distutils.log.ERROR, msg, *args) + + def fatal(self, msg): + self._log_to_stderr(distutils.log.FATAL, msg, *args) + + def log(self, level, msg, *args): + if level in (distutils.log.WARN, distutils.log.ERROR, + distutils.log.FATAL): + self._log_to_stderr(level, msg, *args) + else: + distutils.log.log(level, msg, *args) + + def _log_to_stderr(self, level, msg, *args): + # This is the only truly 'public' way to get the current threshold + # of the log + current_threshold = distutils.log.set_threshold(distutils.log.WARN) + distutils.log.set_threshold(current_threshold) + if level >= current_threshold: + if args: + msg = msg % args + sys.stderr.write('%s\n' % msg) + sys.stderr.flush() + + log = log() + + +BOOTSTRAPPER = _Bootstrapper.main() + + +def use_astropy_helpers(**kwargs): + """ + Ensure that the `astropy_helpers` module is available and is importable. + This supports automatic submodule initialization if astropy_helpers is + included in a project as a git submodule, or will download it from PyPI if + necessary. + + Parameters + ---------- + + path : str or None, optional + A filesystem path relative to the root of the project's source code + that should be added to `sys.path` so that `astropy_helpers` can be + imported from that path. + + If the path is a git submodule it will automatically be initialized + and/or updated. + + The path may also be to a ``.tar.gz`` archive of the astropy_helpers + source distribution. In this case the archive is automatically + unpacked and made temporarily available on `sys.path` as a ``.egg`` + archive. + + If `None` skip straight to downloading. + + download_if_needed : bool, optional + If the provided filesystem path is not found an attempt will be made to + download astropy_helpers from PyPI. It will then be made temporarily + available on `sys.path` as a ``.egg`` archive (using the + ``setup_requires`` feature of setuptools. If the ``--offline`` option + is given at the command line the value of this argument is overridden + to `False`. + + index_url : str, optional + If provided, use a different URL for the Python package index than the + main PyPI server. + + use_git : bool, optional + If `False` no git commands will be used--this effectively disables + support for git submodules. If the ``--no-git`` option is given at the + command line the value of this argument is overridden to `False`. + + auto_upgrade : bool, optional + By default, when installing a package from a non-development source + distribution ah_boostrap will try to automatically check for patch + releases to astropy-helpers on PyPI and use the patched version over + any bundled versions. Setting this to `False` will disable that + functionality. If the ``--offline`` option is given at the command line + the value of this argument is overridden to `False`. + + offline : bool, optional + If `False` disable all actions that require an internet connection, + including downloading packages from the package index and fetching + updates to any git submodule. Defaults to `True`. + """ + + global BOOTSTRAPPER + + config = BOOTSTRAPPER.config + config.update(**kwargs) + + # Create a new bootstrapper with the updated configuration and run it + BOOTSTRAPPER = _Bootstrapper(**config) + BOOTSTRAPPER.run() diff --git a/pyCAOM2/caom2/xml/caom2_xml_constants.py b/caom2/caom2/__init__.py similarity index 78% rename from pyCAOM2/caom2/xml/caom2_xml_constants.py rename to caom2/caom2/__init__.py index abb4b282..a4912145 100644 --- a/pyCAOM2/caom2/xml/caom2_xml_constants.py +++ b/caom2/caom2/__init__.py @@ -1,8 +1,8 @@ # # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,22 +65,30 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # -CAOM2_PKG = 'caom2' +# Licensed under a 3-clause BSD style license - see LICENSE.rst -CAOM20_SCHEMA_FILE = 'CAOM-2.0.xsd' -CAOM21_SCHEMA_FILE = 'CAOM-2.1.xsd' -CAOM22_SCHEMA_FILE = 'CAOM-2.2.xsd' +""" +This is an Astropy affiliated package. +""" -CAOM20_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.0' -CAOM21_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.1' -CAOM22_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.2' +# Affiliated packages may add whatever they like to this file, but +# should keep this content at the top. +# ---------------------------------------------------------------------------- +from ._astropy_init import * +# ---------------------------------------------------------------------------- -CAOM20 = "{%s}" % CAOM20_NAMESPACE -CAOM21 = "{%s}" % CAOM21_NAMESPACE -CAOM22 = "{%s}" % CAOM22_NAMESPACE - -XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance" -XSI = "{%s}" % XSI_NAMESPACE \ No newline at end of file +# For egg_info test builds to pass, put package imports here. +if not _ASTROPY_SETUP_: + from caom_util import * + from common import * + from wcs import * + from shape import * + from chunk import * + from part import * + from artifact import * + from plane import * + from observation import * + from obs_reader_writer import * diff --git a/caom2/caom2/_astropy_init.py b/caom2/caom2/_astropy_init.py new file mode 100644 index 00000000..6d94a38b --- /dev/null +++ b/caom2/caom2/_astropy_init.py @@ -0,0 +1,138 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +__all__ = ['__version__', '__githash__', 'test'] + +# this indicates whether or not we are in the package's setup.py +try: + _ASTROPY_SETUP_ +except NameError: + from sys import version_info + if version_info[0] >= 3: + import builtins + else: + import __builtin__ as builtins + builtins._ASTROPY_SETUP_ = False + +try: + from .version import version as __version__ +except ImportError: + __version__ = '' +try: + from .version import githash as __githash__ +except ImportError: + __githash__ = '' + +# set up the test command +def _get_test_runner(): + import os + from astropy.tests.helper import TestRunner + return TestRunner(os.path.dirname(__file__)) + +def test(package=None, test_path=None, args=None, plugins=None, + verbose=False, pastebin=None, remote_data=False, pep8=False, + pdb=False, coverage=False, open_files=False, **kwargs): + """ + Run the tests using `py.test `__. A proper set + of arguments is constructed and passed to `pytest.main`_. + + .. _py.test: http://pytest.org/latest/ + .. _pytest.main: http://pytest.org/latest/builtin.html#pytest.main + + Parameters + ---------- + package : str, optional + The name of a specific package to test, e.g. 'io.fits' or 'utils'. + If nothing is specified all default tests are run. + + test_path : str, optional + Specify location to test by path. May be a single file or + directory. Must be specified absolutely or relative to the + calling directory. + + args : str, optional + Additional arguments to be passed to pytest.main_ in the ``args`` + keyword argument. + + plugins : list, optional + Plugins to be passed to pytest.main_ in the ``plugins`` keyword + argument. + + verbose : bool, optional + Convenience option to turn on verbose output from py.test_. Passing + True is the same as specifying ``'-v'`` in ``args``. + + pastebin : {'failed','all',None}, optional + Convenience option for turning on py.test_ pastebin output. Set to + ``'failed'`` to upload info for failed tests, or ``'all'`` to upload + info for all tests. + + remote_data : bool, optional + Controls whether to run tests marked with @remote_data. These + tests use online data and are not run by default. Set to True to + run these tests. + + pep8 : bool, optional + Turn on PEP8 checking via the `pytest-pep8 plugin + `_ and disable normal + tests. Same as specifying ``'--pep8 -k pep8'`` in ``args``. + + pdb : bool, optional + Turn on PDB post-mortem analysis for failing tests. Same as + specifying ``'--pdb'`` in ``args``. + + coverage : bool, optional + Generate a test coverage report. The result will be placed in + the directory htmlcov. + + open_files : bool, optional + Fail when any tests leave files open. Off by default, because + this adds extra run time to the test suite. Requires the + `psutil `_ package. + + parallel : int, optional + When provided, run the tests in parallel on the specified + number of CPUs. If parallel is negative, it will use the all + the cores on the machine. Requires the + `pytest-xdist `_ plugin + installed. Only available when using Astropy 0.3 or later. + + kwargs + Any additional keywords passed into this function will be passed + on to the astropy test runner. This allows use of test-related + functionality implemented in later versions of astropy without + explicitly updating the package template. + + """ + test_runner = _get_test_runner() + return test_runner.run_tests( + package=package, test_path=test_path, args=args, + plugins=plugins, verbose=verbose, pastebin=pastebin, + remote_data=remote_data, pep8=pep8, pdb=pdb, + coverage=coverage, open_files=open_files, **kwargs) + +if not _ASTROPY_SETUP_: + import os + from warnings import warn + from astropy import config + + # add these here so we only need to cleanup the namespace at the end + config_dir = None + + if not os.environ.get('ASTROPY_SKIP_CONFIG_UPDATE', False): + config_dir = os.path.dirname(__file__) + config_template = os.path.join(config_dir, __package__ + ".cfg") + if os.path.isfile(config_template): + try: + config.configuration.update_default_config( + __package__, config_dir, version=__version__) + except TypeError as orig_error: + try: + config.configuration.update_default_config( + __package__, config_dir) + except config.configuration.ConfigurationDefaultMissingError as e: + wmsg = (e.args[0] + " Cannot install default profile. If you are " + "importing from source, this is expected.") + warn(config.configuration.ConfigurationDefaultMissingWarning(wmsg)) + del e + except: + raise orig_error diff --git a/pyCAOM2/caom2/caom2_artifact.py b/caom2/caom2/artifact.py similarity index 82% rename from pyCAOM2/caom2/caom2_artifact.py rename to caom2/caom2/artifact.py index 94773df6..446654fe 100644 --- a/pyCAOM2/caom2/caom2_artifact.py +++ b/caom2/caom2/artifact.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,23 +64,38 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """Defines the caom2.Artifact class. """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + from urlparse import urlparse -import util.caom2_util as util -from caom2_entity import AbstractCaom2Entity -from caom2_enums import ProductType, ReleaseType -from caom2_part import Part -from util.caom2_util import TypedOrderedDict +from enum import Enum + +from . import caom_util +from .chunk import ProductType +from .common import AbstractCaomEntity +from .part import Part + +__all__ = ['ReleaseType', 'Artifact'] + + +class ReleaseType(Enum): + """" + DATA: "data" + META: "meta" + """ + DATA = "data" + META = "meta" -class Artifact(AbstractCaom2Entity): +class Artifact(AbstractCaomEntity): """Contains the meta data assocaited with a file. - location of the file (uri) @@ -117,11 +131,11 @@ def __init__(self, self.content_type = content_type self.content_length = content_length if parts is None: - parts = TypedOrderedDict((Part),) + parts = caom_util.TypedOrderedDict(Part,) self.parts = parts def _key(self): - return (self.uri) + return self.uri def __hash__(self): return hash(self._key()) @@ -148,9 +162,9 @@ def uri(self): @uri.setter def uri(self, value): - util.typeCheck(value, str, 'uri') + caom_util.type_check(value, unicode, 'uri') uri = urlparse(value).geturl() - util.valueCheck(value, None, None, 'uri', override=uri) + caom_util.value_check(value, None, None, 'uri', override=uri) self._uri = uri @property @@ -158,15 +172,15 @@ def product_type(self): """The product type associated with the Artifact. type: caom2.ProductType - restricted to caom2.ProductType.names() + restricted to caom2.ProductType - eg. Artifact.product_type = caom2.ProductType('SCIENCE') + eg. Artifact.product_type = caom2.ProductType['SCIENCE'] """ return self._product_type @product_type.setter def product_type(self, value): - util.typeCheck(value, ProductType, "product_type", False) + caom_util.type_check(value, ProductType, "product_type", False) self._product_type = value @property @@ -174,15 +188,15 @@ def release_type(self): """The release type associated with the Artifact. type: caom2.ReleaseType - restricted to caom2.ReleaseType.names() + restricted to caom2.ReleaseType - eg. Artifact.release = caom2.ReleaseType('META') + eg. Artifact.release = caom2.ReleaseType['META'] """ return self._release_type @release_type.setter def release_type(self, value): - util.typeCheck(value, ReleaseType, "release_type", False) + caom_util.type_check(value, ReleaseType, "release_type", False) self._release_type = value @property @@ -195,7 +209,7 @@ def content_type(self): @content_type.setter def content_type(self, value): - util.typeCheck(value, str, "content_type") + caom_util.type_check(value, unicode, "content_type") self._content_type = value @property @@ -210,8 +224,8 @@ def content_length(self): @content_length.setter def content_length(self, value): - util.typeCheck(value, long, "content_length") - util.valueCheck(value, 0, 1E10, "content_length") + caom_util.type_check(value, long, "content_length") + caom_util.value_check(value, 0, 1E10, "content_length") self._content_length = value @property @@ -238,8 +252,6 @@ def parts(self): @parts.setter def parts(self, value): - util.typeCheck(value, - TypedOrderedDict, - 'parts', - override=False) + caom_util.type_check(value, caom_util.TypedOrderedDict, 'parts', + override=False) self._parts = value diff --git a/pyCAOM2/caom2/util/caom2_util.py b/caom2/caom2/caom_util.py similarity index 91% rename from pyCAOM2/caom2/util/caom2_util.py rename to caom2/caom2/caom_util.py index 2640c0f7..3f4c3c7b 100644 --- a/pyCAOM2/caom2/util/caom2_util.py +++ b/caom2/caom2/caom_util.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,7 +64,7 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """ @@ -77,11 +76,131 @@ engineer get the correct meta data more quickly. """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import collections -from datetime import datetime -import sys import struct +import sys import uuid +from datetime import datetime + +__all__ = ['TypedList', 'TypedSet', 'TypedOrderedDict', 'ClassProperty'] + + +# TODO both these are very bad, implement more sensibly +IVOA_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" + + +def validate_path_component(caller, name, test): + """ + Function to validate a URI path component. Component is invalid + if it contains space ( ), slash (/), escape (\\) or percent (%) characters. + + Arguments: + caller : caller object + name : name of the component + test : component to be tested + + An assertionError is thrown when the the provided test argument + is invalid + """ + + assert (' ' not in test and + '/' not in test and + '||' not in test and + '%' not in test), ( + caller.__class__.__name__ + ": invalid " + name + + ": may not contain space ( ), slash (/), escape (\\), or percent (%)") + + +def date2ivoa(d): + """ + Takes a datetime and returns a string formatted + to the IVOA date format yyyy-MM-dd'T'HH:mm:ss.SSS + """ + + if d is None: + return None + return d.strftime(IVOA_DATE_FORMAT)[:23] + + +def str2ivoa(s): + """Takes a IVOA date formatted string and returns a datetime""" + + if s is None: + return None + return datetime.strptime(s, IVOA_DATE_FORMAT) + + +def attr2str(s): + pass + + +def repr2str(s): + pass + + +def uuid2long(uid): + """ + UUID is 128 bits (32 bytes). Unpack the 32 bytes into two + 16 byte longs. For CAOM-2.0 compatibility only the least significant + 16 bytes in the UUID should have a value. + + return the UUID least significant bytes as a long. + """ + longs = struct.unpack(str('>qq'), str(uid.bytes)) + if longs[0] != 0: + raise ValueError("lossy conversion from UUID to long: {}".format(uid)) + return longs[1] + + +def long2uuid(l): + """ + Takes a long and creates a UUID using the 16 byte long + as the least significant bytes in the 32 byte UUID. + """ + if l.bit_length() > 63: + raise ValueError("expected 64 bit long {}".format(l)) + if l < 0: + l = (1<<64L) + l + return uuid.UUID(int=l) + + +def type_check(value, value_type, variable, override=None): + """Check value is of type value_type, or is override""" + + sys.tracebacklimit = None + if not isinstance(value, value_type) and value is not override: + if override is not False: + raise TypeError( + "Excepted {} or {} for {}, received {}".format(value_type, + override, + variable, + type(value))) + else: + raise TypeError( + "Expected {} for {}, received {}".format(value_type, + variable, + type(value))) + return True + + +def value_check(value, min_value, max_value, variable, override=None): + """Check if value is inside allowed range, or override""" + + sys.tracebacklimit = None + if value != override and not (min_value <= value <= max_value): + if override is not False: + raise ValueError( + "Expected {} <= {} <= {} or {}, received {}".format( + min_value, variable, max_value, override, value)) + else: + raise ValueError( + "Expected {} <= {} <= {}, received {}".format( + min_value, variable, max_value, value)) + + return True class TypedList(collections.MutableSequence): @@ -116,12 +235,12 @@ def __str__(self): return "\n".join(["{}".format(v) for v in self]) def __repr__(self): - return "TypedList((%r))," % (self._oktypes) + ( - "(".join(["(%r)" % (v) for v in self]) + ")") + return "TypedList((%r))," % self._oktypes + ( + "(".join(["(%r)" % v for v in self]) + ")") def check(self, v): assert isinstance(v, self._oktypes), ( - "Wrong type in list. OK Types: {0}".format(self._oktypes)) + "Wrong type in list. OK Types: {0}".format(self._oktypes)) def __len__(self): return len(self.list) @@ -141,28 +260,6 @@ def insert(self, i, v): self.list.insert(i, v) -def validate_path_component(caller, name, test): - """ - Function to validate a URI path component. Component is invalid - if it contains space ( ), slash (/), escape (\\) or percent (%) characters. - - Arguments: - caller : caller object - name : name of the component - test : component to be tested - - An assertionError is thrown when the the provided test argument - is invalid - """ - - assert (' ' not in test and - '/' not in test and - '||' not in test and - '%' not in test), ( - caller.__class__.__name__ + ": invalid " + name + - ": may not contain space ( ), slash (/), escape (\\), or percent (%)") - - class TypedSet(collections.MutableSet): """ Class that implements a typed set in Python. Supported types @@ -194,7 +291,7 @@ def __init__(self, oktypes, *args): def check(self, v): assert isinstance(v, self._oktypes), ( - "Wrong type in list. OK Types: {0}".format(self._oktypes)) + "Wrong type in list. OK Types: {0}".format(self._oktypes)) def add(self, v): """Add an element.""" @@ -239,7 +336,7 @@ class TypedOrderedDict(collections.OrderedDict): with the wrong type. """ - def __init__(self, keyType, *args): + def __init__(self, key_type, *args): """ Initializes a TypedOrderedDict. @@ -252,7 +349,7 @@ def __init__(self, keyType, *args): is not the same as keyType. """ super(TypedOrderedDict, self).__init__(self) - self._keyType = keyType + self._keyType = key_type for arg in args: self.__setitem__(arg[0], arg[1]) @@ -261,7 +358,7 @@ def __str__(self): for k, v in self.iteritems()]) def __repr__(self): - return "TypeOrderedDict((%r))," % (self._keyType) + ( + return "TypeOrderedDict((%r))," % self._keyType + ( "(".join(["(%r,%r)" % (k, v) for k, v in self.iteritems()]) + ")") def check(self, key, value): @@ -288,101 +385,7 @@ def __setitem__(self, key, value): super(TypedOrderedDict, self).__setitem__(key, value) -############################### -# To be moved to cadcUtil -############################### class ClassProperty(property): """ """ def __get__(self, cls, owner): return self.fget.__get__(None, owner)() - - -# TODO both these are very bad, implement more sensibly -IVOA_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" - - -def date2ivoa(d): - """ - Takes a datetime and returns a string formatted - to the IVOA date format yyyy-MM-dd'T'HH:mm:ss.SSS - """ - - if d is None: - return None - return d.strftime(IVOA_DATE_FORMAT)[:23] - - -def str2ivoa(s): - """Takes a IVOA date formatted string and returns a datetime""" - - if s is None: - return None - return datetime.strptime(s, IVOA_DATE_FORMAT) - - -def attr2str(s): - pass - - -def repr2str(s): - pass - - -def uuid2long(uid): - """ - UUID is 128 bits (32 bytes). Unpack the 32 bytes into two - 16 byte longs. For CAOM-2.0 compatibility only the least significant - 16 bytes in the UUID should have a value. - - return the UUID least significant bytes as a long. - """ - longs = struct.unpack('>qq', str(uid.bytes)) - if longs[0] != 0: - raise ValueError("lossy conversion from UUID to long: {}".format(uid)) - return longs[1] - - -def long2uuid(l): - """ - Takes a long and creates a UUID using the 16 byte long - as the least significant bytes in the 32 byte UUID. - """ - if l.bit_length() > 63: - raise ValueError("expected 64 bit long {}".format(l)) - return uuid.UUID(bytes='\x00'*8 + str(struct.pack(">q", l))) - - -def typeCheck(value, value_type, variable, override=None): - """Check value is of type value_type, or is override""" - - sys.tracebacklimit = None - if not isinstance(value, value_type) and value is not override: - if override is not False: - raise TypeError( - "Excepted {} or {} for {}, received {}".format(value_type, - override, - variable, - type(value))) - else: - raise TypeError( - "Expected {} for {}, received {}".format(value_type, - variable, - type(value))) - return True - - -def valueCheck(value, min_value, max_value, variable, override=None): - """Check if value is inside allowed range, or override""" - - sys.tracebacklimit = None - if value != override and not (min_value <= value <= max_value): - if override is not False: - raise ValueError( - "Expected {} <= {} <= {} or {}, received {}".format( - min_value, variable, max_value, override, value)) - else: - raise ValueError( - "Expected {} <= {} <= {}, received {}".format( - min_value, variable, max_value, value)) - - return True diff --git a/caom2/caom2/chunk.py b/caom2/caom2/chunk.py new file mode 100644 index 00000000..9482c7ae --- /dev/null +++ b/caom2/caom2/chunk.py @@ -0,0 +1,937 @@ +# -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +# *********************************************************************** +# + +"""Defines caom2.Chunk class. + +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from enum import Enum +from .common import AbstractCaomEntity +from .common import CaomObject +from . import caom_util +from . import wcs + + +class ProductType(Enum): + """ + SCIENCE: "science" + CALIBRATION: "calibration" + PREVIEW: "preview" + INFO: "info" + NOISE: "noise" + WEIGHT: "weight" + AUXILIARY: "auxiliary" + THUMBNAIL: "thumbnail" + """ + SCIENCE = "science" + CALIBRATION = "calibration" + PREVIEW = "preview" + INFO = "info" + NOISE = "noise" + WEIGHT = "weight" + AUXILIARY = "auxiliary" + THUMBNAIL = "thumbnail" + +__all__ = ['ProductType', 'Chunk', 'ObservableAxis', 'SpatialWCS', + 'SpectralWCS', 'TemporalWCS', 'PolarizationWCS'] + + +class Chunk(AbstractCaomEntity): + """A caom2.Chunk object. A chunk is a peice of file part. + + eg. a column in a Table extension of a FITS file. + + The chunk is characterised by world coordinate system (WCS) + metadata plus an extra axis to describe different observables (the + measured values) stored within the data. Different chunks can be + defined which vary only on the range of coordinate values they + include. For example, if a single data array contains different + observable quantities then one can define a chunk (perhaps + representing different slices through a stored array) with each + slice having a different product type. + + Chunks can also be used to define arbitrary tiles in a large data + array; this is useful if there is no WCS solution to describe the + mapping of sky to pixel coordinates but one still wants to be able + to extract smaller sections of the data (e.g. one chunk). + + """ + + def __init__(self, product_type=None, + naxis=None, + position_axis_1=None, + position_axis_2=None, + position=None, + energy_axis=None, + energy=None, + time_axis=None, + time=None, + polarization_axis=None, + polarization=None, + observable_axis=None, + observable=None, + ): + + super(Chunk, self).__init__() + self.product_type = product_type + self.naxis = naxis + self.position_axis_1 = position_axis_1 + self.position_axis_2 = position_axis_2 + self.energy_axis = energy_axis + self.time_axis = time_axis + self.polarization_axis = polarization_axis + self.observable_axis = observable_axis + self.observable = observable + self.position = position + self.energy = energy + self.time = time + self.polarization = polarization + + @property + def product_type(self): + """A word that describes the content of the chunk. + + eg. Chunk.product_type = ProductType.SCIENCE + + Allowed values: + """ + str(list(ProductType)) + """ + + """ + + return self._product_type + + @product_type.setter + def product_type(self, value): + if isinstance(value, unicode) and value in ProductType.names(): + # be helpful + value = ProductType('value') + caom_util.type_check(value, ProductType, 'product_type') + self._product_type = value + + @property + def naxis(self): + """There number of dimensions in this chunk. + + type: int + eg: 2 + + """ + return self._naxis + + @naxis.setter + def naxis(self, value): + caom_util.type_check(value, int, 'naxis') + caom_util.value_check(value, 0, 5, 'naxis') + self._naxis = value + + @property + def position_axis_1(self): + """The first spatial axis (nominally NAXIS1). + + This is the spatial axis whose WCS is connected to CRPIX1, CD1_1, CD2_1 + + eg: position_axis_1 = 1 + type: int + + """ + return self._position_axis_1 + + @position_axis_1.setter + def position_axis_1(self, value): + caom_util.type_check(value, int, 'position_axis_1') +# util.valueCheck(value, 0, self.naxis, 'position_axis_1') + self._position_axis_1 = value + + @property + def position_axis_2(self): + """The second spatial axis (nominally NAXIS2). + + This is the spatial axis whose WCS is connected to CRPIX2, + CD2_2, CD1_2 + + eg: position_axis_2 = 2 + type: int + + """ + return self._position_axis_2 + + @position_axis_2.setter + def position_axis_2(self, value): + caom_util.type_check(value, int, 'position_axis_2') +# util.valueCheck(value, 0, self.naxis, 'position_axis_2') + self._position_axis_2 = value + + @property + def energy_axis(self): + """The axis in the file that is in the energy direction. + + This should be None if the data does not contain an + energy axis. In this case the energy WCS maps to a + single pixel. + + eg: energy_axis = 3 + type: int + + """ + return self._energy_axis + + @energy_axis.setter + def energy_axis(self, value): + caom_util.type_check(value, int, 'energy_axis') +# util.valueCheck(value, 0, self.naxis, 'energy_axis') + self._energy_axis = value + + @property + def time_axis(self): + """The axis in the data chunk that is in the time direction. + + Can and should be None if no time sampling axis exist. + + eg. time_axis = None + type: int + + """ + return self._time_axis + + @time_axis.setter + def time_axis(self, value): + caom_util.type_check(value, int, 'polarization_axis') +# util.valueCheck(value, 0, self._naxis, 'polarization_axis') + self._time_axis = value + + @property + def polarization_axis(self): + """The axis in the data chunk that is in the polarization direction. + + Likely None... + + eg. polarization_axis = None + type: int + + """ + return self._polarization_axis + + @polarization_axis.setter + def polarization_axis(self, value): + caom_util.type_check(value, int, 'polarization_axis') +# util.valueCheck(value, 0, self._naxis, 'polariztion_axis') + self._polarization_axis = value + + @property + def observable_axis(self): + """Used when on of the dimensions of the file contains?? ? + + type: int + + """ + return self._observable_axis + + @observable_axis.setter + def observable_axis(self, value): + caom_util.type_check(value, int, 'obserable_axis') +# util.valueCheck(value, 0, 1E10, 'observable_axis') + self._observable_axis = value + + @property + def observable(self): + """An obserable that is contained in the chunk. + + Observables are quantities that are recorded directly?? + + """ + return self._observable + + @observable.setter + def observable(self, value): + caom_util.type_check(value, ObservableAxis, 'observable_axis') + self._observable = value + + @property + def position(self): + """A SpatialWCS object associated with this chunk. + + The spatialWCS describes the relation between the position_axis + values and the world coordinate. + + type: SpatialWCS. + + """ + return self._position + + @position.setter + def position(self, value): + caom_util.type_check(value, SpatialWCS, 'position') + self._position = value + + @property + def energy(self): + """A SpectralWCS object associated with this chunk. + + Even if energy_axis is None an SpectralWCS should still + be defined. The SpectalWCS in this case will be one pixel + in dimension. + + type: SpectralWCS + + """ + return self._energy + + @energy.setter + def energy(self, value): + caom_util.type_check(value, SpectralWCS, 'energy') + self._energy = value + + @property + def time(self): + """The TemporalWCS object associated with this chunk. + + Even if time_axis is None you should define the TimeWCS + to convey when you observation was taken. + + type: TemporalWCS + + """ + return self._time + + @time.setter + def time(self, value): + caom_util.type_check(value, TemporalWCS, 'time') + self._time = value + + @property + def polarization(self): + """The PolarizationWCS of the observation. + + ususally None + + type: PolarizationWCS + + """ + return self._polarization + + @polarization.setter + def polarization(self, value): + caom_util.type_check(value, PolarizationWCS, 'polarization') + self._polarization = value + + +class ObservableAxis(CaomObject): + """The slice through the data structure that provides the thing being + described by this Axis. + + this data structure is used when a file contains data that has set + of measured values (the dependent variable) and might also have + the coordinate at which those values are measured in another Slice + of the file. + + The Slice refers to a column in a FITS image. The bin is the + column index and ctype/cunit for the axis describe what the column + contiains. + + eg. + + NAXIS=2 + NAXIS1=3 + NAXIS2=N + l1 f1 s1 + l2 f2 s2 + l3 f3 s3 + . + . + lN fN sN + + where l? is the wavelength at which a measure of flux f? has been + made and l is the first column of a FITS data structure that is + 3,N in size. s? is a third slice that would be used to define + another observable. When defining the s? obserable the independent + variable must be defined for that ObservableAxis too. + + The l/f obserable would be recorded as + + dependent=Slice(Axis('wave','nm'),bin=1) + independent=Slice(Axis('flux','Jy'),bin=2) + Chunk.observable_axis=ObservableAxis(dependent, independent) + + + """ + def __init__(self, dependent, independent=None): + + self.dependent = dependent + self.independent = independent + + @property + def dependent(self): + """The dependent (y) variable slice. + + A slice provides the bin and the type/unit of the observable axis + """ + + return self._dependent + + @dependent.setter + def dependent(self, value): + caom_util.type_check(value, wcs.Slice, 'dependent', override=False) + self._dependent = value + + @property + def independent(self): + """The dependent (y) variable slice. + + A slice that provides the pixel value and the type/unit for + conversion + + """ + return self._independent + + @independent.setter + def independent(self, value): + caom_util.type_check(value, wcs.Slice, "independent") + self._independent = value + + +class SpatialWCS(CaomObject): + """this object contains the WCS information needed to convert an + astronomical spatial location (ie. RA/DEC) into a pixel location + in the image. + + During ingestion a variety of extra information is created. + + """ + + def __init__(self, + axis, + coordsys=None, + equinox=None, + resolution=None): + + self.axis = axis + self.coordsys = coordsys + self.equinox = equinox + self.resolution = resolution + + @property + def axis(self): + """A CoordAxis2D object that contains + the actual WCS values (crpix etc.) + + type: CoordAxis2D + + """ + return self._axis + + @axis.setter + def axis(self, value): + caom_util.type_check(value, wcs.CoordAxis2D, 'axis', override=False) + self._axis = value + + @property + def coordsys(self): + """The Coordinate system of the transformation, likely ICRS or FK5. + + eg. SpatialWCS.coordsys="ICRS" + + type: unicode + + """ + return self._coordsys + + @coordsys.setter + def coordsys(self, value): + caom_util.type_check(value, unicode, 'coordsys') + self._coordsys = value + + @property + def equinox(self): + """The Equinox of the coordinate system. + + You might think J2000, but must be expressed as a float, so in years + + unit: years + type: float + + """ + return self._equinox + + @equinox.setter + def equinox(self, value): + caom_util.type_check(value, float, 'equinox') + caom_util.value_check(value, 1800, 2500, 'equinox') + self._equinox = value + + @property + def resolution(self): + """The spatial resolution of the image data (account for seeing/beem). + + unit: arcsec + type: float + + """ + return self._resolution + + @resolution.setter + def resolution(self, value): + caom_util.type_check(value, float, 'resolution') + caom_util.value_check(value, 0, 360 * 3600.0, 'resolution') + self._resolution = value + + +class SpectralWCS(CaomObject): + """A transformation that maps pixel coordinates to spectral ones. + + Note that a 2D image has implicit 'spectral' (and temporal) + dimension that is one pixel in size. Basically pixels are really + multidimensional voxels. + + Due to FITS standards this pixel starts at 0.5 and runs to 1.5 + with the centre being at 1.0 + + """ + + def __init__(self, + axis, + specsys, + ssysobs=None, + ssyssrc=None, + restfrq=None, + restwav=None, + velosys=None, + zsource=None, + velang=None, + bandpass_name=None, + transition=None, + resolving_power=None + ): + """The SpectralWCS can be defined in a number of different ways, to + define one you must provide a CoordAxis1D object that maps the + pixels to WCS values and a reference specsys. After that the + user can add what ever parts seam useful. More info is more + helpful for searching. + + """ + + self.axis = axis + self.specsys = specsys + self.ssysobs = ssysobs + self.ssyssrc = ssyssrc + self.restfrq = restfrq + self.restwav = restwav + self.velosys = velosys + self.zsource = zsource + self.velang = velang + self.bandpass_name = bandpass_name + self.transition = transition + self.resolving_power = resolving_power + + @property + def axis(self): + """A 1D coordinate axis object that contains the pix/wcs + transformation values. + + eg. CoordAxis1D(Axis('wave','flux'),...) + + """ + return self._axis + + @axis.setter + def axis(self, value): + caom_util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) + self._axis = value + + @property + def specsys(self): + """describes the reference frame in use for the spectral-axis + coordinate(s). + + eg. BARYCENT + + type: unicode + """ + return self._specsys + + @specsys.setter + def specsys(self, value): + caom_util.type_check(value, unicode, 'specsys', override=False) + self._specsys = value + + @property + def ssysobs(self): + """describes the spectral reference frame that is constant over the + range of the non-spectral world coordinates + + For example, for a large image the the wavelength at the edges + is different from the centres. This reference frame is one where they + are not different. + + Nominally 'TOPOCENT' + + type: unicode + """ + return self._ssysobs + + @ssysobs.setter + def ssysobs(self, value): + caom_util.type_check(value, unicode, 'ssysobs') + self._ssysobs = value + + @property + def ssyssrc(self): + """The reference frame in which zsource is expressed. + + eg. BARYCENT + type: string + """ + return self._ssyssrc + + @ssyssrc.setter + def ssyssrc(self, value): + caom_util.type_check(value, unicode, 'ssyssrc') + self._ssyssrc = value + + @property + def restfrq(self): + """The frequency of the spectal feature being observed. + + unit: Hz + type: float + """ + return self._restfrq + + @restfrq.setter + def restfrq(self, value): + caom_util.type_check(value, float, 'restfrq') + self._restfrq = value + + @property + def restwav(self): + """The wavelength of spectral feature being observed, + not the wavelength observed but the wavelength of the + feature when at rest.. + + unit: m + type: float + """ + return self._restwav + + @restwav.setter + def restwav(self, value): + caom_util.type_check(value, float, 'restwav') + self._restwav = value + + @property + def velosys(self): + """Relative radial velocity between the observer and the selected + standard of rest in the direction of the celestial reference + coordinate. + + eg. 26000 m/s + + + unit: m/s + type: float + """ + return self._velosys + + @velosys.setter + def velosys(self, value): + caom_util.type_check(value, float, 'velosys') + self._velosys = value + + @property + def zsource(self): + """The redshift of the source emitting the photons. + + almost always None + + unit: z + type: float + """ + return self._zsource + + @zsource.setter + def zsource(self, value): + caom_util.type_check(value, float, 'zsource') + caom_util.value_check(value, -0.5, 1200, 'zsource') + self._zsource = value + + @property + def velang(self): + """I don't know what this is... angle of the velocity ??? """ + return self._velang + + @velang.setter + def velang(self, value): + caom_util.type_check(value, float, 'velang') + self._velang = value + + @property + def bandpass_name(self): + """string the represent the bandpass of the observation. + + eg. r' + type: unicode + """ + return self._bandpass_name + + @bandpass_name.setter + def bandpass_name(self, value): + caom_util.type_check(value, unicode, 'bandpass_name') + self._bandpass_name = value + + @property + def transition(self): + """which molecular transition has been observed. + + type: EnergyTransition object (see caom2.EnergyTransition for help) + """ + return self._transition + + @transition.setter + def transition(self, value): + caom_util.type_check(value, wcs.EnergyTransition, "transition") + self._transition = value + + @property + def resolving_power(self): + """The R value of the spectal coverage. + + Normally this is something like dlamda/lamda + + unit: RATIO + type: float + """ + return self._resolving_power + + @resolving_power.setter + def resolving_power(self, value): + caom_util.type_check(value, float, 'resolving_power') + caom_util.value_check(value, 0, 1E8, 'resolving_power') + self._resolving_power = value + + +class TemporalWCS(CaomObject): + """Describes the Time variation within the data. + + In the case of a single exposure, define the center of the first + pixel (0.5) as the MJD of the exposure and size of the pixel + as the exposure time.""" + + def __init__(self, + axis, + timesys=None, + trefpos=None, + mjdref=None, + exposure=None, + resolution=None + ): + + self.axis = axis + self.timesys = timesys + self.trefpos = trefpos + self.mjdref = mjdref + self.exposure = exposure + self.resolution = resolution + + @property + def axis(self): + """A CoordAxis1D object that describes the TemporalWCS transform. + + eg. CoordAxis1D(Axis) """ + return self._axis + + @axis.setter + def axis(self, value): + caom_util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) + self._axis = value + + @property + def timesys(self): + """The time scale that you are using, almost alwasy UTC. + + eg. timesys = "UTC" + type: unicode + """ + return self._timesys + + @timesys.setter + def timesys(self, value): + caom_util.type_check(value, unicode, 'timesys') + self._timesys = value + + @property + def trefpos(self): + """ specifies the spatial location at which the time is valid, either + where the observation was made or the point in space for which + light-time corrections have been applied. + + eg. trefpos = "TOPOCENTER" + type: unicode + """ + return self._trefpos + + @trefpos.setter + def trefpos(self, value): + caom_util.type_check(value, unicode, 'trefpos') + self._trefpos = value + + @property + def mjdref(self): + """The Modified Julian Date of the at the reference location of the + location of the TimeWCS (aka. pixel 0.5). Nominally this the start + of the exposure. + + Why 0.5? FITS: the middle of the first pixel + is defined as pixel value 1.0 so, the start of that pixel + is location 0.5 + + eg. mjdref = 567643.1234 + unit: d + type: float + """ + return self._mjdref + + @mjdref.setter + def mjdref(self, value): + caom_util.type_check(value, float, 'mjdref') + # set the limits to be after 1800 but before year 2050 + caom_util.value_check(value, -22000, 70000, 'mjdref') + self._mjdref = value + + @property + def exposure(self): + """The median exposure time per pixel. + + The exposure time if this not a time cube you are describing. + + eg. exposure = 100.0 + unit: s + type: float + """ + return self._exposure + + @exposure.setter + def exposure(self, value): + caom_util.type_check(value, float, "exposure") + caom_util.value_check(value, 0, 30 * 24 * 3600.0, "exposure") + self._exposure = value + + @property + def resolution(self): + """the resolution of the time sampling available. + + Normally this is going to be the same as the exposure above, + but a stack of exposures taken over many months has a very + large value for resolution while the exposure value is just + the sum of the individual exposure times. + + + eg. resolution = 100.0s + unit: s + type: float + """ + return self._resolution + + @resolution.setter + def resolution(self, value): + caom_util.type_check(value, float, 'resolution') + caom_util.value_check(value, 0, 100 * 365 * 24 * 3600.0, "resolution") + self._resolution = value + + +class PolarizationWCS(CaomObject): + """A WCS structure that describes the relation ship between a pixel + location and the polarization value. + + """ + + def __init__(self, axis): + """Set up a CoordAxis1D object to represent the Polariation. + + """ + + self.axis = axis + + @property + def axis(self): + """A CoordAxis1D object that describes the pixel/value relation ship + for polarization of the data. + + type: CoordAxis1D + + """ + return self._axis + + @axis.setter + def axis(self, value): + caom_util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) + if value.axis.ctype != 'STOKES': + raise ValueError('CTYPE must be STOKES') + self._axis = value diff --git a/pyCAOM2/caom2/caom2_observation_uri.py b/caom2/caom2/common.py similarity index 60% rename from pyCAOM2/caom2/caom2_observation_uri.py rename to caom2/caom2/common.py index a7fc6c92..f3e7fb15 100644 --- a/pyCAOM2/caom2/caom2_observation_uri.py +++ b/caom2/caom2/common.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,20 +64,95 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # -""" defines the ObservationURI class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) - -from util.caom2_util import validate_path_component -from urlparse import urlsplit +import inspect +import uuid +from datetime import datetime from urlparse import SplitResult -from util import caom2_util as util -from caom2_object import Caom2Object +from urlparse import urlsplit + +from . import caom_util + +__all__ = ['CaomObject', 'AbstractCaomEntity', 'ObservationURI'] + + +class CaomObject(object): + """ + setup all objects with the same generic equality, str and repr methods + """ + + def __init__(self): + pass + + def __str__(self): + args = inspect.getargspec(self.__init__).args[1:] + class_name = self.__class__.__name__ + return "\n".join(["{}.{} : {}". + format(class_name, arg, getattr(self, arg, None)) + for arg in args]) + + def __eq__(self, other): + if type(other) == type(self): + return self.__dict__ == other.__dict__ + else: + return False + + def __repr__(self): + args = inspect.getargspec(self.__init__).args[1:] + class_name = "" + if self.__class__.__module__ != '__main__': + class_name += self.__class__.__module__ + "." + class_name += self.__class__.__name__ + pading = " " * (len(class_name) + 1) + return class_name + "(" + ( + ",\n" + pading).join( + ["%s=%r" % (arg, getattr(self, arg, None) + ) for arg in args]) + ")" + + +class AbstractCaomEntity(CaomObject): + """Class that defines the persistence unique ID and last mod date """ + + def __init__(self, fulluuid=False): + self._id = AbstractCaomEntity._gen_id(fulluuid) + self._last_modified = AbstractCaomEntity._gen_last_modified() + + @classmethod + def _gen_id(cls, fulluuid=False): + """Generate a 128 but UUID by default. For backwards compatibility + allow creation of a 64 bit UUID using a rand number for the + lower 64 bits. First two bytes of the random number are generated + with the random and the last 6 bytes from the current time + in microseconds. + + return: UUID + """ + + gen_id = uuid.uuid4() + if fulluuid: + return gen_id + else: + return uuid.UUID(fields=(0x00000000, 0x0000, 0x0000, + gen_id.clock_seq_hi_variant, gen_id.clock_seq_low, gen_id.node)) + + @classmethod + def _gen_last_modified(cls): + """Generate a datetime with 3 digit microsecond precision. + + return: datatime + IVOA date format to millisecond precision. + """ + now = datetime.now() + return datetime(now.year, now.month, now.day, now.hour, now.minute, \ + now.second, long(str(now.microsecond)[:-3] + '000')) -class ObservationURI(Caom2Object): +class ObservationURI(CaomObject): """ Observation URI """ _SCHEME = str("caom") @@ -95,31 +169,31 @@ def __init__(self, uri): if tmp.scheme != ObservationURI._SCHEME: raise ValueError( "uri must be have scheme of {}. received: {}" - .format(ObservationURI._SCHEME, uri)) + .format(ObservationURI._SCHEME, uri)) if tmp.geturl() != uri: raise ValueError( "uri parsing failure. received: {}".format(uri)) self._uri = tmp.geturl() (collection, observation_id) = tmp.path.split("/") - if collection is None: + if collection is None: raise ValueError( "uri did not contain a collection part. received: {}" - .format(uri)) - validate_path_component(self, "collection", collection) + .format(uri)) + caom_util.validate_path_component(self, "collection", collection) if observation_id is None: raise ValueError( "uri did not contain an observation_id part. received: {}" - .format(uri)) - validate_path_component(self, "observation_id", observation_id) + .format(uri)) + caom_util.validate_path_component(self, "observation_id", observation_id) (self._collection, self._observation_id) = (collection, observation_id) self._print_attributes = ['uri', 'collection', 'observation_id'] def _key(self): - return (self.uri) + return self.uri def __eq__(self, y): - if (isinstance(y, ObservationURI)): + if isinstance(y, ObservationURI): return self._key() == y._key() return False @@ -136,23 +210,22 @@ def get_observation_uri(cls, collection, observation_id): observation_id : ID of the observation """ - util.typeCheck(collection, str, "collection", override=False) - util.typeCheck(observation_id, str, "observation_id", override=False) + caom_util.type_check(collection, unicode, "collection", override=False) + caom_util.type_check(observation_id, unicode, "observation_id", override=False) - validate_path_component(cls, "collection", collection) - validate_path_component(cls, "observation_id", - observation_id) + caom_util.validate_path_component(cls, "collection", collection) + caom_util.validate_path_component(cls, "observation_id", observation_id) - uri = SplitResult(ObservationURI._SCHEME, "", collection + "/" + - observation_id, "", "").geturl() + uri = SplitResult(ObservationURI._SCHEME, "", collection + "/" + observation_id, + "", "").geturl() return cls(uri) # Properties @property @classmethod - def SCHEME(cls): - """The SCHEME defines where this Observation can be looked up. + def scheme(cls): + """The scheme defines where this Observation can be looked up. Only 'caom' is currently supported.""" return cls._SCHEME diff --git a/caom2/caom2/conftest.py b/caom2/caom2/conftest.py new file mode 100644 index 00000000..829ba1d7 --- /dev/null +++ b/caom2/caom2/conftest.py @@ -0,0 +1,38 @@ +# this contains imports plugins that configure py.test for astropy tests. +# by importing them here in conftest.py they are discoverable by py.test +# no matter how it is invoked within the source tree. + +from astropy.tests.pytest_plugins import * + +## Uncomment the following line to treat all DeprecationWarnings as +## exceptions +# enable_deprecations_as_exceptions() + +## Uncomment and customize the following lines to add/remove entries from +## the list of packages for which version numbers are displayed when running +## the tests. Making it pass for KeyError is essential in some cases when +## the package uses other astropy affiliated packages. +# try: +# PYTEST_HEADER_MODULES['Astropy'] = 'astropy' +# PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' +# del PYTEST_HEADER_MODULES['h5py'] +# except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 +# pass + +## Uncomment the following lines to display the version number of the +## package rather than the version number of Astropy in the top line when +## running the tests. +# import os +# +# # This is to figure out the affiliated package version, rather than +# # using Astropy's +# try: +# from .version import version +# except ImportError: +# version = 'dev' +# +# try: +# packagename = os.path.basename(os.path.dirname(__file__)) +# TESTED_VERSIONS[packagename] = version +# except NameError: # Needed to support Astropy <= 1.0.0 +# pass diff --git a/pyCAOM2/caom2/CAOM-2.0.xsd b/caom2/caom2/data/CAOM-2.0.xsd similarity index 100% rename from pyCAOM2/caom2/CAOM-2.0.xsd rename to caom2/caom2/data/CAOM-2.0.xsd diff --git a/pyCAOM2/caom2/CAOM-2.1.xsd b/caom2/caom2/data/CAOM-2.1.xsd similarity index 100% rename from pyCAOM2/caom2/CAOM-2.1.xsd rename to caom2/caom2/data/CAOM-2.1.xsd diff --git a/pyCAOM2/caom2/CAOM-2.2.xsd b/caom2/caom2/data/CAOM-2.2.xsd similarity index 100% rename from pyCAOM2/caom2/CAOM-2.2.xsd rename to caom2/caom2/data/CAOM-2.2.xsd diff --git a/caom2/caom2/obs_reader_writer.py b/caom2/caom2/obs_reader_writer.py new file mode 100644 index 00000000..7c3e59f4 --- /dev/null +++ b/caom2/caom2/obs_reader_writer.py @@ -0,0 +1,2017 @@ +# -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +# *********************************************************************** +# + +""" Defines ObservationReader class """ + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import os +import uuid + +from lxml import etree + +from . import artifact +from . import caom_util +from . import chunk +from . import observation +from . import part +from . import plane +from . import shape +from . import wcs + +DATA_PKG = 'data' + +CAOM20_SCHEMA_FILE = 'CAOM-2.0.xsd' +CAOM21_SCHEMA_FILE = 'CAOM-2.1.xsd' +CAOM22_SCHEMA_FILE = 'CAOM-2.2.xsd' + +CAOM20_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.0' +CAOM21_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.1' +CAOM22_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.2' + +CAOM20 = "{%s}" % CAOM20_NAMESPACE +CAOM21 = "{%s}" % CAOM21_NAMESPACE +CAOM22 = "{%s}" % CAOM22_NAMESPACE + +XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance" +XSI = "{%s}" % XSI_NAMESPACE + +THIS_DIR = os.path.dirname(os.path.realpath(__file__)) + +__all__ = ['ObservationReader', 'ObservationWriter', 'ObservationParsingException'] + + +class ObservationReader(object): + """ObservationReader """ + + def __init__(self, valididate=False): + """Constructor. XML Schema validation may be disabled, in which case + the client is likely to fail in horrible ways if it received invalid + documents. However, performance may be improved. + + Arguments: + validate : If True enable schema validation, False otherwise + """ + self._validate = valididate + + if self._validate: + # caom20_schema_path = pkg_resources.resource_filename( + # DATA_PKG, CAOM20_SCHEMA_FILE) + caom20_schema_path = os.path.join(THIS_DIR + '/' + DATA_PKG, + CAOM20_SCHEMA_FILE) + + parser = etree.XMLParser(remove_blank_text=True) + xsd = etree.parse(caom20_schema_path, parser) + + caom21_schema = etree.Element( + '{http://www.w3.org/2001/XMLSchema}import', + namespace=CAOM21_NAMESPACE, + schemaLocation=CAOM21_SCHEMA_FILE) + xsd.getroot().insert(1, caom21_schema) + + caom22_schema = etree.Element( + '{http://www.w3.org/2001/XMLSchema}import', + namespace=CAOM22_NAMESPACE, + schemaLocation=CAOM22_SCHEMA_FILE) + xsd.getroot().insert(2, caom22_schema) + + self._xmlschema = etree.XMLSchema(xsd) + + def _set_entity_attributes(self, element, ns, caom2_entity): + expect_uuid = True + if CAOM20_NAMESPACE == ns: + expect_uuid = False + + element_id = element.get("{" + ns + "}id") + element_last_modified = element.get("{" + ns + "}lastModified") + + if expect_uuid: + uid = uuid.UUID(element_id) + else: + uid = caom_util.long2uuid(long(element_id)) + caom2_entity._id = uid + + if element_last_modified: + caom2_entity._last_modified = caom_util.str2ivoa(element_last_modified) + + def _get_child_element(self, element_tag, parent, ns, required): + for element in list(parent): + if element.tag == "{" + ns + "}" + element_tag: + if not element.keys() and not element.text: + # element is empty, return None + return None + else: + # element has content, return it + return element + + if required: + error = element_tag + " element not found in " + parent.tag + raise ObservationParsingException(error) + else: + return None + + def _get_child_text(self, element_tag, parent, ns, required): + child_element = self._get_child_element(element_tag, parent, ns, required) + if child_element is None: + return None + else: + return unicode(child_element.text) + + def _get_child_text_as_int(self, element_tag, parent, ns, required): + child_element = self._get_child_element(element_tag, parent, ns, required) + if child_element is None: + return None + else: + return int(child_element.text) + + def _get_child_text_as_long(self, element_tag, parent, ns, required): + child_element = self._get_child_element(element_tag, parent, ns, required) + if child_element is None: + return None + else: + return long(child_element.text) + + def _get_child_text_as_float(self, element_tag, parent, ns, required): + child_element = self._get_child_element(element_tag, parent, ns, required) + if child_element is None: + return None + else: + return float(child_element.text) + + def _get_algorithm(self, element_tag, parent, ns, required): + """Build an Algorithm object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the algorithm element + ns : namespace of the document + required : indicates whether the element is required + return : an Algorithm object or + None if the document does not contain an algorithm element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return observation.Algorithm(self._get_child_text("name", el, ns, True)) + + def _get_meta_release(self, element_tag, parent, ns, required): + """Build a MetaRelease object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the MetaRelease element + ns : namespace of the document + required : indicates whether the element is required + return : a MetaRelease object or + None if the document does not contain a MetaRelease element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + # TODO: need to catch exceptions, + # what kind of exceptions are thrown? + return caom_util.str2ivoa(el.text) + + def _get_proposal(self, element_tag, parent, ns, required): + """Build a Proposal object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Proposal element + ns : namespace of the document + required : indicates whether the element is required + return : a Proposal object or + None if the document does not contain a Proposal element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + proposal = observation.Proposal(self._get_child_text("id", el, ns, True)) + proposal.pi_name = self._get_child_text("pi", el, ns, False) + proposal.project = self._get_child_text("project", el, ns, False) + proposal.title = self._get_child_text("title", el, ns, False) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + proposal.keywords.add(keyword) + return proposal + + def _get_target(self, element_tag, parent, ns, required): + """Build a Target object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Target element + ns : namespace of the document + required : indicates whether the element is required + return : a Target object or + None if the document does not contain a Target element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + target = observation.Target(self._get_child_text("name", el, ns, True)) + target_type = self._get_child_text("type", el, ns, False) + if target_type: + target.target_type = observation.TargetType(target_type) + target.standard = ("true" == + self._get_child_text("standard", el, ns, False)) + target.redshift = ( + self._get_child_text_as_float("redshift", el, ns, False)) + target.moving = ("true" == + self._get_child_text("moving", el, ns, False)) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + target.keywords.add(keyword) + return target + + def _get_target_position(self, element_tag, parent, ns, required): + """Build a TargetPosition object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Target element + ns : namespace of the document + required : indicates whether the element is required + return : a TargetPosition object or + None if the document does not contain a TargetPosition element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + target_position = observation.TargetPosition( + self._get_point("coordinates", el, ns, True), + self._get_child_text("coordsys", el, ns, True)) + target_position.equinox = ( + self._get_child_text_as_float("equinox", el, ns, False)) + return target_position + + def _get_requirements(self, element_tag, parent, ns, required): + """Build an Requirements object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Requirements element + ns : namespace of the document + required : indicates whether the element is required + return : a Requirements object or + None if the document does not contain an Requirements element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + flag = self._get_child_text("flag", el, ns, True) + requirements = observation.Requirements(observation.Status(flag)) + return requirements + + def _get_telescope(self, element_tag, parent, ns, required): + """Build a Telescope object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Telescope element + ns : namespace of the document + required : indicates whether the element is required + return : a Telescope object or + None if the document does not contain a Telescope element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + telescope = observation.Telescope(self._get_child_text("name", el, ns, True)) + telescope.geo_location_x = ( + self._get_child_text_as_float("geoLocationX", el, ns, False)) + telescope.geo_location_y = ( + self._get_child_text_as_float("geoLocationY", el, ns, False)) + telescope.geo_location_z = ( + self._get_child_text_as_float("geoLocationZ", el, ns, False)) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + telescope.keywords.add(keyword) + return telescope + + def _get_instrument(self, element_tag, parent, ns, required): + """Build an Instrument object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Instrument element + ns : namespace of the document + required : indicates whether the element is required + return : a Instrument object or + None if the document does not contain an Instrument element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + instrument = observation.Instrument(self._get_child_text("name", el, ns, True)) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + instrument.keywords.add(keyword) + return instrument + + def _get_environment(self, element_tag, parent, ns, required): + """Build an Environment object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Environment element + ns : namespace of the document + required : indicates whether the element is required + return : a Environment object or + None if the document does not contain an Environment element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + environment = observation.Environment() + environment.seeing = ( + self._get_child_text_as_float("seeing", el, ns, False)) + environment.humidity = ( + self._get_child_text_as_float("humidity", el, ns, False)) + environment.elevation = ( + self._get_child_text_as_float("elevation", el, ns, False)) + environment.tau = ( + self._get_child_text_as_float("tau", el, ns, False)) + environment.wavelength_tau = ( + self._get_child_text_as_float("wavelengthTau", el, ns, False)) + environment.ambient_temp = ( + self._get_child_text_as_float("ambientTemp", el, ns, False)) + environment.photometric = ("true" == + self._get_child_text("photometric", el, ns, False)) + return environment + + def _add_members(self, members, parent, ns): + """Create ObservationURI objects from an XML representation of + ObservationURI elements found in members element, and add them to the + set of ObservationURI's + + Arguments: + members : Set of member's from the parent Observation object + parent : element containing the Environment element + ns : namespace of the document + return : an Environment object or + None if the document does not contain an Environment element + raise : ObservationParsingException + """ + el = self._get_child_element("members", parent, ns, False) + if el is not None: + for member_element in el.iterchildren("{" + ns + "}observationURI"): + members.add(observation.ObservationURI(member_element.text)) + + if not members: + error = "No observationURI element found in members" + raise ObservationParsingException(error) + + def _add_inputs(self, inputs, parent, ns): + """Create PlaneURI objects from an XML representation of the planeURI + elements and add them to the set of PlaneURIs. + + Arguments: + inputs : set of PlaneURI from the Provenance + parent : element containing the PlaneURI elements + ns : namespace of the document + raise : ObservationParsingException + """ + el = self._get_child_element("inputs", parent, ns, False) + if el is not None: + for uri_element in el.iterchildren("{" + ns + "}planeURI"): + inputs.add(plane.PlaneURI(unicode(uri_element.text))) + + if not inputs: + error = "No planeURI element found in members" + raise ObservationParsingException(error) + + def _get_provenance(self, element_tag, parent, ns, required): + """Build a Provenance object from an XML representation of a + Provenance element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Provenance element + ns : namespace of the document + required : indicates whether the element is required + return : a Provenance object or + None if the document does not contain a Provenance element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + prov = plane.Provenance(self._get_child_text("name", el, ns, True)) + prov.version = self._get_child_text("version", el, ns, False) + prov.project = self._get_child_text("project", el, ns, False) + prov.producer = self._get_child_text("producer", el, ns, False) + prov.run_id = self._get_child_text("runID", el, ns, False) + reference = self._get_child_text("reference", el, ns, False) + if reference: + prov.reference = reference + prov.last_executed = caom_util.str2ivoa( + self._get_child_text("lastExecuted", el, ns, False)) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + prov.keywords.add(keyword) + self._add_inputs(prov.inputs, el, ns) + return prov + + def _get_metrics(self, element_tag, parent, ns, required): + """Build a Metrics object from an XML representation of a + Metrics element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Metrics element + ns : namespace of the document + required : indicates whether the element is required + return : a Metrics object or + None if the document does not contain a Metrics element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + metrics = plane.Metrics() + metrics.source_number_density = \ + self._get_child_text_as_float("sourceNumberDensity", el, ns, False) + metrics.background = \ + self._get_child_text_as_float("background", el, ns, False) + metrics.background_std_dev = \ + self._get_child_text_as_float("backgroundStddev", el, ns, False) + metrics.flux_density_limit = \ + self._get_child_text_as_float("fluxDensityLimit", el, ns, False) + metrics.mag_limit = \ + self._get_child_text_as_float("magLimit", el, ns, False) + return metrics + + def _get_quality(self, element_tag, parent, ns, required): + """Build an Quality object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Quality element + ns : namespace of the document + required : indicates whether the element is required + return : a Quality object or + None if the document does not contain an Quality element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + flag = self._get_child_text("flag", el, ns, True) + data_quality = plane.DataQuality(plane.Quality(flag)) + return data_quality + + def _get_point(self, element_tag, parent, ns, required): + """Build an Point object from an XML representation + of an Point element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Point element + ns : namespace of the document + required : indicate whether the element is required + return : an Point object or + None if the document does not contain an Point element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return shape.Point(self._get_child_text_as_float("cval1", el, ns, True), + self._get_child_text_as_float("cval2", el, ns, True)) + + def _get_axis(self, element_tag, parent, ns, required): + """Build an Axis object from an XML representation of an Axis element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Axis element + ns : namespace of the document + required : indicate whether the element is required + return : an Axis object or + None if the document does not contain an Axis element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.Axis(self._get_child_text("ctype", el, ns, True), + self._get_child_text("cunit", el, ns, False)) + + def _get_slice(self, element_tag, parent, ns, required): + """Build a Slice object from an XML representation of a Slice element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Slice element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a Slice object or + None if the document does not contain a Slice element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.Slice(self._get_axis("axis", el, ns, True), + self._get_child_text_as_long("bin", el, ns, True)) + + def _get_observable_axis(self, element_tag, parent, ns, required): + """Build an ObservableAxis object from an XML representation of an + observable element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Observable element + ns : namespace of the document + required : boolean indicating whether the element is required + return : an ObservableAxis object or + None if the document does not contain an Observable element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + observable = chunk.ObservableAxis( + self._get_slice("dependent", el, ns, True)) + observable.independent = \ + self._get_slice("independent", el, ns, False) + return observable + + def _get_coord_error(self, element_tag, parent, ns, required): + """Build a CoordError object from an XML representation of an error + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the error element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordError object or + None if the document does not contain an error element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordError( + self._get_child_text_as_float("syser", el, ns, True), + self._get_child_text_as_float("rnder", el, ns, True)) + + def _get_ref_coord(self, element_tag, parent, ns, required): + """Build a RefCoord object from an XML representation of a coord + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the coord element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a RefCoord object or + None if the document does not contain a coord element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.RefCoord( + self._get_child_text_as_float("pix", el, ns, True), + self._get_child_text_as_float("val", el, ns, True)) + + def _get_coord2d(self, element_tag, parent, ns, required): + """Build a Coord2D object from an XML representation of a coord + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the coord element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a Coord2D object or + None if the document does not contain a coord element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.Coord2D( + self._get_ref_coord("coord1", el, ns, True), + self._get_ref_coord("coord2", el, ns, True)) + + def _get_value_coord2d(self, element_tag, parent, ns, required): + """Build a ValueCoord2D object from an XML representation of a + value coord element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the coord element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a ValueCoord2D object or + None if the document does not contain a coord element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.ValueCoord2D( + self._get_child_text_as_float("coord1", el, ns, True), + self._get_child_text_as_float("coord2", el, ns, True)) + + def _get_coord_range2d(self, element_tag, parent, ns, required): + """Build a CoordRange2D object from an XML representation of a range + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the range element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordRange2D object or + None if the document does not contain a range element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordRange2D( + self._get_coord2d("start", el, ns, True), + self._get_coord2d("end", el, ns, True)) + + def _get_coord_circle2d(self, element_tag, parent, ns, required): + """Build a CoordCircle2D object from an XML representation of a circle + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the circle element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordCircle2D object or + None if the document does not contain a circle element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordCircle2D( + self._get_value_coord2d("center", el, ns, True), + self._get_child_text_as_float("radius", el, ns, True)) + + def _get_coord_polygon2d(self, element_tag, parent, ns, required): + """Build a CoordPolygon2D object from an XML representation + of a polygon element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the polygon element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordPolygon2D object or + None if the document does not contain a polygon element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + vertice_element = self._get_child_element("vertices", el, ns, True) + children_vertices = list( + vertice_element.iterchildren(tag=("{" + ns + "}vertex"))) + if len(children_vertices) < 3: + error = ("CoordPolygon2D must have a minimum of 3 vertices, " + "found " + len(children_vertices)) + raise ObservationParsingException(error) + else: + polygon = wcs.CoordPolygon2D() + for child_vertex_el in children_vertices: + polygon.vertices.append(wcs.ValueCoord2D( + self._get_child_text_as_float( + "coord1", child_vertex_el, ns, True), + self._get_child_text_as_float( + "coord2", child_vertex_el, ns, True))) + return polygon + + def _get_coord_bounds2d(self, element_tag, parent, ns, required): + """Build a CoordBounds2D object from an XML representation of a bounds + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the bounds element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordBounds2D object or + None if the document does not contain a bounds element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + circle = self._get_coord_circle2d("circle", el, ns, False) + if circle is not None: + return circle + else: + polygon = self._get_coord_polygon2d("polygon", el, ns, False) + if polygon is not None: + return polygon + else: + error = "Unsupported element not found in " + element_tag + \ + ": " + el.getText() + raise ObservationParsingException(error) + + def _get_dimension2d(self, element_tag, parent, ns, required): + """Build a Dimension2D object from an XML representation of a dimension + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the dimension element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a Dimention2D object or + None if the document does not contain a dimension element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.Dimension2D( + self._get_child_text_as_long("naxis1", el, ns, True), + self._get_child_text_as_long("naxis2", el, ns, True)) + + def _get_coord_function2d(self, element_tag, parent, ns, required): + """Build a CoordFunction2D object from an XML representation of a + function element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the function element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordFunction2D object or + None if the document does not contain a function element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordFunction2D( + self._get_dimension2d("dimension", el, ns, True), + self._get_coord2d("refCoord", el, ns, True), + self._get_child_text_as_float("cd11", el, ns, True), + self._get_child_text_as_float("cd12", el, ns, True), + self._get_child_text_as_float("cd21", el, ns, True), + self._get_child_text_as_float("cd22", el, ns, True)) + + def _get_coord_axis2d(self, element_tag, parent, ns, required): + """Build a CoordAxis2D object from an XML representation of an axis + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the axis element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordAxis2D object or + None if the document does not contain an axis element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + axis = wcs.CoordAxis2D(self._get_axis("axis1", el, ns, True), + self._get_axis("axis2", el, ns, True)) + axis.error1 = self._get_coord_error("error1", el, ns, False) + axis.error2 = self._get_coord_error("error2", el, ns, False) + axis.range = self._get_coord_range2d("range", el, ns, False) + axis.bounds = self._get_coord_bounds2d("bounds", el, ns, False) + axis.function = self._get_coord_function2d("function", el, ns, False) + return axis + + def _get_spatial_wcs(self, element_tag, parent, ns, required): + """Build a SpatialWCS object from an XML representation of a position + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the position element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a SpatialWCS object or + None if the document does not contain a position element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + position = chunk.SpatialWCS(self._get_coord_axis2d("axis", el, ns, False)) + position.coordsys = self._get_child_text("coordsys", el, ns, False) + position.equinox = \ + self._get_child_text_as_float("equinox", el, ns, False) + position.resolution = \ + self._get_child_text_as_float("resolution", el, ns, False) + return position + + def _add_children_to_coord_range1d_list(self, element_tag, ranges, parent, ns, + required): + """Create CoordRange1D objects from an XML representation of the + range elements and add them to the set of ranges. + + Arguments: + elTag : element tag which identifies the element + ranges : reference to set of ranges + parent : element containing the ranges elements + ns : namespace of the document + required : boolean indicating whether the element is required + """ + for range_element in parent.iterchildren("{" + ns + "}" + element_tag): + ranges.append(wcs.CoordRange1D( + self._get_ref_coord("start", range_element, ns, True), + self._get_ref_coord("end", range_element, ns, True))) + + def _get_coord_bounds1d(self, element_tag, parent, ns, required): + """Build a CoordBounds1D object from an XML representation of a bounds + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the bounds element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordBounds1D object or + None if the document does not contain a bounds element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + coord_bounds1d = wcs.CoordBounds1D() + samples_element = self._get_child_element("samples", el, ns, False) + if samples_element is not None: + self._add_children_to_coord_range1d_list( + "range", coord_bounds1d.samples, samples_element, ns, False) + return coord_bounds1d + + def _get_coord_range1d(self, element_tag, parent, ns, required): + """Build a CoordRange1D object from an XML representation of a range + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the range element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordRange1D object or + None if the document does not contain a range element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordRange1D( + self._get_ref_coord("start", el, ns, True), + self._get_ref_coord("end", el, ns, True)) + + def _get_coord_function1d(self, element_tag, parent, ns, required): + """Build a CoordFunction1D object from an XML representation of a + function element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the function element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordFunction1D object or + None if the document does not contain a function element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordFunction1D( + self._get_child_text_as_long("naxis", el, ns, True), + self._get_child_text_as_float("delta", el, ns, True), + self._get_ref_coord("refCoord", el, ns, True)) + + def _get_coord_axis1d(self, element_tag, parent, ns, required): + """Build a CoordAxis1D object from an XML representation of an axis + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the axis element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordAxis1D object or + None if the document does not contain an axis element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + axis = wcs.CoordAxis1D(self._get_axis("axis", el, ns, True)) + axis.error = self._get_coord_error("error", el, ns, False) + axis.range = self._get_coord_range1d("range", el, ns, False) + axis.bounds = self._get_coord_bounds1d("bounds", el, ns, False) + axis.function = self._get_coord_function1d("function", el, ns, False) + return axis + + def _get_transition(self, element_tag, parent, ns, required): + """Build an EnergyTransition object from an XML representation of + a transition element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the transition element + ns : namespace of the document + required : boolean indicating whether the element is reuiqred + return : an EnergyTransition object or + None if the document does not contain a transition element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return wcs.EnergyTransition( + self._get_child_text("species", el, ns, True), + self._get_child_text("transition", el, ns, True)) + + def _get_spectral_wcs(self, element_tag, parent, ns, required): + """Build a SpectralWCS object from an XML representation of an energy + element. + + Arguments: + elTag : element tag which indentifies the element + parent : element containing the position element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a SpectralWCS object or + None if the document does not contain an energy element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + energy = chunk.SpectralWCS( + self._get_coord_axis1d("axis", el, ns, True), + self._get_child_text("specsys", el, ns, True)) + energy.ssysobs = \ + self._get_child_text("ssysobs", el, ns, False) + energy.ssyssrc = \ + self._get_child_text("ssyssrc", el, ns, False) + energy.restfrq = \ + self._get_child_text_as_float("restfrq", el, ns, False) + energy.restwav = \ + self._get_child_text_as_float("restwav", el, ns, False) + energy.velosys = \ + self._get_child_text_as_float("velosys", el, ns, False) + energy.zsource = \ + self._get_child_text_as_float("zsource", el, ns, False) + energy.velang = \ + self._get_child_text_as_float("velang", el, ns, False) + energy.bandpass_name = \ + self._get_child_text("bandpassName", el, ns, False) + energy.resolving_power = \ + self._get_child_text_as_float("resolvingPower", el, ns, False) + energy.transition = \ + self._get_transition("transition", el, ns, False) + return energy + + def _get_temporal_wcs(self, element_tag, parent, ns, required): + """Build a TemporalWCS object from an XML representation of an time + element. + + Arguments: + elTag : element tag which indentifies the element + parent : element containing the position element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a TemporalWCS object or + None if the document does not contain an time element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + time = chunk.TemporalWCS( + self._get_coord_axis1d("axis", el, ns, True)) + time.timesys = \ + self._get_child_text("timesys", el, ns, False) + time.trefpos = \ + self._get_child_text("trefpos", el, ns, False) + time.mjdref = \ + self._get_child_text_as_float("mjdref", el, ns, False) + time.exposure = \ + self._get_child_text_as_float("exposure", el, ns, False) + time.resolution = \ + self._get_child_text_as_float("resolution", el, ns, False) + return time + + def _get_polarization_wcs(self, element_tag, parent, ns, required): + """Build a PolarizationWCS object from an XML representation of a + polarization element. + + Arguments: + elTag : element tag which indentifies the element + parent : element containing the position element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a PolarizationWCS object or + None if the document does not contain an polarization element + raise : ObservationParsingException + """ + el = self._get_child_element(element_tag, parent, ns, required) + if el is None: + return None + else: + return chunk.PolarizationWCS( + self._get_coord_axis1d("axis", el, ns, False)) + + def _add_chunks(self, chunks, parent, ns): + """Build Chunk objects from an XML representation of Chunk elements + and add them to the set of Chunks. + + Argument: + chunks : set of Chunk objects from the Part + parent : element containing the Chunk elements + ns : namespace of the document + raise : ObservationParsingException + """ + el = self._get_child_element("chunks", parent, ns, False) + if el is None: + return None + else: + for chunk_element in el.iterchildren("{" + ns + "}chunk"): + _chunk = chunk.Chunk() + product_type = \ + self._get_child_text("productType", chunk_element, ns, False) + if product_type: + _chunk.product_type = \ + chunk.ProductType(product_type) + _chunk.naxis = \ + self._get_child_text_as_int("naxis", chunk_element, ns, False) + _chunk.observable_axis = \ + self._get_child_text_as_int("observableAxis", chunk_element, ns, + False) + _chunk.position_axis_1 = \ + self._get_child_text_as_int("positionAxis1", chunk_element, ns, + False) + _chunk.position_axis_2 = \ + self._get_child_text_as_int("positionAxis2", chunk_element, ns, + False) + _chunk.energy_axis = \ + self._get_child_text_as_int("energyAxis", chunk_element, ns, False) + _chunk.time_axis = \ + self._get_child_text_as_int("timeAxis", chunk_element, ns, False) + _chunk.polarization_axis = \ + self._get_child_text_as_int("polarizationAxis", chunk_element, ns, + False) + _chunk.observable = \ + self._get_observable_axis("observable", chunk_element, ns, False) + _chunk.position = \ + self._get_spatial_wcs("position", chunk_element, ns, False) + _chunk.energy = \ + self._get_spectral_wcs("energy", chunk_element, ns, False) + _chunk.time = \ + self._get_temporal_wcs("time", chunk_element, ns, False) + _chunk.polarization = \ + self._get_polarization_wcs("polarization", chunk_element, ns, + False) + self._set_entity_attributes(chunk_element, ns, _chunk) + chunks.append(_chunk) + + def _add_parts(self, parts, parent, ns): + """Build Part objects from an XML representation of Part elements and + add them to the set of Parts. + + Argument: + parts : set of Part objects from the Artifact + parent : element containing the Part elements + ns : namespace of the document + raise : ObservationParsingException + """ + el = self._get_child_element("parts", parent, ns, False) + if el is None: + return None + else: + for part_element in el.iterchildren("{" + ns + "}part"): + _part = \ + part.Part(self._get_child_text("name", part_element, ns, True)) + product_type = \ + self._get_child_text("productType", part_element, ns, False) + if product_type: + _part.product_type = \ + chunk.ProductType(product_type) + self._add_chunks(_part.chunks, part_element, ns) + self._set_entity_attributes(part_element, ns, _part) + parts[_part.name] = _part + + def _add_artifacts(self, artifacts, parent, ns): + """Build artifacts from an XML representation of the artifact elements + and add them to the set of Artifacts. + + Arguments: + artifacts : set of Artifacts from the Plane + parent : element containing the Artifact elements + ns : namespace fo the document + raise : ObservationParsingException + """ + el = self._get_child_element("artifacts", parent, ns, False) + if el is None: + return None + else: + for artifact_element in el.iterchildren("{" + ns + "}artifact"): + uri = self._get_child_text("uri", artifact_element, ns, True) + + product_type = self._get_child_text("productType", artifact_element, ns, False) + if product_type is None: + product_type = chunk.ProductType.SCIENCE + print("Using default Artifact.productType value {0}".format(str(chunk.ProductType.SCIENCE))) + else: + product_type = chunk.ProductType(product_type) + + release_type = self._get_child_text("releaseType", artifact_element, ns, False) + if release_type is None: + release_type = artifact.ReleaseType.DATA + print("Using default Artifact.releaseType value {0}".format(str(artifact.ReleaseType.DATA))) + else: + release_type = artifact.ReleaseType(release_type) + + _artifact = artifact.Artifact(uri, product_type, release_type) + _artifact.content_type = self._get_child_text("contentType", artifact_element, ns, False) + _artifact.content_length = ( + self._get_child_text_as_long("contentLength", artifact_element, ns, False)) + self._add_parts(_artifact.parts, artifact_element, ns) + self._set_entity_attributes(artifact_element, ns, _artifact) + artifacts[_artifact.uri] = _artifact + + def _add_planes(self, planes, parent, ns): + """Create Planes object from XML representation of Plane elements + and add them to the set of Planes. + + Arguments: + planes : Set of planes from the parent Observation object + parent : element containing the Plane elements + ns : namespace of the document + raise : ObservationParsingException + """ + el = self._get_child_element("planes", parent, ns, False) + if el is None: + return None + else: + for plane_element in el.iterchildren("{" + ns + "}plane"): + _plane = plane.Plane( + self._get_child_text("productID", plane_element, ns, True)) + _plane.meta_release = caom_util.str2ivoa( + self._get_child_text("metaRelease", plane_element, ns, False)) + _plane.data_release = caom_util.str2ivoa( + self._get_child_text("dataRelease", plane_element, ns, False)) + data_product_type = \ + self._get_child_text("dataProductType", plane_element, ns, False) + if data_product_type: + _plane.data_product_type = \ + plane.DataProductType(data_product_type) + calibration_level = \ + self._get_child_text("calibrationLevel", plane_element, ns, False) + if calibration_level: + _plane.calibration_level = \ + plane.CalibrationLevel(int(calibration_level)) + _plane.provenance = \ + self._get_provenance("provenance", plane_element, ns, False) + _plane.metrics = \ + self._get_metrics("metrics", plane_element, ns, False) + _plane.quality = \ + self._get_quality("quality", plane_element, ns, False) + self._add_artifacts(_plane.artifacts, plane_element, ns) + self._set_entity_attributes(plane_element, ns, _plane) + planes[_plane.product_id] = _plane + + if not planes: + error = "No plane element found in planes" + raise ObservationParsingException(error) + + def read(self, source): + """Build an Observation object from an XML document located in source. + Source an be a file name/path, a file object, a file-like object or a + URL using the HTTP or FTP protocol. + + Arguments: + source : source of XML document containing an Observation element + return : an Observation object + raise : ObservationParsingException + """ + doc = etree.parse(source) + if self._validate and self._xmlschema: + self._xmlschema.assertValid(doc) + root = doc.getroot() + ns = root.nsmap["caom2"] + collection = unicode(self._get_child_element("collection", root, ns, True).text) + observation_id = \ + unicode(self._get_child_element("observationID", root, ns, True).text) + # Instantiate Algorithm + algorithm = self._get_algorithm("algorithm", root, ns, True) + # Instantiate Observation + if root.get("{http://www.w3.org/2001/XMLSchema-instance}type") \ + == "caom2:SimpleObservation": + obs = observation.SimpleObservation(collection, observation_id) + obs.algorithm = algorithm + else: + obs = \ + observation.CompositeObservation(collection, observation_id, algorithm) + # Instantiate children of Observation + obs.sequence_number = \ + self._get_child_text_as_int("sequenceNumber", root, ns, False) + obs.obs_type = \ + self._get_child_text("type", root, ns, False) + intent = self._get_child_text("intent", root, ns, False) + if intent: + obs.intent = observation.ObservationIntentType(intent) + obs.meta_release = \ + self._get_meta_release("metaRelease", root, ns, False) + obs.proposal = \ + self._get_proposal("proposal", root, ns, False) + obs.target = \ + self._get_target("target", root, ns, False) + obs.target_position = \ + self._get_target_position("targetPosition", root, ns, False) + obs.telescope = \ + self._get_telescope("telescope", root, ns, False) + obs.instrument = \ + self._get_instrument("instrument", root, ns, False) + obs.environment = \ + self._get_environment("environment", root, ns, False) + obs.requirements = \ + self._get_requirements("requirements", root, ns, False) + self._add_planes(obs.planes, root, ns) + if isinstance(obs, observation.CompositeObservation): + self._add_members(obs.members, root, ns) + + self._set_entity_attributes(root, ns, obs) + return obs + + +class ObservationWriter(object): + """ ObservationWriter """ + + def __init__(self, validate=False, write_empty_collections=False, + namespace_prefix="caom2", namespace=None): + """ + Arguments: + validate : If True enable schema validation, False otherwise + write_empty_collections : if True write empty elements for empty collections + namespace_prefix : a CAOM-2.x namespace prefix + namespace : a valid CAOM-2.x target namespace + """ + self._validate = validate + self._write_empty_collections = write_empty_collections + + if namespace_prefix is None or not namespace_prefix: + raise RuntimeError('null or empty namespace_prefix not allowed') + + if namespace is None or namespace == CAOM22_NAMESPACE: + self._output_version = 22 + self._caom2_namespace = CAOM22 + self._namespace = CAOM22_NAMESPACE + elif namespace == CAOM21_NAMESPACE: + self._output_version = 21 + self._caom2_namespace = CAOM21 + self._namespace = CAOM21_NAMESPACE + elif namespace == CAOM20_NAMESPACE: + self._output_version = 20 + self._caom2_namespace = CAOM20 + self._namespace = CAOM20_NAMESPACE + else: + raise RuntimeError('invalid namespace {}'.format(namespace)) + + if self._validate: + if self._output_version == 20: + schema_file = CAOM20_SCHEMA_FILE + elif self._output_version == 21: + schema_file = CAOM21_SCHEMA_FILE + else: + schema_file = CAOM22_SCHEMA_FILE + schema_path = os.path.join(THIS_DIR + '/' + DATA_PKG, + schema_file) + # schema_path = pkg_resources.resource_filename( + # DATA_PKG, schema_file) + xmlschema_doc = etree.parse(schema_path) + self._xmlschema = etree.XMLSchema(xmlschema_doc) + + self._nsmap = {namespace_prefix: self._namespace, "xsi": XSI_NAMESPACE} + + def write(self, obs, out): + assert isinstance(obs, observation.Observation), ( + "observation is not an Observation") + + obs_element = etree.Element(self._caom2_namespace + "Observation", nsmap=self._nsmap) + if isinstance(obs, observation.SimpleObservation): + obs_element.set(XSI + "type", "caom2:SimpleObservation") + else: + obs_element.set(XSI + "type", "caom2:CompositeObservation") + + self._add_enity_attributes(obs, obs_element) + + self._add_element("collection", obs.collection, obs_element) + self._add_element("observationID", obs.observation_id, obs_element) + self._add_datetime_element("metaRelease", obs.meta_release, obs_element) + self._add_element("sequenceNumber", obs.sequence_number, obs_element) + self._add_algorithm_element(obs.algorithm, obs_element) + self._add_element("type", obs.obs_type, obs_element) + if obs.intent is not None: + self._add_element( + "intent",obs.intent.value, obs_element) + + self._add_proposal_element(obs.proposal, obs_element) + self._add_target_element(obs.target, obs_element) + self._add_target_position_element(obs.target_position, obs_element) + self._add_requirements_element(obs.requirements, obs_element) + self._add_telescope_element(obs.telescope, obs_element) + self._add_instrument_element(obs.instrument, obs_element) + self._add_environment_element(obs.environment, obs_element) + self._add_planes_element(obs.planes, obs_element) + + if isinstance(obs, observation.CompositeObservation): + self._add_members_element(obs.members, obs_element) + + if self._validate and self._xmlschema: + self._xmlschema.assertValid(obs_element) + + out.write(etree.tostring(obs_element, xml_declaration=True, encoding='UTF-8', + pretty_print=True)) + + def _add_enity_attributes(self, entity, element): + if self._output_version == 20: + uid = caom_util.uuid2long(entity._id) + self._add_attribute("id", str(uid), element) + else: + self._add_attribute("id", str(entity._id), element) + + if entity._last_modified is not None: + self._add_attribute( + "lastModified", caom_util.date2ivoa(entity._last_modified), element) + + def _add_algorithm_element(self, algorithm, parent): + if algorithm is None: + return + + element = self._get_caom_element("algorithm", parent) + self._add_element("name", algorithm.name, element) + + def _add_proposal_element(self, proposal, parent): + if proposal is None: + return + + element = self._get_caom_element("proposal", parent) + self._add_element("id", proposal.proposal_id, element) + self._add_element("pi", proposal.pi_name, element) + self._add_element("project", proposal.project, element) + self._add_element("title", proposal.title, element) + self._add_list_element("keywords", proposal.keywords, element) + + def _add_target_element(self, target, parent): + if target is None: + return + + element = self._get_caom_element("target", parent) + self._add_element("name", target.name, element) + if target.target_type is not None: + self._add_element("type", target.target_type.value, element) + if target.standard is not None: + self._add_element("standard", str(target.standard).lower(), element) + self._add_element("redshift", target.redshift, element) + if target.moving is not None: + self._add_element("moving", str(target.moving).lower(), element) + self._add_list_element("keywords", target.keywords, element) + + def _add_target_position_element(self, target_position, parent): + if target_position is None: + return + + element = self._get_caom_element("targetPosition", parent) + self._add_element("coordsys", target_position.coordsys, element) + if target_position.equinox is not None: + self._add_element("equinox", target_position.equinox, element) + self._add_point_element("coordinates", target_position.coordinates, + element) + + def _add_requirements_element(self, requirements, parent): + if self._output_version < 21: + return # Requirements added in CAOM-2.1 + if requirements is None: + return + + element = self._get_caom_element("requirements", parent) + self._add_element( + "flag", requirements.flag.value, element) + + def _add_telescope_element(self, telescope, parent): + if telescope is None: + return + + element = self._get_caom_element("telescope", parent) + self._add_element("name", telescope.name, element) + self._add_element("geoLocationX", telescope.geo_location_x, element) + self._add_element("geoLocationY", telescope.geo_location_y, element) + self._add_element("geoLocationZ", telescope.geo_location_z, element) + self._add_list_element("keywords", telescope.keywords, element) + + def _add_instrument_element(self, instrument, parent): + if instrument is None: + return + + element = self._get_caom_element("instrument", parent) + self._add_element("name", instrument.name, element) + self._add_list_element("keywords", instrument.keywords, element) + + def _add_environment_element(self, environment, parent): + if environment is None: + return + + element = self._get_caom_element("environment", parent) + self._add_element("seeing", environment.seeing, element) + self._add_element("humidity", environment.humidity, element) + self._add_element("elevation", environment.elevation, element) + self._add_element("tau", environment.tau, element) + self._add_element("wavelengthTau", environment.wavelength_tau, element) + self._add_element("ambientTemp", environment.ambient_temp, element) + if environment.photometric is not None: + self._add_element("photometric", + str(environment.photometric).lower(), element) + + def _add_members_element(self, members, parent): + if members is None or \ + (len(members) == 0 and not self._write_empty_collections): + return + + element = self._get_caom_element("members", parent) + for member in members: + member_element = self._get_caom_element("observationURI", element) + member_element.text = member.uri + + def _add_planes_element(self, planes, parent): + if planes is None or \ + (len(planes) == 0 and not self._write_empty_collections): + return + + element = self._get_caom_element("planes", parent) + for _plane in planes.itervalues(): + plane_element = self._get_caom_element("plane", element) + self._add_enity_attributes(_plane, plane_element) + self._add_element("productID", _plane.product_id, plane_element) + self._add_datetime_element("metaRelease", _plane.meta_release, + plane_element) + self._add_datetime_element("dataRelease", _plane.data_release, + plane_element) + if _plane.data_product_type is not None: + self._add_element("dataProductType", + _plane.data_product_type.value, + plane_element) + if _plane.calibration_level is not None: + self._add_element("calibrationLevel", + _plane.calibration_level.value, + plane_element) + self._add_provenance_element(_plane.provenance, plane_element) + self._add_metrics_element(_plane.metrics, plane_element) + self._add_quality_element(_plane.quality, plane_element) + self._add_artifacts_element(_plane.artifacts, plane_element) + + def _add_provenance_element(self, provenance, parent): + if provenance is None: + return + + element = self._get_caom_element("provenance", parent) + self._add_element("name", provenance.name, element) + self._add_element("version", provenance.version, element) + self._add_element("project", provenance.project, element) + self._add_element("producer", provenance.producer, element) + self._add_element("runID", provenance.run_id, element) + self._add_element("reference", provenance.reference, element) + self._add_datetime_element("lastExecuted", provenance.last_executed, + element) + self._add_list_element("keywords", provenance.keywords, element) + self._add_inputs_element("inputs", provenance.inputs, element) + + def _add_metrics_element(self, metrics, parent): + if metrics is None: + return + + element = self._get_caom_element("metrics", parent) + self._add_element("sourceNumberDensity", metrics.source_number_density, + element) + self._add_element("background", metrics.background, element) + self._add_element("backgroundStddev", metrics.background_std_dev, + element) + self._add_element("fluxDensityLimit", metrics.flux_density_limit, + element) + self._add_element("magLimit", metrics.mag_limit, element) + + def _add_quality_element(self, quality, parent): + if self._output_version < 21: + return # Requirements added in CAOM-2.1 + if quality is None: + return + + element = self._get_caom_element("quality", parent) + self._add_element("flag", quality.flag.value, element) + + def _add_transition_element(self, transition, parent): + if transition is None: + return + + element = self._get_caom_element("transition", parent) + self._add_element("species", transition.species, element) + self._add_element("transition", transition.transition, element) + + def _add_artifacts_element(self, artifacts, parent): + if artifacts is None: + return + + element = self._get_caom_element("artifacts", parent) + for _artifact in artifacts.itervalues(): + artifact_element = self._get_caom_element("artifact", element) + self._add_enity_attributes(_artifact, artifact_element) + self._add_element("uri", _artifact.uri, artifact_element) + if self._output_version > 21: + self._add_element("productType", _artifact.product_type.value, artifact_element) + self._add_element("releaseType", _artifact.release_type.value, artifact_element) + self._add_element("contentType", _artifact.content_type, artifact_element) + self._add_element("contentLength", _artifact.content_length, artifact_element) + if self._output_version < 22: + self._add_element("productType", _artifact.product_type.value, artifact_element) + self._add_parts_element(_artifact.parts, artifact_element) + + def _add_parts_element(self, parts, parent): + if parts is None: + return + + element = self._get_caom_element("parts", parent) + for _part in parts.itervalues(): + part_element = self._get_caom_element("part", element) + self._add_enity_attributes(_part, part_element) + self._add_element("name", _part.name, part_element) + if _part.product_type is not None: + self._add_element("productType", _part.product_type.value, part_element) + self._add_chunks_element(_part.chunks, part_element) + + def _add_chunks_element(self, chunks, parent): + if chunks is None: + return + + element = self._get_caom_element("chunks", parent) + for _chunk in chunks: + chunk_element = self._get_caom_element("chunk", element) + self._add_enity_attributes(_chunk, chunk_element) + if _chunk.product_type is not None: + self._add_element("productType", + _chunk.product_type.value, + chunk_element) + self._add_element("naxis", _chunk.naxis, chunk_element) + self._add_element("observableAxis", _chunk.observable_axis, + chunk_element) + self._add_element("positionAxis1", _chunk.position_axis_1, + chunk_element) + self._add_element("positionAxis2", _chunk.position_axis_2, + chunk_element) + self._add_element("energyAxis", _chunk.energy_axis, chunk_element) + self._add_element("timeAxis", _chunk.time_axis, chunk_element) + self._add_element("polarizationAxis", _chunk.polarization_axis, + chunk_element) + + self._add_observable_axis_element(_chunk.observable, chunk_element) + self._add_spatial_wcs_element(_chunk.position, chunk_element) + self._add_spectral_wcs_element(_chunk.energy, chunk_element) + self._add_temporal_wcs_element(_chunk.time, chunk_element) + self._add_polarization_wcs_element(_chunk.polarization, chunk_element) + + def _add_observable_axis_element(self, observable, parent): + if observable is None: + return + + element = self._get_caom_element("observable", parent) + self._add_slice_element("dependent", observable.dependent, element) + self._add_slice_element("independent", observable.independent, element) + + def _add_spatial_wcs_element(self, position, parent): + """ Builds a representation of a SpatialWCS and adds it to the + parent element. """ + if position is None: + return + + element = self._get_caom_element("position", parent) + self._add_coord_axis2d_element("axis", position.axis, element) + self._add_element("coordsys", position.coordsys, element) + self._add_element("equinox", position.equinox, element) + self._add_element("resolution", position.resolution, element) + + def _add_spectral_wcs_element(self, energy, parent): + """ Builds a representation of a SpectralWCS and adds it to the + parent element.""" + if energy is None: + return + + element = self._get_caom_element("energy", parent) + self._add_coord_axis1d_element("axis", energy.axis, element) + self._add_element("specsys", energy.specsys, element) + self._add_element("ssysobs", energy.ssysobs, element) + self._add_element("ssyssrc", energy.ssyssrc, element) + self._add_element("restfrq", energy.restfrq, element) + self._add_element("restwav", energy.restwav, element) + self._add_element("velosys", energy.velosys, element) + self._add_element("zsource", energy.zsource, element) + self._add_element("velang", energy.velang, element) + self._add_element("bandpassName", energy.bandpass_name, element) + self._add_element("resolvingPower", energy.resolving_power, element) + self._add_transition_element(energy.transition, element) + + def _add_temporal_wcs_element(self, time, parent): + """ Builds a representation of a TemporalWCS and adds it to the + parent element. """ + if time is None: + return + + element = self._get_caom_element("time", parent) + self._add_coord_axis1d_element("axis", time.axis, element) + self._add_element("timesys", time.timesys, element) + self._add_element("trefpos", time.trefpos, element) + self._add_element("mjdref", time.mjdref, element) + self._add_element("exposure", time.exposure, element) + self._add_element("resolution", time.resolution, element) + + def _add_polarization_wcs_element(self, polarization, parent): + """ Builds a representation of a PolarizationWCS and adds it to the + parent element. """ + if polarization is None: + return + + element = self._get_caom_element("polarization", parent) + self._add_coord_axis1d_element("axis", polarization.axis, element) + + # /*+ CAOM2 Types #-*/ + + def _add_point_element(self, name, point, parent): + """ Builds a representation of a Point and adds it to the + parent element. """ + if point is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("cval1", point.cval1, element) + self._add_element("cval2", point.cval2, element) + + # /*+ WCS Types #-*/ + + def _add_axis_element(self, name, axis, parent): + """ Builds a representation of a Axis and adds it to the + parent element. """ + if axis is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("ctype", axis.ctype, element) + if axis.cunit: + self._add_element("cunit", axis.cunit, element) + + def _add_coord2d_element(self, name, coord, parent): + """ Builds a representation of a Coord2D and adds it to the + parent element. """ + if coord is None: + return + + element = self._get_caom_element(name, parent) + self._add_ref_coord_element("coord1", coord.coord1, element) + self._add_ref_coord_element("coord2", coord.coord2, element) + + def _add_value_coord2d_element(self, name, coord, parent): + """ Builds a representation of a ValueCoord2D and adds it to the + parent element. """ + if coord is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("coord1", coord.coord1, element) + self._add_element("coord2", coord.coord2, element) + + def _add_coord_axis1d_element(self, name, axis, parent): + """ Builds a representation of a CoordAxis1D and adds it to the + parent element. """ + if axis is None: + return + + element = self._get_caom_element(name, parent) + self._add_axis_element("axis", axis.axis, element) + self._add_coord_error_element("error", axis.error, element) + self._add_coord_range1d_element("range", axis.range, element) + self._add_coord_bounds1d_element("bounds", axis.bounds, element) + self._add_coord_function1d_element("function", axis.function, element) + + def _add_coord_axis2d_element(self, name, axis, parent): + """ Builds a representation of a CoordAxis2D and adds it to the + parent element. """ + if axis is None: + return + + element = self._get_caom_element(name, parent) + self._add_axis_element("axis1", axis.axis1, element) + self._add_axis_element("axis2", axis.axis2, element) + self._add_coord_error_element("error1", axis.error1, element) + self._add_coord_error_element("error2", axis.error2, element) + self._add_coord_range2d_element("range", axis.range, element) + self._add_coord_bounds2d_element("bounds", axis.bounds, element) + self._add_coord_function2d_element("function", axis.function, element) + + def _add_coord_bounds1d_element(self, name, bounds, parent): + """ Builds a representation of a CoordBounds1D and adds it to the + parent element. """ + if bounds is None: + return + + element = self._get_caom_element(name, parent) + self._add_coord_range_1d_list_element("samples", bounds.samples, element) + + def _add_coord_bounds2d_element(self, name, bounds, parent): + """Builds a representation of a CoordBounds2D and adds it to the + parent element. """ + if bounds is None: + return + + element = self._get_caom_element(name, parent) + if isinstance(bounds, wcs.CoordCircle2D): + self._add_coord_circle2d_element("circle", + wcs.CoordCircle2D(bounds.center, + bounds.radius), + element) + elif isinstance(bounds, wcs.CoordPolygon2D): + self._add_coord_polygon2d_element("polygon", bounds, element) + else: + raise TypeError("BUG: unsupported CoordBounds2D type " + + bounds.__class__.__name__) + + def _add_coord_circle2d_element(self, name, circle, parent): + """ Builds a representation of a CoordCircle2D and adds it to the + parent element. """ + if circle is None: + return + + element = self._get_caom_element(name, parent) + self._add_value_coord2d_element("center", circle.center, element) + self._add_element("radius", circle.radius, element) + + def _add_coord_error_element(self, name, error, parent): + """ Builds a representation of a CoordError and adds it to the + parent element. """ + if error is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("syser", error.syser, element) + self._add_element("rnder", error.rnder, element) + + def _add_coord_function1d_element(self, name, function, parent): + """ Builds a representation of a CoordFunction1D and adds it to the + parent element. """ + if function is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("naxis", function.naxis, element) + self._add_element("delta", function.delta, element) + self._add_ref_coord_element("refCoord", function.ref_coord, element) + + def _add_coord_function2d_element(self, name, function, parent): + """ Builds a representation of a CoordFunction2D and adds it to the + parent element. """ + if function is None: + return + + element = self._get_caom_element(name, parent) + self._add_dimension2d_element("dimension", function.dimension, element) + self._add_coord2d_element("refCoord", function.ref_coord, element) + self._add_element("cd11", function.cd11, element) + self._add_element("cd12", function.cd12, element) + self._add_element("cd21", function.cd21, element) + self._add_element("cd22", function.cd22, element) + + def _add_coord_polygon2d_element(self, name, polygon, parent): + """ Builds a representation of a CoordPolygon2D and adds it to the + parent element. """ + if polygon is None: + return + + element = self._get_caom_element(name, parent) + if len(polygon.vertices) > 0: + vertices_element = self._get_caom_element("vertices", element) + for vertex in polygon.vertices: + self._add_value_coord2d_element("vertex", vertex, vertices_element) + + def _add_coord_range1d_element(self, name, _range, parent): + """ Builds a representation of a CoordRange1D and adds it to the + parent element. """ + if _range is None: + return + + element = self._get_caom_element(name, parent) + self._add_ref_coord_element("start", _range.start, element) + self._add_ref_coord_element("end", _range.end, element) + + def _add_coord_range2d_element(self, name, _range, parent): + """ Builds a representation of a CoordRange2D and adds it to the + parent element. """ + if _range is None: + return + + element = self._get_caom_element(name, parent) + self._add_coord2d_element("start", _range.start, element) + self._add_coord2d_element("end", _range.end, element) + + def _add_dimension2d_element(self, name, dimension, parent): + """ Builds a representation of a Dimension2D and adds it to the + parent element. """ + if dimension is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("naxis1", dimension.naxis1, element) + self._add_element("naxis2", dimension.naxis2, element) + + def _add_ref_coord_element(self, name, ref_coord, parent): + """ Builds a representation of a RefCoord and adds it to the + parent element. """ + if ref_coord is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("pix", ref_coord.pix, element) + self._add_element("val", ref_coord.val, element) + + def _add_slice_element(self, name, _slice, parent): + """ Builds a representation of a Slice and adds it to the + parent element. """ + if _slice is None: + return + + element = self._get_caom_element(name, parent) + self._add_axis_element("axis", _slice.axis, element) + self._add_element("bin", _slice.bin, element) + + def _add_attribute(self, name, value, element): + element.set(self._caom2_namespace + name, value) + + def _add_element(self, name, text, parent): + if text is None: + return + element = self._get_caom_element(name, parent) + if isinstance(text, str): + element.text = text + else: + element.text = str(text) + + def _add_datetime_element(self, name, value, parent): + if value is None: + return + element = self._get_caom_element(name, parent) + element.text = caom_util.date2ivoa(value) + + def _add_list_element(self, name, collection, parent): + if collection is None or \ + (len(collection) == 0 and not self._write_empty_collections): + return + element = self._get_caom_element(name, parent) + element.text = ' '.join(collection) + + def _add_coord_range_1d_list_element(self, name, values, parent): + if values is None: + return + element = self._get_caom_element(name, parent) + for v in values: + self._add_coord_range1d_element("range", v, element) + + def _add_inputs_element(self, name, collection, parent): + if collection is None or \ + (len(collection) == 0 and not self._write_empty_collections): + return + element = self._get_caom_element(name, parent) + for plane_uri in collection: + self._add_element("planeURI", plane_uri.uri, element) + + def _get_caom_element(self, tag, parent): + return etree.SubElement(parent, self._caom2_namespace + tag) + + +class ObservationParsingException(Exception): + pass diff --git a/caom2/caom2/observation.py b/caom2/caom2/observation.py new file mode 100644 index 00000000..ad997a02 --- /dev/null +++ b/caom2/caom2/observation.py @@ -0,0 +1,1236 @@ +# -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +# *********************************************************************** +# + +"""definition of the caom2.Observation object.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from datetime import datetime + +from enum import Enum + +from . import caom_util +from .common import AbstractCaomEntity +from .common import CaomObject +from .common import ObservationURI +from .plane import Plane +from .shape import Point + +__all__ = ['ObservationIntentType', 'Status', 'TargetType', + 'Observation', 'ObservationURI', 'Algorithm', 'SimpleObservation', + 'CompositeObservation', 'Environment', 'Instrument', 'Proposal', + 'Requirements', 'Target', 'TargetPosition', 'Telescope'] + + +class ObservationIntentType(Enum): + """ + CALIBRATION: "calibration" + SCIENCE: "science" + """ + CALIBRATION = "calibration" + SCIENCE = "science" + + +class Status(Enum): + """ + FAIL: "fail" + """ + FAIL = "fail" + + +class TargetType(Enum): + """ + FIELD: "field", + OBJECT: "object" + """ + FIELD = "field" + OBJECT = "object" + + +class Observation(AbstractCaomEntity): + """ + Observation + + An observation describes a set of empirical data. + + The CAOM2 observation is described at: + http://www.cadc.hia.nrc.gc.ca/caom2 + + The Observation object is the top level container for the + meta-data assocaited with an observation. The variaous attributes + described here provide ways of storing the complete set of + associated meta-data as well as links to the actual observation + data. + + Observation -> Target + -> Plane(s) + -> Instrument + -> Telescope + -> Proposal + -> Environment + -> TargetPosition + + Plane -> Artifact(s) + + Artifact -> Part(s) + + Part -> Chunk(s) + + The actual 'chunks' of observational data are reference by Chunk + objects. Information about the Spatial/Frequency/Time aspects of + an Observation are expressed at the Chunk level. + + The Chunk contains refernces to caom2 objects that fully describe + the circumstances of that chunk of observation. Often a 'Chunk' + is a single extension in a FITS image. But can also be a + particular column of values from a FITS Table or some other data + object. + + Chunk -> SpatialWCS + -> TemporalWCS + -> SpectralWCS + -> PolarizationWCS + -> (Observable) + """ + + def __init__(self, + collection, + observation_id, + algorithm, + sequence_number=None, + intent=None, + obs_type=None, + proposal=None, + telescope=None, + instrument=None, + target=None, + meta_release=None, + planes=None, + environment=None, + target_position=None, + requirements=None + ): + """ + Initializes an Observation instance + + Arguments: collection : where the observation is from + (eg. 'HST') + + observation_id : a unique identifier within that collection + (eg. '111') + + algorithm : the algorithm used to create the observation. For + a telescope observation this is always 'exposure' + """ + super(Observation, self).__init__() + + self.collection = collection + self.observation_id = observation_id + self.algorithm = algorithm + + self.uri = ObservationURI.get_observation_uri(collection, + observation_id) + + self.sequence_number = sequence_number + self.intent = intent + self.obs_type = obs_type + self.proposal = proposal + self.telescope = telescope + self.instrument = instrument + self.target = target + self.environment = environment + self.target_position = target_position + self.requirements = requirements + self.meta_release = meta_release + if planes is None: + planes = caom_util.TypedOrderedDict(Plane,) + self.planes = planes + + # Properties + @property + def collection(self): + """The name of the collection of observations, normally a telescope + name. + + type: unicode + """ + return self._collection + + @collection.setter + def collection(self, value): + caom_util.type_check(value, unicode, 'collection', override=False) + self._collection = value + + @property + def observation_id(self): + """A string that uniquely identifies this obseravtion within the given + collection. + + type: unicode + """ + return self._observation_id + + @observation_id.setter + def observation_id(self, value): + caom_util.type_check(value, unicode, 'observation_id', override=False) + self._observation_id = value + + @property + def uri(self): + """A URI for this observation referenced in the caom system. + + This attribute is auto geneqrated from the other metadata. + type: unicode + """ + return self._uri + + @uri.setter + def uri(self, value): + caom_util.type_check(value, ObservationURI, 'uri') + self._uri = value + + @property + def planes(self): + """A typed ordered dictionary containing plane objects associated with + this observations. + + see caom2.Plane for details about a creating a plane. + + type: TypedOrderDict(Plane,) + + eg. Observation.planes.add(Plane("SCIENCE")) + """ + return self._planes + + @planes.setter + def planes(self, value): + caom_util.type_check(value, caom_util.TypedOrderedDict, 'planes') + self._planes = value + + @property + def algorithm(self): + """The process that was used to select this observation. + + normally 'exposure' for an observation or the name of a group + process for a composite observation""" + return self._algorithm + + @algorithm.setter + def algorithm(self, value): + if isinstance(value, unicode): + value = Algorithm(value) + caom_util.type_check(value, Algorithm, 'algorithm') + self._algorithm = value + + @property + def intent(self): + """The original intent of having this data. + + type: ObservationIntentType + + see ObservationIntentType for allowed values + + """ + return self._intent + + @intent.setter + def intent(self, value): + if isinstance(value, unicode): + value = ObservationIntentType(value) + caom_util.type_check(value, ObservationIntentType, 'intent') + self._intent = value + + @property + def sequence_number(self): + """An integer counter that reprsents this observation within a + collection. eg. EXPNUM type: int + """ + return self._sequence_number + + @sequence_number.setter + def sequence_number(self, value): + caom_util.type_check(value, int, 'sequence_number') + self._sequence_number = value + + @property + def obs_type(self): + """The OBSTYPE of the observation being recorded. + + eg. OBJECT, FLAT, BIAS + type: unicode + """ + return self._obs_type + + @obs_type.setter + def obs_type(self, value): + caom_util.type_check(value, unicode, 'obs_type') + self._obs_type = value + + @property + def proposal(self): + """Refence to a Proposal object that describe the science proposal + that lead to this observation. + + can be None + see caom2.Proposal for help on building a Proposal object + type: caom2.Proposal + """ + return self._proposal + + @proposal.setter + def proposal(self, value): + caom_util.type_check(value, Proposal, "proposal") + self._proposal = value + + @property + def telescope(self): + """Reference to a Telescope object associated with this observation. + + can be None + type: caom2.Telescope + """ + return self._telescope + + @telescope.setter + def telescope(self, value): + caom_util.type_check(value, Telescope, 'telescope') + self._telescope = value + + @property + def instrument(self): + """Reference to an Instrument object associated with this observation. + + can be None + type: caom2.Instrument + """ + return self._instrument + + @instrument.setter + def instrument(self, value): + if isinstance(value, unicode): + value = Instrument(value) + caom_util.type_check(value, Instrument, "instrument") + self._instrument = value + + @property + def target(self): + """Reference to a Target object associated with this observation. + + can be None + type: caom2.Target + """ + return self._target + + @target.setter + def target(self, value): + if isinstance(value, unicode): + value = Target(value) + caom_util.type_check(value, Target, 'target') + self._target = value + + @property + def environment(self): + """Reference to an Environment object associated with this + observation. + + can be None + type: caom2.Environment + """ + return self._environment + + @environment.setter + def environment(self, value): + caom_util.type_check(value, Environment, 'environment') + self._environment = value + + @property + def target_position(self): + """Reference to a TargetPosition object associated + with this observation. + + can be None + type: caom2.TargetPosition + """ + return self._target_position + + @target_position.setter + def target_position(self, value): + caom_util.type_check(value, TargetPosition, 'target_position') + self._target_position = value + + @property + def requirements(self): + """Reference to a Requirements object associated + with this observation. + + can be None + type: caom2.Requirements + """ + return self._requirements + + @requirements.setter + def requirements(self, value): + caom_util.type_check(value, Requirements, 'requirements') + self._requirements = value + + @property + def meta_release(self): + """A datetime value indicating when the meta-data of this observation + is publicly accessible. + + This only controls access to the information about the + observation. Access to the observational data is controlled + via the Plane.data_release attribute (see the planes + attribute). + + eg. '2012/11/28 12:00:00' + type: datatime + """ + return self._meta_release + + @meta_release.setter + def meta_release(self, value): + caom_util.type_check(value, datetime, 'meta_release') + self._meta_release = value + + +class Algorithm(CaomObject): + """ + The concept of Algorithm is to provide a way for users to find all + composite observation sets that have been built using a particular + grouping algorithm (eg. the MegaPipe stacks). For simple + observations the algorithm is 'exposure'. + """ + + def __init__(self, name): + """ + Initializes an Algorithm instance + + Arguments: + name : name of the algorithm. Should be 'exposure' if this is a + simple observation, otherwise name of algorithm that selected + composite members or just 'composite' works too. + """ + caom_util.type_check(name, unicode, 'name', override=False) + self._name = name + + def _key(self): + return self._name + + def __ne__(self, y): + return not self.__eq__(y) + + # Properties + + @property + def name(self): + """ + algorithm that defines the composite grouping; 'exposure' for + simple observations + """ + return self._name + + +class SimpleObservation(Observation): + """A convenience class for building Observations where + algorithm='exposure'. + + Simple Observation : an object to store the metadata associated + with a telescopic observation. + + Simple Observations are the basic package for the CAOM2 + model. Each simple observation refers to an observation by a + telescope. + + The metadata content is stored in a variety of objects, see the + caom2_observtion class for details. + + The algorithm value for a simple observation is forced set to + "exposure" + + """ + + _ALGORITHM = Algorithm("exposure") + + def __init__(self, + collection, + observation_id, + algorithm=None, + sequence_number=None, + intent=None, + obs_type=None, + proposal=None, + telescope=None, + instrument=None, + target=None, + meta_release=None, + planes=None, + environment=None, + target_position=None + ): + """ + collection - A name that describes a collection of data, + nominally the name of a telescope + + observation_id - A UNIQUE identifier with in that collection + """ + if algorithm is None: + algorithm = SimpleObservation._ALGORITHM + if algorithm != SimpleObservation._ALGORITHM: + raise ValueError( + "E{0} (required for SimpleObservation)".format(algorithm)) + super(SimpleObservation, self).__init__(collection, + observation_id, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment, + target_position + ) + + @property + def algorithm(self): + """The algorithm that built the observation, for SimpleObservation + this is always 'exposure'""" + + return super(SimpleObservation, self).algorithm + + @algorithm.setter + def algorithm(self, value=_ALGORITHM): + # build an Algorithm type if passed a string... + if isinstance(value, unicode): + value = Algorithm(value) + caom_util.type_check(value, Algorithm, 'algorithm', override=False) + caom_util.value_check(value, None, None, 'algorithm', override=self._ALGORITHM) + self._algorithm = value + + +class CompositeObservation(Observation): + """ + Composite Observation + + A CompositeObservation is created by collecting data from multiple + SimpleObservations together. + + """ + + def __init__(self, + collection, + observation_id, + algorithm, + sequence_number=None, + intent=None, + obs_type=None, + proposal=None, + telescope=None, + instrument=None, + target=None, + meta_release=None, + planes=None, + environment=None, + target_position=None + ): + if algorithm == SimpleObservation._ALGORITHM: + raise ValueError( + "E{0} (reserved for SimpleObservation)".format(algorithm)) + super(CompositeObservation, self).__init__(collection, + observation_id, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment, + target_position + ) + self._members = caom_util.TypedSet(ObservationURI, ) + + @property + def algorithm(self): + return super(CompositeObservation, self).algorithm + + @algorithm.setter + def algorithm(self, value): + if value is None: + raise ValueError + if value == SimpleObservation._ALGORITHM: + raise ValueError("cannot set CompositeObservation.algorithm to {0}" + " (reserved for SimpleObservation)".format(value)) + self._algorithm = value + + @property + def members(self): + return self._members + + +class Environment(CaomObject): + """A CAOM2 Environment Object. + + This object contains the various values that can be set in the environment + table entry. Normally each Observation object will have an associate + Environment Object.""" + + def __init__(self): + """ + Initializes an Environment instance + + Arguments: + """ + self._seeing = None + self._humidity = None + self._elevation = None + self._tau = None + self._wavelength_tau = None + self._ambient_temp = None + self._photometric = None + + # Properties + @property + def seeing(self): + """atmospheric seeing (FWHM) in arcsec. + + units: arcseconds + """ + return self._seeing + + @seeing.setter + def seeing(self, value): + caom_util.type_check(value, float, 'seeing') + caom_util.value_check(value, 0, 360 * 3600.0, 'seeing') + self._seeing = value + + @property + def humidity(self): + """Relative humidity, expressed as a fraction between 0 and 200. + + units: fraction + """ + return self._humidity + + @humidity.setter + def humidity(self, value): + # set the humidity to value, which must be +ve fraction less than 200 + caom_util.type_check(value, float, 'humidity') + caom_util.value_check(value, 0, 200, 'humidity') + self._humidity = value + + @property + def elevation(self): + """ Elevation above horizon (0 to 90 deg) at which tau was measured. + + units: deg + """ + return self._elevation + + @elevation.setter + def elevation(self, value): + caom_util.type_check(value, float, 'elevation') + caom_util.value_check(value, 0, 90, 'elevation') + self._elevation = value + + @property + def tau(self): + """The tau at zennith at the time of observation. + + units: fraction + + This tau can be used, in combination with the elevation, + to determine the actual tau.""" + return self._tau + + @tau.setter + def tau(self, value): + caom_util.type_check(value, float, 'tau') + caom_util.value_check(value, 0, 1, 'tau') + self._tau = value + + @property + def wavelength_tau(self): + """Wavelength at which tau was measured + (normally 225GHz converted to wavelength). + + units: meters + + """ + return self._wavelength_tau + + @wavelength_tau.setter + def wavelength_tau(self, value): + caom_util.type_check(value, float, 'wavelength_tau') + caom_util.value_check(value, 0, 1E3, 'wavelength_tau') + self._wavelength_tau = value + + @property + def ambient_temp(self): + """The ambient air temperature at time of observation. + + unit: Celsius degrees + """ + return self._ambient_temp + + @ambient_temp.setter + def ambient_temp(self, value): + caom_util.type_check(value, float, 'ambient_temp') + caom_util.value_check(value, -100, 100, 'ambient_temp') + self._ambient_temp = value + + @property + def photometric(self): + """A boolean flag (True/False) indicating if + the observational conditions were photometric.""" + return self._photometric + + @photometric.setter + def photometric(self, value): + caom_util.type_check(value, bool, 'photometric') + self._photometric = value + + +class Instrument(CaomObject): + """The telescopic instrument that recorded a given observation. + + Each observation should have an associated instrument. + + eg: + inst=caom2.Observation('CFHT','123456p','exposure').Instrument("MEGAPRIME") + + Each instrument can have list of keywords. + eg. + inst.keywords.append("shutter=closed") + """ + + def __init__(self, name): + """ + Initializes a Instrument instance + + Arguments: + name - name of the instrument + """ + caom_util.type_check(name, unicode, 'name', override='none') + self._name = name + self._keywords = set() + + # Properties + @property + def name(self): + """The name of the instrument. + + type: unicode + """ + return self._name + + @property + def keywords(self): + """A set of strings that are keywords associated with the instrument. + + eg. keywords.append(("ccd=off","hot","shutter broken")) + + Keywords are stored as text in the database and are searched as text, + so in the above example you can search for ccd=off but that is just + matching the text 'ccd=off' and you can not do 'ccd!=on' to find that + key/value pair. + + Also, the list is concated together and inserted into the + model as a single text field, so keywords like 'shutter + broken' will match 'shutter' and 'broken'. If these keywords + appear in a pick list 'shutter' and 'broken' will be seperate + entries. So shutter_broken is a better choice. + """ + return self._keywords + + +class Proposal(CaomObject): + """ Proposal """ + + def __init__(self, + proposal_id, + pi_name=None, + project=None, + title=None): + """ + Initializes a Proposal instance + + Arguments: + myId : id of the proposal + """ + + self.proposal_id = proposal_id + self.pi_name = pi_name + self.project = project + self.title = title + + self.keywords = set() + + # Properties + + @property + def proposal_id(self): + """The proposal ID. Sometimes also called a RUNID. + + type: unicode + """ + return self._proposal_id + + @proposal_id.setter + def proposal_id(self, value): + caom_util.type_check(value, unicode, 'id') + self._proposal_id = value + + @property + def keywords(self): + """A Set of keywords connected to this proposal. + + keywords are stored as a string of words and do not need to be + key/value pairs. + + eg. Proposal.keywords.add('galaxies') + + type: set + """ + return self._keywords + + @keywords.setter + def keywords(self, value): + caom_util.type_check(value, set, 'keywords', override=False) + self._keywords = value + + @property + def pi_name(self): + """The name (First Last) of the Principle Investigator of the + Proposal. + + type: unicode + """ + return self._pi_name + + @pi_name.setter + def pi_name(self, value): + caom_util.type_check(value, unicode, 'pi_name') + self._pi_name = value + + @property + def project(self): + """The name of a project associated with this proposal. + + type: unicode + """ + return self._project + + @project.setter + def project(self, value): + caom_util.type_check(value, unicode, 'project') + self._project = value + + @property + def title(self): + """The title of the proposal. + + type: unicode + """ + return self._title + + @title.setter + def title(self, value): + caom_util.type_check(value, unicode, 'title') + self._title = value + + +class Requirements(CaomObject): + """ Requirements """ + + def __init__(self, flag): + """ + Construct an Requirements instance + + Arguments: + flag + """ + self.flag = flag + + @property + def flag(self): + """ flag """ + return self._flag + + @flag.setter + def flag(self, value): + caom_util.type_check(value, Status, "flag") + self._flag = value + + +class Target(CaomObject): + """ Target """ + + def __init__(self, name, + target_type=None, + standard=None, + redshift=None, + keywords=None, + moving=None): + """ + Initializes a Target instance + + Arguments: + name : name of the target + type : type of the target + """ + + self.name = name + self.target_type = target_type + self.standard = standard + self.redshift = redshift + if keywords is None: + keywords = set() + self.keywords = keywords + self.moving = moving + + # Properties + + @property + def name(self): + """A name for the target + + eg 'NGC 3115' + type: unicode + + """ + return self._name + + @name.setter + def name(self, value): + caom_util.type_check(value, unicode, "name", override=False) + self._name = value + + @property + def target_type(self): + """A keyword describing the type of target. + + must be from the list + """ + str(list(TargetType)) + """ + type: TargetType + + """ + return self._type + + @target_type.setter + def target_type(self, value): + if isinstance(value, unicode): + value = TargetType(value) + caom_util.type_check(value, TargetType, "target_type") + self._type = value + + @property + def keywords(self): + """A set of keywords associated with this target. + + eg. keywords.add('galaxy') + type: set + + """ + return self._keywords + + @keywords.setter + def keywords(self, value): + caom_util.type_check(value, set, 'keywords', override=False) + self._keywords = value + + @property + def standard(self): + """Is this a standard field? + + eg True + type: bool + + """ + return self._standard + + @standard.setter + def standard(self, value): + caom_util.type_check(value, bool, 'standard') + self._standard = value + + @property + def redshift(self): + """The redshift of the observed target. + + eg 1.2 (can be None) + type: float + + """ + return self._redshift + + @redshift.setter + def redshift(self, value): + caom_util.type_check(value, float, 'redshift') + caom_util.value_check(value, -0.5, 1200, 'redshift') + self._redshift = value + + @property + def moving(self): + """Is this a moving target? + + eg True + type: bool + + """ + return self._moving + + @moving.setter + def moving(self, value): + caom_util.type_check(value, bool, 'moving') + self._moving = value + + +class TargetPosition(CaomObject): + """ TargetPosition """ + + def __init__(self, coordinates, coordsys, equinox=None): + """ + Initialize a TargetPosition instance. + + Arguments: + coordinates : target position as a Point. + coordsys: target coordsys + equinox: target equinox + """ + self.coordinates = coordinates + self.coordsys = coordsys + self.equinox = equinox + + # Properties + + @property + def coordinates(self): + """ Coordinates """ + return self._coordinates + + @coordinates.setter + def coordinates(self, value): + caom_util.type_check(value, Point, "coordinates") + self._coordinates = value + + @property + def coordsys(self): + """ Coordsys """ + return self._coordsys + + @coordsys.setter + def coordsys(self, value): + caom_util.type_check(value, unicode, "coordsys") + self._coordsys = value + + @property + def equinox(self): + """ Equinox """ + return self._equinox + + @equinox.setter + def equinox(self, value): + caom_util.type_check(value, float, "equinox") + self._equinox = value + + +class Telescope(CaomObject): + """ Telescope """ + + def __init__(self, name, + geo_location_x=None, + geo_location_y=None, + geo_location_z=None, + keywords=None + ): + """ + Initializes a Telescope instance + + Arguments: + name : name of the telescope + """ + + assert name is not None, "No telescope name provided" + assert isinstance(name, unicode), "name is not a str: {0}".format(name) + self.name = name + self.geo_location_x = geo_location_x + self.geo_location_y = geo_location_y + self.geo_location_z = geo_location_z + if keywords is None: + keywords = set() + self.keywords = keywords + + # Properties + + @property + def name(self): + """a name for this facility. + + eg. CFHT + type: unicode + + """ + return self._name + + @name.setter + def name(self, value): + caom_util.type_check(value, unicode, 'name', override=False) + self._name = value + + @property + def keywords(self): + """A set that contains keywords associated with this telescope + + eg. keywords.add('big') + type: set + + """ + return self._keywords + + @keywords.setter + def keywords(self, value): + caom_util.type_check(value, set, 'keywords', override=False) + self._keywords = value + + @property + def geo_location_x(self): + """The x geocentric location of the telescope. + + This should be valid at time of MJD-OBS. + + These coordinates should be in the ITRS reference, + basically whatever a GPS device is saying. + + The directions of the x/y/z follow the + Earth Centred Rotation frame. + + units: m + type: float + + """ + return self._geo_location_x + + @geo_location_x.setter + def geo_location_x(self, value): + caom_util.type_check(value, float, 'geo_location_x') + self._geo_location_x = value + + @property + def geo_location_y(self): + """the y geocentric (ECR) location of the telescope. + + This should be valid at time of MJD-OBS. + + These coordinates should be in the ITRS reference, + basically whatever a GPS device is saying. + + The directions of the x/y/z follow the + Earth Centred Rotation frame. + + units: m + type: float + + """ + return self._geo_location_y + + @geo_location_y.setter + def geo_location_y(self, value): + caom_util.type_check(value, float, 'geo_location_y') + self._geo_location_y = value + + @property + def geo_location_z(self): + """the z geocentric (ECR) location of the telescope. + This should be valid at time of MJD-OBS. + + These coordinates should be in the ITRS reference, + basically whatever a GPS device is saying. + + The directions of the x/y/z follow the + Earth Centred Rotation frame. + + units: m + type: float + + """ + return self._geo_location_z + + @geo_location_z.setter + def geo_location_z(self, value): + caom_util.type_check(value, float, 'geo_location_z') + self._geo_location_z = value diff --git a/pyCAOM2/caom2/caom2_part.py b/caom2/caom2/part.py similarity index 86% rename from pyCAOM2/caom2/caom2_part.py rename to caom2/caom2/part.py index 2974b44d..6ae23b9f 100644 --- a/pyCAOM2/caom2/caom2_part.py +++ b/caom2/caom2/part.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,20 +64,24 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """Defines the caom2.Part class which describes the caom2_Observation_Plane_Artifact_Part object.""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) -from caom2_entity import AbstractCaom2Entity -from caom2_chunk import Chunk -from caom2_enums import ProductType -import util.caom2_util as util +from . import caom_util +from .chunk import Chunk +from .chunk import ProductType +from .common import AbstractCaomEntity +__all__ = ['Part'] -class Part(AbstractCaom2Entity): + +class Part(AbstractCaomEntity): """A qualitative subsection of an artifact. eg: a extension of a FITS file. @@ -92,7 +95,7 @@ def __init__(self, name, product_type=None, chunks=None): self.name = name self.product_type = product_type if chunks is None: - chunks = util.TypedList((Chunk),) + chunks = caom_util.TypedList(Chunk, ) self.chunks = chunks def _key(self): @@ -111,12 +114,12 @@ def product_type(self): """The type of data product referred to by this part. Must be one of the allowed data product types: - str(ProductType.names())""" + caom2.ProductType""" return self._product_type @product_type.setter def product_type(self, value): - util.typeCheck(value, ProductType, "product_type") + caom_util.type_check(value, ProductType, "product_type") self._product_type = value @property @@ -129,7 +132,7 @@ def name(self): @name.setter def name(self, value): - util.typeCheck(value, str, 'name', override=False) + caom_util.type_check(value, unicode, 'name', override=False) self._name = value @property @@ -144,5 +147,5 @@ def chunks(self): @chunks.setter def chunks(self, value): - util.typeCheck(value, util.TypedList, 'chunks', override=False) + caom_util.type_check(value, caom_util.TypedList, 'chunks', override=False) self._chunks = value diff --git a/caom2/caom2/plane.py b/caom2/caom2/plane.py new file mode 100644 index 00000000..db693fc3 --- /dev/null +++ b/caom2/caom2/plane.py @@ -0,0 +1,1122 @@ +# -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +# *********************************************************************** +# + +"""defines the caom2.Plane class""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from datetime import datetime +from urlparse import SplitResult +from urlparse import urlsplit + +from enum import Enum + +from . import caom_util +from . import shape +from . import wcs +from .artifact import Artifact +from .common import AbstractCaomEntity +from .common import CaomObject +from .common import ObservationURI + +__all__ = ['CalibrationLevel', 'DataProductType', 'EnergyBand', "PolarizationState", "Quality", + 'Plane', 'PlaneURI', 'DataQuality', 'Metrics', 'Provenance', 'Position', 'Energy', + 'Polarization', 'Time'] + + +class CalibrationLevel(Enum): + """ + RAW_INSTRUMENT: 0 + RAW_STANDARD: 1 + CALIBRATED: 2 + PRODUCT: 3 + """ + RAW_INSTRUMENT = 0 + RAW_STANDARD = 1 + CALIBRATED = 2 + PRODUCT = 3 + + +class DataProductType(Enum): + """ + IMAGE: "image" + CATALOG: "catalog" + CUBE: "cube" + EVENTLIST: "eventlist" + SPECTRUM: "spectrum" + TIMESERIES: "timeseries" + VISIBILITY: "visibility" + """ + IMAGE = "image" + CATALOG = "catalog" + CUBE = "cube" + EVENTLIST = "eventlist" + SPECTRUM = "spectrum" + TIMESERIES = "timeseries" + VISIBILITY = "visibility" + + +class EnergyBand(Enum): + """ + GAMMARAY: "Gamma-ray" + INFRARED: "Infrared" + MILLIMETER: "Millimeter" + OPTICAL: "Optical" + RADIO: "Radio" + UV: "UV" + XRAY: "X-ray" + """ + EUV = "EUV" + GAMMARAY = "Gamma-ray" + INFRARED = "Infrared" + MILLIMETER = "Millimeter" + OPTICAL = "Optical" + RADIO = "Radio" + UV = "UV" + XRAY = "X-ray" + + +class PolarizationState(Enum): + """ + I: "I" + Q: "Q" + U: "U" + V: "V" + LL: "LL" + LR: "LR" + RL: "RL" + RR: "RR" + XX: "XX" + XY: "XY" + YX: "YX" + YY: "YY" + """ + I = "I" + Q = "Q" + U = "U" + V = "V" + LL = "LL" + LR = "LR" + RL = "RL" + RR = "RR" + XX = "XX" + XY = "XY" + YX = "YX" + YY = "YY" + + +class Quality(Enum): + """ + JUNK: junk + """ + JUNK = "junk" + + +class Plane(AbstractCaomEntity): + """ Plane class """ + + def __init__(self, product_id, + artifacts=None, + meta_release=None, + data_release=None, + data_product_type=None, + calibration_level=None, + provenance=None, + metrics=None, + quality=None): + """ + Initialize a Plane instance + + Arguments: + product_id : product ID + """ + super(Plane, self).__init__() + self.product_id = product_id + if artifacts is None: + artifacts = caom_util.TypedOrderedDict(Artifact, ) + self.artifacts = artifacts + + self.meta_release = meta_release + self.data_release = data_release + self.data_product_type = data_product_type + self.calibration_level = calibration_level + self.provenance = provenance + self.metrics = metrics + self.quality = quality + + # computed fields + # aggregated from the Chunks during ingestion + self._position = None + self._energy = None + self._time = None + self._polarization = None + + def _key(self): + return self.product_id + + def __hash__(self): + return hash(self._key()) + + # Properties + @property + def product_id(self): + """A string that identifies the data product, within a given + observation, that is stored in this plane. + + eg: '1234567p' + type: unicode + """ + return self._product_id + + @product_id.setter + def product_id(self, value): + caom_util.type_check(value, unicode, 'product_id', override=False) + self._product_id = value + + @property + def key(self): + """ The dictionary key for a plane is product ID """ + return self._product_id + + @property + def artifacts(self): + """A TypeList of artifacts that are part of this plane. + + individual artifacts are constructed and then added to the plane. + + eg. Plane.artifacts.add(Artifact('ad:CFHT/1234567p')), see the + Arifact help for more info on making an Aritfact object return + """ + return self._artifacts + + @artifacts.setter + def artifacts(self, value): + caom_util.type_check(value, caom_util.TypedOrderedDict, 'artifacts', override=False) + self._artifacts = value + + @property + def meta_release(self): + """The date when the metadata describing this observation become + public. + + eg. Plane.meta_releaes=datetime.datetime(2012,1,1,0,0,0) + indicates that the metadata become public at 00:00:00 on + January 1st 2012. + + if there is no meta_release period, set value to None + + unit: calendar date + type: datetime + """ + return self._meta_release + + @meta_release.setter + def meta_release(self, value): + caom_util.type_check(value, datetime, 'meta_release') + caom_util.value_check(value, + datetime(1800, 1, 1, 0, 0, 0), + datetime(2050, 1, 1, 0, 0, 0), + 'meta_release') + self._meta_release = value + + @property + def data_release(self): + """The date when the data contained in this plane become public. + + eg. Plane.data_releaes=datetime.datetime(2012,1,1,0,0,0) + indicates that ar 00:00:00 on January 1st 2012 the data + assocaited with this Plane will become publicly accessible. + + If there is no data_release period, set value to None. + + unit: calendar date + type: datetime + """ + return self._data_release + + @data_release.setter + def data_release(self, value): + caom_util.type_check(value, datetime, 'data_release') + caom_util.value_check(value, + datetime(1800, 1, 1, 0, 0, 0), + datetime(2050, 1, 1, 0, 0, 0), + 'data_release') + self._data_release = value + + @property + def data_product_type(self): + """The type of file structure that this plane contains. + + eg. + Plane.data_product_type = DataProductType['EVENTLIST'] + + see DataProductType for allowed values + + """ + return self._data_product_type + + @data_product_type.setter + def data_product_type(self, value): + caom_util.type_check(value, DataProductType, 'data_product_type') + self._data_product_type = value + + @property + def calibration_level(self): + """a string that represents the level of calibration (aka processing) + the data contained in this plane have received. The string + is converted to an integer during storage. + + eg. Plane.calibration_level = CalibrationLevel['RAW_STANDARD'] + type: unicode + + Must be one of CalibrationLevel + + """ + return self._calibration_level + + @calibration_level.setter + def calibration_level(self, value): + caom_util.type_check(value, CalibrationLevel, "calibration_level") + self._calibration_level = value + + @property + def provenance(self): + """The process that created the data referred to by this Plane. + + eg. Plane.provenance=caom2.Provenance("Elixir") + """ + return self._provenance + + @provenance.setter + def provenance(self, value): + caom_util.type_check(value, Provenance, "provenance") + self._provenance = value + + @property + def metrics(self): + """reference to an object that contains metrics of this plane. + + eg. Plane.metrics = caom2.Metrics() + """ + return self._metrics + + @metrics.setter + def metrics(self, value): + caom_util.type_check(value, Metrics, 'metrics') + self._metrics = value + + @property + def quality(self): + """reference to an object that describes the quality of the data of this plane. + + eg. Plane.data_quality = caom2.DataQuality() + """ + return self._quality + + @quality.setter + def quality(self, value): + caom_util.type_check(value, DataQuality, 'quality') + self._quality = value + + # @property + # def observable(self): + # """ """ + # return self._observable + + @property + def position(self): + """A caom2 Position object that is developed from + the agregation of the Chunks that are children of + the Plane. + + agregation happens during ingest and is not part + of the python module at this time. + """ + return self._position + + @property + def energy(self): + """A caom2 Energy object that is developed from + the agregation of the Chunks that are children of + the Plane. + + agregation happens during ingest and is not part + of the python module at this time. + """ + """ Energy """ + return self._energy + + @property + def time(self): + """A caom2 Time object that is developed from + the agregation of the Chunks that are children of + the Plane. + + agregation happens during ingest and is not part + of the python module at this time. + """ + """ Time """ + return self._time + + @property + def polarization(self): + """A caom2 Polarization object that is developed from + the agregation of the Chunks that are children of + the Plane. + + agregation happens during ingest and is not part + of the python module at this time. + """ + return self._polarization + + # Compute derived fields + + def compute_position(self): + raise NotImplementedError( + "Aggregation of position has not been implemented in this module") + + def compute_energy(self): + raise NotImplementedError( + "Aggregation of energy has not been implemented in this module") + + def compute_time(self): + raise NotImplementedError( + "Aggregation of time has not been implemented in this module") + + def compute_polarization(self): + raise NotImplementedError( + "Aggregation of polarization " + + "has not been implemented in this module") + + +class PlaneURI(CaomObject): + """ Plane URI """ + + def __init__(self, uri): + """ + Initializes an Plane instance + + Arguments: + uri : URI corresponding to the plane + + Throws: + TypeError : if uri is not a string + ValueError : if uri is invalid + ValueError : if the uri is valid but does not contain the expected + fields (collection, observation_id and product_id) + """ + + self.uri = uri + + def _key(self): + return self.uri + + def __hash__(self): + return hash(self._key()) + + @classmethod + def get_plane_uri(cls, observation_uri, product_id): + """ + Initializes an Plane URI instance + + Arguments: + observation_uri : the uri of the observation + product_id : ID of the product + """ + caom_util.type_check(observation_uri, ObservationURI, "observation_uri", + override=False) + caom_util.type_check(product_id, unicode, "observation_uri", override=False) + caom_util.validate_path_component(cls, "product_id", product_id) + + path = urlsplit(observation_uri.uri).path + uri = SplitResult(ObservationURI._SCHEME, "", path + "/" + + product_id, "", "").geturl() + return cls(uri) + + # Properties + @property + def uri(self): + """A uri that locates the plane object inside caom""" + return self._uri + + @uri.setter + def uri(self, value): + + caom_util.type_check(value, unicode, "uri", override=False) + tmp = urlsplit(value) + + if tmp.scheme != ObservationURI._SCHEME: + raise ValueError("{} doesn't have an allowed scheme".format(value)) + if tmp.geturl() != value: + raise ValueError("Failed to parse uri correctly: {}".format(value)) + + (collection, observation_id, product_id) = tmp.path.split("/") + + if product_id is None: + raise ValueError("Faield to get product ID from uri: {}" + .format(value)) + + self._product_id = product_id + self._observation_uri = \ + ObservationURI.get_observation_uri(collection, observation_id) + self._uri = value + + @property + def product_id(self): + """the product_id associated with this plane""" + return self._product_id + + @property + def observation_uri(self): + """The uri that can be used to find the caom2 observation object that + this plane belongs to""" + return self._observation_uri + + +class DataQuality(CaomObject): + """ DataQuality """ + + def __init__(self, flag): + """ + Construct an DataQuality instance + + Arguments: + flag + """ + self.flag = flag + + @property + def flag(self): + """ flag """ + return self._flag + + @flag.setter + def flag(self, value): + caom_util.type_check(value, Quality, "flag") + self._flag = value + + +class Metrics(CaomObject): + """ Metrics """ + + def __init__(self): + """ + Initializes a Metrics instance + + Arguments: + None + """ + self._source_number_density = None + self._background = None + self._background_std_dev = None + self._flux_density_limit = None + self._mag_limit = None + + # Properties + @property + def source_number_density(self): + """The number of sources brighter than mag_limit (flux_density_limit) + + unit: ct/deg2 + type: float + """ + return self._source_number_density + + @source_number_density.setter + def source_number_density(self, value): + caom_util.type_check(value, float, "source_number_density") + caom_util.value_check(value, 0, 1E10, "source_number_density") + self._source_number_density = value + + @property + def background(self): + """The flux in the sky (background). + + units: Jy/pix + type: float + """ + return self._background + + @background.setter + def background(self, value): + caom_util.type_check(value, float, "background") + caom_util.value_check(value, 0, 1E10, "background") + self._background = value + + @property + def background_std_dev(self): + """the standard deviation (per pixel) in background flux. + + Likely this only makes sense to define if background is also defined. + units: Jy/pix + type: float + """ + return self._background_std_dev + + @background_std_dev.setter + def background_std_dev(self, value): + caom_util.type_check(value, float, "background_std_dev") + caom_util.value_check(value, 0, 1E10, "background") + self._background_std_dev = value + + @property + def flux_density_limit(self): + """flux density where S:N=5 for point source. + + this is intended to provide a measure of the limit of detection. + + units: Jy + type: float + """ + return self._flux_density_limit + + @flux_density_limit.setter + def flux_density_limit(self, value): + caom_util.type_check(value, float, "flux_denisty_limit") + caom_util.value_check(value, 0, 1E10, "flux_density_limit") + self._flux_density_limit = value + + @property + def mag_limit(self): + """AB magnitude limit where S:N=5 for point source. + + Likely specify just mag_limit or flux_density_limit, not both? + + units: AB mag + type: float + """ + return self._mag_limit + + @mag_limit.setter + def mag_limit(self, value): + caom_util.type_check(value, float, 'mag_limit') + caom_util.value_check(value, 0, 40, 'mag_limit') + self._mag_limit = value + + +class Provenance(CaomObject): + """ Provenance """ + + def __init__(self, name, + version=None, + project=None, + producer=None, + run_id=None, + reference=None, + last_executed=None): + """ + Initializes a Provenance instance + + Arguments: + name - name of the provenance + """ + + assert name is not None, "No name provided" + assert isinstance(name, unicode), "name is not a unicode: {0}".format(name) + self._name = name + + self.version = version + self.project = project + self.producer = producer + self.run_id = run_id + self.reference = reference + self.last_executed = last_executed + + self._keywords = set() + self._inputs = caom_util.TypedSet(PlaneURI, ) + + # Properties + + @property + def name(self): + """ Name """ + return self._name + + @property + def version(self): + """ Version """ + return self._version + + @version.setter + def version(self, value): + caom_util.type_check(value, unicode, 'version') + self._version = value + + @property + def project(self): + """ Project """ + return self._project + + @project.setter + def project(self, value): + caom_util.type_check(value, unicode, 'project') + self._project = value + + @property + def producer(self): + """ Producer """ + return self._producer + + @producer.setter + def producer(self, value): + caom_util.type_check(value, unicode, 'producer') + self._producer = value + + @property + def run_id(self): + """ Run ID """ + return self._run_id + + @run_id.setter + def run_id(self, value): + caom_util.type_check(value, unicode, 'run_id') + self._run_id = value + + @property + def reference(self): + """ Reference """ + return self._reference + + @reference.setter + def reference(self, value): + caom_util.type_check(value, unicode, 'version') + if value is not None: + tmp = urlsplit(value) + assert tmp.geturl() == value, "Invalid URI: " + value + self._reference = value + + @property + def last_executed(self): + """ Version """ + return self._last_executed + + @last_executed.setter + def last_executed(self, value): + caom_util.type_check(value, datetime, 'last_executed') + self._last_executed = value + + @property + def keywords(self): + """ Set of keywords as unicode""" + return self._keywords + + @property + def inputs(self): + """ Set of inputs as PlaneURI""" + return self._inputs + + +class Position(CaomObject): + """ Position """ + + def __init__(self, bounds=None, + dimension=None, + resolution=None, + sample_size=None, + time_dependent=None + ): + """ + Initialize a Position instance. + + Arguments: + None + """ + self.bounds = bounds + self.dimension = dimension + self.resolution = resolution + self.sample_size = sample_size + self.time_dependent = time_dependent + + # Properties + + @property + def bounds(self): + """ Bounds """ + return self._bounds + + @bounds.setter + def bounds(self, value): + if value is not None: + assert isinstance(value, (shape.Box, shape.Circle, shape.Polygon)), ( + "bounds is not a Shape: {0}".format(value)) + self._bounds = value + + @property + def dimension(self): + """ Dimension """ + return self._dimension + + @dimension.setter + def dimension(self, value): + if value is not None: + assert isinstance(value, wcs.Dimension2D), ( + "dimension is not a Dimension2D: {0}".format(value)) + self._dimension = value + + @property + def resolution(self): + """ Resolution """ + return self._resolution + + @resolution.setter + def resolution(self, value): + if value is not None: + assert isinstance(value, float), ( + "resolution is not a float: {0}".format(value)) + self._resolution = value + + @property + def sample_size(self): + """ Sample size """ + return self._sample_size + + @sample_size.setter + def sample_size(self, value): + if value is not None: + assert isinstance(value, float), ( + "sample size is not a float: {0}".format(value)) + self._sample_size = value + + @property + def time_dependent(self): + """ Time dependent """ + return self._time_dependent + + @time_dependent.setter + def time_dependent(self, value): + if value is not None: + assert isinstance(value, bool), ( + "time dependent is not a bool: {0}".format(value)) + self._time_dependent = value + + +class Energy(CaomObject): + """ Energy """ + + def __init__(self): + """ + Initialize an Energy instance. + + Arguments: + None + """ + self._value = None + self._bounds = None + self._dimension = None + self._resolving_power = None + self._sample_size = None + self._bandpass_name = None + self._em_band = None + self._transition = None + + # Properties + @property + def value(self): + """ Energy value """ + return self._value + + @value.setter + def value(self, value): + if value is not None: + assert isinstance(value, float), ( + "energy value is not a float: {0}".format(value)) + self._value = value + + @property + def bounds(self): + """ Energy bounds """ + return self._bounds + + @bounds.setter + def bounds(self, value): + if value is not None: + assert isinstance(value, shape.Interval), ( + "energy bounds is not an Interval: {0}".format(value)) + self._bounds = value + + @property + def dimension(self): + """DIMENSION (NUMBER OF PIXELS) ALONG ENERGY AXIS.""" + return self._dimension + + @dimension.setter + def dimension(self, value): + if value is not None: + assert isinstance(value, long), ( + "energy dimension is not a long: {0}".format(value)) + self._dimension = value + + @property + def resolving_power(self): + """ Resolving power """ + return self._resolving_power + + @resolving_power.setter + def resolving_power(self, value): + if value is not None: + assert isinstance(value, float), ( + "resolving power is not a float: {0}".format(value)) + self._resolving_power = value + + @property + def sample_size(self): + """ Sample size """ + return self._sample_size + + @sample_size.setter + def sample_size(self, value): + if value is not None: + assert isinstance(value, float), ( + "sample size is not a float: {0}".format(value)) + self._sample_size = value + + @property + def bandpass_name(self): + """ Bandpass name """ + return self._bandpass_name + + @bandpass_name.setter + def bandpass_name(self, value): + if value is not None: + assert isinstance(value, unicode), ( + "bandpass name is not unicode: {0}".format(value)) + self._bandpass_name = value + + @property + def em_band(self): + """ EM Band """ + return self._em_band + + @em_band.setter + def em_band(self, value): + if value is not None: + assert isinstance(value, EnergyBand), ( + "em_Band is not an EnergyBand: {0}".format(value)) + self._em_band = value + + @property + def transition(self): + """ Energy transition """ + return self._transition + + @transition.setter + def transition(self, value): + if value is not None: + assert isinstance(value, wcs.EnergyTransition), ( + "transition is not an EnergyTransition: {0}".format(value)) + self._transition = value + + +class Polarization(CaomObject): + """ Polarization """ + + def __init__(self, + dimension=None, + polarization_states=None): + """ + Initialize a Polarization instance. + + Arguments: + None + """ + self.dimension = dimension + self.polarization_states = polarization_states + + # Properties + @property + def dimension(self): + """number of samples (pixels) along polarization axis. + + unit: pix + type: int + """ + return self._dimension + + @dimension.setter + def dimension(self, value): + caom_util.type_check(value, int, 'dimension') + caom_util.value_check(value, 0, 1E10, 'dimension') + self._dimension = value + + +class Time(CaomObject): + """ Time """ + + def __init__(self, + value=None, + bounds=None, + dimension=None, + resolution=None, + sample_size=None, + exposure=None): + """ + Initialize a Time instance. + + Arguments: + None + """ + self.value = value + self.bounds = bounds + self.dimension = dimension + self.resolution = resolution + self.sample_size = sample_size + self.exposure = exposure + + # Properties + + @property + def value(self): + """ Actual time value, seconds since epoch. + + quesion is, what epoch? + + units: s + """ + return self._value + + @value.setter + def value(self, value): + caom_util.type_check(value, float, 'value') + self._value = value + + @property + def bounds(self): + """an interval object that gives start and end of an time interval + + Not actually implemented yet. Likely you want a TemporalWCS + instead + + type: Interval(lower_mjd, upper_mjd) + unit: mjd + + """ + return self._bounds + + @bounds.setter + def bounds(self, value): + caom_util.type_check(value, shape.Interval, 'bounds') + self._bounds = value + + @property + def dimension(self): + """Number of pixel in the time direction, normally 1. + + eg 1 + type: long + + """ + return self._dimension + + @dimension.setter + def dimension(self, value): + caom_util.type_check(value, long, 'dimension') + self._dimension = value + + @property + def resolution(self): + """Time resolution of the samples, in seconds. + + normally this is the same as the exposure time, + but in a stack you might have a larger resolution value than + exposure time. + + eg. 1000 + unit: s + type: float + + """ + return self._resolution + + @resolution.setter + def resolution(self, value): + caom_util.type_check(value, float, 'resolution') + self._resolution = value + + @property + def sample_size(self): + """nominally the exposure time, in seconds. + + """ + return self._sample_size + + @sample_size.setter + def sample_size(self, value): + caom_util.type_check(value, float, 'sample_size') + self._sample_size = value + + @property + def exposure(self): + """Duration of the exposure, in seconds""" + return self._exposure + + @exposure.setter + def exposure(self, value): + caom_util.type_check(value, float, 'exposure') + self._exposure = value diff --git a/pyCAOM2/caom2/types/caom2_point.py b/caom2/caom2/shape.py similarity index 77% rename from pyCAOM2/caom2/types/caom2_point.py rename to caom2/caom2/shape.py index f484ac59..c5520a49 100644 --- a/pyCAOM2/caom2/types/caom2_point.py +++ b/caom2/caom2/shape.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,16 +64,49 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # -""" defines Point class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) -import caom2.util.caom2_util as util -from caom2.caom2_object import Caom2Object +from enum import Enum +from . import common +from . import caom_util +__all__ = ['SegmentType', 'Box', 'Circle', 'Interval', 'Point', 'Polygon', 'Vertex'] -class Point(Caom2Object): + +class SegmentType(Enum): + """ + CLOSE: 0 + LINE: 1 + MOVE: 2 + """ + CLOSE = 0 + LINE = 1 + MOVE = 2 + + +class Box(common.CaomObject): + + def __init__(self): + pass + + +class Circle(common.CaomObject): + + def __init__(self): + pass + + +class Interval(common.CaomObject): + + def __init__(self): + pass + + +class Point(common.CaomObject): def __init__(self, cval1, cval2): @@ -90,7 +122,7 @@ def cval1(self): @cval1.setter def cval1(self, value): - util.typeCheck(value, float, 'cval1', override=False) + caom_util.type_check(value, float, 'cval1', override=False) self._cval1 = value @property @@ -102,5 +134,17 @@ def cval2(self): @cval2.setter def cval2(self, value): - util.typeCheck(value, float, 'cval2', override=False) + caom_util.type_check(value, float, 'cval2', override=False) self._cval2 = value + + +class Polygon(common.CaomObject): + + def __init__(self): + pass + + +class Vertex(common.CaomObject): + + def __init__(self): + pass diff --git a/caom2/caom2/tests/__init__.py b/caom2/caom2/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/caom2/caom2/tests/caom_test_instances.py b/caom2/caom2/tests/caom_test_instances.py new file mode 100644 index 00000000..3a6a4a84 --- /dev/null +++ b/caom2/caom2/tests/caom_test_instances.py @@ -0,0 +1,425 @@ +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines Caom2TestInstances class """ + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import collections +from datetime import datetime + +from caom2 import artifact +from caom2 import caom_util +from caom2 import chunk +from caom2 import observation +from caom2 import part +from caom2 import plane +from caom2 import shape +from caom2 import wcs + + +class Caom2TestInstances(object): + + _collection = "collection" + _observation_id = "observationID" + _product_id = "productId" + _keywords = {"keyword1", "keyword2"} + _ivoa_date = datetime(2012, 07, 11, 13, 26, 37, 0) + + def __init__(self): + self.depth = 5 + self.complete = True + self.bounds_is_circle = True + self.caom_version = 20 + + @property + def depth(self): + return self._depth + + @depth.setter + def depth(self, v): + self._depth = v + + @property + def complete(self): + return self._complete + + @complete.setter + def complete(self, v): + self._complete = v + + @property + def bounds_is_circle(self): + return self._bounds_is_circle + + @bounds_is_circle.setter + def bounds_is_circle(self, v): + self._bounds_is_circle = v + + @property + def caom_version(self): + return self._caom_version + + @caom_version.setter + def caom_version(self, v): + self._caom_version = v + + def get_simple_observation(self): + simple_observation = \ + observation.SimpleObservation(Caom2TestInstances._collection, + Caom2TestInstances._observation_id) + if self.complete: + simple_observation.sequence_number = int(5) + simple_observation.obs_type = "flat" + simple_observation.intent = observation.ObservationIntentType.CALIBRATION + simple_observation.meta_release = Caom2TestInstances._ivoa_date + simple_observation.proposal = self.get_proposal() + simple_observation.target = self.get_target() + simple_observation.target_position = self.get_target_position() + if self.caom_version == 21: + simple_observation.requirements = self.get_requirements() + simple_observation.telescope = self.get_telescope() + simple_observation.instrument = self.get_instrument() + simple_observation.environment = self.get_environment() + if self.depth > 1: + simple_observation.planes.update(self.get_planes()) + return simple_observation + + def get_composite_observation(self): + composite_observation = \ + observation.CompositeObservation(Caom2TestInstances._collection, + Caom2TestInstances._observation_id, + self.get_algorithm()) + if self.complete: + composite_observation.sequence_number = int(10) + composite_observation.obs_type = "filed" + composite_observation.intent = observation.ObservationIntentType.SCIENCE + composite_observation.meta_release = Caom2TestInstances._ivoa_date + composite_observation.proposal = self.get_proposal() + composite_observation.target = self.get_target() + composite_observation.target_position = self.get_target_position() + if self.caom_version == 21: + composite_observation.requirements = self.get_requirements() + composite_observation.telescope = self.get_telescope() + composite_observation.instrument = self.get_instrument() + composite_observation.environment = self.get_environment() + if self.depth > 1: + composite_observation.planes.update(self.get_planes()) + composite_observation.members.update(self.get_members()) + return composite_observation + + def get_algorithm(self): + return observation.Algorithm("algorithmName") + + def get_proposal(self): + proposal = observation.Proposal("proposalId") + proposal.pi_name = "proposalPi" + proposal.project = "proposalProject" + proposal.title = "proposalTitle" + proposal.keywords.update(Caom2TestInstances._keywords) + return proposal + + def get_target(self): + target = observation.Target("targetName") + target.target_type = observation.TargetType.OBJECT + target.standard = False + target.redshift = 1.5 + target.keywords.update(Caom2TestInstances._keywords) + return target + + def get_target_position(self): + point = shape.Point(1.0, 2.0) + target_position = observation.TargetPosition(point, "coordsys") + target_position.equinox = 3.0 + return target_position + + def get_requirements(self): + return observation.Requirements(observation.Status.FAIL) + + def get_telescope(self): + telescope = observation.Telescope("telescopeName") + telescope.geo_location_x = 1.0 + telescope.geo_location_y = 2.0 + telescope.geo_location_z = 3.0 + telescope.keywords.update(Caom2TestInstances._keywords) + return telescope + + def get_instrument(self): + instrument = observation.Instrument("instrumentName") + instrument.keywords.update(Caom2TestInstances._keywords) + return instrument + + def get_environment(self): + env = observation.Environment() + env.seeing = 0.08 + env.humidity = 0.35 + env.elevation = 2.7 + env.tau = 0.7 + env.wavelength_tau = 450e-6 + env.ambient_temp = 20.0 + env.photometric = True + return env + + def get_members(self): + members = caom_util.TypedSet( + observation.ObservationURI, observation.ObservationURI("caom:foo/bar")) + return members + + def get_planes(self): + planes = collections.OrderedDict() + _plane = plane.Plane("productID") + if self.complete: + _plane.meta_release = Caom2TestInstances._ivoa_date + _plane.data_release = Caom2TestInstances._ivoa_date + _plane.data_product_type = plane.DataProductType.IMAGE + _plane.calibration_level = plane.CalibrationLevel.PRODUCT + _plane.provenance = self.get_provenance() + _plane.metrics = self.get_metrics() + if self.caom_version == 21: + _plane.quality = self.get_quality() + + if self.depth > 2: + for k, v in self.get_artifacts().iteritems(): + _plane.artifacts[k] = v + planes["productID"] = _plane + return planes + + def get_provenance(self): + provenance = plane.Provenance("name") + provenance.version = "version" + provenance.product = "product" + provenance.producer = "producer" + provenance.run_id = "run_id" + provenance.reference = "http://foo/bar" + provenance.last_executed = Caom2TestInstances._ivoa_date + provenance.keywords.update(Caom2TestInstances._keywords) + provenance.inputs.update(self.get_inputs()) + return provenance + + def get_inputs(self): + return caom_util.TypedSet(plane.PlaneURI, + plane.PlaneURI("caom:foo/bar/plane1"), + plane.PlaneURI("caom:foo/bar/plane2")) + + def get_metrics(self): + metrics = plane.Metrics() + metrics.source_number_density = float(1.0) + metrics.background = float(2.0) + metrics.background_std_dev = float(3.0) + metrics.flux_density_limit = float(4.0) + metrics.mag_limit = float(5.0) + return metrics + + def get_quality(self): + return plane.DataQuality(plane.Quality.JUNK) + + def get_artifacts(self): + artifacts = collections.OrderedDict() + _artifact = artifact.Artifact("ad:foo/bar1", + chunk.ProductType.SCIENCE, + artifact.ReleaseType.META) + if self.complete: + _artifact.content_type = "application/fits" + _artifact.content_length = 12345L + if self.depth > 3: + for k, v in self.get_parts().iteritems(): + _artifact.parts[k] = v + artifacts["ad:foo/bar1"] = _artifact + return artifacts + + def get_parts(self): + parts = collections.OrderedDict() + _part = part.Part("x") + if self.complete: + _part.product_type = chunk.ProductType.SCIENCE + if self.depth > 4: + for _chunk in self.get_chunks(): + _part.chunks.append(_chunk) + parts["x"] = _part + return parts + + def get_chunks(self): + chunks = caom_util.TypedList(chunk.Chunk, ) + _chunk = chunk.Chunk() + if self.complete: + _chunk.product_type = chunk.ProductType.SCIENCE + _chunk.naxis = 5 + _chunk.observable_axis = 1 + _chunk.position_axis_1 = 1 + _chunk.position_axis_2 = 2 + _chunk.energy_axis = 3 + _chunk.time_axis = 4 + _chunk.polarization_axis = 5 + _chunk.observable = self.get_observable_axis() + _chunk.position = self.get_spatial_wcs() + _chunk.energy = self.get_spectral_wcs() + _chunk.time = self.get_temporal_wcs() + _chunk.polarization = self.get_polarization_wcs() + chunks.append(_chunk) + return chunks + + def get_observable_axis(self): + observable = chunk.ObservableAxis(self.get_slice()) + if self.complete: + observable.independent = self.get_slice() + return observable + + def get_spatial_wcs(self): + coord_axis2d = self.get_coord_axis2d() + position = chunk.SpatialWCS(coord_axis2d) + if self.complete: + position.coordsys = "position coordsys" + position.equinox = 2000.0 + position.resolution = 0.5 + return position + + def get_spectral_wcs(self): + axis = self.get_coord_axis1d() + energy = chunk.SpectralWCS(axis, "energy specsys") + if self.complete: + energy.ssysobs = "energy ssysobs" + energy.ssyssrc = "energy ssyssrc" + energy.restfrq = 1.0 + energy.restwav = 2.0 + energy.velosys = 3.0 + energy.zsource = 4.0 + energy.velang = 5.0 + energy.bandpassName = "energy bandpassName" + energy.resolvingPower = 6.0 + energy.transition = wcs.EnergyTransition("H", "21cm") + return energy + + def get_temporal_wcs(self): + axis = self.get_coord_axis1d() + time = chunk.TemporalWCS(axis) + if self.complete: + time.exposure = 1.0 + time.resolution = 2.0 + time.timesys = "UTC" + time.trefpos = "TOPOCENTER" + time.mjdref = 3.0 + return time + + def get_polarization_wcs(self): + axis = wcs.Axis('STOKES') + axis1d = wcs.CoordAxis1D(axis) + #IQUV + axis1d.function = wcs.CoordFunction1D(4L, 1.0, + wcs.RefCoord(1.0, 1.0)) + pol = chunk.PolarizationWCS(axis1d) + return pol + + def get_slice(self): + return wcs.Slice(wcs.Axis("sliceCtype", "sliceCunit"), 1L) + + def get_coord_axis1d(self): + coord_axis1d = wcs.CoordAxis1D(wcs.Axis("axisCtype", "axisCunit")) + if self.complete: + coord_axis1d.error = wcs.CoordError(1.0, 1.5) + coord_axis1d.range = wcs.CoordRange1D(wcs.RefCoord(2.0, 2.5), + wcs.RefCoord(3.0, 3.5)) + coord_axis1d.function = ( + wcs.CoordFunction1D(4L, 4.5, wcs.RefCoord(5.0, 5.5))) + bounds = wcs.CoordBounds1D() + bounds.samples.append(wcs.CoordRange1D(wcs.RefCoord(6.0, 6.5), + wcs.RefCoord(7.0, 7.5))) + bounds.samples.append(wcs.CoordRange1D(wcs.RefCoord(8.0, 8.5), + wcs.RefCoord(9.0, 9.5))) + coord_axis1d.bounds = bounds + return coord_axis1d + + def get_coord_axis2d(self): + axis1 = wcs.Axis("axis1Ctype", "axis1Cunit") + axis2 = wcs.Axis("axis2Ctype", "axis2Cunit") + coord_axis2d = wcs.CoordAxis2D(axis1, axis2) + if self.complete: + coord_axis2d.error1 = wcs.CoordError(1.0, 1.5) + coord_axis2d.error2 = wcs.CoordError(2.0, 2.5) + start = wcs.Coord2D(wcs.RefCoord(3.0, 3.5), + wcs.RefCoord(4.0, 4.5)) + end = wcs.Coord2D(wcs.RefCoord(5.0, 5.5), + wcs.RefCoord(6.0, 6.5)) + coord_axis2d.range = wcs.CoordRange2D(start, end) + dimension = wcs.Dimension2D(7L, 8L) + ref_coord = wcs.Coord2D(wcs.RefCoord(9.0, 9.5), + wcs.RefCoord(10.0, 10.5)) + coord_axis2d.function = ( + wcs.CoordFunction2D(dimension, ref_coord, + 11.0, 12.0, 13.0, 14.0)) + if self.bounds_is_circle: + center = wcs.ValueCoord2D(15.0, 16.0) + coord_axis2d.bounds = wcs.CoordCircle2D(center, 17.0) + else: + polygon = wcs.CoordPolygon2D() + polygon.vertices.append(wcs.ValueCoord2D(15.0, 16.0)) + polygon.vertices.append(wcs.ValueCoord2D(17.0, 18.0)) + polygon.vertices.append(wcs.ValueCoord2D(19.0, 20.0)) + coord_axis2d.bounds = polygon + return coord_axis2d diff --git a/caom2/caom2/tests/coveragerc b/caom2/caom2/tests/coveragerc new file mode 100644 index 00000000..bec7c291 --- /dev/null +++ b/caom2/caom2/tests/coveragerc @@ -0,0 +1,31 @@ +[run] +source = {packagename} +omit = + {packagename}/_astropy_init* + {packagename}/conftest* + {packagename}/cython_version* + {packagename}/setup_package* + {packagename}/*/setup_package* + {packagename}/*/*/setup_package* + {packagename}/tests/* + {packagename}/*/tests/* + {packagename}/*/*/tests/* + {packagename}/version* + +[report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about packages we have installed + except ImportError + + # Don't complain if tests don't hit assertions + raise AssertionError + raise NotImplementedError + + # Don't complain about script hooks + def main\(.*\): + + # Ignore branches that don't pertain to this version of Python + pragma: py{ignore_python_version} \ No newline at end of file diff --git a/pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml b/caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml similarity index 95% rename from pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml rename to caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml index 7e250326..e6b84306 100644 --- a/pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml +++ b/caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml b/caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml similarity index 95% rename from pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml rename to caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml index fad972de..2e0b3506 100644 --- a/pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml +++ b/caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteCompositeCircle.xml b/caom2/caom2/tests/data/CompleteCompositeCircle.xml similarity index 94% rename from pyCAOM2/caom2/test/data/CompleteCompositeCircle.xml rename to caom2/caom2/tests/data/CompleteCompositeCircle.xml index db2f1467..3dc12e60 100644 --- a/pyCAOM2/caom2/test/data/CompleteCompositeCircle.xml +++ b/caom2/caom2/tests/data/CompleteCompositeCircle.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml b/caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml similarity index 94% rename from pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml rename to caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml index 596d97fb..4408806e 100644 --- a/pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml +++ b/caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml b/caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml similarity index 95% rename from pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml rename to caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml index 647cefed..8dfd6c7c 100644 --- a/pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml +++ b/caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteCompositePolygon.xml b/caom2/caom2/tests/data/CompleteCompositePolygon.xml similarity index 94% rename from pyCAOM2/caom2/test/data/CompleteCompositePolygon.xml rename to caom2/caom2/tests/data/CompleteCompositePolygon.xml index e431778e..cdc68e0e 100644 --- a/pyCAOM2/caom2/test/data/CompleteCompositePolygon.xml +++ b/caom2/caom2/tests/data/CompleteCompositePolygon.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml b/caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml similarity index 94% rename from pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml rename to caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml index 1b061723..8e1fcc92 100644 --- a/pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml +++ b/caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml b/caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml similarity index 95% rename from pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml rename to caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml index b3043373..dc4af87e 100644 --- a/pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml +++ b/caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteSimpleCircle.xml b/caom2/caom2/tests/data/CompleteSimpleCircle.xml similarity index 94% rename from pyCAOM2/caom2/test/data/CompleteSimpleCircle.xml rename to caom2/caom2/tests/data/CompleteSimpleCircle.xml index 4a6b8189..d27ead15 100644 --- a/pyCAOM2/caom2/test/data/CompleteSimpleCircle.xml +++ b/caom2/caom2/tests/data/CompleteSimpleCircle.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml b/caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml similarity index 94% rename from pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml rename to caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml index 885d01fe..592c2627 100644 --- a/pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml +++ b/caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml b/caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml similarity index 95% rename from pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml rename to caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml index 96fdd25a..f30d5e63 100644 --- a/pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml +++ b/caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/CompleteSimplePolygon.xml b/caom2/caom2/tests/data/CompleteSimplePolygon.xml similarity index 94% rename from pyCAOM2/caom2/test/data/CompleteSimplePolygon.xml rename to caom2/caom2/tests/data/CompleteSimplePolygon.xml index 0297191b..d075ef52 100644 --- a/pyCAOM2/caom2/test/data/CompleteSimplePolygon.xml +++ b/caom2/caom2/tests/data/CompleteSimplePolygon.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/pyCAOM2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml b/caom2/caom2/tests/data/MinimalCompositeCircle-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml rename to caom2/caom2/tests/data/MinimalCompositeCircle-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml b/caom2/caom2/tests/data/MinimalCompositeCircle-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml rename to caom2/caom2/tests/data/MinimalCompositeCircle-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositeCircle.xml b/caom2/caom2/tests/data/MinimalCompositeCircle.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositeCircle.xml rename to caom2/caom2/tests/data/MinimalCompositeCircle.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml b/caom2/caom2/tests/data/MinimalCompositePolygon-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml rename to caom2/caom2/tests/data/MinimalCompositePolygon-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml b/caom2/caom2/tests/data/MinimalCompositePolygon-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml rename to caom2/caom2/tests/data/MinimalCompositePolygon-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositePolygon.xml b/caom2/caom2/tests/data/MinimalCompositePolygon.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositePolygon.xml rename to caom2/caom2/tests/data/MinimalCompositePolygon.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml b/caom2/caom2/tests/data/MinimalSimpleCircle-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml rename to caom2/caom2/tests/data/MinimalSimpleCircle-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml b/caom2/caom2/tests/data/MinimalSimpleCircle-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml rename to caom2/caom2/tests/data/MinimalSimpleCircle-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimpleCircle.xml b/caom2/caom2/tests/data/MinimalSimpleCircle.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimpleCircle.xml rename to caom2/caom2/tests/data/MinimalSimpleCircle.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml b/caom2/caom2/tests/data/MinimalSimplePolygon-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml rename to caom2/caom2/tests/data/MinimalSimplePolygon-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml b/caom2/caom2/tests/data/MinimalSimplePolygon-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml rename to caom2/caom2/tests/data/MinimalSimplePolygon-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimplePolygon.xml b/caom2/caom2/tests/data/MinimalSimplePolygon.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimplePolygon.xml rename to caom2/caom2/tests/data/MinimalSimplePolygon.xml diff --git a/caom2/caom2/tests/setup_package.py b/caom2/caom2/tests/setup_package.py new file mode 100644 index 00000000..6e4be679 --- /dev/null +++ b/caom2/caom2/tests/setup_package.py @@ -0,0 +1,7 @@ +def get_package_data(): + return { + _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} + + +def requires_2to3(): + return False diff --git a/pyCAOM2/caom2/test/test_artifact.py b/caom2/caom2/tests/test_artifact.py similarity index 56% rename from pyCAOM2/caom2/test/test_artifact.py rename to caom2/caom2/tests/test_artifact.py index d5313ab6..d2d82b4d 100644 --- a/pyCAOM2/caom2/test/test_artifact.py +++ b/caom2/caom2/tests/test_artifact.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -70,75 +69,98 @@ """ Defines TestArtifact class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest from urlparse import urlparse -from caom2.caom2_artifact import Artifact -from caom2.caom2_enums import ProductType, ReleaseType -from caom2.caom2_part import Part +from .. import artifact +from .. import part + + +class TestEnums(unittest.TestCase): + + def test_all(self): + self.assertEqual(artifact.ReleaseType.DATA.value, "data") + self.assertEqual(artifact.ReleaseType.META.value, "meta") class TestArtifact(unittest.TestCase): def test_all(self): with self.assertRaises(TypeError): - artifact = Artifact("caom:GEMINI/12345") + test_artifact = artifact.Artifact("caom:GEMINI/12345") with self.assertRaises(TypeError): - artifact = Artifact("caom:GEMINI/12345", ReleaseType('META'), ProductType('THUMBNAIL')) + test_artifact = artifact.Artifact("caom:GEMINI/12345", + artifact.ReleaseType.META, + artifact.ProductType.THUMBNAIL) with self.assertRaises(TypeError): - artifact = Artifact("caom:GEMINI/12345", ProductType('THUMBNAIL'), None) + test_artifact = artifact.Artifact("caom:GEMINI/12345", + artifact.ProductType.THUMBNAIL, + None) with self.assertRaises(TypeError): - artifact = Artifact("caom:GEMINI/12345", None, ReleaseType('META')) + test_artifact = artifact.Artifact("caom:GEMINI/12345", + None, + artifact.ReleaseType.META) - artifact = Artifact("caom:GEMINI/12345", ProductType('THUMBNAIL'), ReleaseType('META')) + test_artifact = artifact.Artifact("caom:GEMINI/12345", + artifact.ProductType.THUMBNAIL, + artifact.ReleaseType.META) urlparse("caom:GEMINI/12345") - self.assertEqual("caom:GEMINI/12345", artifact.uri, "Artifact URI") - self.assertEqual(ProductType('THUMBNAIL'), artifact.product_type, "Artifact ProductType") - self.assertEqual(ReleaseType('META'), artifact.release_type, "Artifact ReleaseType") + self.assertEqual("caom:GEMINI/12345", + test_artifact.uri, + "Artifact URI") + self.assertEqual(artifact.ProductType.THUMBNAIL, + test_artifact.product_type, + "Artifact ProductType") + self.assertEqual(artifact.ReleaseType.META, + test_artifact.release_type, + "Artifact ReleaseType") - self.assertIsNone(artifact.content_type, "Default content type") - artifact.content_type = "FITS" - self.assertEquals("FITS", artifact.content_type, "Content type") - self.assertIsNone(artifact.content_length, "Default content length") - artifact.content_length = 23L - self.assertEquals(23L, artifact.content_length, "Content length") - artifact.product_type = ProductType.PREVIEW - self.assertEquals(ProductType.PREVIEW, artifact.product_type, "Product type") - self.assertEquals(0, len(artifact.parts), "Default parts") - part1 = Part("1") - artifact.parts["1"] = part1 - self.assertEquals(1, len(artifact.parts), "Parts") - self.assertTrue("1" in artifact.parts.keys()) + self.assertIsNone(test_artifact.content_type, "Default content type") + test_artifact.content_type = "FITS" + self.assertEquals("FITS", test_artifact.content_type, "Content type") + self.assertIsNone(test_artifact.content_length, + "Default content length") + test_artifact.content_length = 23L + self.assertEquals(23L, test_artifact.content_length, "Content length") + test_artifact.product_type = artifact.ProductType.PREVIEW + self.assertEquals(artifact.ProductType.PREVIEW, + test_artifact.product_type, + "Product type") + self.assertEquals(0, len(test_artifact.parts), "Default parts") + part1 = part.Part("1") + test_artifact.parts["1"] = part1 + self.assertEquals(1, len(test_artifact.parts), "Parts") + self.assertTrue("1" in test_artifact.parts.keys()) #add same part again - part2 = Part("2") - artifact.parts["2"] = part2 - self.assertEquals(2, len(artifact.parts), "Parts") - self.assertTrue("1" in artifact.parts.keys()) - self.assertTrue("2" in artifact.parts.keys()) + part2 = part.Part("2") + test_artifact.parts["2"] = part2 + self.assertEquals(2, len(test_artifact.parts), "Parts") + self.assertTrue("1" in test_artifact.parts.keys()) + self.assertTrue("2" in test_artifact.parts.keys()) # try to add duplicates part3 = part1 - artifact.parts["1"] = part3 - self.assertEquals(2, len(artifact.parts), "Parts") - self.assertTrue("1" in artifact.parts.keys()) - self.assertTrue("2" in artifact.parts.keys()) + test_artifact.parts["1"] = part3 + self.assertEquals(2, len(test_artifact.parts), "Parts") + self.assertTrue("1" in test_artifact.parts.keys()) + self.assertTrue("2" in test_artifact.parts.keys()) - part4 = Part("1") - artifact.parts["1"] = part4 - self.assertEquals(2, len(artifact.parts), "Parts") - self.assertTrue("1" in artifact.parts.keys()) - self.assertTrue("2" in artifact.parts.keys()) + part4 = part.Part("1") + test_artifact.parts["1"] = part4 + self.assertEquals(2, len(test_artifact.parts), "Parts") + self.assertTrue("1" in test_artifact.parts.keys()) + self.assertTrue("2" in test_artifact.parts.keys()) #incorrect URI exception = False try: - artifact = Artifact("caom://#observation://? something#//", ReleaseType('META'), ProductType('THUMBNAIL')) - print artifact.uri + test_artifact = artifact.Artifact( + "caom://#observation://? something#//", + artifact.ReleaseType('META'), + artifact.ProductType('THUMBNAIL')) except ValueError: exception = True self.assertTrue(exception, "Missing exception") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_caom2_util.py b/caom2/caom2/tests/test_caom_util.py similarity index 54% rename from pyCAOM2/caom2/test/test_caom2_util.py rename to caom2/caom2/tests/test_caom_util.py index febdd2e0..728bd88d 100644 --- a/pyCAOM2/caom2/test/test_caom2_util.py +++ b/caom2/caom2/tests/test_caom_util.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -68,274 +67,259 @@ #*********************************************************************** # -""" Defines TestCaomUtil class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) import unittest import uuid -from caom2.caom2_artifact import Artifact -from caom2.caom2_energy import Energy -from caom2.caom2_enums import ProductType, ReleaseType -from caom2.caom2_part import Part -from caom2.caom2_plane import Plane -from caom2.caom2_plane_uri import PlaneURI -from caom2.util.caom2_util import TypedList -from caom2.util.caom2_util import TypedOrderedDict -from caom2.util.caom2_util import TypedSet -from caom2.util.caom2_util import long2uuid -from caom2.util.caom2_util import uuid2long -from caom2.util.caom2_util import validate_path_component +from .. import artifact +from .. import caom_util +from .. import chunk +from .. import part +from .. import plane class TestCaomUtil(unittest.TestCase): - def testTypedList(self): - mylist1 = TypedList((str), "Test1") - self.assertEquals(1, len(mylist1), "list1 length") - self.assertEqual("Test1", mylist1[0], "Non matching elements") + def test_typed_list(self): + my_list1 = caom_util.TypedList(unicode, "Test1") + self.assertEquals(1, len(my_list1), "list1 length") + self.assertEqual("Test1", my_list1[0], "Non matching elements") - mylist1.append("Test2") - self.assertEquals(2, len(mylist1), "list1 length") - self.assertEqual("Test1", mylist1[0], "Non matching elements") - self.assertEqual("Test2", mylist1[1], "Non matching elements") + my_list1.append("Test2") + self.assertEquals(2, len(my_list1), "list1 length") + self.assertEqual("Test1", my_list1[0], "Non matching elements") + self.assertEqual("Test2", my_list1[1], "Non matching elements") # try to add the wrong type exception = False try: - mylist1.append(3) + my_list1.append(3) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") exception = False try: - mylist1.extend([2, 4]) + my_list1.extend([2, 4]) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") exception = False try: - mylist2 = TypedList((int), 2) - mylist1.extend(mylist2) + my_list2 = caom_util.TypedList(int, 2) + my_list1.extend(my_list2) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") exception = False try: - mylist1.insert(1, 3) + my_list1.insert(1, 3) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") exception = False try: - mylist2 = TypedList((str), 1, 3) + my_list2 = caom_util.TypedList(unicode, 1, 3) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") - self.assertEquals(2, len(mylist1), "list1 length") - self.assertEqual("Test1", mylist1[0], "Non matching elements") - self.assertEqual("Test2", mylist1[1], "Non matching elements") - - mylist2 = TypedList((str), "Test3", "Test4") - mylist1.extend(mylist2) - self.assertEquals(4, len(mylist1), "list1 length") - self.assertEqual("Test1", mylist1[0], "Non matching elements") - self.assertEqual("Test2", mylist1[1], "Non matching elements") - self.assertEqual("Test3", mylist1[2], "Non matching elements") - self.assertEqual("Test4", mylist1[3], "Non matching elements") - - mylist1.insert(0, "Test0") - self.assertEquals(5, len(mylist1), "list1 length") - self.assertEqual("Test0", mylist1[0], "Non matching elements") - self.assertEqual("Test1", mylist1[1], "Non matching elements") - self.assertEqual("Test2", mylist1[2], "Non matching elements") - self.assertEqual("Test3", mylist1[3], "Non matching elements") - self.assertEqual("Test4", mylist1[4], "Non matching elements") - - mylist2 = TypedList((Energy),) - self.assertEquals(0, len(mylist2), "list2 length") + self.assertEquals(2, len(my_list1), "list1 length") + self.assertEqual("Test1", my_list1[0], "Non matching elements") + self.assertEqual("Test2", my_list1[1], "Non matching elements") + + my_list2 = caom_util.TypedList(unicode, "Test3", "Test4") + my_list1.extend(my_list2) + self.assertEquals(4, len(my_list1), "list1 length") + self.assertEqual("Test1", my_list1[0], "Non matching elements") + self.assertEqual("Test2", my_list1[1], "Non matching elements") + self.assertEqual("Test3", my_list1[2], "Non matching elements") + self.assertEqual("Test4", my_list1[3], "Non matching elements") + + my_list1.insert(0, "Test0") + self.assertEquals(5, len(my_list1), "list1 length") + self.assertEqual("Test0", my_list1[0], "Non matching elements") + self.assertEqual("Test1", my_list1[1], "Non matching elements") + self.assertEqual("Test2", my_list1[2], "Non matching elements") + self.assertEqual("Test3", my_list1[3], "Non matching elements") + self.assertEqual("Test4", my_list1[4], "Non matching elements") + + my_list2 = caom_util.TypedList(plane.Energy,) + self.assertEquals(0, len(my_list2), "list2 length") def test_validate_path_component(self): - energy = Energy() - validate_path_component(energy, "something", "some:test\\path") + energy = plane.Energy() + caom_util.validate_path_component(energy, "something", "some:test\\path") exception = False try: - validate_path_component(energy, "energyfield", "some:test path") + caom_util.validate_path_component(energy, "energyfield", "some:test path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - validate_path_component(energy, "energyfield", "some:test/path") + caom_util.validate_path_component(energy, "energyfield", "some:test/path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - validate_path_component(energy, "energyfield", "some:test||path") + caom_util.validate_path_component(energy, "energyfield", "some:test||path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - validate_path_component(energy, "energyfield", "some:test %path") + caom_util.validate_path_component(energy, "energyfield", "some:test %path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") - def testTypedSet(self): + def test_typed_set(self): - myset = TypedSet((str),) + my_set = caom_util.TypedSet(unicode,) with self.assertRaises(AssertionError): - myset.add(float(1.0)) - myset.add(long(1)) - myset.add(bool(1)) + my_set.add(float(1.0)) + my_set.add(long(1)) + my_set.add(bool(1)) - self.assertRaises(AssertionError, TypedSet, (str), float(1.0)) + self.assertRaises(AssertionError, caom_util.TypedSet, unicode, float(1.0)) - myset = TypedSet((str), "Test1") - self.assertEquals(1, len(myset)) - self.assertEqual("Test1", myset.pop()) + my_set = caom_util.TypedSet(unicode, "Test1") + self.assertEquals(1, len(my_set)) + self.assertEqual("Test1", my_set.pop()) - myset.add("Test1") - myset.add("Test2") - self.assertEquals(2, len(myset), "set length") + my_set.add("Test1") + my_set.add("Test2") + self.assertEquals(2, len(my_set), "set length") with self.assertRaises(AssertionError): - myset.add(float(1.0)) - myset.add(long(1)) - myset.add(bool(1)) - myset.add("Test1") + my_set.add(float(1.0)) + my_set.add(long(1)) + my_set.add(bool(1)) + my_set.add("Test1") - myset = TypedSet((str),) - myset.add("Test1") - myset.add("Test1") - self.assertTrue(len(myset) == 1) + my_set = caom_util.TypedSet(unicode,) + my_set.add("Test1") + my_set.add("Test1") + self.assertTrue(len(my_set) == 1) - def testTypedOrderedDict(self): + def test_typed_ordered_dict(self): # test validation and constructor with an empty dictionary - testPlane10 = Plane('key10') - testArtifact66 = Artifact('caom:CFHT/55/66', ProductType.SCIENCE, ReleaseType.DATA) - testPart10 = Part("10") - testPlaneURI = PlaneURI('caom:CFHT/55/66') - myDictPlane = TypedOrderedDict((Plane),) + test_plane10 = plane.Plane('key10') + test_artifact66 = artifact.Artifact("caom:CFHT/55/66", + chunk.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + test_part10 = part.Part("10") + test_plane_uri = plane.PlaneURI('caom:CFHT/55/66') + my_dict_plane = caom_util.TypedOrderedDict(plane.Plane,) with self.assertRaises(ValueError): - myDictPlane['key11'] = testPlane10 - myDictArtifact = TypedOrderedDict((Artifact),) + my_dict_plane['key11'] = test_plane10 + my_dict_artifact = caom_util.TypedOrderedDict(artifact.Artifact,) with self.assertRaises(ValueError): - myDictArtifact['caom:CFHT/55/6'] = testArtifact66 - myDictPart = TypedOrderedDict((Part),) + my_dict_artifact['caom:CFHT/55/6'] = test_artifact66 + my_dict_part = caom_util.TypedOrderedDict(part.Part,) with self.assertRaises(ValueError): - myDictPart['11'] = testPart10 - myDictWrongType = TypedOrderedDict((PlaneURI),) + my_dict_part['11'] = test_part10 + my_dict_wrong_type = caom_util.TypedOrderedDict(plane.PlaneURI,) with self.assertRaises(AttributeError): - myDictWrongType['caom:CFHT/55/66'] = testPlaneURI + my_dict_wrong_type['caom:CFHT/55/66'] = test_plane_uri with self.assertRaises(TypeError): - myDictPlane['key2'] = 'value2' + my_dict_plane['key2'] = 'value2' with self.assertRaises(TypeError): - myDictPlane['key1'] = float(2.0) + my_dict_plane['key1'] = float(2.0) # test assignment - myDict = TypedOrderedDict((Plane),) - testPlane2 = Plane('key2') - testPlane1 = Plane('key1') - myDict['key2'] = testPlane2 - myDict['key1'] = testPlane1 - self.assertEqual(2, len(myDict), + my_dict = caom_util.TypedOrderedDict(plane.Plane,) + test_plane2 = plane.Plane('key2') + test_plane1 = plane.Plane('key1') + my_dict['key2'] = test_plane2 + my_dict['key1'] = test_plane1 + self.assertEqual(2, len(my_dict), 'mismatch in the number of entries in dictionary.') - self.assertEqual('key2', myDict.keys()[0], + self.assertEqual('key2', my_dict.keys()[0], 'key mismatch for 1st key') - self.assertEqual('key1', myDict.keys()[1], + self.assertEqual('key1', my_dict.keys()[1], 'key mismatch for 2nd key') - self.assertEqual(testPlane2, myDict.values()[0], + self.assertEqual(test_plane2, my_dict.values()[0], 'value mismatch for 1st value') - self.assertEqual(testPlane1, myDict.values()[1], + self.assertEqual(test_plane1, my_dict.values()[1], 'value mismatch for 2nd value') # test constructor with non-empty dictionary - testPlane1 = Plane('key1') - testPlane2 = Plane('key2') - myDict1 = TypedOrderedDict((Plane), ('key1', testPlane1), - ('key2', testPlane2)) - self.assertEqual(2, len(myDict1), + test_plane1 = plane.Plane('key1') + test_plane2 = plane.Plane('key2') + my_dict1 = caom_util.TypedOrderedDict(plane.Plane, ('key1', test_plane1), + ('key2', test_plane2)) + self.assertEqual(2, len(my_dict1), 'mismatch in the number of entries in dictionary.') # test assignment via setdefault - self.assertRaises(TypeError, myDict1.setdefault, + self.assertRaises(TypeError, my_dict1.setdefault, 'key3', 'wrong value') - myDict1.setdefault('key3', Plane('key3')) - self.assertEqual(3, len(myDict1), + my_dict1.setdefault('key3', plane.Plane('key3')) + self.assertEqual(3, len(my_dict1), 'mismatch in the number of entries in dictionary.') # test assignment via update - myDict1.update(myDict) - self.assertEqual(3, len(myDict1), + my_dict1.update(my_dict) + self.assertEqual(3, len(my_dict1), 'mismatch in the number of entries in dictionary.') - self.assertEqual('key2', myDict.keys()[0], + self.assertEqual('key2', my_dict.keys()[0], 'key mismatch for 1st key') - self.assertEqual('key1', myDict.keys()[1], + self.assertEqual('key1', my_dict.keys()[1], 'key mismatch for 2nd key') - #self.assertEqual(testPlane1, myDict.values()[0], - # 'value mismatch for 1st value') - #self.assertEqual(testPlane2, myDict.values()[1], - # 'value mismatch for 2nd value') # test add function - myDict1.add(Plane('key4')) - self.assertEqual(4, len(myDict1), + my_dict1.add(plane.Plane('key4')) + self.assertEqual(4, len(my_dict1), 'mismatch in the number of entries in dictionary.') - self.assertEqual('key1', myDict1.keys()[0], + self.assertEqual('key1', my_dict1.keys()[0], 'key mismatch for 1st key') - self.assertEqual('key2', myDict1.keys()[1], + self.assertEqual('key2', my_dict1.keys()[1], 'key mismatch for 2nd key') - self.assertEqual('key3', myDict1.keys()[2], + self.assertEqual('key3', my_dict1.keys()[2], 'key mismatch for 3rd key') - self.assertEqual('key4', myDict1.keys()[3], + self.assertEqual('key4', my_dict1.keys()[3], 'key mismatch for 4th key') - # self.assertEqual(testPlane1, myDict1.values()[0], - # 'value mismatch for 1st value') - #self.assertEqual(testPlane2, myDict1.values()[1], - # 'value mismatch for 2nd value') - plane5 = Plane("key5") - myDict1[plane5.key] = plane5 + + plane5 = plane.Plane("key5") + my_dict1[plane5.key] = plane5 with self.assertRaises(AttributeError): - myDict1.add(testPlaneURI) + my_dict1.add(test_plane_uri) - def testuuid2long(self): + def test_uuid2long(self): # > 64 bit uuid - u = uuid.UUID('3d26e30b-10cc-4301-8193-f2e0c6b63302') + u = uuid.UUID('{3d26e30b-10cc-4301-8193-f2e0c6b63302}') try: - uuid2long(u) + caom_util.uuid2long(u) self.fail("> 64 uuid should raise ValueError") except ValueError: pass u = uuid.UUID('00000000-0000-0000-0000-000000000001') - l = uuid2long(u) + l = caom_util.uuid2long(u) self.assertEqual(1L, l) u = uuid.UUID('00000000-0000-0000-0000-000000bc614e') - l = uuid2long(u) + l = caom_util.uuid2long(u) self.assertEqual(12345678L, l) - def testlong2uuid(self): + def test_long2uuid(self): # > 64 bit long l = 123456781234567812345678L try: - long2uuid(l) + caom_util.long2uuid(l) self.fail("> 64 bit long should raise ValueError") except ValueError: pass l = 3296038095975885829 - uid = long2uuid(l) + uid = caom_util.long2uuid(l) self.assertEqual('00000000-0000-0000-2dbd-e12f64cc2c05', str(uid)) - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2/caom2/tests/test_chunk.py b/caom2/caom2/tests/test_chunk.py new file mode 100644 index 00000000..ccc91c50 --- /dev/null +++ b/caom2/caom2/tests/test_chunk.py @@ -0,0 +1,346 @@ +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines TestChunk class """ + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import unittest + +from .. import chunk +from .. import wcs + + +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + with self.assertRaises(ValueError): + chunk.ProductType("no_such_string") + with self.assertRaises(ValueError): + chunk.ProductType(None) + with self.assertRaises(ValueError): + chunk.ProductType(1) + + # test that we can get the object for each enum by name + self.assertEqual(chunk.ProductType.SCIENCE.name, "SCIENCE") + self.assertEqual(chunk.ProductType[ + chunk.ProductType.SCIENCE.name].name, "SCIENCE") + self.assertEqual(chunk.ProductType['SCIENCE'].value, "science") + self.assertEqual(chunk.ProductType[ + chunk.ProductType.SCIENCE.name].value, "science") + + self.assertEqual(chunk.ProductType.SCIENCE.value, "science") + self.assertEqual(chunk.ProductType.CALIBRATION.value, "calibration") + self.assertEqual(chunk.ProductType.PREVIEW.value, "preview") + self.assertEqual(chunk.ProductType.INFO.value, "info") + self.assertEqual(chunk.ProductType.NOISE.value, "noise") + self.assertEqual(chunk.ProductType.WEIGHT.value, "weight") + self.assertEqual(chunk.ProductType.AUXILIARY.value, "auxiliary") + self.assertEqual(chunk.ProductType.THUMBNAIL.value, "thumbnail") + + +class TestChunk(unittest.TestCase): + + def test_init(self): + + test_chunk = chunk.Chunk() + self.assertIsNone(test_chunk.product_type) + self.assertIsNone(test_chunk.naxis) + self.assertIsNone(test_chunk.position_axis_1) + self.assertIsNone(test_chunk.position_axis_2) + self.assertIsNone(test_chunk.energy_axis) + self.assertIsNone(test_chunk.time_axis) + self.assertIsNone(test_chunk.polarization_axis) + self.assertIsNone(test_chunk.observable) + self.assertIsNone(test_chunk.position) + self.assertIsNone(test_chunk.energy) + self.assertIsNone(test_chunk.time) + self.assertIsNone(test_chunk.polarization) + + def test_attributes(self): + + test_chunk = chunk.Chunk() + with self.assertRaises(TypeError): + test_chunk.product_type = float(1.0) + test_chunk.naxis = float(1.0) + test_chunk.position_axis_1 = float(1.0) + test_chunk.position_axis_2 = float(1.0) + test_chunk.energy_axis = float(1.0) + test_chunk.time_axis = float(1.0) + test_chunk.polarization_axis = float(1.0) + test_chunk.observable = float(1.0) + test_chunk.position = float(1.0) + test_chunk.energy = float(1.0) + test_chunk.time = float(1.0) + test_chunk.polarization = float(1.0) + + test_chunk.product_type = chunk.ProductType.SCIENCE + self.assertEqual(chunk.ProductType.SCIENCE.name, test_chunk.product_type.name) + + test_chunk.naxis = int(5) + self.assertEqual(int(5), test_chunk.naxis) + + test_chunk.position_axis_1 = int(1) + self.assertEqual(int(1), test_chunk.position_axis_1) + + test_chunk.position_axis_2 = int(2) + self.assertEqual(int(2), test_chunk.position_axis_2) + + test_chunk.energy_axis = int(3) + self.assertEqual(int(3), test_chunk.energy_axis) + + test_chunk.time_axis = int(4) + self.assertEqual(int(4), test_chunk.time_axis) + + test_chunk.polarization_axis = int(5) + self.assertEqual(int(5), test_chunk.polarization_axis) + + axis = wcs.Axis("ctype", "cunit") + dependent = wcs.Slice(axis, long(1)) + observable = chunk.ObservableAxis(dependent) + test_chunk.observable = observable + self.assertEqual(observable, test_chunk.observable) + + axis1 = wcs.Axis("ctype1", "cunit1") + axis2 = wcs.Axis("ctype2", "cunit2") + axis_2d = wcs.CoordAxis2D(axis1, axis2) + position = chunk.SpatialWCS(axis_2d) + test_chunk.position = position + self.assertEqual(position, test_chunk.position) + + axis_1d = wcs.CoordAxis1D(axis) + energy = chunk.SpectralWCS(axis_1d, "specsys") + test_chunk.energy = energy + self.assertEqual(energy, test_chunk.energy) + + time = chunk.TemporalWCS(axis_1d) + test_chunk.time = time + self.assertEqual(time, test_chunk.time) + + polarization = chunk.PolarizationWCS(wcs.CoordAxis1D(wcs.Axis('STOKES'))) + test_chunk.polarization = polarization + self.assertEqual(polarization, test_chunk.polarization) + + +class TestObservableAxis(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, chunk.ObservableAxis, None) + self.assertRaises(TypeError, chunk.ObservableAxis, int(1)) + + dependent = wcs.Slice(wcs.Axis("ctype1", "cunit1"), long(1)) + independent = wcs.Slice(wcs.Axis("ctype2", "cunit2"), long(2)) + + observable = chunk.ObservableAxis(dependent) + self.assertEqual(observable.dependent, dependent) + + observable.independent = independent + self.assertEqual(observable.independent, independent) + + +class TestSpatialWCS(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, chunk.SpatialWCS, None) + self.assertRaises(TypeError, chunk.SpatialWCS, int(1)) + + axis1 = wcs.Axis("ctype1", "cunit1") + axis2 = wcs.Axis("ctype2", "cunit2") + axis_2d = wcs.CoordAxis2D(axis1, axis2) + position = chunk.SpatialWCS(axis_2d) + self.assertEqual(position.axis, axis_2d) + with self.assertRaises(TypeError): + position.coordsys = float(1.0) + position.bounds = str("s") + position.function = str("s") + + position.coordsys = "coordsys" + self.assertEqual(position.coordsys, "coordsys") + + self.assertRaises(ValueError, position.equinox, float(1.0)) + position.equinox = float(2000.0) + self.assertEqual(position.equinox, float(2000.0)) + + position.resolution = float(2.0) + self.assertEqual(position.resolution, float(2.0)) + + +class TestSpectralWCS(unittest.TestCase): + + def test_init(self): + + axis = wcs.Axis("ctype", "cunit") + axis_1d = wcs.CoordAxis1D(axis) + + self.assertRaises(TypeError, chunk.SpectralWCS, None, None) + self.assertRaises(TypeError, chunk.SpectralWCS, None, str("s")) + self.assertRaises(TypeError, chunk.SpectralWCS, axis_1d, None) + self.assertRaises(TypeError, chunk.SpectralWCS, int(1), str("s")) + self.assertRaises(TypeError, chunk.SpectralWCS, axis_1d, int(1)) + + energy = chunk.SpectralWCS(axis_1d, "specsys") + self.assertEqual(energy.axis, axis_1d) + self.assertEqual(energy.specsys, "specsys") + with self.assertRaises(TypeError): + energy.ssysobs = int(1) + energy.ssyssrc = int(1) + energy.restfrq = int(1) + energy.restwav = int(1) + energy.velosys = int(1) + energy.zsource = int(1) + energy.velang = int(1) + energy.bandpass_name = int(1) + energy.transition = int(1) + energy.resolving_power = int(1) + + with self.assertRaises(ValueError): + energy.zsource = float(-1) + energy.zsource = float(1201) + energy.resolving_power = float(-1) + energy.resolving_power = float(1.1e8) + + + energy.ssysobs = "ssysobs" + self.assertEqual(energy.ssysobs, "ssysobs") + + energy.ssyssrc = "ssyssrc" + self.assertEqual(energy.ssyssrc, "ssyssrc") + + energy.restfrq = float(1.0) + self.assertEqual(energy.restfrq, float(1.0)) + + energy.restwav = float(2.0) + self.assertEqual(energy.restwav, float(2.0)) + + energy.velosys = float(3.0) + self.assertEqual(energy.velosys, float(3.0)) + + energy.zsource = float(4.0) + self.assertEqual(energy.zsource, float(4.0)) + + energy.velang = float(5.0) + self.assertEqual(energy.velang, float(5.0)) + + energy.bandpass_name = "bandpass_name" + self.assertEqual(energy.bandpass_name, "bandpass_name") + + transition = wcs.EnergyTransition("species", "transition") + energy.transition = transition + self.assertEqual(energy.transition, transition) + + energy.resolving_power = float(6.0) + self.assertEqual(energy.resolving_power, float(6.0)) + + +class TestTemporalWCS(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, chunk.TemporalWCS, None) + self.assertRaises(TypeError, chunk.TemporalWCS, int(1)) + + axis = wcs.Axis("ctype", "cunit") + axis_1d = wcs.CoordAxis1D(axis) + time = chunk.TemporalWCS(axis_1d) + self.assertEqual(time.axis, axis_1d) + with self.assertRaises(TypeError): + time.exposure = str("s") + time.resolution = str("s") + + time.exposure = float(1.0) + self.assertEqual(time.exposure, float(1.0)) + + time.resolution = float(2.0) + self.assertEqual(time.resolution, float(2.0)) + + time.timesys = "timesys" + self.assertEqual(time.timesys, "timesys") + + time.trefpos = "trefpos" + self.assertEqual(time.trefpos, "trefpos") + + time.mjdref = float(3.0) + self.assertEqual(time.mjdref, float(3.0)) + + +class TestPolarizationWCS(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, chunk.PolarizationWCS, None) + self.assertRaises(TypeError, chunk.PolarizationWCS, int(1)) + + axis = wcs.Axis('STOKES') + axis_1d = wcs.CoordAxis1D(axis) + polarization = chunk.PolarizationWCS(axis_1d) + self.assertEqual(polarization.axis, axis_1d) diff --git a/pyCAOM2/caom2/test/test_observation_uri.py b/caom2/caom2/tests/test_common.py similarity index 68% rename from pyCAOM2/caom2/test/test_observation_uri.py rename to caom2/caom2/tests/test_common.py index e90edd5f..6bed5256 100644 --- a/pyCAOM2/caom2/test/test_observation_uri.py +++ b/caom2/caom2/tests/test_common.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -68,41 +67,69 @@ #*********************************************************************** # -""" Defines TestObservationURI class """ +""" Defines TestCaom2IdGenerator class """ + +from __future__ import (absolute_import, division, print_function, + unicode_literals) import unittest -from caom2.caom2_observation_uri import ObservationURI +from .. import common +from .. import chunk +from .. import part +from .. import plane +from .. import artifact +from .. import observation + + +class TestCaom2IdGenerator(unittest.TestCase): + + def test_all(self): + # Not much for now. Just to make sure that all the clients work + test_entity = common.AbstractCaomEntity() + print(test_entity._id, test_entity._last_modified) + test_artifact = artifact.Artifact("caom2:/blah/blah", + chunk.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + print(test_artifact._id, test_artifact._last_modified) + + test_chunk = chunk.Chunk() + print(test_chunk._id, test_chunk._last_modified) + + algorithm = observation.Algorithm("myAlg") + test_observation = observation.Observation("colect", "obs", algorithm) + print(test_observation._id, test_observation._last_modified) + + test_part = part.Part("part") + print(test_part._id, test_part._last_modified) + + test_plane = plane.Plane("prodid") + print(test_plane._id, test_plane._last_modified) class TestObservationURI(unittest.TestCase): - def testAll(self): - obsURI = ObservationURI("caom:GEMINI/12345") - self.assertEqual("caom:GEMINI/12345", obsURI.uri, "Observation URI") - self.assertEqual("GEMINI", obsURI.collection, "Collection") - self.assertEqual("12345", obsURI.observation_id, "Observation ID") + def test_all(self): + obs_uri = observation.ObservationURI("caom:GEMINI/12345") + self.assertEqual("caom:GEMINI/12345", obs_uri.uri, "Observation URI") + self.assertEqual("GEMINI", obs_uri.collection, "Collection") + self.assertEqual("12345", obs_uri.observation_id, "Observation ID") - obsURI = ObservationURI.get_observation_uri("CFHT", "654321") - self.assertEqual("caom:CFHT/654321", obsURI.uri, "Observation URI") - self.assertEqual("CFHT", obsURI.collection, "Collection") - self.assertEqual("654321", obsURI.observation_id, "Observation ID") + obs_uri = observation.ObservationURI.get_observation_uri("CFHT", "654321") + self.assertEqual("caom:CFHT/654321", obs_uri.uri, "Observation URI") + self.assertEqual("CFHT", obs_uri.collection, "Collection") + self.assertEqual("654321", obs_uri.observation_id, "Observation ID") exception = False try: - obsURI = ObservationURI.get_observation_uri(None, "123") + obs_uri = observation.ObservationURI.get_observation_uri(None, "123") except TypeError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - obsURI = ObservationURI.get_observation_uri("GEMINI", None) + obs_uri = observation.ObservationURI.get_observation_uri("GEMINI", None) except TypeError: exception = True self.assertTrue(exception, "Missing exception") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2/caom2/tests/test_obs_reader_writer.py b/caom2/caom2/tests/test_obs_reader_writer.py new file mode 100644 index 00000000..e2973ec9 --- /dev/null +++ b/caom2/caom2/tests/test_obs_reader_writer.py @@ -0,0 +1,884 @@ +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines TestObservationReaderWriter class """ + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import StringIO +import os +import unittest + +from lxml import etree +from xml_compare import xml_compare + +from . import caom_test_instances +from .. import obs_reader_writer +from .. import observation +from .. import wcs + +THIS_DIR = os.path.dirname(os.path.realpath(__file__)) + + +def minimal_simple(depth, bounds_is_circle, version): + instances = caom_test_instances.Caom2TestInstances() + instances.complete = False + instances.depth = depth + instances.bounds_is_circle = bounds_is_circle + instances.caom_version = version + return instances.get_simple_observation() + + +def complete_simple(depth, bounds_is_circle, version): + instances = caom_test_instances.Caom2TestInstances() + instances.complete = True + instances.depth = depth + instances.bounds_is_circle = bounds_is_circle + instances.caom_version = version + return instances.get_simple_observation() + + +def minimal_composite(depth, bounds_is_circle, version): + instances = caom_test_instances.Caom2TestInstances() + instances.complete = False + instances.depth = depth + instances.bounds_is_circle = bounds_is_circle + instances.caom_version = version + return instances.get_composite_observation() + + +def complete_composite(depth, bounds_is_circle, version): + instances = caom_test_instances.Caom2TestInstances() + instances.complete = True + instances.depth = depth + instances.bounds_is_circle = bounds_is_circle + instances.caom_version = version + return instances.get_composite_observation() + + +class TestObservationReaderWriter(unittest.TestCase): + + def test_invalid_long_id(self): + simple_observation = minimal_simple(1, False, 20) + writer = obs_reader_writer.ObservationWriter( + False, False, "caom2", obs_reader_writer.CAOM20_NAMESPACE) + output = StringIO.StringIO() + writer.write(simple_observation, output) + xml = output.getvalue() + output.close() + xml = xml.replace("caom2:id=\"", "caom2:id=\"x") + f = open('/tmp/test.xml', 'w') + f.write(xml) + f.close() + reader = obs_reader_writer.ObservationReader(False) + try: + reader.read('/tmp/test.xml') + self.fail("invalid long id should throw ValueError") + except ValueError: + pass + + def test_invalid_uuid(self): + simple_observation = minimal_simple(1, False, 21) + writer = obs_reader_writer.ObservationWriter(False, False) # default writer is 2.1 + output = StringIO.StringIO() + writer.write(simple_observation, output) + xml = output.getvalue() + output.close() + xml = xml.replace("0000", "xxxx", 1) + f = open('/tmp/test.xml', 'w') + f.write(xml) + f.close() + reader = obs_reader_writer.ObservationReader(False) + try: + reader.read('/tmp/test.xml') + self.fail("invalid uuid id should throw ValueError") + except ValueError: + pass + + def test_minimal_simple(self): + for version in (20, 21): + for i in range(1, 6): + print("Test Minimal Simple {} version {}".format(i, version)) + # CoordBounds2D as CoordCircle2D + simple_observation = minimal_simple(i, True, version) + # write empty elements + self.observation_test(simple_observation, True, True, version) + # do not write empty elements + self.observation_test(simple_observation, True, False, version) + # CoordBounds2D as CoordPolygon2D + simple_observation = minimal_simple(i, False, version) + # write empty elements + self.observation_test(simple_observation, True, True, version) + # do not write empty elements + self.observation_test(simple_observation, True, False, version) + + def test_complete_simple(self): + for version in (20, 21, 22): + for i in range(1, 6): + print("Test Complete Simple {} version {}".format(i, version)) + # CoordBounds2D as CoordCircle2D + simple_observation = complete_simple(i, True, version) + # write empty elements + self.observation_test(simple_observation, True, True, version) + # do not write empty elements + self.observation_test(simple_observation, True, False, version) + # CoordBounds2D as CoordPolygon2D + simple_observation = complete_simple(i, False, version) + # write empty elements + self.observation_test(simple_observation, True, True, version) + # do not write empty elements + self.observation_test(simple_observation, True, False, version) + + def test_minimal_composite(self): + for version in (20, 21, 22): + for i in range(1, 6): + print("Test Minimal Composite {} version {}".format(i, version)) + # CoordBounds2D as CoordCircle2D + composite_observation = minimal_composite(i, True, version) + # write empty elements + self.observation_test(composite_observation, True, True, version) + # do not write empty elements + self.observation_test(composite_observation, True, False, version) + # CoordBounds2D as CoordPolygon2D + composite_observation = minimal_composite(i, False, version) + # write empty elements + self.observation_test(composite_observation, True, True, version) + # do not write empty elements + self.observation_test(composite_observation, True, False, version) + + def test_complete_composite(self): + for version in (20, 21, 22): + for i in range(1, 6): + print("Test Complete Composite {} version {}".format(i, version)) + # CoordBounds2D as CoordCircle2D + composite_observation = complete_composite(i, True, version) + # write empty elements + self.observation_test(composite_observation, True, True, version) + # do not write empty elements + self.observation_test(composite_observation, True, False, version) + # CoordBounds2D as CoordPolygon2D + composite_observation = complete_composite(i, False, version) + # write empty elements + self.observation_test(composite_observation, True, True, version) + # do not write empty elements + self.observation_test(composite_observation, True, False, version) + + def test_versions(self): + composite_observation = complete_composite(6, True, 20) + self.observation_test(composite_observation, True, True, 20) + self.observation_test(composite_observation, True, True, 21) + self.observation_test(composite_observation, True, True, 22) + + composite_observation = complete_composite(6, True, 21) + self.observation_test(composite_observation, True, True, 20) + self.observation_test(composite_observation, True, True, 21) + self.observation_test(composite_observation, True, True, 22) + + composite_observation = complete_composite(6, True, 22) + self.observation_test(composite_observation, True, True, 20) + self.observation_test(composite_observation, True, True, 21) + self.observation_test(composite_observation, True, True, 22) + + def observation_test(self, obs, validate, write_empty_collections, version): + if version == 20: + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections, "caom2", + obs_reader_writer.CAOM20_NAMESPACE) + elif version == 21: + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections, "caom2", + obs_reader_writer.CAOM21_NAMESPACE) + else: + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections) + xml_file = open('/tmp/test.xml', 'w') + writer.write(obs, xml_file) + xml_file.close() + reader = obs_reader_writer.ObservationReader(True) + returned = reader.read('/tmp/test.xml') + self.compare_observations(obs, returned, version) + + def compare_observations(self, expected, actual, version): + + assert ((isinstance(expected, observation.SimpleObservation) and + isinstance(actual, observation.SimpleObservation)) or + (isinstance(expected, observation.CompositeObservation) and + isinstance(actual, observation.CompositeObservation))), ( + "Observation types do not match 0 vs 1". + format(expected.__class__.__name__, + actual.__class__.__name__)) + + self.assertIsNotNone(expected.collection) + self.assertIsNotNone(actual.collection) + self.assertEqual(expected.collection, actual.collection) + + self.assertIsNotNone(expected.observation_id) + self.assertIsNotNone(actual.observation_id) + self.assertEqual(expected.observation_id, actual.observation_id) + + self.assertIsNotNone(expected._id) + self.assertIsNotNone(actual._id) + self.assertEqual(expected._id, actual._id) + + self.assertIsNotNone(expected._last_modified) + self.assertIsNotNone(actual._last_modified) + self.assertEqual(expected._last_modified, actual._last_modified) + + self.assertIsNotNone(expected.algorithm) + self.assertIsNotNone(actual.algorithm) + self.assertEqual(expected.algorithm.name, actual.algorithm.name) + + self.assertEqual(expected.sequence_number, actual.sequence_number) + self.assertEqual(expected.intent, actual.intent) + self.assertEqual(expected.meta_release, actual.meta_release) + self.compare_proposal(expected.proposal, actual.proposal) + self.compare_target(expected.target, actual.target) + self.compare_target_position(expected.target_position, + actual.target_position) + self.compare_telescope(expected.telescope, actual.telescope) + self.compare_instrument(expected.instrument, actual.instrument) + self.compare_environment(expected.environment, actual.environment) + if version == 21: + self.compare_requirements(expected.requirements, actual.requirements) + + self.compare_planes(expected.planes, actual.planes, version) + + if (isinstance(expected, observation.CompositeObservation) and + isinstance(actual, observation.CompositeObservation)): + self.compare_members(expected.members, actual.members) + + def compare_proposal(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.proposal_id, actual.proposal_id) + self.assertEqual(expected.pi_name, actual.pi_name) + self.assertEqual(expected.project, actual.project) + self.assertEqual(expected.title, actual.title) + self.assertEqual(len(expected.keywords), len(actual.keywords)) + for keyword in expected.keywords: + self.assertTrue(keyword in actual.keywords) + + def compare_target(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.name, actual.name) + self.assertEqual(expected.target_type, actual.target_type) + self.assertEqual(expected.redshift, actual.redshift) + for keyword in expected.keywords: + self.assertTrue(keyword in actual.keywords) + + def compare_target_position(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.coordinates) + self.assertIsNotNone(actual.coordsys) + self.compare_point(expected.coordinates, actual.coordinates) + self.assertEqual(expected.coordsys, actual.coordsys) + self.assertEqual(expected.equinox, actual.equinox) + + def compare_telescope(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.name, actual.name) + self.assertEqual(expected.geo_location_x, actual.geo_location_x) + self.assertEqual(expected.geo_location_y, actual.geo_location_y) + self.assertEqual(expected.geo_location_z, actual.geo_location_z) + for keyword in expected.keywords: + self.assertTrue(keyword in actual.keywords) + + def compare_instrument(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.name, actual.name) + for keyword in expected.keywords: + self.assertTrue(keyword in actual.keywords) + + def compare_environment(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.seeing, actual.seeing) + self.assertEqual(expected.humidity, actual.humidity) + self.assertEqual(expected.elevation, actual.elevation) + self.assertEqual(expected.tau, actual.tau) + self.assertEqual(expected.wavelength_tau, actual.wavelength_tau) + self.assertEqual(expected.ambient_temp, actual.ambient_temp) + self.assertEqual(expected.photometric, actual.photometric) + + def compare_members(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for expected_member, actual_member in zip(expected, actual): + self.compare_observation_uri(expected_member, actual_member) + + def compare_observation_uri(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEquals(expected.uri, actual.uri) + self.assertEquals(expected.collection, actual.collection) + self.assertEquals(expected.observation_id, actual.observation_id) + + def compare_requirements(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEquals(expected.flag, actual.flag) + + def compare_planes(self, expected, actual, version): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for key in expected: + self.assertTrue(key in actual) + expected_plane = expected[key] + actual_plane = actual[key] + self.assertIsNotNone(expected_plane) + self.assertIsNotNone(actual_plane) + self.assertEqual(expected_plane.product_id, actual_plane.product_id) + self.assertIsNotNone(expected_plane._id) + self.assertIsNotNone(actual_plane._id) + self.assertEqual(expected_plane._id, actual_plane._id) + self.assertIsNotNone(expected_plane._last_modified) + self.assertIsNotNone(actual_plane._last_modified) + self.assertEqual(expected_plane._last_modified, + actual_plane._last_modified) + self.assertEqual(expected_plane.meta_release, + actual_plane.meta_release) + self.assertEqual(expected_plane.data_release, + actual_plane.data_release) + self.assertEqual(expected_plane.data_product_type, + actual_plane.data_product_type) + self.assertEqual(expected_plane.calibration_level, + actual_plane.calibration_level) + self.compare_provenance(expected_plane.provenance, + actual_plane.provenance) + self.compare_metrics(expected_plane.metrics, actual_plane.metrics) + if version == 21: + self.compare_quality(expected_plane.quality, + actual_plane.quality) + + self.compare_artifacts(expected_plane.artifacts, + actual_plane.artifacts, version) + + def compare_provenance(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.version, actual.version) + self.assertEqual(expected.project, actual.project) + self.assertEqual(expected.producer, actual.producer) + self.assertEqual(expected.run_id, actual.run_id) + self.assertEqual(expected.reference, actual.reference) + self.assertEqual(expected.last_executed, actual.last_executed) + self.compare_inputs(expected.inputs, actual.inputs) + + def compare_metrics(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.source_number_density, + actual.source_number_density) + self.assertEqual(expected.background, actual.background) + self.assertEqual(expected.background_std_dev, actual.background_std_dev) + self.assertEqual(expected.flux_density_limit, actual.flux_density_limit) + self.assertEqual(expected.mag_limit, actual.mag_limit) + + def compare_quality(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.flag, actual.flag) + + def compare_inputs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for expected_plane_uri, actual_plane_uri in zip(expected, actual): + self.assertEqual(expected_plane_uri, actual_plane_uri) + + def compare_artifacts(self, expected, actual, version): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for key in expected: + self.assertTrue(key in actual) + expected_artifact = expected[key] + actual_artifact = actual[key] + self.assertIsNotNone(expected_artifact) + self.assertIsNotNone(actual_artifact) + self.assertIsNotNone(expected_artifact._id) + self.assertIsNotNone(actual_artifact._id) + self.assertEqual(expected_artifact._id, actual_artifact._id) + self.assertIsNotNone(expected_artifact._last_modified) + self.assertIsNotNone(actual_artifact._last_modified) + self.assertEqual(expected_artifact._last_modified, + actual_artifact._last_modified) + self.assertEqual(expected_artifact.uri, actual_artifact.uri) + self.assertEqual(expected_artifact.content_type, + actual_artifact.content_type) + self.assertEqual(expected_artifact.content_length, + actual_artifact.content_length) + self.assertEqual(expected_artifact.product_type, + actual_artifact.product_type) + if version > 21: + self.assertEqual(expected_artifact.release_type, + actual_artifact.release_type) + self.compare_parts(expected_artifact.parts, + actual_artifact.parts, version) + + def compare_parts(self, expected, actual, version): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for key in expected: + self.assertTrue(key in actual) + expected_part = expected[key] + actual_part = actual[key] + self.assertIsNotNone(expected_part) + self.assertIsNotNone(actual_part) + self.assertIsNotNone(expected_part._id) + self.assertIsNotNone(actual_part._id) + self.assertEqual(expected_part._id, actual_part._id) + self.assertIsNotNone(expected_part._last_modified) + self.assertIsNotNone(actual_part._last_modified) + self.assertEqual(expected_part._last_modified, + actual_part._last_modified) + self.assertEqual(expected_part.name, actual_part.name) + self.assertEqual(expected_part.product_type, actual_part.product_type) + self.compare_chunks(expected_part.chunks, actual_part.chunks) + + def compare_chunks(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for expected_chunk, actual_chunk in zip(expected, actual): + self.assertIsNotNone(expected_chunk) + self.assertIsNotNone(actual_chunk) + self.assertIsNotNone(expected_chunk._id) + self.assertIsNotNone(actual_chunk._id) + self.assertEqual(expected_chunk._id, actual_chunk._id) + self.assertIsNotNone(expected_chunk._last_modified) + self.assertIsNotNone(actual_chunk._last_modified) + self.assertEqual(expected_chunk._last_modified, + actual_chunk._last_modified) + self.assertEqual(expected_chunk.product_type, + actual_chunk.product_type) + self.assertEqual(expected_chunk.naxis, actual_chunk.naxis) + self.assertEqual(expected_chunk.observable_axis, + actual_chunk.observable_axis) + self.assertEqual(expected_chunk.position_axis_1, + actual_chunk.position_axis_1) + self.assertEqual(expected_chunk.position_axis_2, + actual_chunk.position_axis_2) + self.assertEqual(expected_chunk.energy_axis, actual_chunk.energy_axis) + self.assertEqual(expected_chunk.time_axis, actual_chunk.time_axis) + self.assertEqual(expected_chunk.polarization_axis, + actual_chunk.polarization_axis) + self.compare_observable_axis(expected_chunk.observable, + actual_chunk.observable) + self.compare_spatial_wcs(expected_chunk.position, + actual_chunk.position) + self.compare_spectral_wcs(expected_chunk.energy, actual_chunk.energy) + self.compare_temporal_wcs(expected_chunk.time, actual_chunk.time) + self.compare_polarization_wcs(expected_chunk.polarization, + actual_chunk.polarization) + + def compare_observable_axis(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_slice(expected.dependent, actual.dependent) + self.compare_slice(expected.independent, actual.independent) + + def compare_spatial_wcs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_coord_axis2d(expected.axis, actual.axis) + self.assertEqual(expected.coordsys, actual.coordsys) + self.assertEqual(expected.equinox, actual.equinox) + self.assertEqual(expected.resolution, actual.resolution) + + def compare_spectral_wcs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_coord_axis1d(expected.axis, actual.axis) + self.assertEqual(expected.bandpass_name, actual.bandpass_name) + self.assertEqual(expected.resolving_power, actual.resolving_power) + self.assertEqual(expected.restfrq, actual.restfrq) + self.assertEqual(expected.restwav, actual.restwav) + self.assertEqual(expected.specsys, actual.specsys) + self.assertEqual(expected.ssysobs, actual.ssysobs) + self.assertEqual(expected.ssyssrc, actual.ssyssrc) + self.assertEqual(expected.velang, actual.velang) + self.assertEqual(expected.velosys, actual.velosys) + self.assertEqual(expected.zsource, actual.zsource) + + def compare_temporal_wcs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_coord_axis1d(expected.axis, actual.axis) + self.assertEqual(expected.exposure, actual.exposure) + self.assertEqual(expected.resolution, actual.resolution) + self.assertEqual(expected.timesys, actual.timesys) + self.assertEqual(expected.trefpos, actual.trefpos) + self.assertEqual(expected.mjdref, actual.mjdref) + + def compare_polarization_wcs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_coord_axis1d(expected.axis, actual.axis) + + def compare_axis(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.ctype) + self.assertIsNotNone(actual.cunit) + self.assertEqual(expected.ctype, actual.ctype) + self.assertEqual(expected.cunit, actual.cunit) + + def compare_coord2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.compare_ref_coord(expected.coord1, actual.coord1) + self.compare_ref_coord(expected.coord2, actual.coord2) + + def compare_value_coord2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertEqual(expected.coord1, actual.coord1) + self.assertEqual(expected.coord2, actual.coord2) + + def compare_coord_axis1d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.compare_coord_error(expected.error, actual.error) + self.compare_coord_range1d(expected.range, actual.range) + self.compare_coord_bounds1d(expected.bounds, actual.bounds) + self.compare_coord_function1d(expected.function, actual.function) + + def compare_coord_axis2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.axis1) + self.assertIsNotNone(actual.axis2) + self.compare_axis(expected.axis1, actual.axis1) + self.compare_axis(expected.axis2, actual.axis2) + self.compare_coord_error(expected.error1, actual.error1) + self.compare_coord_error(expected.error2, actual.error2) + self.compare_coord_range2d(expected.range, actual.range) + self.compare_coord_bounds2d(expected.bounds, actual.bounds) + self.compare_coord_function2d(expected.function, actual.function) + + def compare_coord_bounds1d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(expected.samples) + self.assertIsNotNone(actual.samples) + self.assertEqual(len(expected.samples), len(actual.samples)) + for expected_range, actual_range in zip(expected.samples, actual.samples): + self.compare_coord_range1d(expected_range, actual_range) + + def compare_coord_bounds2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + if (isinstance(expected, wcs.CoordCircle2D) and + isinstance(actual, wcs.CoordCircle2D)): + self.compare_coord_circle2d(expected, actual) + elif (isinstance(expected, wcs.CoordPolygon2D) and + isinstance(actual, wcs.CoordPolygon2D)): + self.compare_coord_polygon2d(expected, actual) + else: + self.fail("CoordBounds2D expected and actual are different types.") + + def compare_coord_circle2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.center) + self.assertIsNotNone(actual.radius) + self.compare_value_coord2d(expected.center, actual.center) + self.assertEqual(expected.radius, actual.radius) + + def compare_coord_error(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + + self.assertIsNotNone(actual) + if expected.syser: + self.assertIsNotNone(actual.syser) + self.assertEqual(expected.syser, actual.syser) + if expected.rnder: + self.assertIsNotNone(actual.rnder) + self.assertEqual(expected.rnder, actual.rnder) + + def compare_coord_function1d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertEqual(expected.naxis, actual.naxis) + self.assertEqual(expected.delta, actual.delta) + self.compare_ref_coord(expected.ref_coord, actual.ref_coord) + + def compare_coord_function2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.dimension) + self.assertIsNotNone(actual.ref_coord) + self.assertIsNotNone(actual.cd11) + self.assertIsNotNone(actual.cd12) + self.assertIsNotNone(actual.cd21) + self.assertIsNotNone(actual.cd22) + self.compare_dimension2d(expected.dimension, actual.dimension) + self.compare_coord2d(expected.ref_coord, actual.ref_coord) + self.assertEqual(expected.cd11, actual.cd11, 0.0) + self.assertEqual(expected.cd12, actual.cd12, 0.0) + self.assertEqual(expected.cd21, actual.cd21, 0.0) + self.assertEqual(expected.cd22, actual.cd22, 0.0) + + def compare_coord_polygon2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(expected.vertices) + self.assertIsNotNone(actual.vertices) + self.assertEqual(len(expected.vertices), len(actual.vertices)) + for expected_coord_2d, actual_coord_2d in zip(expected.vertices, + actual.vertices): + self.compare_value_coord2d(expected_coord_2d, actual_coord_2d) + + def compare_coord_range1d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.compare_ref_coord(expected.start, actual.start) + self.compare_ref_coord(expected.end, actual.end) + + def compare_coord_range2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.start) + self.assertIsNotNone(actual.end) + self.compare_coord2d(expected.start, actual.start) + self.compare_coord2d(expected.end, actual.end) + + def compare_dimension2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertEqual(expected.naxis1, actual.naxis1) + self.assertEqual(expected.naxis2, actual.naxis2) + + def compare_ref_coord(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertEqual(expected.pix, actual.pix) + self.assertEqual(expected.val, actual.val) + + def compare_slice(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.bin) + self.assertIsNotNone(actual.axis) + self.assertEqual(expected.bin, actual.bin) + self.compare_axis(expected.axis, actual.axis) + + def compare_point(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.cval1) + self.assertIsNotNone(actual.cval2) + self.assertEqual(expected.cval1, actual.cval1) + self.assertEqual(expected.cval2, actual.cval2) + + +class TestRoundTrip(unittest.TestCase): + + TEST_DATA = 'data' + + def init(self): + pass + + def get_file_list(self): + return [f for f in os.listdir(THIS_DIR + "/" + TestRoundTrip.TEST_DATA) + if f.endswith('.xml')] + + def do_test(self, reader, writer, filename): + source_file_path = os.path.join(THIS_DIR + "/" + + TestRoundTrip.TEST_DATA + "/" + filename) + source_xml_fp = open(source_file_path, 'r') + obs = reader.read(source_file_path) + source_xml_fp.close() + dest_file = StringIO.StringIO() + writer.write(obs, dest_file) + + source_dom = etree.parse(source_file_path).getroot() + dest_dom = etree.fromstring(dest_file.getvalue()) + self.assertTrue(xml_compare(source_dom, dest_dom), + 'files are different') + + # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 + # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 + # objects. The two XML files are then compared to ensure that they + # are the same. The test fails if the files are not the same. The + # test/data/*.xml files can be used in this test. + + def test_round_trip(self): + print("Test Round Trip") + + try: + self.init() + files = self.get_file_list() + self.assertTrue(len(files) > 0, 'No XML files in test data directory') + + reader = obs_reader_writer.ObservationReader(True) + writer20 = obs_reader_writer.ObservationWriter( + True, False, "caom2", obs_reader_writer.CAOM20_NAMESPACE) + writer21 = obs_reader_writer.ObservationWriter( + True, False, "caom2", obs_reader_writer.CAOM21_NAMESPACE) + writer22 = obs_reader_writer.ObservationWriter(True, False, "caom2") + for filename in files: + if filename.endswith("CAOM-2.2.xml"): + self.do_test(reader, writer22, filename) + elif filename.endswith("CAOM-2.1.xml"): + self.do_test(reader, writer21, filename) + else: + self.do_test(reader, writer20, filename) + + except Exception: + raise diff --git a/caom2/caom2/tests/test_observation.py b/caom2/caom2/tests/test_observation.py new file mode 100644 index 00000000..f6b5dae1 --- /dev/null +++ b/caom2/caom2/tests/test_observation.py @@ -0,0 +1,718 @@ +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines TestObservation class """ + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import unittest +from datetime import datetime + +from .. import caom_util +from .. import observation +from .. import plane +from .. import shape + + +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + with self.assertRaises(KeyError): + observation.ObservationIntentType["no_such_string"] + with self.assertRaises(ValueError): + observation.ObservationIntentType(None) + with self.assertRaises(ValueError): + observation.ObservationIntentType(1) + + with self.assertRaises(KeyError): + observation.Status["no_such_string"] + with self.assertRaises(ValueError): + observation.Status(None) + with self.assertRaises(ValueError): + observation.Status(1) + + with self.assertRaises(KeyError): + observation.TargetType["no_such_string"] + with self.assertRaises(ValueError): + observation.TargetType(None) + with self.assertRaises(ValueError): + observation.TargetType(1) + + # test that we can get the object for each enum by name + self.assertEqual(observation.ObservationIntentType.CALIBRATION.value, "calibration") + self.assertEqual(observation.ObservationIntentType.SCIENCE.value, "science") + + self.assertEqual(observation.Status.FAIL.value, "fail") + + self.assertEqual(observation.TargetType.FIELD.value, "field") + self.assertEqual(observation.TargetType.OBJECT.value, "object") + + +class TestObservation(unittest.TestCase): + + def test_all(self): + algorithm = observation.Algorithm("myAlg") + obs = observation.Observation("GSA", "A12345", algorithm) + self.assertEqual("GSA", obs.collection, "Collection") + self.assertEqual("A12345", obs.observation_id, "Observation ID") + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + new_algorithm = observation.Algorithm("myNewAlg") + obs.algorithm = new_algorithm + self.assertEquals(new_algorithm, obs.algorithm, "New algorithm") + + self.assertIsNone(obs.intent, "Default intent") + obs.intent = observation.ObservationIntentType.CALIBRATION + self.assertEqual(observation.ObservationIntentType.CALIBRATION, + obs.intent, "Observation intent") + + self.assertIsNone(obs.obs_type, "Default obs_type") + obs.obs_type = "obstype1" + self.assertEqual("obstype1", + obs.obs_type, "obs type") + + self.assertIsNone(obs.proposal, "Default proposal") + proposal = observation.Proposal("ABC") + obs.proposal = proposal + self.assertEqual(proposal, + obs.proposal, "Proposal") + + self.assertIsNone(obs.telescope, "Default telescope") + telescope = observation.Telescope("GSAGN") + obs.telescope = telescope + self.assertEqual(telescope, obs.telescope, "Telescope") + + self.assertIsNone(obs.instrument, "Default instrument") + instrument = observation.Instrument("NIRI") + obs.instrument = instrument + self.assertEqual(instrument, obs.instrument, "Instrument") + + self.assertIsNone(obs.target, "Default target") + target = observation.Target("TGT") + obs.target = target + self.assertEqual(target, obs.target, "Target") + + self.assertIsNone(obs.target_position, "Default target position") + target_position = observation.TargetPosition(shape.Point(1.0, 2.0), "coordsys") + obs.target_position = target_position + self.assertEqual(target_position, + obs.target_position, "TargetPosition") + + self.assertIsNone(obs.requirements, "Default requirements") + requirements = observation.Requirements(observation.Status.FAIL) + obs.requirements = requirements + self.assertEqual(requirements, + obs.requirements, "Requirements") + + self.assertIsNone(obs.environment, "Default environment") + environment = observation.Environment() + obs.environment = environment + self.assertEqual(environment, + obs.environment, "Environment") + + self.assertIsNone(obs.meta_release, "Default metadata release") + date_now = datetime.now() + obs.meta_release = date_now + self.assertEqual(date_now, + obs.meta_release, "Metadata release") + + self.assertEqual(0, len(obs.planes), "Default planes") + plane1 = plane.Plane("myPlaneID") + obs.planes["myPlaneID"] = plane1 + self.assertEqual(1, len(obs.planes), "Planes") + self.assertTrue("myPlaneID" in obs.planes.keys()) + + plane2 = plane.Plane("myPlaneID2") + obs.planes["myPlaneID2"] = plane2 + self.assertEqual(2, len(obs.planes), "Planes") + self.assertTrue("myPlaneID" in obs.planes) + self.assertTrue("myPlaneID2" in obs.planes.keys()) + + # test duplicates + plane3 = plane.Plane("myPlaneID2") + obs.planes["myPlaneID2"] = plane3 + self.assertEqual(2, len(obs.planes), "Planes") + self.assertTrue("myPlaneID" in obs.planes) + self.assertTrue("myPlaneID2" in obs.planes.keys()) + + obs2 = observation.Observation( + obs.collection, + obs.observation_id, + obs.algorithm, + planes=obs.planes, + sequence_number=obs.sequence_number, + intent=obs.intent, + obs_type=obs.obs_type, + proposal=obs.proposal, + telescope=obs.telescope, + instrument=obs.instrument, + target=obs.target, + meta_release=obs.meta_release, + environment=obs.environment, + target_position=obs.target_position) + + +class TestSimpleObservation(unittest.TestCase): + + def test_all(self): + algorithm = observation.SimpleObservation._ALGORITHM + obs = observation.SimpleObservation("GSA", "A12345") + self.assertEqual("GSA", obs.collection, "Collection") + self.assertEqual("A12345", obs.observation_id, "Observation ID") + + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + obs.algorithm = algorithm + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + # try to set algorithm + exception = False + try: + obs.algorithm = observation.Algorithm("myAlg") + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + # run the rest of the Observation tests + self.assertIsNone(obs.intent, "Default intent") + obs.intent = observation.ObservationIntentType.CALIBRATION + self.assertEqual(observation.ObservationIntentType.CALIBRATION, + obs.intent, "Observation intent") + + self.assertIsNone(obs.obs_type, "Default obs_type") + obs.obs_type = "obstype1" + self.assertEqual("obstype1", + obs.obs_type, "obs type") + + self.assertIsNone(obs.proposal, "Default proposal") + proposal = observation.Proposal("ABC") + obs.proposal = proposal + self.assertEqual(proposal, + obs.proposal, "Proposal") + + self.assertIsNone(obs.telescope, "Default telescope") + telescope = observation.Telescope("GSAGN") + obs.telescope = telescope + self.assertEqual(telescope, + obs.telescope, "Telescope") + + self.assertIsNone(obs.instrument, "Default instrument") + instrument = observation.Instrument("NIRI") + obs.instrument = instrument + self.assertEqual(instrument, + obs.instrument, "Instrument") + + self.assertIsNone(obs.target, "Default target") + target = observation.Target("TGT") + obs.target = target + self.assertEqual(target, + obs.target, "Target") + + self.assertIsNone(obs.environment, "Default environment") + environment = observation.Environment() + obs.environment = environment + self.assertEqual(environment, + obs.environment, "Environment") + + self.assertIsNone(obs.target_position, "Default target position") + target_position = observation.TargetPosition(shape.Point(1.0, 2.0), "coordsys") + obs.target_position = target_position + self.assertEqual(target_position, + obs.target_position, "TargetPosition") + + self.assertIsNone(obs.requirements, "Default requirements") + requirements = observation.Requirements(observation.Status.FAIL) + obs.requirements = requirements + self.assertEquals(requirements, obs.requirements, "requirements") + + self.assertIsNone(obs.meta_release, "Default metadata release") + date_now = datetime.now() + obs.meta_release = date_now + self.assertEqual(date_now, + obs.meta_release, "Metadata release") + + # Test the complete constructor + def test_complete_init(self): + collection = "CFHT" + observation_id = "543210" + algorithm = observation.SimpleObservation._ALGORITHM + sequence_number = int(3) + intent = observation.ObservationIntentType.SCIENCE + obs_type = "foo" + proposal = observation.Proposal("123") + telescope = observation.Telescope("TEL") + instrument = observation.Instrument("INST") + target = observation.Target("LMC") + meta_release = datetime.now() + planes = caom_util.TypedOrderedDict(plane.Plane,) + environment = observation.Environment() + + obs = observation.SimpleObservation( + collection, + observation_id, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment) + + self.assertIsNotNone(obs.collection, "Collection") + self.assertEqual(collection, obs.collection, "Collection") + + self.assertIsNotNone(obs.observation_id, "Observation ID") + self.assertEqual(observation_id, obs.observation_id, "Observation ID") + + self.assertIsNotNone(obs.algorithm, "Algorithm") + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + self.assertIsNotNone(obs.intent, "Observation intent") + self.assertEqual(intent, obs.intent, "Observation intent") + + self.assertIsNotNone(obs.obs_type, "obs type") + self.assertEqual(obs_type, obs.obs_type, "obs type") + + self.assertIsNotNone(obs.proposal, "Proposal") + self.assertEqual(proposal, obs.proposal, "Proposal") + + self.assertIsNotNone(obs.telescope, "Telescope") + self.assertEqual(telescope, obs.telescope, "Telescope") + + self.assertIsNotNone(obs.instrument, "Instrument") + self.assertEqual(instrument, obs.instrument, "Instrument") + + self.assertIsNotNone(obs.target, "Target") + self.assertEqual(target, obs.target, "Target") + + self.assertIsNotNone(obs.meta_release, "Metadata release") + self.assertEqual(meta_release, obs.meta_release, "Metadata release") + + self.assertIsNotNone(obs.planes, "Planes") + self.assertEqual(planes, obs.planes, "Planes") + + self.assertIsNotNone(obs.environment, "Environment") + self.assertEqual(environment, obs.environment, "Environment") + + +class TestCompositeObservation(unittest.TestCase): + + def test_all(self): + algorithm = observation.Algorithm("mozaic") + obs = observation.CompositeObservation("GSA", "A12345", algorithm) + self.assertEqual("GSA", obs.collection, "Collection") + self.assertEqual("A12345", obs.observation_id, "Observation ID") + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + obs.algorithm = algorithm + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + # try to set algorithm to an invalid value + exception = False + try: + obs.algorithm = observation.SimpleObservation._ALGORITHM + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + # try to set algorithm to None + exception = False + try: + obs.algorithm = None + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + self.assertEqual(0, len(obs.members), "Members") + observation_uri1 = observation.ObservationURI("caom:collection/obsID") + obs.members.add(observation_uri1) + self.assertEqual(1, len(obs.members), "Members") + self.assertTrue(observation_uri1 in obs.members) + + observation_uri2 = observation.ObservationURI("caom:collection/obsID2") + obs.members.add(observation_uri2) + self.assertEqual(2, len(obs.members), "Members") + self.assertTrue(observation_uri1 in obs.members) + self.assertTrue(observation_uri2 in obs.members) + + #duplicates + observation_uri3 = observation.ObservationURI("caom:collection/obsID") + obs.members.add(observation_uri3) + self.assertEqual(2, len(obs.members), "Members") + self.assertTrue(observation_uri1 in obs.members) + self.assertTrue(observation_uri2 in obs.members) + + # run the rest of the Observation tests + self.assertIsNone(obs.intent, "Default intent") + obs.intent = observation.ObservationIntentType.CALIBRATION + self.assertEqual(observation.ObservationIntentType.CALIBRATION, + obs.intent, "Observation intent") + + self.assertIsNone(obs.obs_type, "Default obs_type") + obs.obs_type = "obstype1" + self.assertEqual("obstype1", + obs.obs_type, "obs type") + + self.assertIsNone(obs.proposal, "Default proposal") + proposal = observation.Proposal("ABC") + obs.proposal = proposal + self.assertEqual(proposal, + obs.proposal, "Proposal") + + self.assertIsNone(obs.telescope, "Default telescope") + telescope = observation.Telescope("GSAGN") + obs.telescope = telescope + self.assertEqual(telescope, + obs.telescope, "Telescope") + + self.assertIsNone(obs.instrument, "Default instrument") + instrument = observation.Instrument("NIRI") + obs.instrument = instrument + self.assertEqual(instrument, + obs.instrument, "Instrument") + + self.assertIsNone(obs.target, "Default target") + target = observation.Target("TGT") + obs.target = target + self.assertEqual(target, + obs.target, "Target") + + self.assertIsNone(obs.environment, "Default environment") + environment = observation.Environment() + obs.environment = environment + self.assertEqual(environment, + obs.environment, "Environment") + + self.assertIsNone(obs.target_position, "Default target position") + target_position = observation.TargetPosition(shape.Point(1.0, 2.0), "coordsys") + obs.target_position = target_position + self.assertEqual(target_position, + obs.target_position, "TargetPosition") + + self.assertIsNone(obs.requirements, "Default requirements") + requirements = observation.Requirements(observation.Status.FAIL) + obs.requirements = requirements + self.assertEquals(requirements, obs.requirements, "requirements") + + self.assertIsNone(obs.meta_release, "Default metadata release") + date_now = datetime.now() + obs.meta_release = date_now + self.assertEqual(date_now, + obs.meta_release, "Metadata release") + + # Test the complete constructor + def test_complete_init(self): + collection = "CFHT" + observation_id = "543210" + algorithm = "algo" + sequence_number = int(3) + intent = observation.ObservationIntentType.SCIENCE + obs_type = "foo" + proposal = observation.Proposal("123") + telescope = observation.Telescope("TEL") + instrument = observation.Instrument("INST") + target = observation.Target("LMC") + meta_release = datetime.now() + planes = caom_util.TypedOrderedDict(plane.Plane,) + environment = observation.Environment() + target_position = observation.TargetPosition(shape.Point(1.0, 2.0), "coordsys") + + obs = observation.CompositeObservation( + collection, + observation_id, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment, + target_position) + + self.assertIsNotNone(obs.collection, "Collection") + self.assertEqual(collection, obs.collection, "Collection") + + self.assertIsNotNone(obs.observation_id, "Observation ID") + self.assertEqual(observation_id, obs.observation_id, "Observation ID") + + self.assertIsNotNone(obs.algorithm, "Algorithm") + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + self.assertIsNotNone(obs.intent, "Observation intent") + self.assertEqual(intent, obs.intent, "Observation intent") + + self.assertIsNotNone(obs.obs_type, "obs type") + self.assertEqual(obs_type, obs.obs_type, "obs type") + + self.assertIsNotNone(obs.proposal, "Proposal") + self.assertEqual(proposal, obs.proposal, "Proposal") + + self.assertIsNotNone(obs.telescope, "Telescope") + self.assertEqual(telescope, obs.telescope, "Telescope") + + self.assertIsNotNone(obs.instrument, "Instrument") + self.assertEqual(instrument, obs.instrument, "Instrument") + + self.assertIsNotNone(obs.target, "Target") + self.assertEqual(target, obs.target, "Target") + + self.assertIsNotNone(obs.meta_release, "Metadata release") + self.assertEqual(meta_release, obs.meta_release, "Metadata release") + + self.assertIsNotNone(obs.planes, "Planes") + self.assertEqual(planes, obs.planes, "Planes") + + self.assertIsNotNone(obs.environment, "Environment") + self.assertEqual(environment, obs.environment, "Environment") + + self.assertIsNotNone(obs.target_position, "TargetPosition") + self.assertEqual(target_position, obs.target_position, + "TargetPosition") + + # Try changing the algorithm + algorithm2 = str("new algo") + obs.algorithm = algorithm2 + self.assertIsNotNone(obs.algorithm, "Algorithm") + self.assertNotEqual(algorithm, obs.algorithm, "Algorithm") + self.assertEqual(algorithm2, obs.algorithm, "Algorithm") + + +class TestAlgorithm(unittest.TestCase): + + def test_all(self): + algorithm = observation.Algorithm("myAlgorithm") + self.assertEqual("myAlgorithm", algorithm.name, "Algorithm name") + + +class TestEnvironment(unittest.TestCase): + + def test_all(self): + environment = observation.Environment() + + self.assertIsNone(environment.seeing, "Default seeing") + environment.seeing = 123.321 + self.assertEqual(123.321, environment.seeing, "Seeing") + self.assertIsNone(environment.humidity, "Default humidity") + environment.humidity = 0.333 + self.assertEqual(0.333, environment.humidity, "humidity") + self.assertIsNone(environment.elevation, "Default elevation") + environment.elevation = 12.12 + self.assertEqual(12.12, environment.elevation, "Elevation") + self.assertIsNone(environment.tau, "Default tau") + environment.tau = 0.456 + self.assertEqual(0.456, environment.tau, "Tau") + self.assertIsNone(environment.wavelength_tau, "Default wavelength tau") + environment.wavelength_tau = 200.02 + self.assertEqual(200.02, environment.wavelength_tau, "Wavelength tau") + self.assertIsNone(environment.ambient_temp, + "Default ambient temperature") + environment.ambient_temp = 12.44 + self.assertEqual(12.44, environment.ambient_temp, + "Ambient temperature") + self.assertIsNone(environment.photometric, "Default photometric") + environment.photometric = True + self.assertTrue(environment.photometric, "Photometric") + + +class TestIntrument(unittest.TestCase): + + def test_all(self): + instrument = observation.Instrument("myInstrument") + self.assertEqual("myInstrument", instrument.name, "Instrument name") + self.assertEqual(0, len(instrument.keywords), "Default number of keywords") + + instrument.keywords.add("optical") + self.assertEqual(1, len(instrument.keywords), "Number of keywords") + self.assertTrue("optical" in instrument.keywords, "Keyword not found") + + instrument.keywords.add("radio") + self.assertEqual(2, len(instrument.keywords), "Number of keywords") + self.assertTrue("radio" in instrument.keywords, "Keyword not found") + + +class TestProposal(unittest.TestCase): + + def test_all(self): + proposal = observation.Proposal("myProposal") + self.assertEqual("myProposal", proposal.proposal_id, "Proposal ID") + self.assertEqual(0, len(proposal.keywords), "Default number of keywords") + proposal.keywords.add("optical") + self.assertEqual(1, len(proposal.keywords), "Number of keywords") + self.assertTrue("optical" in proposal.keywords, "Keyword not found") + self.assertIsNone(proposal.pi_name, "Default PI") + proposal.pi_name = "John Doe" + self.assertEqual("John Doe", proposal.pi_name, "PI") + self.assertIsNone(proposal.project, "Default PI") + proposal.project = "Project A" + self.assertEqual("Project A", proposal.project, "Project") + self.assertIsNone(proposal.title, "Default title") + proposal.title = "Something Interesting" + self.assertEqual("Something Interesting", proposal.title, "Title") + + +class TestRequirements(unittest.TestCase): + + def test_all(self): + self.assertRaises(TypeError, observation.Requirements, "string") + requirements = observation.Requirements(observation.Status.FAIL) + self.assertEqual(observation.Status.FAIL, requirements.flag, + "Requirements flag") + + +class TestTarget(unittest.TestCase): + + def test_all(self): + target = observation.Target("myTarget") + self.assertEqual("myTarget", target.name, "target name") + + target.target_type = observation.TargetType.FIELD + self.assertEqual(observation.TargetType.FIELD.name, target.target_type.name, "target type") + + self.assertEqual(0, len(target.keywords), "Default number of keywords") + target.keywords.add("optical") + self.assertEqual(1, len(target.keywords), "Number of keywords") + self.assertTrue("optical" in target.keywords, "Keyword not found") + + self.assertIsNone(target.redshift, "Default redshift") + target.redshift = 123.321 + self.assertEqual(123.321, target.redshift, "Redshift") + + self.assertIsNone(target.standard, "Default standard") + target.standard = True + self.assertTrue(target.standard, "Standard") + + self.assertIsNone(target.moving, "Default moving") + target.moving = True + self.assertTrue(target.moving, "Moving") + + target = observation.Target("myOtherTarget", observation.TargetType.OBJECT, False, 1.2, {"radio"}, False) + self.assertEquals("myOtherTarget", target.name, "target name") + self.assertEquals(observation.TargetType.OBJECT, target.target_type, "target type") + self.assertFalse(target.standard, "Standard") + self.assertEquals(1.2, target.redshift, "Redshift") + self.assertEquals(1, len(target.keywords), "Keywords") + self.assertTrue("radio" in target.keywords, "Keywords") + self.assertFalse(target.moving, "Moving") + + +class TestTargetPosition(unittest.TestCase): + + def test_all(self): + self.assertRaises(TypeError, observation.TargetPosition, "string") + point = shape.Point(1.0, 2.0) + target_position = observation.TargetPosition(point, "coordsys") + self.assertIsNotNone(target_position.coordinates, + "target position coordinates") + self.assertEqual(point.cval1, target_position.coordinates.cval1, + "coordinates cval1") + self.assertEqual(point.cval2, target_position.coordinates.cval2, + "coordinates cval2") + self.assertIsNotNone(target_position.coordsys, + "target position coordsys") + self.assertEqual("coordsys", target_position.coordsys, "coordsys") + self.assertIsNone(target_position.equinox, + "target position equinox") + + target_position = observation.TargetPosition(point, "coordsys", 1.0) + self.assertIsNotNone(target_position.equinox, + "target position equinox") + self.assertEqual(1.0, target_position.equinox, + "equinox") + + +class TestTelescope(unittest.TestCase): + + def test_all(self): + telescope = observation.Telescope("myTelescope") + self.assertEqual("myTelescope", telescope.name, "telescope name") + self.assertEqual(0, len(telescope.keywords), "Default number of keywords") + + telescope.keywords.add("optical") + self.assertEqual(1, len(telescope.keywords), "Number of keywords") + self.assertTrue("optical" in telescope.keywords, "Keyword not found") + + self.assertIsNone(telescope.geo_location_x, "Default geo location x") + telescope.geo_location_x = 123.321 + self.assertEqual(123.321, telescope.geo_location_x, "Geo location x") + + self.assertIsNone(telescope.geo_location_y, "Default geo location y") + telescope.geo_location_y = 333.33 + self.assertEqual(333.33, telescope.geo_location_y, "Geo location y") + + self.assertIsNone(telescope.geo_location_z, "Default geo location z") + telescope.geo_location_z = 12.12 + self.assertEqual(12.12, telescope.geo_location_z, "Geo location z") diff --git a/pyCAOM2/caom2/test/test_part.py b/caom2/caom2/tests/test_part.py similarity index 77% rename from pyCAOM2/caom2/test/test_part.py rename to caom2/caom2/tests/test_part.py index 33aa7bba..edad821f 100644 --- a/pyCAOM2/caom2/test/test_part.py +++ b/caom2/caom2/tests/test_part.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -70,48 +69,31 @@ """ Defines TestPart class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest -from caom2.caom2_chunk import Chunk -from caom2.caom2_enums import ProductType -from caom2.caom2_part import Part +from .. import chunk +from .. import part class TestPart(unittest.TestCase): - def testInit(self): - - self.assertRaises(TypeError, Part, long(1)) - - part = Part("partName") - self.assertEquals("partName", part.name, "Part name") - self.assertIsNone(part.product_type) - self.assertTrue(len(part.chunks) == 0) - - part.product_type = ProductType.SCIENCE - self.assertEqual(ProductType.SCIENCE, part.product_type) - - chunk = Chunk() - chunk.naxis = 5 - part.chunks.append(chunk) - self.assertTrue(len(part.chunks) == 1) - self.assertEqual(chunk, part.chunks.pop()) - -# # the set prevents adding the same object multiple times ... -# chunk_alias = chunk -# part.chunks.add(chunk_alias) -# part.chunks.add(chunk_alias) -# part.chunks.add(chunk_alias) -# self.assertTrue(len(part.chunks) == 1) -# -# # ... but everything else is not a duplicate -# chunk = Chunk() -# chunk.naxis = 33 -# part.chunks.add(chunk) -# self.assertTrue(len(part.chunks) == 2) + def test_init(self): + self.assertRaises(TypeError, part.Part, long(1)) + test_part = part.Part("partName") + self.assertEquals("partName", test_part.name, "Part name") + self.assertIsNone(test_part.product_type) + self.assertTrue(len(test_part.chunks) == 0) -if __name__ == '__main__': - unittest.main() + test_part.product_type = chunk.ProductType.SCIENCE + self.assertEqual(chunk.ProductType.SCIENCE, test_part.product_type) + test_chunk = chunk.Chunk() + test_chunk.naxis = 5 + test_part.chunks.append(test_chunk) + self.assertTrue(len(test_part.chunks) == 1) + self.assertEqual(test_chunk, test_part.chunks.pop()) diff --git a/caom2/caom2/tests/test_plane.py b/caom2/caom2/tests/test_plane.py new file mode 100644 index 00000000..98983c58 --- /dev/null +++ b/caom2/caom2/tests/test_plane.py @@ -0,0 +1,562 @@ +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines TestPlane class """ + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import unittest +from datetime import datetime + +from .. import artifact +from .. import observation +from .. import plane +from .. import chunk +from .. import wcs + + +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + with self.assertRaises(ValueError): + plane.CalibrationLevel("no_such_string") + with self.assertRaises(ValueError): + plane.CalibrationLevel(None) + with self.assertRaises(ValueError): + plane.CalibrationLevel(999) + + with self.assertRaises(ValueError): + plane.DataProductType("no_such_string") + with self.assertRaises(ValueError): + plane.DataProductType(None) + with self.assertRaises(ValueError): + plane.DataProductType(1) + + with self.assertRaises(ValueError): + plane.EnergyBand("no_such_string") + with self.assertRaises(ValueError): + plane.EnergyBand(None) + with self.assertRaises(ValueError): + plane.EnergyBand(1) + + with self.assertRaises(ValueError): + plane.PolarizationState("no_such_string") + with self.assertRaises(ValueError): + plane.PolarizationState(None) + with self.assertRaises(ValueError): + plane.PolarizationState(1) + + with self.assertRaises(ValueError): + plane.Quality("no_such_string") + with self.assertRaises(ValueError): + plane.Quality(None) + with self.assertRaises(ValueError): + plane.Quality(1) + + # test that we can get the object for each enum by name + self.assertEqual(plane.CalibrationLevel.RAW_INSTRUMENT.value, 0) + self.assertEqual(plane.CalibrationLevel.RAW_STANDARD.value, 1) + self.assertEqual(plane.CalibrationLevel.CALIBRATED.value, 2) + self.assertEqual(plane.CalibrationLevel.PRODUCT.value, 3) + + self.assertEqual(plane.DataProductType.IMAGE.value, "image") + self.assertEqual(plane.DataProductType.CATALOG.value, "catalog") + self.assertEqual(plane.DataProductType.CUBE.value, "cube") + self.assertEqual(plane.DataProductType.EVENTLIST.value, "eventlist") + self.assertEqual(plane.DataProductType.SPECTRUM.value, "spectrum") + self.assertEqual(plane.DataProductType.TIMESERIES.value, "timeseries") + self.assertEqual(plane.DataProductType.VISIBILITY.value, "visibility") + + self.assertEqual(plane.EnergyBand['RADIO'].value, "Radio") + self.assertEqual(plane.EnergyBand['MILLIMETER'].value, "Millimeter") + self.assertEqual(plane.EnergyBand['INFRARED'].value, "Infrared") + self.assertEqual(plane.EnergyBand['OPTICAL'].value, "Optical") + self.assertEqual(plane.EnergyBand['UV'].value, "UV") + self.assertEqual(plane.EnergyBand['EUV'].value, "EUV") + self.assertEqual(plane.EnergyBand['XRAY'].value, "X-ray") + self.assertEqual(plane.EnergyBand['GAMMARAY'].value, "Gamma-ray") + + self.assertEqual(plane.PolarizationState['I'].value, "I") + self.assertEqual(plane.PolarizationState['Q'].value, "Q") + self.assertEqual(plane.PolarizationState['U'].value, "U") + self.assertEqual(plane.PolarizationState['V'].value, "V") + self.assertEqual(plane.PolarizationState['LL'].value, "LL") + self.assertEqual(plane.PolarizationState['LR'].value, "LR") + self.assertEqual(plane.PolarizationState['RL'].value, "RL") + self.assertEqual(plane.PolarizationState['RR'].value, "RR") + self.assertEqual(plane.PolarizationState['XX'].value, "XX") + self.assertEqual(plane.PolarizationState['XY'].value, "XY") + self.assertEqual(plane.PolarizationState['YX'].value, "YX") + self.assertEqual(plane.PolarizationState['YY'].value, "YY") + + self.assertEqual(plane.Quality['JUNK'].value, "junk") + + +class TestPlane(unittest.TestCase): + + def test_all(self): + test_plane = plane.Plane("ProdID") + self.assertEqual("ProdID", test_plane.product_id, "Product ID") + self.assertEqual(0, len(test_plane.artifacts), + "Default number of artifacts") + self.assertIsNone(test_plane.meta_release, "Default meta release date") + date_now = datetime.now() + test_plane.meta_release = date_now + self.assertEqual(date_now, test_plane.meta_release, "Metadata release date") + self.assertIsNone(test_plane.data_release, "Default data release date") + date_now = datetime.now() + test_plane.data_release = date_now + self.assertEqual(date_now, test_plane.data_release, "Data release date") + self.assertIsNone(test_plane.data_product_type, "Default data product type") + test_plane.data_product_type = plane.DataProductType.IMAGE + self.assertEqual(plane.DataProductType.IMAGE, test_plane.data_product_type, + "Data product type") + self.assertIsNone(test_plane.calibration_level, + "Default calibration level") + test_plane.calibration_level = plane.CalibrationLevel.CALIBRATED + self.assertEqual(plane.CalibrationLevel.CALIBRATED, + test_plane.calibration_level, "plane.CalibrationLevel") + self.assertIsNone(test_plane.quality, + "Default quality") + quality = plane.DataQuality(plane.Quality.JUNK) + test_plane.quality = quality + self.assertEqual(quality, + test_plane.quality, "plane.Quality") + self.assertIsNone(test_plane.provenance, "Default provenance") + provenance = plane.Provenance("myProv") + test_plane.provenance = provenance + self.assertEqual("myProv", test_plane.provenance.name, "Provenance - name") + self.assertIsNone(test_plane.metrics, "Default metrics") + metrics = plane.Metrics() + test_plane.metrics = metrics + self.assertEqual(metrics, test_plane.metrics, "Provenance - metrics") + #self.assertIsNone(plane.observable, "Default observable") + self.assertIsNone(test_plane.position, "Default position") + self.assertIsNone(test_plane.energy, "Default energy") + self.assertIsNone(test_plane.time, "Default time") + self.assertIsNone(test_plane.polarization, "Default polarization") + + test_artifact1 = artifact.Artifact("caom:GEMINI/222/333", + chunk.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + test_plane.artifacts["caom:GEMINI/222/333"] = test_artifact1 + self.assertEquals(1, len(test_plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in test_plane.artifacts.keys()) + + test_artifact2 = artifact.Artifact("caom:CFHT/55/66", + chunk.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + test_plane.artifacts["caom:CFHT/55/66"] = test_artifact2 + self.assertEquals(2, len(test_plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in test_plane.artifacts.keys()) + self.assertTrue("caom:CFHT/55/66" in test_plane.artifacts.keys()) + + #try to append a duplicate artifact + test_artifact3 = artifact.Artifact("caom:GEMINI/222/333", + chunk.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + test_plane.artifacts["caom:GEMINI/222/333"] = test_artifact3 + self.assertEquals(2, len(test_plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in test_plane.artifacts.keys()) + self.assertTrue("caom:CFHT/55/66" in test_plane.artifacts.keys()) + + #Error cases + exception = False + try: + test_plane = plane.Plane(None) + except TypeError: + exception = True + self.assertTrue(exception, "Null argument in initialize") + + #exception = False + #try: + # plane.compute_observable() + #except TypeError: + # exception = True + #self.assertTrue(exception, + # "compute_observable implemented - Testing needed") + + #exception = False + #try: + # plane.compute_position() + #except TypeError: + # exception = True + #self.assertTrue(exception, + # "compute_position implemented - Testing needed") + + exception = False + try: + test_plane.compute_energy() + except NotImplementedError: + exception = True + self.assertTrue(exception, + "compute_energy implemented - Testing needed") + + exception = False + try: + test_plane.compute_time() + except NotImplementedError: + exception = True + self.assertTrue(exception, "compute_time implemented - Testing needed") + + exception = False + try: + test_plane.compute_polarization() + except NotImplementedError: + exception = True + self.assertTrue(exception, "compute_polarization implemented" + " - Testing needed") + + +class TestPlaneURI(unittest.TestCase): + + def test_all(self): + plane_uri = plane.PlaneURI("caom:GEMINI/12345/3333") + self.assertEqual("caom:GEMINI/12345/3333", plane_uri.uri, + "Plane URI") + self.assertEqual("GEMINI", plane_uri.observation_uri.collection, + "Collection") + self.assertEqual("12345", plane_uri.observation_uri.observation_id, + "Observation ID") + self.assertEqual("3333", plane_uri.product_id, "Product ID") + + plane_uri = plane.PlaneURI.get_plane_uri(observation.ObservationURI("caom:CFHT/654321"), + "555") + self.assertEqual("caom:CFHT/654321/555", plane_uri.uri, + "Observation URI") + self.assertEqual("CFHT", plane_uri.observation_uri.collection, + "Collection") + self.assertEqual("654321", plane_uri.observation_uri.observation_id, + "Observation ID") + self.assertEqual("555", plane_uri.product_id, "Product ID") + + exception = False + try: + plane_uri = plane.PlaneURI.get_plane_uri(None, "123") + except TypeError: + exception = True + self.assertTrue(exception, "Missing exception") + + exception = False + try: + plane_uri = plane.PlaneURI.get_plane_uri("GEMINI", None) + except TypeError: + exception = True + self.assertTrue(exception, "Missing exception") + + #wrong scheme + exception = False + try: + plane_uri = plane.PlaneURI("somescheme:GEMINI/12345/3333") + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + exception = False + try: + plane_uri = plane.PlaneURI("caom:GEMINI/12345") + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + +class TestDataQuality(unittest.TestCase): + + def test_all(self): + + self.assertRaises(TypeError, plane.DataQuality, "string") + quality = plane.DataQuality(plane.Quality.JUNK) + self.assertEqual(plane.Quality.JUNK, quality.flag, + "DataQuality flag") + + +class TestMetrics(unittest.TestCase): + + def test_all(self): + metrics = plane.Metrics() + + self.assertIsNone(metrics.source_number_density, + "Default source number density") + metrics.source_number_density = 22.22 + self.assertEquals(22.22, metrics.source_number_density, + "Source number density") + self.assertIsNone(metrics.background, "Default background") + metrics.background = 12.34 + self.assertEquals(12.34, metrics.background, "Background") + self.assertIsNone(metrics.background_std_dev, + "Default background standard deviation") + metrics.background_std_dev = 34.34 + self.assertEquals(34.34, metrics.background_std_dev, + "Background standard deviation") + self.assertIsNone(metrics.flux_density_limit, + "Default flux density limit") + metrics.flux_density_limit = 55.55 + self.assertEquals(55.55, metrics.flux_density_limit, + "Flux density limit") + self.assertIsNone(metrics.mag_limit, "Default mag limit") + metrics.mag_limit = 20.08 + self.assertEquals(20.08, metrics.mag_limit, "Mag limit") + + +class TestProvenance(unittest.TestCase): + + def test_all(self): + provenance = plane.Provenance("MyProvenance") + self.assertEqual("MyProvenance", provenance.name, "Name") + + self.assertIsNone(provenance.version, "Default version") + provenance.version = "XII" + self.assertEquals("XII", provenance.version, "Version") + self.assertIsNone(provenance.project, "Default project") + provenance.project = "CFHTLS" + self.assertEquals("CFHTLS", provenance.project, "Project") + self.assertIsNone(provenance.producer, "Default producer") + provenance.producer = "prod" + self.assertEquals("prod", provenance.producer, "Producer") + self.assertIsNone(provenance.run_id, "Default run ID") + provenance.run_id = "A23" + self.assertEquals("A23", provenance.run_id, "Run ID") + self.assertIsNone(provenance.reference, "Default reference") + + self.assertEqual(0, len(provenance.inputs), "Default inputs") + plane_uri1 = plane.PlaneURI("caom:HST/11/00") + provenance.inputs.add(plane_uri1) + self.assertEqual(1, len(provenance.inputs), "Default inputs") + self.assertTrue(plane_uri1 in provenance.inputs) + + plane_uri2 = plane.PlaneURI("caom:HST/22/00") + provenance.inputs.add(plane_uri2) + self.assertEqual(2, len(provenance.inputs), "Default inputs") + self.assertTrue(plane_uri1 in provenance.inputs) + self.assertTrue(plane_uri2 in provenance.inputs) + + # testing duplicates + plane_uri3 = plane.PlaneURI("caom:HST/22/00") + provenance.inputs.add(plane_uri3) + self.assertEqual(2, len(provenance.inputs), "Default inputs") + self.assertTrue(plane_uri1 in provenance.inputs) + self.assertTrue(plane_uri2 in provenance.inputs) + + self.assertIsNone(provenance.last_executed, "Default last executed") + now_date = datetime.now() + provenance.last_executed = now_date + self.assertEquals(now_date, provenance.last_executed, "Last executed") + + self.assertEquals(0, len(provenance.keywords), "0 default keywords") + provenance.keywords.add("keyword1") + self.assertEquals(1, len(provenance.keywords), "1 keyword") + self.assertTrue("keyword1" in provenance.keywords, "Keyword not found") + + provenance.keywords.add("keyword2") + self.assertEquals(2, len(provenance.keywords), "2 keyword") + self.assertTrue("keyword2" in provenance.keywords, "Keyword not found") + + # test the full constructor + provenance = plane.Provenance("MyOtherProvenance", + "Version2.0", + "JCMT", + "Mutt Lang", + "b32", + "caom:JCMT/33/00", + now_date) + + self.assertIsNotNone(provenance.name) + self.assertIsNotNone(provenance.version) + self.assertIsNotNone(provenance.project) + self.assertIsNotNone(provenance.producer) + self.assertIsNotNone(provenance.run_id) + self.assertIsNotNone(provenance.reference) + self.assertIsNotNone(provenance.last_executed) + + self.assertEquals("MyOtherProvenance", provenance.name, "name") + self.assertEquals("Version2.0", provenance.version, "version") + self.assertEquals("JCMT", provenance.project, "project") + self.assertEquals("Mutt Lang", provenance.producer, "producer") + self.assertEquals("b32", provenance.run_id, "run_id") + self.assertEquals("caom:JCMT/33/00", provenance.reference, "reference") + self.assertEquals(now_date, provenance.last_executed, "last_executed") + + +class TestPosition(unittest.TestCase): + + def test_all(self): + position = plane.Position() + + self.assertIsNone(position.bounds, "Default bounds") + #position.bounds = 123 + #self.assertEqual(123, position.bounds, "Bounds") + self.assertIsNone(position.dimension, "Default dimension") + #position.dimension = 123 + #self.assertEqual(123, position.dimension, "Dimension") + self.assertIsNone(position.resolution, "Default resolution") + position.resolution = 123.321 + self.assertEqual(123.321, position.resolution, "Resolution") + self.assertIsNone(position.sample_size, "Default sample size") + position.sample_size = 321.123 + self.assertEqual(321.123, position.sample_size, "Sample size") + self.assertFalse(position.time_dependent, "Default time dependent") + position.time_dependent = True + self.assertTrue(position.time_dependent, "Time dependent") + + +class TestEnergy(unittest.TestCase): + + def test_all(self): + energy = plane.Energy() + self.assertIsNone(energy.value, "Default energy value") + energy.value = 33.33 + self.assertEqual(33.33, energy.value, "Energy value") + self.assertIsNone(energy.bounds, "Default energy bounds") + #TODO switch to Interval + #energy.bounds = 22 + self.assertIsNone(energy.dimension, "Default energy dimension") + energy.dimension = 1000L + self.assertEqual(1000L, energy.dimension, "Energy dimension") + self.assertIsNone(energy.resolving_power, + "Default energy resolving power") + energy.resolving_power = 123.12 + self.assertEqual(123.12, energy.resolving_power, + "Energy resolving power") + self.assertIsNone(energy.sample_size, "Default energy sample size") + energy.sample_size = 123.321 + self.assertEqual(123.321, energy.sample_size, "Energy sample size") + self.assertIsNone(energy.bandpass_name, "Default energy band pass") + energy.bandpass_name = "EBN" + self.assertEqual("EBN", energy.bandpass_name, "Energy bandpass name") + self.assertIsNone(energy.em_band, "Default energy em band") + energy.em_band = plane.EnergyBand.OPTICAL + self.assertEqual(plane.EnergyBand.OPTICAL, energy.em_band, "Energy band") + self.assertIsNone(energy.transition, "Default energy transition") + #TODO replace with EnergyTransistion + #energy.transition = "BLAH" + + +class TestEnergyTransition(unittest.TestCase): + + def test__init__(self): + # test for invalid values + self.assertRaises(TypeError, wcs.EnergyTransition, None, None) + self.assertRaises(TypeError, wcs.EnergyTransition, 'aString', None) + self.assertRaises(TypeError, wcs.EnergyTransition, None, 'aString') + self.assertRaises(TypeError, wcs.EnergyTransition, 1, 'aString') + self.assertRaises(TypeError, wcs.EnergyTransition, 'aString', 2) + # test for happy path + transition = wcs.EnergyTransition("aSpecies", "aTransition") + self.assertEqual(transition._species, "aSpecies") + self.assertEqual(transition._transition, "aTransition") + + def test_setters(self): + # test that we cannot change the attribute values + transition = wcs.EnergyTransition("aSpecies", "aTransition") + try: + transition.species = "newSpecies" + transition.transition = "newTransition" + except AttributeError: + pass + else: + raise AttributeError("at least one attribute was changed") + + +class TestPolarizaton(unittest.TestCase): + + def test_all(self): + polarization = plane.Polarization() + + self.assertIsNone(polarization.dimension, + "Default polarization dimension") + energy = plane.Energy() + energy.bandpass_name = '123' + self.assertEqual('123', energy.bandpass_name, "Polarization dimension") + + #TODO add test for state + + +class TestTime(unittest.TestCase): + + def test_all(self): + time = plane.Time() + self.assertIsNone(time.value, "Default value") + self.assertIsNone(time.bounds, "Default bounds") + self.assertIsNone(time.dimension, "Default dimension") + self.assertIsNone(time.resolution, "Default resolution") + self.assertIsNone(time.sample_size, "Default sample size") + self.assertIsNone(time.exposure, "Default exposure") + + time.value = 34.34 + self.assertEqual(34.34, time.value, "Value") + time.dimension = 777L + self.assertEqual(777L, time.dimension, "Dimension") + time.resolution = 77.777 + self.assertEqual(77.777, time.resolution, "Resolution") + time.sample_size = 12.34 + self.assertEqual(12.34, time.sample_size, "Sample size") + time.exposure = 55.55 + self.assertEqual(55.55, time.exposure, "Exposure") diff --git a/pyCAOM2/caom2/test/test_point.py b/caom2/caom2/tests/test_shape.py similarity index 76% rename from pyCAOM2/caom2/test/test_point.py rename to caom2/caom2/tests/test_shape.py index 18a668de..2e9d0e6d 100644 --- a/pyCAOM2/caom2/test/test_point.py +++ b/caom2/caom2/tests/test_shape.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -68,26 +67,46 @@ #*********************************************************************** # -""" Defines TestPoint class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest -from caom2.types.caom2_point import Point +from .. import shape + + +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + with self.assertRaises(KeyError): + shape.SegmentType["foo"] + with self.assertRaises(KeyError): + shape.SegmentType[None] + with self.assertRaises(KeyError): + shape.SegmentType[999] + + with self.assertRaises(ValueError): + shape.SegmentType("foo") + with self.assertRaises(ValueError): + shape.SegmentType(None) + with self.assertRaises(ValueError): + shape.SegmentType(4) + self.assertEqual(shape.SegmentType.CLOSE.value, 0) + self.assertEqual(shape.SegmentType.LINE.value, 1) + self.assertEqual(shape.SegmentType.MOVE.value, 2) class TestPoint(unittest.TestCase): - def testInit(self): + def test_all(self): - self.assertRaises(TypeError, Point, None, None) - self.assertRaises(TypeError, Point, None, 1.0) - self.assertRaises(TypeError, Point, 1.0, None) - self.assertRaises(TypeError, Point, "string", int(1)) - self.assertRaises(TypeError, Point, int(1), "string") + self.assertRaises(TypeError, shape.Point, None, None) + self.assertRaises(TypeError, shape.Point, None, 1.0) + self.assertRaises(TypeError, shape.Point, 1.0, None) + self.assertRaises(TypeError, shape.Point, "string", int(1)) + self.assertRaises(TypeError, shape.Point, int(1), "string") - point = Point(1.0, 2.0) + point = shape.Point(1.0, 2.0) self.assertEqual(point.cval1, 1.0) self.assertEqual(point.cval2, 2.0) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2/caom2/tests/test_wcs.py b/caom2/caom2/tests/test_wcs.py new file mode 100644 index 00000000..105aeacc --- /dev/null +++ b/caom2/caom2/tests/test_wcs.py @@ -0,0 +1,457 @@ +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import unittest + +from .. import wcs + + +class TestAxis(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.Axis, None, None) + self.assertRaises(TypeError, wcs.Axis, None, "cunit") + self.assertRaises(TypeError, wcs.Axis, "ctype", int(1)) + self.assertRaises(TypeError, wcs.Axis, int(1), "cunit") + + axis = wcs.Axis("ctype", "cunit") + self.assertEqual(axis.ctype, "ctype") + self.assertEqual(axis.cunit, "cunit") + + +class TestCoord2D(unittest.TestCase): + + def test_init(self): + + coord1 = wcs.RefCoord(float(1.0), float(2.0)) + coord2 = wcs.RefCoord(float(3.0), float(4.0)) + + self.assertRaises(TypeError, wcs.Coord2D, None, None) + self.assertRaises(TypeError, wcs.Coord2D, None, coord2) + self.assertRaises(TypeError, wcs.Coord2D, coord1, None) + self.assertRaises(TypeError, wcs.Coord2D, str("s"), coord2) + self.assertRaises(TypeError, wcs.Coord2D, coord1, str("s")) + + coord_2d = wcs.Coord2D(coord1, coord2) + self.assertEqual(coord_2d.coord1, coord1) + self.assertEqual(coord_2d.coord2, coord2) + + +class TestCoordAxis1D(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.CoordAxis1D, None) + self.assertRaises(TypeError, wcs.CoordAxis1D, int(1)) + + axis = wcs.Axis("ctype", "cunit") + axis_1d = wcs.CoordAxis1D(axis) + self.assertEqual(axis_1d.axis, axis) + with self.assertRaises(TypeError): + axis_1d.error = str("s") + axis_1d.bounds = str("s") + axis_1d.function = str("s") + axis_1d.range = str("s") + + error = wcs.CoordError(float(1.0), float(2.0)) + axis_1d.error = error + self.assertEqual(axis_1d.error, error) + + start = wcs.RefCoord(float(1.0), float(2.0)) + end = wcs.RefCoord(float(3.0), float(4.0)) + coordRange = wcs.CoordRange1D(start, end) + axis_1d.range = coordRange + self.assertEqual(axis_1d.range, coordRange) + + bounds = wcs.CoordBounds1D() + axis_1d.bounds = bounds + self.assertEqual(axis_1d.bounds, bounds) + + naxis = long(1) + delta = float(2.5) + ref_coord = wcs.RefCoord(float(1.0), float(2.0)) + function = wcs.CoordFunction1D(naxis, delta, ref_coord) + axis_1d.function = function + self.assertEqual(axis_1d.function, function) + + +class TestCoordAxis2D(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.CoordAxis2D, None, None) + self.assertRaises(TypeError, wcs.CoordAxis2D, None, int(1)) + self.assertRaises(TypeError, wcs.CoordAxis2D, int(1), None) + + axis1 = wcs.Axis("ctype1", "cunit1") + axis2 = wcs.Axis("ctype2", "cunit2") + axis_2d = wcs.CoordAxis2D(axis1, axis2) + self.assertEqual(axis_2d.axis1, axis1) + self.assertEqual(axis_2d.axis2, axis2) + with self.assertRaises(TypeError): + axis_2d.error1 = str("s") + axis_2d.error2 = str("s") + axis_2d.bounds = str("s") + axis_2d.function = str("s") + axis_2d.range = str("s") + + error1 = wcs.CoordError(float(1.0), float(2.0)) + axis_2d.error1 = error1 + self.assertEqual(axis_2d.error1, error1) + + error2 = wcs.CoordError(float(3.0), float(4.0)) + axis_2d.error2 = error2 + self.assertEqual(axis_2d.error2, error2) + + start = wcs.Coord2D(wcs.RefCoord(float(1.0), float(2.0)), + wcs.RefCoord(float(3.0), float(4.0))) + end = wcs.Coord2D(wcs.RefCoord(float(5.0), float(6.0)), + wcs.RefCoord(float(7.0), float(8.0))) + coordRange = wcs.CoordRange2D(start, end) + axis_2d.range = coordRange + self.assertEqual(axis_2d.range, coordRange) + + center = wcs.ValueCoord2D(float(1.0), float(2.0)) + radius = float(1.5) + circle = wcs.CoordCircle2D(center, radius) + axis_2d.bounds = circle + self.assertEqual(axis_2d.bounds, circle) + + polygon = wcs.CoordPolygon2D() + axis_2d.bounds = polygon + self.assertEqual(axis_2d.bounds, polygon) + + dimension = wcs.Dimension2D(long(1), long(2)) + ref_coord = wcs.Coord2D(wcs.RefCoord(float(9.0), float(10.0)), + wcs.RefCoord(float(11.0), float(12.0))) + cd11 = float(1.1) + cd12 = float(1.2) + cd21 = float(2.1) + cd22 = float(2.2) + function = wcs.CoordFunction2D(dimension, ref_coord, + cd11, cd12, cd21, cd22) + axis_2d.function = function + self.assertEqual(axis_2d.function, function) + + +class TestCoordBounds1D(unittest.TestCase): + + def test_init(self): + + start = wcs.RefCoord(float(1.0), float(2.0)) + end = wcs.RefCoord(float(3.0), float(4.0)) + coordRange = wcs.CoordRange1D(start, end) + + bounds = wcs.CoordBounds1D() + bounds.samples.append(coordRange) + self.assertTrue(bounds.samples.count(coordRange) == 1) + self.assertEqual(bounds.samples.pop(), coordRange) + + with self.assertRaises(TypeError): + bounds.samples = [str("s")] + + +class TestCoordBounds2D(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.CoordBounds2D, None) + self.assertRaises(TypeError, wcs.CoordBounds2D, float(1.0)) + + center = wcs.ValueCoord2D(float(1.0), float(2.0)) + radius = float(1.5) + circle = wcs.CoordCircle2D(center, radius) + + polygon = wcs.CoordPolygon2D() + polygon.vertices.append(wcs.ValueCoord2D(float(1.0), float(2.0))) + + bounds = wcs.CoordBounds2D(circle) + self.assertEqual(bounds.bounds, circle) + + bounds = wcs.CoordBounds2D(polygon) + self.assertEqual(bounds.bounds, polygon) + + +class TestCoordCircle2D(unittest.TestCase): + + def test_init(self): + + center = wcs.ValueCoord2D(float(1.0), float(2.0)) + radius = float(1.5) + + self.assertRaises(TypeError, wcs.CoordCircle2D, None, None) + self.assertRaises(TypeError, wcs.CoordCircle2D, None, radius) + self.assertRaises(TypeError, wcs.CoordCircle2D, center, None) + self.assertRaises(TypeError, wcs.CoordCircle2D, int(1), radius) + self.assertRaises(TypeError, wcs.CoordCircle2D, center, int(1)) + + circle = wcs.CoordCircle2D(center, radius) + self.assertEqual(circle.center, center) + self.assertEqual(circle.radius, radius) + + +class TestCoordError(unittest.TestCase): + + def test_init(self): + self.assertRaises(TypeError, wcs.CoordError, None, None) + self.assertRaises(TypeError, wcs.CoordError, None, float(1.0)) + self.assertRaises(TypeError, wcs.CoordError, float(1.0), None) + self.assertRaises(TypeError, wcs.CoordError, int(1), float(1.0)) + self.assertRaises(TypeError, wcs.CoordError, float(1.0), int(1)) + + error = wcs.CoordError(float(1), float(2)) + self.assertIsNotNone(error) + self.assertEqual(error.syser, float(1)) + self.assertEqual(error.rnder, float(2)) + + +class TestCoordFunction1D(unittest.TestCase): + + def test_init(self): + + naxis = long(1) + delta = float(2.5) + ref_coord = wcs.RefCoord(float(1.0), float(2.0)) + + self.assertRaises(TypeError, wcs.CoordFunction1D, None, None, + None) + self.assertRaises(TypeError, wcs.CoordFunction1D, None, delta, + ref_coord) + self.assertRaises(TypeError, wcs.CoordFunction1D, naxis, None, + ref_coord) + self.assertRaises(TypeError, wcs.CoordFunction1D, naxis, delta, + None) + self.assertRaises(TypeError, wcs.CoordFunction1D, int(1), delta, + ref_coord) + self.assertRaises(TypeError, wcs.CoordFunction1D, naxis, int(1), + ref_coord) + self.assertRaises(TypeError, wcs.CoordFunction1D, naxis, delta, + int(1)) + + function = wcs.CoordFunction1D(naxis, delta, ref_coord) + self.assertEqual(function.naxis, naxis) + self.assertEqual(function.delta, delta) + self.assertEqual(function.ref_coord, ref_coord) + + +class TestCoordFunction2D(unittest.TestCase): + + def test_init(self): + + dimension = wcs.Dimension2D(long(1), long(2)) + ref_coord = wcs.Coord2D(wcs.RefCoord(float(9.0), float(10.0)), + wcs.RefCoord(float(11.0), float(12.0))) + cd11 = float(1.1) + cd12 = float(1.2) + cd21 = float(2.1) + cd22 = float(2.2) + + self.assertRaises(TypeError, wcs.CoordFunction2D, None, + ref_coord, cd11, cd12, cd21, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + None, cd11, cd12, cd21, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + ref_coord, None, cd12, cd21, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + ref_coord, cd11, None, cd21, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + ref_coord, cd11, cd12, None, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + ref_coord, cd11, cd12, cd21, None) + + function = wcs.CoordFunction2D(dimension, ref_coord, + cd11, cd12, cd21, cd22) + self.assertEqual(function.dimension, dimension) + self.assertEqual(function.ref_coord, ref_coord) + self.assertEqual(function.cd11, cd11) + self.assertEqual(function.cd12, cd12) + self.assertEqual(function.cd21, cd21) + self.assertEqual(function.cd22, cd22) + + +class TestCoordPolygon2D(unittest.TestCase): + + def test_init(self): + + value_coord2d = wcs.ValueCoord2D(float(1.0), float(2.0)) + + polygon = wcs.CoordPolygon2D() + polygon.vertices.append(value_coord2d) + self.assertTrue(polygon.vertices.count(value_coord2d) == 1) + self.assertEqual(polygon.vertices.pop(), value_coord2d) + + with self.assertRaises(TypeError): + polygon.vertices = [str("s")] + + +class TestCoordRange1D(unittest.TestCase): + + def test_init(self): + + start = wcs.RefCoord(float(1.0), float(2.0)) + end = wcs.RefCoord(float(3.0), float(4.0)) + + self.assertRaises(TypeError, wcs.CoordRange1D, None, None) + self.assertRaises(TypeError, wcs.CoordRange1D, None, end) + self.assertRaises(TypeError, wcs.CoordRange1D, start, None) + self.assertRaises(TypeError, wcs.CoordRange1D, int(1), end) + self.assertRaises(TypeError, wcs.CoordRange1D, start, int(1)) + + coordRange = wcs.CoordRange1D(start, end) + self.assertEqual(coordRange.start, start) + self.assertEqual(coordRange.end, end) + + +class TestCoordRange2D(unittest.TestCase): + + def test_init(self): + + start = wcs.Coord2D(wcs.RefCoord(float(1.0), float(2.0)), + wcs.RefCoord(float(3.0), float(4.0))) + end = wcs.Coord2D(wcs.RefCoord(float(5.0), float(6.0)), + wcs.RefCoord(float(7.0), float(8.0))) + + self.assertRaises(TypeError, wcs.CoordRange2D, None, None) + self.assertRaises(TypeError, wcs.CoordRange2D, None, end) + self.assertRaises(TypeError, wcs.CoordRange2D, start, None) + self.assertRaises(TypeError, wcs.CoordRange2D, int(1), end) + self.assertRaises(TypeError, wcs.CoordRange2D, start, int(1)) + + coordRange = wcs.CoordRange2D(start, end) + self.assertEqual(coordRange.start, start) + self.assertEqual(coordRange.end, end) + + +class TestDimension2D(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.Dimension2D, None, None) + self.assertRaises(TypeError, wcs.Dimension2D, long(1), None) + self.assertRaises(TypeError, wcs.Dimension2D, None, long(1)) + self.assertRaises(TypeError, wcs.Dimension2D, int(1), long(1)) + self.assertRaises(TypeError, wcs.Dimension2D, long(1), int(1)) + + dimension = wcs.Dimension2D(long(1), long(2)) + self.assertEqual(dimension.naxis1, long(1)) + self.assertEqual(dimension.naxis2, long(2)) + + +class TestRefCoord(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.RefCoord, None, None) + self.assertRaises(TypeError, wcs.RefCoord, None, float(1.0)) + self.assertRaises(TypeError, wcs.RefCoord, float(1.0), None) + self.assertRaises(TypeError, wcs.RefCoord, int(1), float(1.0)) + self.assertRaises(TypeError, wcs.RefCoord, float(1.0), int(1)) + + ref_coord = wcs.RefCoord(float(1), float(2)) + self.assertIsNotNone(ref_coord) + self.assertEqual(ref_coord.pix, float(1)) + self.assertEqual(ref_coord.val, float(2)) + + +class TestSlice(unittest.TestCase): + + def test_init(self): + + axis = wcs.Axis("ctype", "cunit") + myBin = long(1) + + self.assertRaises(TypeError, wcs.Slice, None, None) + self.assertRaises(TypeError, wcs.Slice, None, myBin) + self.assertRaises(TypeError, wcs.Slice, axis, None) + self.assertRaises(TypeError, wcs.Slice, str("s"), myBin) + self.assertRaises(TypeError, wcs.Slice, axis, int(1)) + + mySlice = wcs.Slice(axis, myBin) + self.assertEqual(mySlice.axis, axis) + self.assertEqual(mySlice.bin, long(1)) + + +class TestValueCoord2d(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.ValueCoord2D, None, None) + self.assertRaises(TypeError, wcs.ValueCoord2D, None, float(1.0)) + self.assertRaises(TypeError, wcs.ValueCoord2D, float(1.0), None) + self.assertRaises(TypeError, wcs.ValueCoord2D, int(1), float(1.0)) + self.assertRaises(TypeError, wcs.ValueCoord2D, float(1.0), int(1)) + + value_coord2d = wcs.ValueCoord2D(float(1), float(2)) + self.assertIsNotNone(value_coord2d) + self.assertEqual(value_coord2d.coord1, float(1)) + self.assertEqual(value_coord2d.coord2, float(2)) diff --git a/caom2/caom2/wcs.py b/caom2/caom2/wcs.py new file mode 100644 index 00000000..70e8e4bc --- /dev/null +++ b/caom2/caom2/wcs.py @@ -0,0 +1,1001 @@ +# -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +# *********************************************************************** +# + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from . import common +from . import caom_util + +__all__ = ['Axis', 'Coord2D', 'CoordAxis1D', 'CoordAxis2D', 'CoordBounds1D', 'CoordBounds2D', 'CoordCircle2D', + 'CoordError', 'CoordFunction1D', 'CoordFunction2D', 'CoordPolygon2D', 'CoordRange1D', 'CoordRange2D', + 'Dimension2D', 'EnergyTransition', 'RefCoord', 'Slice', 'ValueCoord2D'] + + +class Axis(common.CaomObject): + """the Axis class holds the definition of the axis type and units""" + + def __init__(self, ctype, cunit=None): + + self.ctype = ctype + self.cunit = cunit + + @property + def ctype(self): + """The Coordinate Type value for this axis. + + eg. DEC + type: unicode + + """ + return self._ctype + + @ctype.setter + def ctype(self, value): + caom_util.type_check(value, unicode, 'ctype', override=False) + self._ctype = value + + @property + def cunit(self): + """The unit of the coordinate that results after transform. + + eg. deg + type: unicode + + """ + return self._cunit + + @cunit.setter + def cunit(self, value): + caom_util.type_check(value, unicode, 'cunit') + self._cunit = value + + +class Coord2D(common.CaomObject): + """Represents the reference point. + + eg: Coord2D(RefCoord(crpix1,crval1),RefCoord(crpix2,crval2)) + """ + + def __init__(self, coord1, coord2): + self.coord1 = coord1 + self.coord2 = coord2 + + @property + def coord1(self): + """A coordinate axis1 coordinate/pix pair, crpix1, crval1. + + eg. RefCoord(crpix1, crval1) + """ + return self._coord1 + + @coord1.setter + def coord1(self, value): + caom_util.type_check(value, RefCoord, 'coord1', override=False) + self._coord1 = value + + @property + def coord2(self): + """The axis2 coordinate reference pair (ei. crpix2/crval2. + + eg. RefCorrd(crpix2, crval2) + """ + return self._coord2 + + @coord2.setter + def coord2(self, value): + caom_util.type_check(value, RefCoord, 'coord2', override=False) + self._coord2 = value + + +class CoordAxis1D(common.CaomObject): + """Holds the metadata needed to transform a 1D pixel value into a + World Coordinate value. + + """ + + def __init__(self, axis, error=None, range=None, + bounds=None, function=None): + + self.axis = axis + self.error = error + self.range = range + self.bounds = bounds + self.function = function + + @property + def axis(self): + """An axis object which describes the type and units of this + coordinate axis. + + eg. Axis(ctype1,cunit1) + + """ + return self._axis + + @axis.setter + def axis(self, value): + caom_util.type_check(value, Axis, "Axis", override=False) + self._axis = value + + @property + def error(self): + """A CoordError object that describes the uncertainty in the. + + eg. CoordError(syser=0.1, rnder=0.1) + unit: cunit1 [of axis] + + """ + return self._error + + @error.setter + def error(self, value): + caom_util.type_check(value, CoordError, 'error') + self._error = value + + @property + def range(self): + """A range that defines a coordinate transformation. + + the transform is a linear interpolation over the range + given which is a specified as a set of two pix/val reference pair. + eg. CoordRange1D(start=RefCoord(pix1,val1),end=RefCoord(pix2,val2)) + unit: same as the axis you are defining. + + """ + return self._range + + @range.setter + def range(self, value): + caom_util.type_check(value, CoordRange1D, 'range') + self._range = value + + @property + def bounds(self): + """A polygon that defines the boundary of this axis, in 1D. + + eg. CoordBounds1D(ListOfRanges()) + The ranges are like those given for the range attribute. + + """ + return self._bounds + + @bounds.setter + def bounds(self, value): + caom_util.type_check(value, CoordBounds1D, "bounds") + self._bounds = value + + @property + def function(self): + """A linear function that describes the tranformation between pixel + and world coordinate value. + + Since this is a 1D object and linear, the function is + y = m*x + b. + eg. CoordFunction1D(naxis, delta, RefCoord) + + """ + return self._function + + @function.setter + def function(self, value): + caom_util.type_check(value, CoordFunction1D, 'function') + self._function = value + + +class CoordAxis2D(common.CaomObject): + """This object hold the metadata need to transform a 2D pixel + array (say an image) into a World position, say RA/DEC + + """ + + def __init__(self, axis1, axis2, + error1=None, error2=None, + range=None, bounds=None, + function=None): + + self.axis1 = axis1 + self.axis2 = axis2 + self.error1 = error1 + self.error2 = error2 + self.range = range + self.bounds = bounds + self.function = function + + @property + def axis1(self): + """An axis object that desciribes the first dimension + of this 2d system. + + eg. axis1=Axis("RA","deg") + + """ + return self._axis1 + + @axis1.setter + def axis1(self, value): + caom_util.type_check(value, Axis, "axis1", override=False) + self._axis1 = value + + @property + def axis2(self): + """An axis objet that describes the 2nd dimensiotn of this 2d coord + system. + + eg. axis2=Axis("DEG","deg") + + """ + return self._axis2 + + @axis2.setter + def axis2(self, value): + caom_util.type_check(value, Axis, "axis2", override=False) + self._axis2 = value + + @property + def error1(self): + """An object that descibes the uncertainty in the pix/world transform. + + eg. CoordError() + type: CoordError + + """ + return self._error1 + + @error1.setter + def error1(self, value): + caom_util.type_check(value, CoordError, 'error1') + self._error1 = value + + @property + def error2(self): + """An object that describes the uncertainty in the pix/world transform + for the 2nd axis + + type: CoordError + + """ + return self._error2 + + @error2.setter + def error2(self, value): + caom_util.type_check(value, CoordError, "error2") + self._error2 = value + + @property + def range(self): + """Coordinate range defined by this CoordAxis2d object. + + type: CoordRange2D + """ + return self._range + + @range.setter + def range(self, value): + caom_util.type_check(value, CoordRange2D, 'range') + self._range = value + + @property + def bounds(self): + """The Coordinate boundary mapped by this CoordAxis2D object. + + ag. CoordPolygon2d((234,10),(234,11),(233,11),(234,11),(234,10)) + type: CoordPolygon2D or CoordCircle2D + """ + return self._bounds + + @bounds.setter + def bounds(self, value): + caom_util.type_check(value, (CoordCircle2D, CoordPolygon2D), 'bounds') + self._bounds = value + + @property + def function(self): + """A function object that describes the relation + between pixels and wcs. + + ag. CoordFunction2D (see the help for that puppy) + type: CoordFunction2D + """ + return self._function + + @function.setter + def function(self, value): + caom_util.type_check(value, CoordFunction2D, 'function') + self._function = value + + +class CoordBounds1D(common.CaomObject): + """Contains the bounds for a 1D axis, a list of ranges + + """ + + def __init__(self, samples=None): + + if samples is None: + samples = caom_util.TypedList(CoordRange1D,) + self.samples = samples + + @property + def samples(self): + """A list of CoordRange1D objects that define the + boundary of a 1D axis. + + see also caom2.util.TypedList and caom2.wcs.CoordRange1D + + eg. + samples.add(CoordRange1D(RefCoord(pix,val),RefCoord(pix,val))) + + """ + return self._samples + + @samples.setter + def samples(self, value): + caom_util.type_check(value, caom_util.TypedList, 'samples', override=False) + self._samples = value + + +class CoordBounds2D(common.CaomObject): + """Contains the bounds for a 2D axis + + """ + + def __init__(self, bounds): + if (isinstance(bounds, CoordCircle2D) or + isinstance(bounds, CoordPolygon2D)): + self.bounds = bounds + else: + raise TypeError( + "Expected CoordCircle2D or CoordPolygon2D, received {}" + .format(type(bounds))) + + @property + def bounds(self): + """The bounds expressed as a circle or polygon. + + eg CoordBounds2D(CoordCircle2D()) + type: CoordCircle2D or CoordPolygon2D + """ + return self._bounds + + @bounds.setter + def bounds(self, value): + self._bounds = value + + +class CoordCircle2D(common.CaomObject): + """A circle expressed in both pixel and WCS value coordinates. + + These objects are used to map out the bounds of spatial WCS. + + Currently radius is only given in WCS units.. should be both. + + """ + + def __init__(self, center, radius): + self.center = center + self.radius = radius + + @property + def center(self): + """The pixel/world coordinate location of the centre. + + eg ValueCoord2D(coord1, coord2) + type: ValueCoord2D + """ + return self._center + + @center.setter + def center(self, value): + caom_util.type_check(value, ValueCoord2D, 'center', override=False) + self._center = value + + @property + def radius(self): + """The radius of the circle. + + NOTE::: This should likely be a RefCoord too... + + unit: same as centre which is pix/cunit + type: float + """ + return self._radius + + @radius.setter + def radius(self, value): + caom_util.type_check(value, float, 'radius', override=False) + caom_util.value_check(value, 0, 1E10, 'radius') + self._radius = value + + +class CoordError(common.CaomObject): + """Holds the systematic (syser) and random (rnder) error on a + coordinate. + + The concept is that these values are functions of the coordinate + transformation but likely be expressed with sufficient precision + (for a query model) using a systematic and random component. Both + are taken to be symetric. + + Likely either of these could be 'None', but best set to '0' if + that's what you really want to express. + + """ + + def __init__(self, syser, rnder): + + self.syser = syser + self.rnder = rnder + + # Properties + @property + def syser(self): + """the systematic uncertainty in a coordinate transform. + + units: should be the same as the CoordAxis (s, arcsec, deg?) + + """ + return self._syser + + @syser.setter + def syser(self, value): + caom_util.type_check(value, float, "syser", override=False) + self._syser = value + + @property + def rnder(self): + """the random uncertainty in a coordinate transform. + + units: should be the same as the CoordAxis transform. + + """ + return self._rnder + + @rnder.setter + def rnder(self, value): + caom_util.type_check(value, float, "rnder", override=False) + self._rnder = value + + +class CoordFunction1D(common.CaomObject): + """Defines a linear function that transforms from pixel to WCS + values. + + """ + + def __init__(self, naxis, delta, ref_coord): + """ + Need to define the length of the axis, the slope of the + conversion and a reference coordinate. All are needed for a + valid 1D function. + + """ + + self.naxis = naxis + self.delta = delta + self.ref_coord = ref_coord + + @property + def naxis(self): + """The length of the axis. + + unit: pix + type: long + + """ + return self._naxis + + @naxis.setter + def naxis(self, value): + caom_util.type_check(value, long, 'naxis', override=False) + self._naxis = value + + @property + def delta(self): + """The step in WCS between pixels. + + unit: WCS/pix (days if this is a timeWCS) + type: float + + """ + return self._delta + + @delta.setter + def delta(self, value): + caom_util.type_check(value, float, 'delta', override=False) + self._delta = value + + @property + def ref_coord(self): + """the (pix,val) reference for this transformtion. + + eg. ref_coord=RefCoord(pix,val) + type: RefCoord + + """ + return self._ref_coord + + @ref_coord.setter + def ref_coord(self, value): + caom_util.type_check(value, RefCoord, 'ref_coord', override=False) + self._ref_coord = value + + +class CoordFunction2D(common.CaomObject): + """Describes the parameters needed for the standard CD matrix. + + defines a linear translation between pixel and WCS. + + """ + + def __init__(self, dimension, ref_coord, cd11, cd12, cd21, cd22): + self.dimension = dimension + self.ref_coord = ref_coord + self.cd11 = cd11 + self.cd12 = cd12 + self.cd21 = cd21 + self.cd22 = cd22 + + @property + def dimension(self): + """A Dimension2D object that holds the lengths of the axis + + eg. Diemnsion2D(naxis1=1024,naxis2=2048) + type: Dimension2D + + """ + return self._dimension + + @dimension.setter + def dimension(self, value): + caom_util.type_check(value, Dimension2D, 'dimension', override=False) + self._dimension = value + + @property + def ref_coord(self): + """A Coord2D object that holds the reference pixel location + + eg. Coord2D((crpix1,crval1),(crpix2,crval2)) + type: Coord2D + + """ + return self._ref_coord + + @ref_coord.setter + def ref_coord(self, value): + caom_util.type_check(value, Coord2D, 'ref_coord', override=False) + self._ref_coord = value + + @property + def cd11(self): + """The CD1_1 value (depenence of RA scale on x-pixel value) + + eg. cd11 = 5E-5 + unit: deg/pix + type: float + + """ + return self._cd11 + + @cd11.setter + def cd11(self, value): + caom_util.type_check(value, float, 'cd11', override=False) + self._cd11 = value + + @property + def cd12(self): + """The CD1_2 value (depenence of RA scale on y-pixel value) + + eg. cd12 = 5E-10 + unit: deg/pix + type: float + + """ + return self._cd12 + + @cd12.setter + def cd12(self, value): + caom_util.type_check(value, float, 'cd12', override=False) + self._cd12 = value + + @property + def cd21(self): + """The CD1_1 value (depenence of DEC scale on x-pixel value) + + eg. cd11 = 5E-10 + unit: deg/pix + type: float + + """ + return self._cd21 + + @cd21.setter + def cd21(self, value): + caom_util.type_check(value, float, 'cd21', override=False) + self._cd21 = value + + @property + def cd22(self): + """The CD2_2 value (depenence of DEC scale on y-pixel value) + + eg. cd12 = 5E-5 + unit: deg/pix + type: float + + """ + return self._cd22 + + @cd22.setter + def cd22(self, value): + caom_util.type_check(value, float, 'cd22', override=False) + self._cd22 = value + + +class CoordPolygon2D(common.CaomObject): + """A object to contain a TypeList ValueCoord2D vertices that are a + polygon. The vertices are given as ValueCoord2D objects, which are + coordinate pairs. + + eg. vertices.add(ValueCoord2D(coord1,coord2)) + + """ + + def __init__(self, vertices=None): + if vertices is None: + vertices = caom_util.TypedList(ValueCoord2D,) + self.vertices = vertices + + @property + def vertices(self): + """A TypedList of ValueCoord2D objects that layout the vertices of a + polygon. + + A vertices can be added using the 'add' method.. + eg: vertices.add(ValueCoord2D()) + + see the caom2.wcs.ValueCoord2D help for details on making a + coordinate pair. + + type: TypedList((ValueCoord2D),) + + """ + return self._vertices + + @vertices.setter + def vertices(self, value): + caom_util.type_check(value, caom_util.TypedList, 'vertices', override=False) + self._vertices = value + + +class CoordRange1D(common.CaomObject): + """a CoordRange1D object contains the start and end of + a range of values, expressed in both pixel and WCS units. + + """ + + def __init__(self, start, end): + self.start = start + self.end = end + + @property + def start(self): + """The pixel and world coordinate of the start of a range. + + eg. RefCoord(pix,val) + type: RefCoord + + """ + return self._start + + @start.setter + def start(self, value): + caom_util.type_check(value, RefCoord, "start", override=False) + self._start = value + + @property + def end(self): + """The pixel and world coordinate of the end of a range. + + eg. RefCoord(pix,val) + type: RefCoord + + """ + return self._end + + @end.setter + def end(self, value): + caom_util.type_check(value, RefCoord, "end", override=False) + self._end = value + + +class CoordRange2D(common.CaomObject): + """A range (x1,y1) to (x2,y2) in two dimenstions. + + The range object should know the coordinate in both + pixels and WCS units. + + """ + + def __init__(self, start, end): + self.start = start + self.end = end + + @property + def start(self): + """The starting coordinate pair of a range, in wcs units. + + eg: Coord2D(RefCoord(crpix1,crval1), RefCoord(crpix2,crval2)) + """ + return self._start + + @start.setter + def start(self, value): + caom_util.type_check(value, Coord2D, 'start', override=False) + self._start = value + + @property + def end(self): + """The reference for the ending coordinate of a range. + + eg: Coord2D(RefCoord(crpix1,crval1), RefCoord(crpix2,crval2)) + """ + return self._end + + @end.setter + def end(self, value): + caom_util.type_check(value, Coord2D, 'end', override=False) + self._end = value + + +class Dimension2D(common.CaomObject): + """Hey, how big is this thing? What are its dimensions. That's what + Dimension2D will tell you. + + """ + + def __init__(self, naxis1, naxis2): + self.naxis1 = naxis1 + self.naxis2 = naxis2 + + @property + def naxis1(self): + """The length of the first (x) dimension. + + eg. naxis1=1024 + unit: pix + type: long + + """ + return self._naxis1 + + @naxis1.setter + def naxis1(self, value): + caom_util.type_check(value, long, 'naxis1', override=False) + caom_util.value_check(value, 0, 1E10, 'naxis1', override=False) + self._naxis1 = value + + @property + def naxis2(self): + """The length of the second (y) dimension. + + eg. naxis2=2048 + unit: pix + type: long + + """ + return self._naxis2 + + @naxis2.setter + def naxis2(self, value): + caom_util.type_check(value, long, 'naxis2', override=False) + caom_util.value_check(value, 0, 1E10, 'naxis2', override=False) + self._naxis2 = value + + +class EnergyTransition(common.CaomObject): + """ EnergyTransition """ + + def __init__(self, species, transition): + """ + Construct an EnergyTransition instance + + Arguments: + species + transition + """ + caom_util.type_check(species, unicode, "species", override=False) + caom_util.type_check(transition, unicode, "transition", override=False) + self._species = species + self._transition = transition + + @property + def species(self): + """ Species """ + return self._species + + @property + def transition(self): + """ Transition """ + return self._transition + + +class RefCoord(common.CaomObject): + """A refernce coordinate object, maps pixel value to wcs value + + """ + + def __init__(self, pix, val): + """maps a pixel location to a wcs value, as a reference spot. + + eg. RefCoord(crpix1, crval1) + + """ + self.pix = pix + self.val = val + + @property + def pix(self): + """The pixel location of a reference position. + + units: pix + type: float + + """ + return self._pix + + @pix.setter + def pix(self, value): + caom_util.type_check(value, float, 'pix', override=False) + self._pix = value + + @property + def val(self): + """The WCS value at the reference position. + + units: CUNIT + type: float + + """ + return self._val + + @val.setter + def val(self, value): + caom_util.type_check(value, float, 'val', override=False) + self._val = value + + +class Slice(common.CaomObject): + """defines a slice in a set of data contains values. + + The slice keeps track of the type/unit and values. + + ctype and cunit are stored in the axis variable. + values are stored in the bins + + """ + def __init__(self, axis, bin_): + self.axis = axis + self.bin = bin_ + + @property + def axis(self): + """A ctype/cunit pair for this slice of data. + + type: Axis(ctype,cunit) + + """ + return self._axis + + @axis.setter + def axis(self, value): + caom_util.type_check(value, Axis, 'axis', override=False) + self._axis = value + + @property + def bin(self): + """The pixel value on the axis. + + This value is use to transform to the WCS for this axis. + unit: pixel + type: long + """ + return self._bin + + @bin.setter + def bin(self, value): + caom_util.type_check(value, long, 'long', override=False) + self._bin = value + + +class ValueCoord2D(common.CaomObject): + """Represents the reference point.""" + + def __init__(self, coord1, coord2): + self.coord1 = coord1 + self.coord2 = coord2 + + @property + def coord1(self): + """Coordinate 1""" + return self._coord1 + + @coord1.setter + def coord1(self, value): + caom_util.type_check(value, float, 'coord1', override=False) + self._coord1 = value + + @property + def coord2(self): + """Coordinate 2""" + return self._coord2 + + @coord2.setter + def coord2(self, value): + caom_util.type_check(value, float, 'coord2', override=False) + self._coord2 = value diff --git a/caom2/dev_requirements.txt b/caom2/dev_requirements.txt new file mode 100644 index 00000000..b3caf8fd --- /dev/null +++ b/caom2/dev_requirements.txt @@ -0,0 +1,7 @@ +numpy==1.12.0b1 +astropy==1.2.1 +-e . +funcsigs==1.0.2 +mock==2.0.0 +xml-compare==1.0.5 +enum34==1.1.6 diff --git a/caom2/docs/Makefile b/caom2/docs/Makefile new file mode 100644 index 00000000..fb03f26e --- /dev/null +++ b/caom2/docs/Makefile @@ -0,0 +1,133 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +#This is needed with git because git doesn't create a dir if it's empty +$(shell [ -d "_static" ] || mkdir -p _static) + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf $(BUILDDIR) + -rm -rf api + -rm -rf generated + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Astropy.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Astropy.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Astropy" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Astropy" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + @echo "Run 'python setup.py test' in the root directory to run doctests " \ + @echo "in the documentation." diff --git a/caom2/docs/_templates/autosummary/base.rst b/caom2/docs/_templates/autosummary/base.rst new file mode 100644 index 00000000..9cabaf52 --- /dev/null +++ b/caom2/docs/_templates/autosummary/base.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/base.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2/docs/_templates/autosummary/class.rst b/caom2/docs/_templates/autosummary/class.rst new file mode 100644 index 00000000..6b214a5c --- /dev/null +++ b/caom2/docs/_templates/autosummary/class.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/class.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2/docs/_templates/autosummary/module.rst b/caom2/docs/_templates/autosummary/module.rst new file mode 100644 index 00000000..f38315b2 --- /dev/null +++ b/caom2/docs/_templates/autosummary/module.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/module.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2/docs/conf.py b/caom2/docs/conf.py new file mode 100644 index 00000000..78d20fd8 --- /dev/null +++ b/caom2/docs/conf.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# +# Astropy documentation build configuration file. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this file. +# +# All configuration values have a default. Some values are defined in +# the global Astropy configuration which is loaded here before anything else. +# See astropy.sphinx.conf for which values are set there. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('..')) +# IMPORTANT: the above commented section was generated by sphinx-quickstart, but +# is *NOT* appropriate for astropy or Astropy affiliated packages. It is left +# commented out with this explanation to make it clear why this should not be +# done. If the sys.path entry above is added, when the astropy.sphinx.conf +# import occurs, it will import the *source* version of astropy instead of the +# version installed (if invoked as "make html" or directly with sphinx), or the +# version in the build directory (if "python setup.py build_sphinx" is used). +# Thus, any C-extensions that are needed to build the documentation will *not* +# be accessible, and the documentation will not build correctly. + +import datetime +import os +import sys + +try: + import astropy_helpers +except ImportError: + # Building from inside the docs/ directory? + if os.path.basename(os.getcwd()) == 'docs': + a_h_path = os.path.abspath(os.path.join('..', 'astropy_helpers')) + if os.path.isdir(a_h_path): + sys.path.insert(1, a_h_path) + +# Load all of the global Astropy configuration +from astropy_helpers.sphinx.conf import * + +# Get configuration information from setup.cfg +try: + from ConfigParser import ConfigParser +except ImportError: + from configparser import ConfigParser +conf = ConfigParser() + +conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')]) +setup_cfg = dict(conf.items('metadata')) + +# -- General configuration ---------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.2' + +# To perform a Sphinx version check that needs to be more specific than +# major.minor, call `check_sphinx_version("x.y.z")` here. +# check_sphinx_version("1.2.1") + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns.append('_templates') + +# This is added to the end of RST files - a good place to put substitutions to +# be used globally. +rst_epilog += """ +""" + +# -- Project information ------------------------------------------------------ + +# This does not *have* to match the package name, but typically does +project = setup_cfg['package_name'] +author = setup_cfg['author'] +copyright = '{0}, {1}'.format( + datetime.datetime.now().year, setup_cfg['author']) + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. + +__import__(setup_cfg['package_name']) +package = sys.modules[setup_cfg['package_name']] + +# The short X.Y version. +version = package.__version__.split('-', 1)[0] +# The full version, including alpha/beta/rc tags. +release = package.__version__ + + +# -- Options for HTML output -------------------------------------------------- + +# A NOTE ON HTML THEMES +# The global astropy configuration uses a custom theme, 'bootstrap-astropy', +# which is installed along with astropy. A different theme can be used or +# the options for this theme can be modified by overriding some of the +# variables set in the global configuration. The variables set in the +# global configuration are listed below, commented out. + + +# Please update these texts to match the name of your package. +html_theme_options = { + 'logotext1': 'package', # white, semi-bold + 'logotext2': '-template', # orange, light + 'logotext3': ':docs' # white, light + } + +# Add any paths that contain custom themes here, relative to this directory. +# To use a different custom theme, add the directory containing the theme. +#html_theme_path = [] + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. To override the custom theme, set this to the +# name of a builtin theme or the name of a custom theme in html_theme_path. +#html_theme = None + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = '' + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '' + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +html_title = '{0} v{1}'.format(project, release) + +# Output file base name for HTML help builder. +htmlhelp_basename = project + 'doc' + + +# -- Options for LaTeX output ------------------------------------------------- + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [('index', project + '.tex', project + u' Documentation', + author, 'manual')] + + +# -- Options for manual page output ------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [('index', project.lower(), project + u' Documentation', + [author], 1)] + + +# -- Options for the edit_on_github extension --------------------------------- + +if eval(setup_cfg.get('edit_on_github')): + extensions += ['astropy_helpers.sphinx.ext.edit_on_github'] + + versionmod = __import__(setup_cfg['package_name'] + '.version') + edit_on_github_project = setup_cfg['github_project'] + if versionmod.version.release: + edit_on_github_branch = "v" + versionmod.version.version + else: + edit_on_github_branch = "master" + + edit_on_github_source_root = "" + edit_on_github_doc_root = "docs" + +# -- Resolving issue number to links in changelog ----------------------------- +github_issues_url = 'https://github.com/{0}/issues/'.format(setup_cfg['github_project']) + diff --git a/caom2/docs/index.rst b/caom2/docs/index.rst new file mode 100644 index 00000000..e69de29b diff --git a/caom2/docs/make.bat b/caom2/docs/make.bat new file mode 100644 index 00000000..93dfe92b --- /dev/null +++ b/caom2/docs/make.bat @@ -0,0 +1,170 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Astropy.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Astropy.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/caom2/ez_setup.py b/caom2/ez_setup.py new file mode 100644 index 00000000..fc22046b --- /dev/null +++ b/caom2/ez_setup.py @@ -0,0 +1,425 @@ +#!/usr/bin/env python + +""" +Setuptools bootstrapping installer. + +Maintained at https://github.com/pypa/setuptools/tree/bootstrap. + +Run this script to install or upgrade setuptools. +""" + +import os +import shutil +import sys +import tempfile +import zipfile +import optparse +import subprocess +import platform +import textwrap +import contextlib +import json +import codecs + +from distutils import log + +try: + from urllib.request import urlopen + from urllib.parse import urljoin +except ImportError: + from urllib2 import urlopen + from urlparse import urljoin + +try: + from site import USER_SITE +except ImportError: + USER_SITE = None + +LATEST = object() +DEFAULT_VERSION = LATEST +DEFAULT_URL = "https://pypi.io/packages/source/s/setuptools/" +DEFAULT_SAVE_DIR = os.curdir + + +def _python_cmd(*args): + """ + Execute a command. + + Return True if the command succeeded. + """ + args = (sys.executable,) + args + return subprocess.call(args) == 0 + + +def _install(archive_filename, install_args=()): + """Install Setuptools.""" + with archive_context(archive_filename): + # installing + log.warn('Installing Setuptools') + if not _python_cmd('setup.py', 'install', *install_args): + log.warn('Something went wrong during the installation.') + log.warn('See the error message above.') + # exitcode will be 2 + return 2 + + +def _build_egg(egg, archive_filename, to_dir): + """Build Setuptools egg.""" + with archive_context(archive_filename): + # building an egg + log.warn('Building a Setuptools egg in %s', to_dir) + _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) + # returning the result + log.warn(egg) + if not os.path.exists(egg): + raise IOError('Could not build the egg.') + + +class ContextualZipFile(zipfile.ZipFile): + + """Supplement ZipFile class to support context manager for Python 2.6.""" + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + def __new__(cls, *args, **kwargs): + """Construct a ZipFile or ContextualZipFile as appropriate.""" + if hasattr(zipfile.ZipFile, '__exit__'): + return zipfile.ZipFile(*args, **kwargs) + return super(ContextualZipFile, cls).__new__(cls) + + +@contextlib.contextmanager +def archive_context(filename): + """ + Unzip filename to a temporary directory, set to the cwd. + + The unzipped target is cleaned up after. + """ + tmpdir = tempfile.mkdtemp() + log.warn('Extracting in %s', tmpdir) + old_wd = os.getcwd() + try: + os.chdir(tmpdir) + with ContextualZipFile(filename) as archive: + archive.extractall() + + # going in the directory + subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) + os.chdir(subdir) + log.warn('Now working in %s', subdir) + yield + + finally: + os.chdir(old_wd) + shutil.rmtree(tmpdir) + + +def _do_download(version, download_base, to_dir, download_delay): + """Download Setuptools.""" + egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' + % (version, sys.version_info[0], sys.version_info[1])) + if not os.path.exists(egg): + archive = download_setuptools(version, download_base, + to_dir, download_delay) + _build_egg(egg, archive, to_dir) + sys.path.insert(0, egg) + + # Remove previously-imported pkg_resources if present (see + # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). + if 'pkg_resources' in sys.modules: + _unload_pkg_resources() + + import setuptools + setuptools.bootstrap_install_from = egg + + +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=DEFAULT_SAVE_DIR, download_delay=15): + """ + Ensure that a setuptools version is installed. + + Return None. Raise SystemExit if the requested version + or later cannot be installed. + """ + version = _resolve_version(version) + to_dir = os.path.abspath(to_dir) + + # prior to importing, capture the module state for + # representative modules. + rep_modules = 'pkg_resources', 'setuptools' + imported = set(sys.modules).intersection(rep_modules) + + try: + import pkg_resources + pkg_resources.require("setuptools>=" + version) + # a suitable version is already installed + return + except ImportError: + # pkg_resources not available; setuptools is not installed; download + pass + except pkg_resources.DistributionNotFound: + # no version of setuptools was found; allow download + pass + except pkg_resources.VersionConflict as VC_err: + if imported: + _conflict_bail(VC_err, version) + + # otherwise, unload pkg_resources to allow the downloaded version to + # take precedence. + del pkg_resources + _unload_pkg_resources() + + return _do_download(version, download_base, to_dir, download_delay) + + +def _conflict_bail(VC_err, version): + """ + Setuptools was imported prior to invocation, so it is + unsafe to unload it. Bail out. + """ + conflict_tmpl = textwrap.dedent(""" + The required version of setuptools (>={version}) is not available, + and can't be installed while this script is running. Please + install a more recent version first, using + 'easy_install -U setuptools'. + + (Currently using {VC_err.args[0]!r}) + """) + msg = conflict_tmpl.format(**locals()) + sys.stderr.write(msg) + sys.exit(2) + + +def _unload_pkg_resources(): + sys.meta_path = [ + importer + for importer in sys.meta_path + if importer.__class__.__module__ != 'pkg_resources.extern' + ] + del_modules = [ + name for name in sys.modules + if name.startswith('pkg_resources') + ] + for mod_name in del_modules: + del sys.modules[mod_name] + + +def _clean_check(cmd, target): + """ + Run the command to download target. + + If the command fails, clean up before re-raising the error. + """ + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError: + if os.access(target, os.F_OK): + os.unlink(target) + raise + + +def download_file_powershell(url, target): + """ + Download the file at url to target using Powershell. + + Powershell will validate trust. + Raise an exception if the command cannot complete. + """ + target = os.path.abspath(target) + ps_cmd = ( + "[System.Net.WebRequest]::DefaultWebProxy.Credentials = " + "[System.Net.CredentialCache]::DefaultCredentials; " + '(new-object System.Net.WebClient).DownloadFile("%(url)s", "%(target)s")' + % locals() + ) + cmd = [ + 'powershell', + '-Command', + ps_cmd, + ] + _clean_check(cmd, target) + + +def has_powershell(): + """Determine if Powershell is available.""" + if platform.system() != 'Windows': + return False + cmd = ['powershell', '-Command', 'echo test'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_powershell.viable = has_powershell + + +def download_file_curl(url, target): + cmd = ['curl', url, '--location', '--silent', '--output', target] + _clean_check(cmd, target) + + +def has_curl(): + cmd = ['curl', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_curl.viable = has_curl + + +def download_file_wget(url, target): + cmd = ['wget', url, '--quiet', '--output-document', target] + _clean_check(cmd, target) + + +def has_wget(): + cmd = ['wget', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_wget.viable = has_wget + + +def download_file_insecure(url, target): + """Use Python to download the file, without connection authentication.""" + src = urlopen(url) + try: + # Read all the data in one block. + data = src.read() + finally: + src.close() + + # Write all the data in one block to avoid creating a partial file. + with open(target, "wb") as dst: + dst.write(data) +download_file_insecure.viable = lambda: True + + +def get_best_downloader(): + downloaders = ( + download_file_powershell, + download_file_curl, + download_file_wget, + download_file_insecure, + ) + viable_downloaders = (dl for dl in downloaders if dl.viable()) + return next(viable_downloaders, None) + + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=DEFAULT_SAVE_DIR, delay=15, + downloader_factory=get_best_downloader): + """ + Download setuptools from a specified location and return its filename. + + `version` should be a valid setuptools version number that is available + as an sdist for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download + attempt. + + ``downloader_factory`` should be a function taking no arguments and + returning a function for downloading a URL to a target. + """ + version = _resolve_version(version) + # making sure we use the absolute path + to_dir = os.path.abspath(to_dir) + zip_name = "setuptools-%s.zip" % version + url = download_base + zip_name + saveto = os.path.join(to_dir, zip_name) + if not os.path.exists(saveto): # Avoid repeated downloads + log.warn("Downloading %s", url) + downloader = downloader_factory() + downloader(url, saveto) + return os.path.realpath(saveto) + + +def _resolve_version(version): + """ + Resolve LATEST version + """ + if version is not LATEST: + return version + + meta_url = urljoin(DEFAULT_URL, '/pypi/setuptools/json') + resp = urlopen(meta_url) + with contextlib.closing(resp): + try: + charset = resp.info().get_content_charset() + except Exception: + # Python 2 compat; assume UTF-8 + charset = 'UTF-8' + reader = codecs.getreader(charset) + doc = json.load(reader(resp)) + + return str(doc['info']['version']) + + +def _build_install_args(options): + """ + Build the arguments to 'python setup.py install' on the setuptools package. + + Returns list of command line arguments. + """ + return ['--user'] if options.user_install else [] + + +def _parse_args(): + """Parse the command line for options.""" + parser = optparse.OptionParser() + parser.add_option( + '--user', dest='user_install', action='store_true', default=False, + help='install in user site package') + parser.add_option( + '--download-base', dest='download_base', metavar="URL", + default=DEFAULT_URL, + help='alternative URL from where to download the setuptools package') + parser.add_option( + '--insecure', dest='downloader_factory', action='store_const', + const=lambda: download_file_insecure, default=get_best_downloader, + help='Use internal, non-validating downloader' + ) + parser.add_option( + '--version', help="Specify which version to download", + default=DEFAULT_VERSION, + ) + parser.add_option( + '--to-dir', + help="Directory to save (and re-use) package", + default=DEFAULT_SAVE_DIR, + ) + options, args = parser.parse_args() + # positional arguments are ignored + return options + + +def _download_args(options): + """Return args for download_setuptools function from cmdline args.""" + return dict( + version=options.version, + download_base=options.download_base, + downloader_factory=options.downloader_factory, + to_dir=options.to_dir, + ) + + +def main(): + """Install or upgrade setuptools and EasyInstall.""" + options = _parse_args() + archive = download_setuptools(**_download_args(options)) + return _install(archive, _build_install_args(options)) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/caom2/setup.cfg b/caom2/setup.cfg new file mode 100644 index 00000000..c3ce8310 --- /dev/null +++ b/caom2/setup.cfg @@ -0,0 +1,36 @@ +[build_sphinx] +source-dir = docs +build-dir = docs/_build +all_files = 1 + +[build_docs] +source-dir = docs +build-dir = docs/_build +all_files = 1 + +[upload_docs] +upload-dir = docs/_build/html +show-response = 1 + +[pytest] +minversion = 2.2 +norecursedirs = build docs/_build +doctest_plus = enabled + +[ah_bootstrap] +auto_use = True + +[metadata] +package_name = caom2 +description = CAOM-2.2 library +long_description = Python library for the CAOM-2.2 data model +author = Canadian Astronomy Data Centre +author_email = cadc@nrc-cnrc.gc.ca +license = AGPLv3 +url = http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2 +edit_on_github = False +github_project = opencadc/caom2tools +# version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) +version = 2.2.2 + +[entry_points] diff --git a/caom2/setup.py b/caom2/setup.py new file mode 100755 index 00000000..aa4ee731 --- /dev/null +++ b/caom2/setup.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +import glob +import os +import sys + +import ah_bootstrap +from setuptools import setup + +# A dirty hack to get around some early import/configurations ambiguities +if sys.version_info[0] >= 3: + import builtins +else: + import __builtin__ as builtins +builtins._ASTROPY_SETUP_ = True + +from astropy_helpers.setup_helpers import (register_commands, get_debug_option, + get_package_info) +from astropy_helpers.git_helpers import get_git_devstr +from astropy_helpers.version_helpers import generate_version_py + +# Get some values from the setup.cfg +try: + from ConfigParser import ConfigParser +except ImportError: + from configparser import ConfigParser + +conf = ConfigParser() +conf.read(['setup.cfg']) +metadata = dict(conf.items('metadata')) + +PACKAGENAME = metadata.get('package_name', 'packagename') +DESCRIPTION = metadata.get('description', 'Astropy affiliated package') +AUTHOR = metadata.get('author', '') +AUTHOR_EMAIL = metadata.get('author_email', '') +LICENSE = metadata.get('license', 'unknown') +URL = metadata.get('url', 'http://astropy.org') + +# Get the long description from the package's docstring +__import__(PACKAGENAME) +package = sys.modules[PACKAGENAME] +LONG_DESCRIPTION = package.__doc__ + +# Store the package name in a built-in variable so it's easy +# to get from other parts of the setup infrastructure +builtins._ASTROPY_PACKAGE_NAME_ = PACKAGENAME + +# VERSION should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) +VERSION = metadata.get('version', '0.dev') + +# Indicates if this version is a release version +RELEASE = 'dev' not in VERSION + +if not RELEASE: + VERSION += get_git_devstr(False) + +# Populate the dict of setup command overrides; this should be done before +# invoking any other functionality from distutils since it can potentially +# modify distutils' behavior. +cmdclassd = register_commands(PACKAGENAME, VERSION, RELEASE) + +# Freeze build information in version.py +generate_version_py(PACKAGENAME, VERSION, RELEASE, + get_debug_option(PACKAGENAME)) + +# Treat everything in scripts except README.rst as a script to be installed +scripts = [fname for fname in glob.glob(os.path.join('scripts', '*')) + if os.path.basename(fname) != 'README.rst'] + + +# Get configuration information from all of the various subpackages. +# See the docstring for setup_helpers.update_package_files for more +# details. +package_info = get_package_info() + +# Add the project-global data +package_info['package_data'].setdefault(PACKAGENAME, []) +package_info['package_data'][PACKAGENAME].append('data/*') +package_info['package_data'][PACKAGENAME].append('tests/data/*') + +# Define entry points for command-line scripts +entry_points = {'console_scripts': []} + +entry_point_list = conf.items('entry_points') +for entry_point in entry_point_list: + entry_points['console_scripts'].append('{0} = {1}'.format(entry_point[0], + entry_point[1])) + +# Include all .c files, recursively, including those generated by +# Cython, since we can not do this in MANIFEST.in with a "dynamic" +# directory name. +c_files = [] +for root, dirs, files in os.walk(PACKAGENAME): + for filename in files: + if filename.endswith('.c'): + c_files.append( + os.path.join( + os.path.relpath(root, PACKAGENAME), filename)) +package_info['package_data'][PACKAGENAME].extend(c_files) + +# Note that requires and provides should not be included in the call to +# ``setup``, since these are now deprecated. See this link for more details: +# https://groups.google.com/forum/#!topic/astropy-dev/urYO8ckB2uM + +setup(name=PACKAGENAME, + version=VERSION, + description=DESCRIPTION, + scripts=scripts, + install_requires=['lxml', 'enum34'], + author=AUTHOR, + author_email=AUTHOR_EMAIL, + license=LICENSE, + url=URL, + long_description=LONG_DESCRIPTION, + cmdclass=cmdclassd, + zip_safe=False, + use_2to3=False, + entry_points=entry_points, + **package_info +) diff --git a/caom2repoClient/COPYING b/caom2repo/LICENSE similarity index 99% rename from caom2repoClient/COPYING rename to caom2repo/LICENSE index dba13ed2..dbbe3558 100644 --- a/caom2repoClient/COPYING +++ b/caom2repo/LICENSE @@ -633,8 +633,8 @@ the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/caom2repo/MANIFEST.in b/caom2repo/MANIFEST.in new file mode 100644 index 00000000..c3bf88f0 --- /dev/null +++ b/caom2repo/MANIFEST.in @@ -0,0 +1,40 @@ +include README.rst +include CHANGES.rst + +include ez_setup.py +include ah_bootstrap.py +include setup.cfg + +recursive-include packagename *.pyx *.c *.pxd +recursive-include docs * +recursive-include licenses * +recursive-include cextern * +recursive-include scripts * + +prune build +prune docs/_build +prune docs/api + + +# the next few stanzas are for astropy_helpers. It's derived from the +# astropy_helpers/MANIFEST.in, but requires additional includes for the actual +# package directory and egg-info. + +include astropy_helpers/README.rst +include astropy_helpers/CHANGES.rst +include astropy_helpers/LICENSE.rst +recursive-include astropy_helpers/licenses * + +include astropy_helpers/ez_setup.py +include astropy_helpers/ah_bootstrap.py + +recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h +recursive-include astropy_helpers/astropy_helpers.egg-info * +# include the sphinx stuff with "*" because there are css/html/rst/etc. +recursive-include astropy_helpers/astropy_helpers/sphinx * + +prune astropy_helpers/build +prune astropy_helpers/astropy_helpers/tests + + +global-exclude *.pyc *.o diff --git a/caom2repo/README.md b/caom2repo/README.md new file mode 100644 index 00000000..f276ac90 --- /dev/null +++ b/caom2repo/README.md @@ -0,0 +1,2 @@ +# caom2repo +Common Archive Observation Model - repo access library and client diff --git a/caom2repo/ah_bootstrap.py b/caom2repo/ah_bootstrap.py new file mode 100644 index 00000000..0dc50071 --- /dev/null +++ b/caom2repo/ah_bootstrap.py @@ -0,0 +1,987 @@ +""" +This bootstrap module contains code for ensuring that the astropy_helpers +package will be importable by the time the setup.py script runs. It also +includes some workarounds to ensure that a recent-enough version of setuptools +is being used for the installation. + +This module should be the first thing imported in the setup.py of distributions +that make use of the utilities in astropy_helpers. If the distribution ships +with its own copy of astropy_helpers, this module will first attempt to import +from the shipped copy. However, it will also check PyPI to see if there are +any bug-fix releases on top of the current version that may be useful to get +past platform-specific bugs that have been fixed. When running setup.py, use +the ``--offline`` command-line option to disable the auto-upgrade checks. + +When this module is imported or otherwise executed it automatically calls a +main function that attempts to read the project's setup.cfg file, which it +checks for a configuration section called ``[ah_bootstrap]`` the presences of +that section, and options therein, determine the next step taken: If it +contains an option called ``auto_use`` with a value of ``True``, it will +automatically call the main function of this module called +`use_astropy_helpers` (see that function's docstring for full details). +Otherwise no further action is taken (however, +``ah_bootstrap.use_astropy_helpers`` may be called manually from within the +setup.py script). + +Additional options in the ``[ah_boostrap]`` section of setup.cfg have the same +names as the arguments to `use_astropy_helpers`, and can be used to configure +the bootstrap script when ``auto_use = True``. + +See https://github.com/astropy/astropy-helpers for more details, and for the +latest version of this module. +""" + +import contextlib +import errno +import imp +import io +import locale +import os +import re +import subprocess as sp +import sys + +try: + from ConfigParser import ConfigParser, RawConfigParser +except ImportError: + from configparser import ConfigParser, RawConfigParser + + +if sys.version_info[0] < 3: + _str_types = (str, unicode) + _text_type = unicode + PY3 = False +else: + _str_types = (str, bytes) + _text_type = str + PY3 = True + + +# What follows are several import statements meant to deal with install-time +# issues with either missing or misbehaving pacakges (including making sure +# setuptools itself is installed): + + +# Some pre-setuptools checks to ensure that either distribute or setuptools >= +# 0.7 is used (over pre-distribute setuptools) if it is available on the path; +# otherwise the latest setuptools will be downloaded and bootstrapped with +# ``ez_setup.py``. This used to be included in a separate file called +# setuptools_bootstrap.py; but it was combined into ah_bootstrap.py +try: + import pkg_resources + _setuptools_req = pkg_resources.Requirement.parse('setuptools>=0.7') + # This may raise a DistributionNotFound in which case no version of + # setuptools or distribute is properly installed + _setuptools = pkg_resources.get_distribution('setuptools') + if _setuptools not in _setuptools_req: + # Older version of setuptools; check if we have distribute; again if + # this results in DistributionNotFound we want to give up + _distribute = pkg_resources.get_distribution('distribute') + if _setuptools != _distribute: + # It's possible on some pathological systems to have an old version + # of setuptools and distribute on sys.path simultaneously; make + # sure distribute is the one that's used + sys.path.insert(1, _distribute.location) + _distribute.activate() + imp.reload(pkg_resources) +except: + # There are several types of exceptions that can occur here; if all else + # fails bootstrap and use the bootstrapped version + from ez_setup import use_setuptools + use_setuptools() + + +# Note: The following import is required as a workaround to +# https://github.com/astropy/astropy-helpers/issues/89; if we don't import this +# module now, it will get cleaned up after `run_setup` is called, but that will +# later cause the TemporaryDirectory class defined in it to stop working when +# used later on by setuptools +try: + import setuptools.py31compat +except ImportError: + pass + + +# matplotlib can cause problems if it is imported from within a call of +# run_setup(), because in some circumstances it will try to write to the user's +# home directory, resulting in a SandboxViolation. See +# https://github.com/matplotlib/matplotlib/pull/4165 +# Making sure matplotlib, if it is available, is imported early in the setup +# process can mitigate this (note importing matplotlib.pyplot has the same +# issue) +try: + import matplotlib + matplotlib.use('Agg') + import matplotlib.pyplot +except: + # Ignore if this fails for *any* reason* + pass + + +# End compatibility imports... + + +# In case it didn't successfully import before the ez_setup checks +import pkg_resources + +from setuptools import Distribution +from setuptools.package_index import PackageIndex +from setuptools.sandbox import run_setup + +from distutils import log +from distutils.debug import DEBUG + + +# TODO: Maybe enable checking for a specific version of astropy_helpers? +DIST_NAME = 'astropy-helpers' +PACKAGE_NAME = 'astropy_helpers' + +# Defaults for other options +DOWNLOAD_IF_NEEDED = True +INDEX_URL = 'https://pypi.python.org/simple' +USE_GIT = True +OFFLINE = False +AUTO_UPGRADE = True + +# A list of all the configuration options and their required types +CFG_OPTIONS = [ + ('auto_use', bool), ('path', str), ('download_if_needed', bool), + ('index_url', str), ('use_git', bool), ('offline', bool), + ('auto_upgrade', bool) +] + + +class _Bootstrapper(object): + """ + Bootstrapper implementation. See ``use_astropy_helpers`` for parameter + documentation. + """ + + def __init__(self, path=None, index_url=None, use_git=None, offline=None, + download_if_needed=None, auto_upgrade=None): + + if path is None: + path = PACKAGE_NAME + + if not (isinstance(path, _str_types) or path is False): + raise TypeError('path must be a string or False') + + if PY3 and not isinstance(path, _text_type): + fs_encoding = sys.getfilesystemencoding() + path = path.decode(fs_encoding) # path to unicode + + self.path = path + + # Set other option attributes, using defaults where necessary + self.index_url = index_url if index_url is not None else INDEX_URL + self.offline = offline if offline is not None else OFFLINE + + # If offline=True, override download and auto-upgrade + if self.offline: + download_if_needed = False + auto_upgrade = False + + self.download = (download_if_needed + if download_if_needed is not None + else DOWNLOAD_IF_NEEDED) + self.auto_upgrade = (auto_upgrade + if auto_upgrade is not None else AUTO_UPGRADE) + + # If this is a release then the .git directory will not exist so we + # should not use git. + git_dir_exists = os.path.exists(os.path.join(os.path.dirname(__file__), '.git')) + if use_git is None and not git_dir_exists: + use_git = False + + self.use_git = use_git if use_git is not None else USE_GIT + # Declared as False by default--later we check if astropy-helpers can be + # upgraded from PyPI, but only if not using a source distribution (as in + # the case of import from a git submodule) + self.is_submodule = False + + @classmethod + def main(cls, argv=None): + if argv is None: + argv = sys.argv + + config = cls.parse_config() + config.update(cls.parse_command_line(argv)) + + auto_use = config.pop('auto_use', False) + bootstrapper = cls(**config) + + if auto_use: + # Run the bootstrapper, otherwise the setup.py is using the old + # use_astropy_helpers() interface, in which case it will run the + # bootstrapper manually after reconfiguring it. + bootstrapper.run() + + return bootstrapper + + @classmethod + def parse_config(cls): + if not os.path.exists('setup.cfg'): + return {} + + cfg = ConfigParser() + + try: + cfg.read('setup.cfg') + except Exception as e: + if DEBUG: + raise + + log.error( + "Error reading setup.cfg: {0!r}\n{1} will not be " + "automatically bootstrapped and package installation may fail." + "\n{2}".format(e, PACKAGE_NAME, _err_help_msg)) + return {} + + if not cfg.has_section('ah_bootstrap'): + return {} + + config = {} + + for option, type_ in CFG_OPTIONS: + if not cfg.has_option('ah_bootstrap', option): + continue + + if type_ is bool: + value = cfg.getboolean('ah_bootstrap', option) + else: + value = cfg.get('ah_bootstrap', option) + + config[option] = value + + return config + + @classmethod + def parse_command_line(cls, argv=None): + if argv is None: + argv = sys.argv + + config = {} + + # For now we just pop recognized ah_bootstrap options out of the + # arg list. This is imperfect; in the unlikely case that a setup.py + # custom command or even custom Distribution class defines an argument + # of the same name then we will break that. However there's a catch22 + # here that we can't just do full argument parsing right here, because + # we don't yet know *how* to parse all possible command-line arguments. + if '--no-git' in argv: + config['use_git'] = False + argv.remove('--no-git') + + if '--offline' in argv: + config['offline'] = True + argv.remove('--offline') + + return config + + def run(self): + strategies = ['local_directory', 'local_file', 'index'] + dist = None + + # First, remove any previously imported versions of astropy_helpers; + # this is necessary for nested installs where one package's installer + # is installing another package via setuptools.sandbox.run_setup, as in + # the case of setup_requires + for key in list(sys.modules): + try: + if key == PACKAGE_NAME or key.startswith(PACKAGE_NAME + '.'): + del sys.modules[key] + except AttributeError: + # Sometimes mysterious non-string things can turn up in + # sys.modules + continue + + # Check to see if the path is a submodule + self.is_submodule = self._check_submodule() + + for strategy in strategies: + method = getattr(self, 'get_{0}_dist'.format(strategy)) + dist = method() + if dist is not None: + break + else: + raise _AHBootstrapSystemExit( + "No source found for the {0!r} package; {0} must be " + "available and importable as a prerequisite to building " + "or installing this package.".format(PACKAGE_NAME)) + + # This is a bit hacky, but if astropy_helpers was loaded from a + # directory/submodule its Distribution object gets a "precedence" of + # "DEVELOP_DIST". However, in other cases it gets a precedence of + # "EGG_DIST". However, when activing the distribution it will only be + # placed early on sys.path if it is treated as an EGG_DIST, so always + # do that + dist = dist.clone(precedence=pkg_resources.EGG_DIST) + + # Otherwise we found a version of astropy-helpers, so we're done + # Just active the found distribution on sys.path--if we did a + # download this usually happens automatically but it doesn't hurt to + # do it again + # Note: Adding the dist to the global working set also activates it + # (makes it importable on sys.path) by default. + + try: + pkg_resources.working_set.add(dist, replace=True) + except TypeError: + # Some (much) older versions of setuptools do not have the + # replace=True option here. These versions are old enough that all + # bets may be off anyways, but it's easy enough to work around just + # in case... + if dist.key in pkg_resources.working_set.by_key: + del pkg_resources.working_set.by_key[dist.key] + pkg_resources.working_set.add(dist) + + @property + def config(self): + """ + A `dict` containing the options this `_Bootstrapper` was configured + with. + """ + + return dict((optname, getattr(self, optname)) + for optname, _ in CFG_OPTIONS if hasattr(self, optname)) + + def get_local_directory_dist(self): + """ + Handle importing a vendored package from a subdirectory of the source + distribution. + """ + + if not os.path.isdir(self.path): + return + + log.info('Attempting to import astropy_helpers from {0} {1!r}'.format( + 'submodule' if self.is_submodule else 'directory', + self.path)) + + dist = self._directory_import() + + if dist is None: + log.warn( + 'The requested path {0!r} for importing {1} does not ' + 'exist, or does not contain a copy of the {1} ' + 'package.'.format(self.path, PACKAGE_NAME)) + elif self.auto_upgrade and not self.is_submodule: + # A version of astropy-helpers was found on the available path, but + # check to see if a bugfix release is available on PyPI + upgrade = self._do_upgrade(dist) + if upgrade is not None: + dist = upgrade + + return dist + + def get_local_file_dist(self): + """ + Handle importing from a source archive; this also uses setup_requires + but points easy_install directly to the source archive. + """ + + if not os.path.isfile(self.path): + return + + log.info('Attempting to unpack and import astropy_helpers from ' + '{0!r}'.format(self.path)) + + try: + dist = self._do_download(find_links=[self.path]) + except Exception as e: + if DEBUG: + raise + + log.warn( + 'Failed to import {0} from the specified archive {1!r}: ' + '{2}'.format(PACKAGE_NAME, self.path, str(e))) + dist = None + + if dist is not None and self.auto_upgrade: + # A version of astropy-helpers was found on the available path, but + # check to see if a bugfix release is available on PyPI + upgrade = self._do_upgrade(dist) + if upgrade is not None: + dist = upgrade + + return dist + + def get_index_dist(self): + if not self.download: + log.warn('Downloading {0!r} disabled.'.format(DIST_NAME)) + return None + + log.warn( + "Downloading {0!r}; run setup.py with the --offline option to " + "force offline installation.".format(DIST_NAME)) + + try: + dist = self._do_download() + except Exception as e: + if DEBUG: + raise + log.warn( + 'Failed to download and/or install {0!r} from {1!r}:\n' + '{2}'.format(DIST_NAME, self.index_url, str(e))) + dist = None + + # No need to run auto-upgrade here since we've already presumably + # gotten the most up-to-date version from the package index + return dist + + def _directory_import(self): + """ + Import astropy_helpers from the given path, which will be added to + sys.path. + + Must return True if the import succeeded, and False otherwise. + """ + + # Return True on success, False on failure but download is allowed, and + # otherwise raise SystemExit + path = os.path.abspath(self.path) + + # Use an empty WorkingSet rather than the man + # pkg_resources.working_set, since on older versions of setuptools this + # will invoke a VersionConflict when trying to install an upgrade + ws = pkg_resources.WorkingSet([]) + ws.add_entry(path) + dist = ws.by_key.get(DIST_NAME) + + if dist is None: + # We didn't find an egg-info/dist-info in the given path, but if a + # setup.py exists we can generate it + setup_py = os.path.join(path, 'setup.py') + if os.path.isfile(setup_py): + with _silence(): + run_setup(os.path.join(path, 'setup.py'), + ['egg_info']) + + for dist in pkg_resources.find_distributions(path, True): + # There should be only one... + return dist + + return dist + + def _do_download(self, version='', find_links=None): + if find_links: + allow_hosts = '' + index_url = None + else: + allow_hosts = None + index_url = self.index_url + + # Annoyingly, setuptools will not handle other arguments to + # Distribution (such as options) before handling setup_requires, so it + # is not straightforward to programmatically augment the arguments which + # are passed to easy_install + class _Distribution(Distribution): + def get_option_dict(self, command_name): + opts = Distribution.get_option_dict(self, command_name) + if command_name == 'easy_install': + if find_links is not None: + opts['find_links'] = ('setup script', find_links) + if index_url is not None: + opts['index_url'] = ('setup script', index_url) + if allow_hosts is not None: + opts['allow_hosts'] = ('setup script', allow_hosts) + return opts + + if version: + req = '{0}=={1}'.format(DIST_NAME, version) + else: + req = DIST_NAME + + attrs = {'setup_requires': [req]} + + try: + if DEBUG: + _Distribution(attrs=attrs) + else: + with _silence(): + _Distribution(attrs=attrs) + + # If the setup_requires succeeded it will have added the new dist to + # the main working_set + return pkg_resources.working_set.by_key.get(DIST_NAME) + except Exception as e: + if DEBUG: + raise + + msg = 'Error retrieving {0} from {1}:\n{2}' + if find_links: + source = find_links[0] + elif index_url != INDEX_URL: + source = index_url + else: + source = 'PyPI' + + raise Exception(msg.format(DIST_NAME, source, repr(e))) + + def _do_upgrade(self, dist): + # Build up a requirement for a higher bugfix release but a lower minor + # release (so API compatibility is guaranteed) + next_version = _next_version(dist.parsed_version) + + req = pkg_resources.Requirement.parse( + '{0}>{1},<{2}'.format(DIST_NAME, dist.version, next_version)) + + package_index = PackageIndex(index_url=self.index_url) + + upgrade = package_index.obtain(req) + + if upgrade is not None: + return self._do_download(version=upgrade.version) + + def _check_submodule(self): + """ + Check if the given path is a git submodule. + + See the docstrings for ``_check_submodule_using_git`` and + ``_check_submodule_no_git`` for further details. + """ + + if (self.path is None or + (os.path.exists(self.path) and not os.path.isdir(self.path))): + return False + + if self.use_git: + return self._check_submodule_using_git() + else: + return self._check_submodule_no_git() + + def _check_submodule_using_git(self): + """ + Check if the given path is a git submodule. If so, attempt to initialize + and/or update the submodule if needed. + + This function makes calls to the ``git`` command in subprocesses. The + ``_check_submodule_no_git`` option uses pure Python to check if the given + path looks like a git submodule, but it cannot perform updates. + """ + + cmd = ['git', 'submodule', 'status', '--', self.path] + + try: + log.info('Running `{0}`; use the --no-git option to disable git ' + 'commands'.format(' '.join(cmd))) + returncode, stdout, stderr = run_cmd(cmd) + except _CommandNotFound: + # The git command simply wasn't found; this is most likely the + # case on user systems that don't have git and are simply + # trying to install the package from PyPI or a source + # distribution. Silently ignore this case and simply don't try + # to use submodules + return False + + stderr = stderr.strip() + + if returncode != 0 and stderr: + # Unfortunately the return code alone cannot be relied on, as + # earlier versions of git returned 0 even if the requested submodule + # does not exist + + # This is a warning that occurs in perl (from running git submodule) + # which only occurs with a malformatted locale setting which can + # happen sometimes on OSX. See again + # https://github.com/astropy/astropy/issues/2749 + perl_warning = ('perl: warning: Falling back to the standard locale ' + '("C").') + if not stderr.strip().endswith(perl_warning): + # Some other unknown error condition occurred + log.warn('git submodule command failed ' + 'unexpectedly:\n{0}'.format(stderr)) + return False + + # Output of `git submodule status` is as follows: + # + # 1: Status indicator: '-' for submodule is uninitialized, '+' if + # submodule is initialized but is not at the commit currently indicated + # in .gitmodules (and thus needs to be updated), or 'U' if the + # submodule is in an unstable state (i.e. has merge conflicts) + # + # 2. SHA-1 hash of the current commit of the submodule (we don't really + # need this information but it's useful for checking that the output is + # correct) + # + # 3. The output of `git describe` for the submodule's current commit + # hash (this includes for example what branches the commit is on) but + # only if the submodule is initialized. We ignore this information for + # now + _git_submodule_status_re = re.compile( + '^(?P[+-U ])(?P[0-9a-f]{40}) ' + '(?P\S+)( .*)?$') + + # The stdout should only contain one line--the status of the + # requested submodule + m = _git_submodule_status_re.match(stdout) + if m: + # Yes, the path *is* a git submodule + self._update_submodule(m.group('submodule'), m.group('status')) + return True + else: + log.warn( + 'Unexpected output from `git submodule status`:\n{0}\n' + 'Will attempt import from {1!r} regardless.'.format( + stdout, self.path)) + return False + + def _check_submodule_no_git(self): + """ + Like ``_check_submodule_using_git``, but simply parses the .gitmodules file + to determine if the supplied path is a git submodule, and does not exec any + subprocesses. + + This can only determine if a path is a submodule--it does not perform + updates, etc. This function may need to be updated if the format of the + .gitmodules file is changed between git versions. + """ + + gitmodules_path = os.path.abspath('.gitmodules') + + if not os.path.isfile(gitmodules_path): + return False + + # This is a minimal reader for gitconfig-style files. It handles a few of + # the quirks that make gitconfig files incompatible with ConfigParser-style + # files, but does not support the full gitconfig syntax (just enough + # needed to read a .gitmodules file). + gitmodules_fileobj = io.StringIO() + + # Must use io.open for cross-Python-compatible behavior wrt unicode + with io.open(gitmodules_path) as f: + for line in f: + # gitconfig files are more flexible with leading whitespace; just + # go ahead and remove it + line = line.lstrip() + + # comments can start with either # or ; + if line and line[0] in (':', ';'): + continue + + gitmodules_fileobj.write(line) + + gitmodules_fileobj.seek(0) + + cfg = RawConfigParser() + + try: + cfg.readfp(gitmodules_fileobj) + except Exception as exc: + log.warn('Malformatted .gitmodules file: {0}\n' + '{1} cannot be assumed to be a git submodule.'.format( + exc, self.path)) + return False + + for section in cfg.sections(): + if not cfg.has_option(section, 'path'): + continue + + submodule_path = cfg.get(section, 'path').rstrip(os.sep) + + if submodule_path == self.path.rstrip(os.sep): + return True + + return False + + def _update_submodule(self, submodule, status): + if status == ' ': + # The submodule is up to date; no action necessary + return + elif status == '-': + if self.offline: + raise _AHBootstrapSystemExit( + "Cannot initialize the {0} submodule in --offline mode; " + "this requires being able to clone the submodule from an " + "online repository.".format(submodule)) + cmd = ['update', '--init'] + action = 'Initializing' + elif status == '+': + cmd = ['update'] + action = 'Updating' + if self.offline: + cmd.append('--no-fetch') + elif status == 'U': + raise _AHBoostrapSystemExit( + 'Error: Submodule {0} contains unresolved merge conflicts. ' + 'Please complete or abandon any changes in the submodule so that ' + 'it is in a usable state, then try again.'.format(submodule)) + else: + log.warn('Unknown status {0!r} for git submodule {1!r}. Will ' + 'attempt to use the submodule as-is, but try to ensure ' + 'that the submodule is in a clean state and contains no ' + 'conflicts or errors.\n{2}'.format(status, submodule, + _err_help_msg)) + return + + err_msg = None + cmd = ['git', 'submodule'] + cmd + ['--', submodule] + log.warn('{0} {1} submodule with: `{2}`'.format( + action, submodule, ' '.join(cmd))) + + try: + log.info('Running `{0}`; use the --no-git option to disable git ' + 'commands'.format(' '.join(cmd))) + returncode, stdout, stderr = run_cmd(cmd) + except OSError as e: + err_msg = str(e) + else: + if returncode != 0: + err_msg = stderr + + if err_msg is not None: + log.warn('An unexpected error occurred updating the git submodule ' + '{0!r}:\n{1}\n{2}'.format(submodule, err_msg, + _err_help_msg)) + +class _CommandNotFound(OSError): + """ + An exception raised when a command run with run_cmd is not found on the + system. + """ + + +def run_cmd(cmd): + """ + Run a command in a subprocess, given as a list of command-line + arguments. + + Returns a ``(returncode, stdout, stderr)`` tuple. + """ + + try: + p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) + # XXX: May block if either stdout or stderr fill their buffers; + # however for the commands this is currently used for that is + # unlikely (they should have very brief output) + stdout, stderr = p.communicate() + except OSError as e: + if DEBUG: + raise + + if e.errno == errno.ENOENT: + msg = 'Command not found: `{0}`'.format(' '.join(cmd)) + raise _CommandNotFound(msg, cmd) + else: + raise _AHBoostrapSystemExit( + 'An unexpected error occurred when running the ' + '`{0}` command:\n{1}'.format(' '.join(cmd), str(e))) + + + # Can fail of the default locale is not configured properly. See + # https://github.com/astropy/astropy/issues/2749. For the purposes under + # consideration 'latin1' is an acceptable fallback. + try: + stdio_encoding = locale.getdefaultlocale()[1] or 'latin1' + except ValueError: + # Due to an OSX oddity locale.getdefaultlocale() can also crash + # depending on the user's locale/language settings. See: + # http://bugs.python.org/issue18378 + stdio_encoding = 'latin1' + + # Unlikely to fail at this point but even then let's be flexible + if not isinstance(stdout, _text_type): + stdout = stdout.decode(stdio_encoding, 'replace') + if not isinstance(stderr, _text_type): + stderr = stderr.decode(stdio_encoding, 'replace') + + return (p.returncode, stdout, stderr) + + +def _next_version(version): + """ + Given a parsed version from pkg_resources.parse_version, returns a new + version string with the next minor version. + + Examples + ======== + >>> _next_version(pkg_resources.parse_version('1.2.3')) + '1.3.0' + """ + + if hasattr(version, 'base_version'): + # New version parsing from setuptools >= 8.0 + if version.base_version: + parts = version.base_version.split('.') + else: + parts = [] + else: + parts = [] + for part in version: + if part.startswith('*'): + break + parts.append(part) + + parts = [int(p) for p in parts] + + if len(parts) < 3: + parts += [0] * (3 - len(parts)) + + major, minor, micro = parts[:3] + + return '{0}.{1}.{2}'.format(major, minor + 1, 0) + + +class _DummyFile(object): + """A noop writeable object.""" + + errors = '' # Required for Python 3.x + encoding = 'utf-8' + + def write(self, s): + pass + + def flush(self): + pass + + +@contextlib.contextmanager +def _silence(): + """A context manager that silences sys.stdout and sys.stderr.""" + + old_stdout = sys.stdout + old_stderr = sys.stderr + sys.stdout = _DummyFile() + sys.stderr = _DummyFile() + exception_occurred = False + try: + yield + except: + exception_occurred = True + # Go ahead and clean up so that exception handling can work normally + sys.stdout = old_stdout + sys.stderr = old_stderr + raise + + if not exception_occurred: + sys.stdout = old_stdout + sys.stderr = old_stderr + + +_err_help_msg = """ +If the problem persists consider installing astropy_helpers manually using pip +(`pip install astropy_helpers`) or by manually downloading the source archive, +extracting it, and installing by running `python setup.py install` from the +root of the extracted source code. +""" + + +class _AHBootstrapSystemExit(SystemExit): + def __init__(self, *args): + if not args: + msg = 'An unknown problem occurred bootstrapping astropy_helpers.' + else: + msg = args[0] + + msg += '\n' + _err_help_msg + + super(_AHBootstrapSystemExit, self).__init__(msg, *args[1:]) + + +if sys.version_info[:2] < (2, 7): + # In Python 2.6 the distutils log does not log warnings, errors, etc. to + # stderr so we have to wrap it to ensure consistency at least in this + # module + import distutils + + class log(object): + def __getattr__(self, attr): + return getattr(distutils.log, attr) + + def warn(self, msg, *args): + self._log_to_stderr(distutils.log.WARN, msg, *args) + + def error(self, msg): + self._log_to_stderr(distutils.log.ERROR, msg, *args) + + def fatal(self, msg): + self._log_to_stderr(distutils.log.FATAL, msg, *args) + + def log(self, level, msg, *args): + if level in (distutils.log.WARN, distutils.log.ERROR, + distutils.log.FATAL): + self._log_to_stderr(level, msg, *args) + else: + distutils.log.log(level, msg, *args) + + def _log_to_stderr(self, level, msg, *args): + # This is the only truly 'public' way to get the current threshold + # of the log + current_threshold = distutils.log.set_threshold(distutils.log.WARN) + distutils.log.set_threshold(current_threshold) + if level >= current_threshold: + if args: + msg = msg % args + sys.stderr.write('%s\n' % msg) + sys.stderr.flush() + + log = log() + + +BOOTSTRAPPER = _Bootstrapper.main() + + +def use_astropy_helpers(**kwargs): + """ + Ensure that the `astropy_helpers` module is available and is importable. + This supports automatic submodule initialization if astropy_helpers is + included in a project as a git submodule, or will download it from PyPI if + necessary. + + Parameters + ---------- + + path : str or None, optional + A filesystem path relative to the root of the project's source code + that should be added to `sys.path` so that `astropy_helpers` can be + imported from that path. + + If the path is a git submodule it will automatically be initialized + and/or updated. + + The path may also be to a ``.tar.gz`` archive of the astropy_helpers + source distribution. In this case the archive is automatically + unpacked and made temporarily available on `sys.path` as a ``.egg`` + archive. + + If `None` skip straight to downloading. + + download_if_needed : bool, optional + If the provided filesystem path is not found an attempt will be made to + download astropy_helpers from PyPI. It will then be made temporarily + available on `sys.path` as a ``.egg`` archive (using the + ``setup_requires`` feature of setuptools. If the ``--offline`` option + is given at the command line the value of this argument is overridden + to `False`. + + index_url : str, optional + If provided, use a different URL for the Python package index than the + main PyPI server. + + use_git : bool, optional + If `False` no git commands will be used--this effectively disables + support for git submodules. If the ``--no-git`` option is given at the + command line the value of this argument is overridden to `False`. + + auto_upgrade : bool, optional + By default, when installing a package from a non-development source + distribution ah_boostrap will try to automatically check for patch + releases to astropy-helpers on PyPI and use the patched version over + any bundled versions. Setting this to `False` will disable that + functionality. If the ``--offline`` option is given at the command line + the value of this argument is overridden to `False`. + + offline : bool, optional + If `False` disable all actions that require an internet connection, + including downloading packages from the package index and fetching + updates to any git submodule. Defaults to `True`. + """ + + global BOOTSTRAPPER + + config = BOOTSTRAPPER.config + config.update(**kwargs) + + # Create a new bootstrapper with the updated configuration and run it + BOOTSTRAPPER = _Bootstrapper(**config) + BOOTSTRAPPER.run() diff --git a/caom2repo/caom2repo/__init__.py b/caom2repo/caom2repo/__init__.py new file mode 100755 index 00000000..e7095e0b --- /dev/null +++ b/caom2repo/caom2repo/__init__.py @@ -0,0 +1,16 @@ + +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +""" +This is an Astropy affiliated package. +""" + +# Affiliated packages may add whatever they like to this file, but +# should keep this content at the top. +# ---------------------------------------------------------------------------- +from ._astropy_init import * +# ---------------------------------------------------------------------------- + +# For egg_info test builds to pass, put package imports here. +#if not _ASTROPY_SETUP_: +# from .caom2repo import * \ No newline at end of file diff --git a/caom2repo/caom2repo/_astropy_init.py b/caom2repo/caom2repo/_astropy_init.py new file mode 100644 index 00000000..6d94a38b --- /dev/null +++ b/caom2repo/caom2repo/_astropy_init.py @@ -0,0 +1,138 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +__all__ = ['__version__', '__githash__', 'test'] + +# this indicates whether or not we are in the package's setup.py +try: + _ASTROPY_SETUP_ +except NameError: + from sys import version_info + if version_info[0] >= 3: + import builtins + else: + import __builtin__ as builtins + builtins._ASTROPY_SETUP_ = False + +try: + from .version import version as __version__ +except ImportError: + __version__ = '' +try: + from .version import githash as __githash__ +except ImportError: + __githash__ = '' + +# set up the test command +def _get_test_runner(): + import os + from astropy.tests.helper import TestRunner + return TestRunner(os.path.dirname(__file__)) + +def test(package=None, test_path=None, args=None, plugins=None, + verbose=False, pastebin=None, remote_data=False, pep8=False, + pdb=False, coverage=False, open_files=False, **kwargs): + """ + Run the tests using `py.test `__. A proper set + of arguments is constructed and passed to `pytest.main`_. + + .. _py.test: http://pytest.org/latest/ + .. _pytest.main: http://pytest.org/latest/builtin.html#pytest.main + + Parameters + ---------- + package : str, optional + The name of a specific package to test, e.g. 'io.fits' or 'utils'. + If nothing is specified all default tests are run. + + test_path : str, optional + Specify location to test by path. May be a single file or + directory. Must be specified absolutely or relative to the + calling directory. + + args : str, optional + Additional arguments to be passed to pytest.main_ in the ``args`` + keyword argument. + + plugins : list, optional + Plugins to be passed to pytest.main_ in the ``plugins`` keyword + argument. + + verbose : bool, optional + Convenience option to turn on verbose output from py.test_. Passing + True is the same as specifying ``'-v'`` in ``args``. + + pastebin : {'failed','all',None}, optional + Convenience option for turning on py.test_ pastebin output. Set to + ``'failed'`` to upload info for failed tests, or ``'all'`` to upload + info for all tests. + + remote_data : bool, optional + Controls whether to run tests marked with @remote_data. These + tests use online data and are not run by default. Set to True to + run these tests. + + pep8 : bool, optional + Turn on PEP8 checking via the `pytest-pep8 plugin + `_ and disable normal + tests. Same as specifying ``'--pep8 -k pep8'`` in ``args``. + + pdb : bool, optional + Turn on PDB post-mortem analysis for failing tests. Same as + specifying ``'--pdb'`` in ``args``. + + coverage : bool, optional + Generate a test coverage report. The result will be placed in + the directory htmlcov. + + open_files : bool, optional + Fail when any tests leave files open. Off by default, because + this adds extra run time to the test suite. Requires the + `psutil `_ package. + + parallel : int, optional + When provided, run the tests in parallel on the specified + number of CPUs. If parallel is negative, it will use the all + the cores on the machine. Requires the + `pytest-xdist `_ plugin + installed. Only available when using Astropy 0.3 or later. + + kwargs + Any additional keywords passed into this function will be passed + on to the astropy test runner. This allows use of test-related + functionality implemented in later versions of astropy without + explicitly updating the package template. + + """ + test_runner = _get_test_runner() + return test_runner.run_tests( + package=package, test_path=test_path, args=args, + plugins=plugins, verbose=verbose, pastebin=pastebin, + remote_data=remote_data, pep8=pep8, pdb=pdb, + coverage=coverage, open_files=open_files, **kwargs) + +if not _ASTROPY_SETUP_: + import os + from warnings import warn + from astropy import config + + # add these here so we only need to cleanup the namespace at the end + config_dir = None + + if not os.environ.get('ASTROPY_SKIP_CONFIG_UPDATE', False): + config_dir = os.path.dirname(__file__) + config_template = os.path.join(config_dir, __package__ + ".cfg") + if os.path.isfile(config_template): + try: + config.configuration.update_default_config( + __package__, config_dir, version=__version__) + except TypeError as orig_error: + try: + config.configuration.update_default_config( + __package__, config_dir) + except config.configuration.ConfigurationDefaultMissingError as e: + wmsg = (e.args[0] + " Cannot install default profile. If you are " + "importing from source, this is expected.") + warn(config.configuration.ConfigurationDefaultMissingWarning(wmsg)) + del e + except: + raise orig_error diff --git a/caom2repo/caom2repo/conftest.py b/caom2repo/caom2repo/conftest.py new file mode 100644 index 00000000..829ba1d7 --- /dev/null +++ b/caom2repo/caom2repo/conftest.py @@ -0,0 +1,38 @@ +# this contains imports plugins that configure py.test for astropy tests. +# by importing them here in conftest.py they are discoverable by py.test +# no matter how it is invoked within the source tree. + +from astropy.tests.pytest_plugins import * + +## Uncomment the following line to treat all DeprecationWarnings as +## exceptions +# enable_deprecations_as_exceptions() + +## Uncomment and customize the following lines to add/remove entries from +## the list of packages for which version numbers are displayed when running +## the tests. Making it pass for KeyError is essential in some cases when +## the package uses other astropy affiliated packages. +# try: +# PYTEST_HEADER_MODULES['Astropy'] = 'astropy' +# PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' +# del PYTEST_HEADER_MODULES['h5py'] +# except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 +# pass + +## Uncomment the following lines to display the version number of the +## package rather than the version number of Astropy in the top line when +## running the tests. +# import os +# +# # This is to figure out the affiliated package version, rather than +# # using Astropy's +# try: +# from .version import version +# except ImportError: +# version = 'dev' +# +# try: +# packagename = os.path.basename(os.path.dirname(__file__)) +# TESTED_VERSIONS[packagename] = version +# except NameError: # Needed to support Astropy <= 1.0.0 +# pass diff --git a/caom2repo/caom2repo/core.py b/caom2repo/caom2repo/core.py new file mode 100755 index 00000000..26b2679c --- /dev/null +++ b/caom2repo/caom2repo/core.py @@ -0,0 +1,382 @@ +## -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2016. (c) 2016. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# +from __future__ import (absolute_import, division, print_function, + unicode_literals) +from datetime import datetime +import logging +import argparse +import imp +import os +import sys +import os.path +#TODO to be changed to io.StringIO when caom2 is prepared for python3 +from StringIO import StringIO +from cadcutils import net +from cadcutils import util + +from caom2.obs_reader_writer import ObservationReader, ObservationWriter + +__all__ = ['CAOM2RepoClient'] + +BATCH_SIZE = int(10000) +SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/' #TODO replace with SERVICE_URI when server supports it +DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" #IVOA dateformat +SERVICE = 'caom2repo' + +class CAOM2RepoClient: + + """Class to do CRUD + visitor actions on a CAOM2 collection repo.""" + + def __init__(self, anon=True, cert_file=None, server=None): + """ + Instance of a CAOM2RepoClient + :param anon: True if anonymous access, False otherwise + :param cert_file: Location of X509 certificate used for authentication + :param server: Host server for the caom2repo service + """ + + # repo client to use + s = SERVICE_URL + if server is not None: + s = server + if not s.endswith('/'): + s = s + "/" + agent = 'CAOM2RepoClient' #TODO add version + self._repo_client = net.BaseWsClient(s + SERVICE, anon=anon, cert_file=cert_file, agent=agent, retry=True) + logging.info('Service URL: {}'.format(self._repo_client.base_url)) + + + def visit(self, plugin, collection, start=None, end=None): + """ + Main processing function that iterates through the observations of + the collection and updates them according to the algorithm + of the plugin function + :param plugin: path to python file that contains the algorithm to be applied to visited + observations + :param collection: name of the CAOM2 collection + :param start: optional earliest date-time of the targeted observation set + :param end: optional latest date-time of the targeted observation set + :return: number of visited observations + """ + if not os.path.isfile(plugin): + raise Exception('Cannot find plugin file ' + plugin) + assert collection is not None + if start is not None: + assert type(start) is datetime + if end is not None: + assert type(end) is datetime + self._load_plugin_class(plugin) + self._start = start # this is updated by _get_observations with the timestamp of last observation in the batch + count = 0 + observations = self._get_observations(collection, self._start, end) + while len(observations) > 0: + for observationID in observations: + observation = self.get_observation(collection, observationID) + logging.info("Process observation: " + observation.observation_id) + self.plugin.update(observation) + self.post_observation(observation) + count += 1 + if len(observations) == BATCH_SIZE: + observations = self._get_observations(collection) + else: + # the last batch was smaller so it must have been the last + break + return count + + def _get_observations(self, collection, start=None, end=None): + """ + Returns a list of datasets from the collection + :param collection: name of the collection + :param start: earliest observation + :param end: latest observation + :return: + """ + assert collection is not None + observations = [] + params = {'MAXREC':BATCH_SIZE} + if start is not None: + params['START'] = start.strftime(DATE_FORMAT) + if end is not None: + params['END'] = end.strftime(DATE_FORMAT) + + response = self._repo_client.get(collection, params=params) + last_datetime = None + for line in response.content.splitlines(): + (obs, last_datetime) = line.split(',') + observations.append(obs) + if last_datetime is not None: + self._start = datetime.strptime(last_datetime, DATE_FORMAT) + return observations + + + def _load_plugin_class(self, filepath): + """ + Loads the plugin method and sets the self.plugin to refer to it. + :param filepath: path to the file containing the python function + """ + expected_class = 'ObservationUpdater' + + mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1]) + + if file_ext.lower() == '.pyc': + py_mod = imp.load_compiled(mod_name, filepath) + else: + py_mod = imp.load_source(mod_name, filepath) + + if hasattr(py_mod, expected_class): + self.plugin = getattr(py_mod, expected_class)() + else: + raise Exception( + 'Cannot find ObservationUpdater class in pluging file ' + filepath) + + if not hasattr(self.plugin, 'update'): + raise Exception('Cannot find update method in plugin class ' +\ + filepath) + + + def get_observation(self, collection, observationID): + """ + Get an observation from the CAOM2 repo + :param collection: name of the collection + :param observationID: the ID of the observation + :return: the caom2.observation.Observation object + """ + assert collection is not None + assert observationID is not None + resource = '/{}/{}'.format(collection, observationID) + logging.debug('GET '.format(resource)) + + response = self._repo_client.get(resource) + obs_reader = ObservationReader() + content = response.content + if len(content) == 0: + logging.error(response.status_code) + response.close() + raise Exception('Got empty response for resource: {}'.format(resource)) + return obs_reader.read(StringIO(content)) + + + def post_observation(self, observation): + """ + Updates an observation in the CAOM2 repo + :param observation: observation to update + :return: updated observation + """ + assert observation.collection is not None + assert observation.observation_id is not None + resource = '/{}/{}'.format(observation.collection, observation.observation_id) + logging.debug('POST {}'.format(resource)) + + ibuffer = StringIO() + ObservationWriter().write(observation, ibuffer) + obs_xml = ibuffer.getvalue() + headers = {'Content-Type': 'application/xml'} + response = self._repo_client.post( + resource, headers=headers, data=obs_xml) + logging.debug('Successfully updated Observation\n') + + + def put_observation(self, observation): + """ + Add an observation to the CAOM2 repo + :param observation: observation to add to the CAOM2 repo + :return: Added observation + """ + assert observation.collection is not None + resource = '/{}'.format(observation.collection) + logging.debug('PUT {}'.format(resource)) + + ibuffer = StringIO() + ObservationWriter().write(observation, ibuffer) + obs_xml = ibuffer.getvalue() + headers = {'Content-Type': 'application/xml'} + response = self._repo_client.put( + resource, headers=headers, data=obs_xml) + logging.debug('Successfully put Observation\n') + + + def delete_observation(self, collection, observationID): + """ + Delete an observation from the CAOM2 repo + :param collection: Name of the collection + :param observationID: ID of the observation + """ + assert observationID is not None + resource = '/{}/{}'.format(collection, observationID) + logging.debug('DELETE {}'.format(resource)) + response = self._repo_client.delete(resource) + logging.info('Successfully deleted Observation {}\n') + + +def main(): + + parser = util.BaseParser() + + parser.description = ('Client for a CAOM2 repo. In addition to CRUD (Create, Read, Update and Delete) ' + 'operations it also implements a visitor operation that allows for updating ' + 'multiple observations in a collection') + parser.formatter_class = argparse.RawTextHelpFormatter + + subparsers = parser.add_subparsers(dest='cmd') + create_parser = subparsers.add_parser('create', description='Create a new observation') + create_parser.add_argument('observation', metavar='', type=file) + + read_parser = subparsers.add_parser('read', description='Read an existing observation') + read_parser.add_argument('--collection', metavar='', required=True) + read_parser.add_argument('--output', '-o', metavar='', required=False) + read_parser.add_argument('observation', metavar='') + + update_parser = subparsers.add_parser('update', description='Update an existing observation') + update_parser.add_argument('observation', metavar='', type=file) + + delete_parser = subparsers.add_parser('delete', description='Delete an existing observation') + delete_parser.add_argument('--collection', metavar='', required=True) + delete_parser.add_argument('observationID', metavar='') + + # Note: RawTextHelpFormatter allows for the use of newline in epilog + visit_parser = subparsers.add_parser('visit', formatter_class=argparse.RawTextHelpFormatter, + description='Visit observations in a collection') + visit_parser.add_argument('--plugin', required=True, type=file, + metavar=(''), + help='Pluging class to update each observation') + visit_parser.add_argument('--start', metavar='', + type=util.str2ivoa, + help='oldest dataset to visit (UTC %%Y-%%m-%%d format)') + visit_parser.add_argument('--end', metavar='', + type=util.str2ivoa, + help='earliest dataset to visit (UTC %%Y-%%m-%%d format)') + visit_parser.add_argument('--retries', metavar='', + type=int, + help='number of tries with transient server errors') + visit_parser.add_argument("-s", "--server", metavar=(''), + help="URL of the CAOM2 repo server") + + visit_parser.add_argument('collection', metavar='', type=str, + help='data collection in CAOM2 repo') + visit_parser.epilog =\ +""" +Minimum plugin file format: +---- + from caom2.caom2_observation import Observation + + class ObservationUpdater: + + def update(self, observation): + assert isinstance(observation, Observation), ( + 'observation {} is not an Observation'.format(observation)) + # custom code to update the observation +---- +""" + args = parser.parse_args() + + + if args.verbose: + logging.basicConfig(level=logging.INFO) + + if args.debug: + logging.basicConfig(level=logging.DEBUG) + certfile = None + if os.path.isfile(args.certfile): + certfile = args.certfile + client = CAOM2RepoClient(anon=args.anonymous, cert_file=certfile, server=args.host) + if args.cmd == 'visit': + print ("Visit") + plugin = args.plugin + start = args.start + end = args.end + retries = args.retries + collection = args.collection + logging.debug("Call visitor with plugin={}, start={}, end={}, dataset={}". + format(plugin, start, end, collection, retries)) + client.visit(plugin.name, collection, start=start, end=end) + + elif args.cmd == 'create': + print("Create") + obs_reader = ObservationReader() + client.put_observation(obs_reader.read(args.observation)) + elif args.cmd == 'read': + print("Read") + observation = client.get_observation(args.collection, args.observation) + observation_writer = ObservationWriter() + if args.output: + with open(args.output, 'w') as obsfile: + observation_writer.write(observation, obsfile) + else: + observation_writer.write(observation, sys.stdout) + elif args.cmd == 'update': + print("Update") + obs_reader = ObservationReader() + client.post_observation(obs_reader.read(args.observation)) #TODO not sure if need to read in string first + else: + print("Delete") + client.delete_observation(collection=args.collection, observation=args.observationID) + + print("DONE") + + diff --git a/pyCAOM2/caom2/util/__init__.py b/caom2repo/caom2repo/tests/__init__.py similarity index 99% rename from pyCAOM2/caom2/util/__init__.py rename to caom2repo/caom2repo/tests/__init__.py index cd6c6be3..2a4a293e 100755 --- a/pyCAOM2/caom2/util/__init__.py +++ b/caom2repo/caom2repo/tests/__init__.py @@ -68,4 +68,5 @@ #*********************************************************************** # -""" Defines __init__ """ +""" Deines __init__ """ + diff --git a/caom2repo/caom2repo/tests/addplaneplugin.py b/caom2repo/caom2repo/tests/addplaneplugin.py new file mode 100755 index 00000000..fd3bdaa9 --- /dev/null +++ b/caom2repo/caom2repo/tests/addplaneplugin.py @@ -0,0 +1,85 @@ +# # -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2016. (c) 2016. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +# *********************************************************************** +# +from __future__ import (absolute_import, division, print_function, + unicode_literals) +from caom2.observation import Observation +from caom2.plane import Plane + + +class ObservationUpdater: + + """ObservationUpdater that adds a plane to the observation.""" + + def update(self, observation): + """ + Processes an observation and updates it + """ + assert isinstance(observation, Observation), ( + "observation %s is not an Observation".format(observation)) + observation.planes.add(Plane('PREVIEW')) diff --git a/caom2repo/caom2repo/tests/coveragerc b/caom2repo/caom2repo/tests/coveragerc new file mode 100644 index 00000000..bec7c291 --- /dev/null +++ b/caom2repo/caom2repo/tests/coveragerc @@ -0,0 +1,31 @@ +[run] +source = {packagename} +omit = + {packagename}/_astropy_init* + {packagename}/conftest* + {packagename}/cython_version* + {packagename}/setup_package* + {packagename}/*/setup_package* + {packagename}/*/*/setup_package* + {packagename}/tests/* + {packagename}/*/tests/* + {packagename}/*/*/tests/* + {packagename}/version* + +[report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about packages we have installed + except ImportError + + # Don't complain if tests don't hit assertions + raise AssertionError + raise NotImplementedError + + # Don't complain about script hooks + def main\(.*\): + + # Ignore branches that don't pertain to this version of Python + pragma: py{ignore_python_version} \ No newline at end of file diff --git a/caom2repoClient/scripts/caom2repo.py b/caom2repo/caom2repo/tests/passplugin.py similarity index 91% rename from caom2repoClient/scripts/caom2repo.py rename to caom2repo/caom2repo/tests/passplugin.py index 33fc2054..a7b11f48 100755 --- a/caom2repoClient/scripts/caom2repo.py +++ b/caom2repo/caom2repo/tests/passplugin.py @@ -1,10 +1,9 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# # -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # -# (c) 2010. (c) 2010. +# (c) 2016. (c) 2016. # Government of Canada Gouvernement du Canada # National Research Council Conseil national de recherches # Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 @@ -65,15 +64,21 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # -import caom2repoClient +from caom2.observation import Observation -__author__ = 'jenkinsd' -"""Client script to access the CAOM-2 Observation Repository""" +class ObservationUpdater: + + """Plugin that does not update the observation""" + + def update(self, observation): + """ + Processes an observation and updates it + """ + assert isinstance(observation, Observation), ( + "observation %s is not an Observation".format(observation)) + -if __name__ == '__main__': - client = caom2repoClient.CAOM2RepoClient() - client.main() diff --git a/caom2repo/caom2repo/tests/setup_package.py b/caom2repo/caom2repo/tests/setup_package.py new file mode 100644 index 00000000..6e4be679 --- /dev/null +++ b/caom2repo/caom2repo/tests/setup_package.py @@ -0,0 +1,7 @@ +def get_package_data(): + return { + _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} + + +def requires_2to3(): + return False diff --git a/caom2repo/caom2repo/tests/test_core.py b/caom2repo/caom2repo/tests/test_core.py new file mode 100644 index 00000000..785af5d9 --- /dev/null +++ b/caom2repo/caom2repo/tests/test_core.py @@ -0,0 +1,639 @@ +# # -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2016. (c) 2016. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +# *********************************************************************** +# +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import copy +import os +import sys +import unittest +# TODO to be changed to io.StringIO when caom2 is prepared for python3 +from StringIO import StringIO +from datetime import datetime + +import requests +from cadcutils import util +from caom2.obs_reader_writer import ObservationWriter +from caom2.observation import SimpleObservation +from mock import Mock, patch, MagicMock, ANY + +from caom2repo import core +from caom2repo.core import CAOM2RepoClient, DATE_FORMAT + +THIS_DIR = os.path.dirname(os.path.realpath(__file__)) + + +class MyExitError(Exception): + pass + + +class TestCAOM2Repo(unittest.TestCase): + + """Test the Caom2Visitor class""" + + def test_plugin_class(self): + # plugin class does not change the observation + collection = 'cfht' + observation_id = '7000000o' + visitor = CAOM2RepoClient() + obs = SimpleObservation(collection, observation_id) + expect_obs = copy.deepcopy(obs) + visitor._load_plugin_class(os.path.join(THIS_DIR, 'passplugin.py')) + visitor.plugin.update(obs) + self.assertEquals(expect_obs, obs) + + # plugin class adds a plane to the observation + visitor = CAOM2RepoClient() + obs = SimpleObservation('cfht', '7000000o') + expect_obs = copy.deepcopy(obs) + visitor._load_plugin_class(os.path.join(THIS_DIR, 'addplaneplugin.py')) + visitor.plugin.update(obs) + self.assertNotEquals(expect_obs, obs) + self.assertEquals(len(expect_obs.planes) + 1, len(obs.planes)) + + # non-existent the plugin file + with self.assertRaises(Exception): + visitor._load_plugin_class(os.path.join(THIS_DIR, 'blah.py')) + + # non-existent ObservationUpdater class in the plugin file + with self.assertRaises(Exception): + visitor._load_plugin_class(os.path.join(THIS_DIR, 'test_visitor.py')) + + # non-existent update method in ObservationUpdater class + with self.assertRaises(Exception): + visitor._load_plugin_class(os.path.join(THIS_DIR, 'noupdateplugin.py')) + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.open', MagicMock(), create=True) + @patch('cadcutils.net.ws.Session.send') + def test_get_observation(self, mock_get): + collection = 'cfht' + observation_id = '7000000o' + service_url = 'www.cadc.nrc.ca/caom2repo' + obs = SimpleObservation(collection, observation_id) + writer = ObservationWriter() + ibuffer = StringIO() + writer.write(obs, ibuffer) + response = MagicMock() + response.status_code = 200 + response.content = ibuffer.getvalue() + mock_get.return_value = response + ibuffer.seek(0) # reposition the buffer for reading + visitor = CAOM2RepoClient(server=service_url) + self.assertEquals(obs, visitor.get_observation(collection, observation_id)) + + # signal problems + http_error = requests.HTTPError() + response.status_code = 500 + http_error.response = response + response.raise_for_status.side_effect = [http_error] + with self.assertRaises(requests.HTTPError): + visitor.get_observation(collection, observation_id) + + # temporary transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + response.raise_for_status.side_effect = [http_error, None] + visitor.get_observation(collection, observation_id) + + # permanent transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + + def raise_error(): raise http_error + response.raise_for_status.side_effect = raise_error + with self.assertRaises(requests.HTTPError): + visitor.get_observation(collection, observation_id) + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.open', MagicMock(), create=True) + @patch('caom2repo.core.net.BaseWsClient.get') + def test_get_observations(self, mock_get): + # This is almost similar to the previous test except that it gets + # observations matching a collection and start/end criteria + # Also, patch the CAOM2RepoClient now. + + response = MagicMock() + response.status_code = 200 + last_datetime = '2000-10-10T12:30:00.333' + response.content = '700000o,2000-10-10T12:20:11.123\n700001o,' +\ + last_datetime + mock_get.return_value = response + + visitor = CAOM2RepoClient() + end_date = datetime.strptime(last_datetime, DATE_FORMAT) + + expect_observations = ['700000o', '700001o'] + self.assertEquals(expect_observations, visitor._get_observations('cfht')) + self.assertEquals(end_date, visitor._start) + mock_get.assert_called_once_with('cfht', params={'MAXREC': core.BATCH_SIZE}) + + mock_get.reset_mock() + visitor._get_observations('cfht', end=datetime.strptime('2000-11-11', '%Y-%m-%d')) + mock_get.assert_called_once_with('cfht', params={'END': '2000-11-11T00:00:00.000000', + 'MAXREC': core.BATCH_SIZE}) + + mock_get.reset_mock() + visitor._get_observations('cfht', + start=datetime.strptime('2000-11-11', '%Y-%m-%d'), + end=datetime.strptime('2000-11-12', '%Y-%m-%d')) + mock_get.assert_called_once_with('cfht', params={'START': '2000-11-11T00:00:00.000000', + 'END': '2000-11-12T00:00:00.000000', + 'MAXREC': core.BATCH_SIZE}) + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.auth.get_user_password', Mock(return_value=('usr', 'passwd'))) + @patch('cadcutils.net.ws.Session.send') + def test_post_observation(self, mock_conn): + collection = 'cfht' + observation_id = '7000000o' + service = 'caom2repo' + service_url = 'www.cadc.nrc.ca' + + obs = SimpleObservation(collection, observation_id) + visitor = CAOM2RepoClient(anon=False, server=service_url) + response = MagicMock() + response.status = 200 + mock_conn.return_value = response + iobuffer = StringIO() + ObservationWriter().write(obs, iobuffer) + obsxml = iobuffer.getvalue() + response.content = obsxml + + visitor.post_observation(obs) + self.assertEqual('POST', mock_conn.call_args[0][0].method) + self.assertEqual('/{}/auth/{}/{}'.format(service, collection, observation_id), + mock_conn.call_args[0][0].path_url) + self.assertEqual('application/xml', mock_conn.call_args[0][0].headers['Content-Type']) + self.assertEqual(obsxml, mock_conn.call_args[0][0].body) + + # signal problems + http_error = requests.HTTPError() + response.status_code = 500 + http_error.response = response + response.raise_for_status.side_effect = [http_error] + with self.assertRaises(requests.HTTPError): + visitor.post_observation(obs) + + # temporary transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + response.raise_for_status.side_effect = [http_error, None] + visitor.post_observation(obs) + + # permanent transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + + def raise_error(): raise http_error + response.raise_for_status.side_effect = raise_error + with self.assertRaises(requests.HTTPError): + visitor.post_observation(obs) + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.Session.send') + def test_put_observation(self, mock_conn): + collection = 'cfht' + observation_id = '7000000o' + service = 'caom2repo' + service_url = 'www.cadc.nrc.ca/' + + obs = SimpleObservation(collection, observation_id) + visitor = CAOM2RepoClient(cert_file='somefile.pem', server=service_url) + response = MagicMock() + response.status = 200 + mock_conn.return_value = response + iobuffer = StringIO() + ObservationWriter().write(obs, iobuffer) + obsxml = iobuffer.getvalue() + response.content = obsxml + + visitor.put_observation(obs) + self.assertEqual('PUT', mock_conn.call_args[0][0].method) + self.assertEqual('/{}/{}'.format(service, collection), + mock_conn.call_args[0][0].path_url) + self.assertEqual('application/xml', mock_conn.call_args[0][0].headers['Content-Type']) + self.assertEqual(obsxml, mock_conn.call_args[0][0].body) + + # signal problems + http_error = requests.HTTPError() + response.status_code = 500 + http_error.response = response + response.raise_for_status.side_effect = [http_error] + with self.assertRaises(requests.HTTPError): + visitor.put_observation(obs) + + # temporary transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + response.raise_for_status.side_effect = [http_error, None] + visitor.put_observation(obs) + + # permanent transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + + def raise_error(): raise http_error + + response.raise_for_status.side_effect = raise_error + with self.assertRaises(requests.HTTPError): + visitor.put_observation(obs) + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.Session.send') + def test_delete_observation(self, mock_conn): + collection = 'cfht' + observation_id = '7000000o' + service_url = 'www.cadc.nrc.ca/caom2repo' + + obs = SimpleObservation(collection, observation_id) + visitor = CAOM2RepoClient(server=service_url) + response = MagicMock() + response.status = 200 + mock_conn.return_value = response + + visitor.delete_observation(collection, observation_id) + self.assertEqual('DELETE', mock_conn.call_args[0][0].method) + + # signal problems + http_error = requests.HTTPError() + response.status_code = 500 + http_error.response = response + response.raise_for_status.side_effect = [http_error] + with self.assertRaises(requests.HTTPError): + visitor.delete_observation(collection, observation_id) + + # temporary transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + response.raise_for_status.side_effect = [http_error, None] + visitor.delete_observation(collection, observation_id) + + # permanent transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + + def raise_error(): raise http_error + + response.raise_for_status.side_effect = raise_error + with self.assertRaises(requests.HTTPError): + visitor.delete_observation(collection, observation_id) + + def test_process(self): + core.BATCH_SIZE = 3 # size of the batch is 3 + obs = [['a', 'b', 'c'], ['d'], []] + visitor = CAOM2RepoClient() + visitor.get_observation = MagicMock(return_value=MagicMock(spec=SimpleObservation)) + visitor.post_observation = MagicMock() + visitor._get_observations = MagicMock(side_effect=obs) + + self.assertEquals(4, visitor.visit(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht')) + + obs = [['a', 'b', 'c'], ['d', 'e', 'f'], []] + visitor._get_observations = MagicMock(side_effect=obs) + self.assertEquals(6, visitor.visit(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht')) + + @patch('caom2repo.core.CAOM2RepoClient') + def test_main(self, client_mock): + collection = 'cfht' + observation_id = '7000000o' + service = 'caom2repo' + ifile = '/tmp/inputobs' + + obs = SimpleObservation(collection, observation_id) + + # test create + with open(ifile, 'w') as infile: + ObservationWriter().write(obs, infile) + sys.argv = ["caom2tools", "create", ifile] + core.main() + client_mock.return_value.put_observation.assert_called_with(obs) + + # test update + sys.argv = ["caom2tools", "update", ifile] + core.main() + client_mock.return_value.post_observation.assert_called_with(obs) + + # test read + sys.argv = ["caom2tools", "read", "--collection", collection, observation_id] + client_mock.return_value.get_observation.return_value = obs + core.main() + client_mock.return_value.get_observation.assert_called_with(collection, observation_id) + # repeat with output argument + sys.argv = ["caom2tools", "read", "--collection", collection, "--output", ifile, observation_id] + client_mock.return_value.get_observation.return_value = obs + core.main() + client_mock.return_value.get_observation.assert_called_with(collection, observation_id) + os.remove(ifile) + + # test delete + sys.argv = ["caom2tools", "delete", "--collection", collection, observation_id] + core.main() + client_mock.return_value.delete_observation.assert_called_with(collection=collection, + observation=observation_id) + + # test visit + # get the absolute path to be able to run the tests with the astropy frameworks + plugin_file = THIS_DIR + "/passplugin.py" + sys.argv = ["caom2tools", "visit", "--plugin", plugin_file, "--start", "2012-01-01T11:22:33.44", + "--end", "2013-01-01T11:33:22.443", collection] + with open(plugin_file, 'r') as infile: + core.main() + client_mock.return_value.visit.assert_called_with( + ANY, collection, + start=util.str2ivoa("2012-01-01T11:22:33.44"), + end=util.str2ivoa("2013-01-01T11:33:22.443")) + + @patch('sys.exit', Mock(side_effect=[MyExitError, MyExitError, MyExitError, + MyExitError, MyExitError, MyExitError])) + def test_help(self): + """ Tests the helper displays for commands and subcommands in main""" + + # expected helper messages + usage =\ +"""usage: caom2-client [-h] [--certfile CERTFILE] [--anonymous] [--host HOST] + [--verbose] [--debug] [--quiet] + {create,read,update,delete,visit} ... + +Client for a CAOM2 repo. In addition to CRUD (Create, Read, Update and Delete) operations it also implements a visitor operation that allows for updating multiple observations in a collection + +positional arguments: + {create,read,update,delete,visit} + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" + + create_usage =\ +"""usage: caom2-client create [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + + +Create a new observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" + + read_usage =\ +"""usage: caom2-client read [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + --collection + [--output ] + + +Read an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --collection + --output , -o +""" + + update_usage =\ +"""usage: caom2-client update [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + + +Update an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" + + delete_usage =\ +"""usage: caom2-client delete [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + --collection + + +Delete an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --collection +""" + + visit_usage =\ +"""usage: caom2-client visit [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + --plugin + [--start ] + [--end ] + [--retries ] + [-s ] + + +Visit observations in a collection + +positional arguments: + data collection in CAOM2 repo + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --plugin + Pluging class to update each observation + --start + oldest dataset to visit (UTC %Y-%m-%d format) + --end + earliest dataset to visit (UTC %Y-%m-%d format) + --retries + number of tries with transient server errors + -s , --server + URL of the CAOM2 repo server + +Minimum plugin file format: +---- + from caom2.caom2_observation import Observation + + class ObservationUpdater: + + def update(self, observation): + assert isinstance(observation, Observation), ( + 'observation {} is not an Observation'.format(observation)) + # custom code to update the observation +---- +""" + + # --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "--help"] + with self.assertRaises(MyExitError): + core.main() + self.assertEqual(usage, stdout_mock.getvalue()) + + # create --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "create", "--help"] + with self.assertRaises(MyExitError): + core.main() + self.assertEqual(create_usage, stdout_mock.getvalue()) + + # read --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "read", "--help"] + with self.assertRaises(MyExitError): + core.main() + self.assertEqual(read_usage, stdout_mock.getvalue()) + + # update --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "update", "--help"] + with self.assertRaises(MyExitError): + core.main() + self.assertEqual(update_usage, stdout_mock.getvalue()) + + # delete --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "delete", "--help"] + with self.assertRaises(MyExitError): + core.main() + self.assertEqual(delete_usage, stdout_mock.getvalue()) + + # visit --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "visit", "--help"] + with self.assertRaises(MyExitError): + core.main() + self.assertEqual(visit_usage, stdout_mock.getvalue()) diff --git a/caom2repo/dev_requirements.txt b/caom2repo/dev_requirements.txt new file mode 100644 index 00000000..0d69562b --- /dev/null +++ b/caom2repo/dev_requirements.txt @@ -0,0 +1,7 @@ +numpy==1.12.0b1 +astropy==1.2.1 +cadctools==0.1.dev11 +-e . +funcsigs==1.0.2 +mock==2.0.0 +xml-compare==1.0.5 diff --git a/caom2repo/docs/Makefile b/caom2repo/docs/Makefile new file mode 100644 index 00000000..fb03f26e --- /dev/null +++ b/caom2repo/docs/Makefile @@ -0,0 +1,133 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +#This is needed with git because git doesn't create a dir if it's empty +$(shell [ -d "_static" ] || mkdir -p _static) + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf $(BUILDDIR) + -rm -rf api + -rm -rf generated + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Astropy.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Astropy.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Astropy" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Astropy" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + @echo "Run 'python setup.py test' in the root directory to run doctests " \ + @echo "in the documentation." diff --git a/caom2repo/docs/_templates/autosummary/base.rst b/caom2repo/docs/_templates/autosummary/base.rst new file mode 100644 index 00000000..9cabaf52 --- /dev/null +++ b/caom2repo/docs/_templates/autosummary/base.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/base.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2repo/docs/_templates/autosummary/class.rst b/caom2repo/docs/_templates/autosummary/class.rst new file mode 100644 index 00000000..6b214a5c --- /dev/null +++ b/caom2repo/docs/_templates/autosummary/class.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/class.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2repo/docs/_templates/autosummary/module.rst b/caom2repo/docs/_templates/autosummary/module.rst new file mode 100644 index 00000000..f38315b2 --- /dev/null +++ b/caom2repo/docs/_templates/autosummary/module.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/module.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2repo/docs/conf.py b/caom2repo/docs/conf.py new file mode 100644 index 00000000..78d20fd8 --- /dev/null +++ b/caom2repo/docs/conf.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# +# Astropy documentation build configuration file. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this file. +# +# All configuration values have a default. Some values are defined in +# the global Astropy configuration which is loaded here before anything else. +# See astropy.sphinx.conf for which values are set there. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('..')) +# IMPORTANT: the above commented section was generated by sphinx-quickstart, but +# is *NOT* appropriate for astropy or Astropy affiliated packages. It is left +# commented out with this explanation to make it clear why this should not be +# done. If the sys.path entry above is added, when the astropy.sphinx.conf +# import occurs, it will import the *source* version of astropy instead of the +# version installed (if invoked as "make html" or directly with sphinx), or the +# version in the build directory (if "python setup.py build_sphinx" is used). +# Thus, any C-extensions that are needed to build the documentation will *not* +# be accessible, and the documentation will not build correctly. + +import datetime +import os +import sys + +try: + import astropy_helpers +except ImportError: + # Building from inside the docs/ directory? + if os.path.basename(os.getcwd()) == 'docs': + a_h_path = os.path.abspath(os.path.join('..', 'astropy_helpers')) + if os.path.isdir(a_h_path): + sys.path.insert(1, a_h_path) + +# Load all of the global Astropy configuration +from astropy_helpers.sphinx.conf import * + +# Get configuration information from setup.cfg +try: + from ConfigParser import ConfigParser +except ImportError: + from configparser import ConfigParser +conf = ConfigParser() + +conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')]) +setup_cfg = dict(conf.items('metadata')) + +# -- General configuration ---------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.2' + +# To perform a Sphinx version check that needs to be more specific than +# major.minor, call `check_sphinx_version("x.y.z")` here. +# check_sphinx_version("1.2.1") + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns.append('_templates') + +# This is added to the end of RST files - a good place to put substitutions to +# be used globally. +rst_epilog += """ +""" + +# -- Project information ------------------------------------------------------ + +# This does not *have* to match the package name, but typically does +project = setup_cfg['package_name'] +author = setup_cfg['author'] +copyright = '{0}, {1}'.format( + datetime.datetime.now().year, setup_cfg['author']) + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. + +__import__(setup_cfg['package_name']) +package = sys.modules[setup_cfg['package_name']] + +# The short X.Y version. +version = package.__version__.split('-', 1)[0] +# The full version, including alpha/beta/rc tags. +release = package.__version__ + + +# -- Options for HTML output -------------------------------------------------- + +# A NOTE ON HTML THEMES +# The global astropy configuration uses a custom theme, 'bootstrap-astropy', +# which is installed along with astropy. A different theme can be used or +# the options for this theme can be modified by overriding some of the +# variables set in the global configuration. The variables set in the +# global configuration are listed below, commented out. + + +# Please update these texts to match the name of your package. +html_theme_options = { + 'logotext1': 'package', # white, semi-bold + 'logotext2': '-template', # orange, light + 'logotext3': ':docs' # white, light + } + +# Add any paths that contain custom themes here, relative to this directory. +# To use a different custom theme, add the directory containing the theme. +#html_theme_path = [] + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. To override the custom theme, set this to the +# name of a builtin theme or the name of a custom theme in html_theme_path. +#html_theme = None + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = '' + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '' + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +html_title = '{0} v{1}'.format(project, release) + +# Output file base name for HTML help builder. +htmlhelp_basename = project + 'doc' + + +# -- Options for LaTeX output ------------------------------------------------- + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [('index', project + '.tex', project + u' Documentation', + author, 'manual')] + + +# -- Options for manual page output ------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [('index', project.lower(), project + u' Documentation', + [author], 1)] + + +# -- Options for the edit_on_github extension --------------------------------- + +if eval(setup_cfg.get('edit_on_github')): + extensions += ['astropy_helpers.sphinx.ext.edit_on_github'] + + versionmod = __import__(setup_cfg['package_name'] + '.version') + edit_on_github_project = setup_cfg['github_project'] + if versionmod.version.release: + edit_on_github_branch = "v" + versionmod.version.version + else: + edit_on_github_branch = "master" + + edit_on_github_source_root = "" + edit_on_github_doc_root = "docs" + +# -- Resolving issue number to links in changelog ----------------------------- +github_issues_url = 'https://github.com/{0}/issues/'.format(setup_cfg['github_project']) + diff --git a/caom2repo/docs/index.rst b/caom2repo/docs/index.rst new file mode 100644 index 00000000..e69de29b diff --git a/caom2repo/docs/make.bat b/caom2repo/docs/make.bat new file mode 100644 index 00000000..93dfe92b --- /dev/null +++ b/caom2repo/docs/make.bat @@ -0,0 +1,170 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Astropy.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Astropy.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/caom2repo/ez_setup.py b/caom2repo/ez_setup.py new file mode 100644 index 00000000..fc22046b --- /dev/null +++ b/caom2repo/ez_setup.py @@ -0,0 +1,425 @@ +#!/usr/bin/env python + +""" +Setuptools bootstrapping installer. + +Maintained at https://github.com/pypa/setuptools/tree/bootstrap. + +Run this script to install or upgrade setuptools. +""" + +import os +import shutil +import sys +import tempfile +import zipfile +import optparse +import subprocess +import platform +import textwrap +import contextlib +import json +import codecs + +from distutils import log + +try: + from urllib.request import urlopen + from urllib.parse import urljoin +except ImportError: + from urllib2 import urlopen + from urlparse import urljoin + +try: + from site import USER_SITE +except ImportError: + USER_SITE = None + +LATEST = object() +DEFAULT_VERSION = LATEST +DEFAULT_URL = "https://pypi.io/packages/source/s/setuptools/" +DEFAULT_SAVE_DIR = os.curdir + + +def _python_cmd(*args): + """ + Execute a command. + + Return True if the command succeeded. + """ + args = (sys.executable,) + args + return subprocess.call(args) == 0 + + +def _install(archive_filename, install_args=()): + """Install Setuptools.""" + with archive_context(archive_filename): + # installing + log.warn('Installing Setuptools') + if not _python_cmd('setup.py', 'install', *install_args): + log.warn('Something went wrong during the installation.') + log.warn('See the error message above.') + # exitcode will be 2 + return 2 + + +def _build_egg(egg, archive_filename, to_dir): + """Build Setuptools egg.""" + with archive_context(archive_filename): + # building an egg + log.warn('Building a Setuptools egg in %s', to_dir) + _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) + # returning the result + log.warn(egg) + if not os.path.exists(egg): + raise IOError('Could not build the egg.') + + +class ContextualZipFile(zipfile.ZipFile): + + """Supplement ZipFile class to support context manager for Python 2.6.""" + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + def __new__(cls, *args, **kwargs): + """Construct a ZipFile or ContextualZipFile as appropriate.""" + if hasattr(zipfile.ZipFile, '__exit__'): + return zipfile.ZipFile(*args, **kwargs) + return super(ContextualZipFile, cls).__new__(cls) + + +@contextlib.contextmanager +def archive_context(filename): + """ + Unzip filename to a temporary directory, set to the cwd. + + The unzipped target is cleaned up after. + """ + tmpdir = tempfile.mkdtemp() + log.warn('Extracting in %s', tmpdir) + old_wd = os.getcwd() + try: + os.chdir(tmpdir) + with ContextualZipFile(filename) as archive: + archive.extractall() + + # going in the directory + subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) + os.chdir(subdir) + log.warn('Now working in %s', subdir) + yield + + finally: + os.chdir(old_wd) + shutil.rmtree(tmpdir) + + +def _do_download(version, download_base, to_dir, download_delay): + """Download Setuptools.""" + egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' + % (version, sys.version_info[0], sys.version_info[1])) + if not os.path.exists(egg): + archive = download_setuptools(version, download_base, + to_dir, download_delay) + _build_egg(egg, archive, to_dir) + sys.path.insert(0, egg) + + # Remove previously-imported pkg_resources if present (see + # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). + if 'pkg_resources' in sys.modules: + _unload_pkg_resources() + + import setuptools + setuptools.bootstrap_install_from = egg + + +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=DEFAULT_SAVE_DIR, download_delay=15): + """ + Ensure that a setuptools version is installed. + + Return None. Raise SystemExit if the requested version + or later cannot be installed. + """ + version = _resolve_version(version) + to_dir = os.path.abspath(to_dir) + + # prior to importing, capture the module state for + # representative modules. + rep_modules = 'pkg_resources', 'setuptools' + imported = set(sys.modules).intersection(rep_modules) + + try: + import pkg_resources + pkg_resources.require("setuptools>=" + version) + # a suitable version is already installed + return + except ImportError: + # pkg_resources not available; setuptools is not installed; download + pass + except pkg_resources.DistributionNotFound: + # no version of setuptools was found; allow download + pass + except pkg_resources.VersionConflict as VC_err: + if imported: + _conflict_bail(VC_err, version) + + # otherwise, unload pkg_resources to allow the downloaded version to + # take precedence. + del pkg_resources + _unload_pkg_resources() + + return _do_download(version, download_base, to_dir, download_delay) + + +def _conflict_bail(VC_err, version): + """ + Setuptools was imported prior to invocation, so it is + unsafe to unload it. Bail out. + """ + conflict_tmpl = textwrap.dedent(""" + The required version of setuptools (>={version}) is not available, + and can't be installed while this script is running. Please + install a more recent version first, using + 'easy_install -U setuptools'. + + (Currently using {VC_err.args[0]!r}) + """) + msg = conflict_tmpl.format(**locals()) + sys.stderr.write(msg) + sys.exit(2) + + +def _unload_pkg_resources(): + sys.meta_path = [ + importer + for importer in sys.meta_path + if importer.__class__.__module__ != 'pkg_resources.extern' + ] + del_modules = [ + name for name in sys.modules + if name.startswith('pkg_resources') + ] + for mod_name in del_modules: + del sys.modules[mod_name] + + +def _clean_check(cmd, target): + """ + Run the command to download target. + + If the command fails, clean up before re-raising the error. + """ + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError: + if os.access(target, os.F_OK): + os.unlink(target) + raise + + +def download_file_powershell(url, target): + """ + Download the file at url to target using Powershell. + + Powershell will validate trust. + Raise an exception if the command cannot complete. + """ + target = os.path.abspath(target) + ps_cmd = ( + "[System.Net.WebRequest]::DefaultWebProxy.Credentials = " + "[System.Net.CredentialCache]::DefaultCredentials; " + '(new-object System.Net.WebClient).DownloadFile("%(url)s", "%(target)s")' + % locals() + ) + cmd = [ + 'powershell', + '-Command', + ps_cmd, + ] + _clean_check(cmd, target) + + +def has_powershell(): + """Determine if Powershell is available.""" + if platform.system() != 'Windows': + return False + cmd = ['powershell', '-Command', 'echo test'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_powershell.viable = has_powershell + + +def download_file_curl(url, target): + cmd = ['curl', url, '--location', '--silent', '--output', target] + _clean_check(cmd, target) + + +def has_curl(): + cmd = ['curl', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_curl.viable = has_curl + + +def download_file_wget(url, target): + cmd = ['wget', url, '--quiet', '--output-document', target] + _clean_check(cmd, target) + + +def has_wget(): + cmd = ['wget', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_wget.viable = has_wget + + +def download_file_insecure(url, target): + """Use Python to download the file, without connection authentication.""" + src = urlopen(url) + try: + # Read all the data in one block. + data = src.read() + finally: + src.close() + + # Write all the data in one block to avoid creating a partial file. + with open(target, "wb") as dst: + dst.write(data) +download_file_insecure.viable = lambda: True + + +def get_best_downloader(): + downloaders = ( + download_file_powershell, + download_file_curl, + download_file_wget, + download_file_insecure, + ) + viable_downloaders = (dl for dl in downloaders if dl.viable()) + return next(viable_downloaders, None) + + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=DEFAULT_SAVE_DIR, delay=15, + downloader_factory=get_best_downloader): + """ + Download setuptools from a specified location and return its filename. + + `version` should be a valid setuptools version number that is available + as an sdist for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download + attempt. + + ``downloader_factory`` should be a function taking no arguments and + returning a function for downloading a URL to a target. + """ + version = _resolve_version(version) + # making sure we use the absolute path + to_dir = os.path.abspath(to_dir) + zip_name = "setuptools-%s.zip" % version + url = download_base + zip_name + saveto = os.path.join(to_dir, zip_name) + if not os.path.exists(saveto): # Avoid repeated downloads + log.warn("Downloading %s", url) + downloader = downloader_factory() + downloader(url, saveto) + return os.path.realpath(saveto) + + +def _resolve_version(version): + """ + Resolve LATEST version + """ + if version is not LATEST: + return version + + meta_url = urljoin(DEFAULT_URL, '/pypi/setuptools/json') + resp = urlopen(meta_url) + with contextlib.closing(resp): + try: + charset = resp.info().get_content_charset() + except Exception: + # Python 2 compat; assume UTF-8 + charset = 'UTF-8' + reader = codecs.getreader(charset) + doc = json.load(reader(resp)) + + return str(doc['info']['version']) + + +def _build_install_args(options): + """ + Build the arguments to 'python setup.py install' on the setuptools package. + + Returns list of command line arguments. + """ + return ['--user'] if options.user_install else [] + + +def _parse_args(): + """Parse the command line for options.""" + parser = optparse.OptionParser() + parser.add_option( + '--user', dest='user_install', action='store_true', default=False, + help='install in user site package') + parser.add_option( + '--download-base', dest='download_base', metavar="URL", + default=DEFAULT_URL, + help='alternative URL from where to download the setuptools package') + parser.add_option( + '--insecure', dest='downloader_factory', action='store_const', + const=lambda: download_file_insecure, default=get_best_downloader, + help='Use internal, non-validating downloader' + ) + parser.add_option( + '--version', help="Specify which version to download", + default=DEFAULT_VERSION, + ) + parser.add_option( + '--to-dir', + help="Directory to save (and re-use) package", + default=DEFAULT_SAVE_DIR, + ) + options, args = parser.parse_args() + # positional arguments are ignored + return options + + +def _download_args(options): + """Return args for download_setuptools function from cmdline args.""" + return dict( + version=options.version, + download_base=options.download_base, + downloader_factory=options.downloader_factory, + to_dir=options.to_dir, + ) + + +def main(): + """Install or upgrade setuptools and EasyInstall.""" + options = _parse_args() + archive = download_setuptools(**_download_args(options)) + return _install(archive, _build_install_args(options)) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/caom2repo/setup.cfg b/caom2repo/setup.cfg new file mode 100644 index 00000000..9687baeb --- /dev/null +++ b/caom2repo/setup.cfg @@ -0,0 +1,37 @@ +[build_sphinx] +source-dir = docs +build-dir = docs/_build +all_files = 1 + +[build_docs] +source-dir = docs +build-dir = docs/_build +all_files = 1 + +[upload_docs] +upload-dir = docs/_build/html +show-response = 1 + +[pytest] +minversion = 2.2 +norecursedirs = build docs/_build +doctest_plus = enabled + +[ah_bootstrap] +auto_use = True + +[metadata] +package_name = caom2repo +description = CAOM-2.2 repo access and tools +long_description = Tools for accessing a repo for the CAOM-2.2 data model +author = Canadian Astronomy Data Centre +author_email = cadc@nrc-cnrc.gc.ca +license = AGPLv3 +url = http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2 +edit_on_github = False +github_project = opencadc/caom2tools +# version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) +version = 1.0 + +[entry_points] +caom2-repo-client = caom2repo.core:main diff --git a/caom2repo/setup.py b/caom2repo/setup.py new file mode 100755 index 00000000..85687d31 --- /dev/null +++ b/caom2repo/setup.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +import glob +import os +import sys + +import ah_bootstrap +from setuptools import setup + +# A dirty hack to get around some early import/configurations ambiguities +if sys.version_info[0] >= 3: + import builtins +else: + import __builtin__ as builtins +builtins._ASTROPY_SETUP_ = True + +from astropy_helpers.setup_helpers import (register_commands, get_debug_option, + get_package_info) +from astropy_helpers.git_helpers import get_git_devstr +from astropy_helpers.version_helpers import generate_version_py + +# Get some values from the setup.cfg +try: + from ConfigParser import ConfigParser +except ImportError: + from configparser import ConfigParser + +conf = ConfigParser() +conf.read(['setup.cfg']) +metadata = dict(conf.items('metadata')) + +PACKAGENAME = metadata.get('package_name', 'packagename') +DESCRIPTION = metadata.get('description', 'Astropy affiliated package') +AUTHOR = metadata.get('author', '') +AUTHOR_EMAIL = metadata.get('author_email', '') +LICENSE = metadata.get('license', 'unknown') +URL = metadata.get('url', 'http://astropy.org') + +# Get the long description from the package's docstring +__import__(PACKAGENAME) +package = sys.modules[PACKAGENAME] +LONG_DESCRIPTION = package.__doc__ + +# Store the package name in a built-in variable so it's easy +# to get from other parts of the setup infrastructure +builtins._ASTROPY_PACKAGE_NAME_ = PACKAGENAME + +# VERSION should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) +VERSION = metadata.get('version', '1.0.dev') + +# Indicates if this version is a release version +RELEASE = 'dev' not in VERSION + +if not RELEASE: + VERSION += get_git_devstr(False) + +# Populate the dict of setup command overrides; this should be done before +# invoking any other functionality from distutils since it can potentially +# modify distutils' behavior. +cmdclassd = register_commands(PACKAGENAME, VERSION, RELEASE) + +# Freeze build information in version.py +generate_version_py(PACKAGENAME, VERSION, RELEASE, + get_debug_option(PACKAGENAME)) + +# Treat everything in scripts except README.rst as a script to be installed +scripts = [fname for fname in glob.glob(os.path.join('scripts', '*')) + if os.path.basename(fname) != 'README.rst'] + + +# Get configuration information from all of the various subpackages. +# See the docstring for setup_helpers.update_package_files for more +# details. +package_info = get_package_info() + +# Add the project-global data +package_info['package_data'].setdefault(PACKAGENAME, []) +package_info['package_data'][PACKAGENAME].append('data/*') +package_info['package_data'][PACKAGENAME].append('caom2/test/data/*') + +# Define entry points for command-line scripts +entry_points = {'console_scripts': []} + +entry_point_list = conf.items('entry_points') +for entry_point in entry_point_list: + entry_points['console_scripts'].append('{0} = {1}'.format(entry_point[0], + entry_point[1])) + +# Include all .c files, recursively, including those generated by +# Cython, since we can not do this in MANIFEST.in with a "dynamic" +# directory name. +c_files = [] +for root, dirs, files in os.walk(PACKAGENAME): + for filename in files: + if filename.endswith('.c'): + c_files.append( + os.path.join( + os.path.relpath(root, PACKAGENAME), filename)) +package_info['package_data'][PACKAGENAME].extend(c_files) + +# Note that requires and provides should not be included in the call to +# ``setup``, since these are now deprecated. See this link for more details: +# https://groups.google.com/forum/#!topic/astropy-dev/urYO8ckB2uM + +setup(name=PACKAGENAME, + version=VERSION, + description=DESCRIPTION, + scripts=scripts, + install_requires=['cadcutils'], + author=AUTHOR, + author_email=AUTHOR_EMAIL, + license=LICENSE, + url=URL, + long_description=LONG_DESCRIPTION, + cmdclass=cmdclassd, + zip_safe=False, + use_2to3=False, + entry_points=entry_points, + **package_info +) diff --git a/caom2repoClient/MANIFEST.in b/caom2repoClient/MANIFEST.in deleted file mode 100644 index 8b137891..00000000 --- a/caom2repoClient/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ - diff --git a/caom2repoClient/README b/caom2repoClient/README deleted file mode 100644 index b1f2a4c7..00000000 --- a/caom2repoClient/README +++ /dev/null @@ -1,7 +0,0 @@ - -This is a simple client for interacting with the CAOM-2.0 repository at CADC. It can -get, put, update, and delete observations from the repository. - -Note: The CAOM-2.0.xsd file found here is a copy of the definitive one, which is located in the -caom2 (java) library. If there is a discrepancy the file here is likely out of date. This file -is not currently used but validation may be added at some point. diff --git a/caom2repoClient/build.xml b/caom2repoClient/build.xml deleted file mode 100644 index b98f740b..00000000 --- a/caom2repoClient/build.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/caom2repoClient/caom2repoClient/__init__.py b/caom2repoClient/caom2repoClient/__init__.py deleted file mode 100755 index c74efab3..00000000 --- a/caom2repoClient/caom2repoClient/__init__.py +++ /dev/null @@ -1,74 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -from caom2repoClient import CAOM2RepoClient - -__all__ = ['caom2repoClient'] - diff --git a/caom2repoClient/caom2repoClient/caom2repoClient.py b/caom2repoClient/caom2repoClient/caom2repoClient.py deleted file mode 100755 index c2bdb883..00000000 --- a/caom2repoClient/caom2repoClient/caom2repoClient.py +++ /dev/null @@ -1,373 +0,0 @@ -## -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -import base64 -import errno -import httplib -import logging -import netrc -import os -import sys -import time -from argparse import ArgumentParser -from httplib import HTTPSConnection, HTTPConnection -from urlparse import urlparse - -__author__ = 'jenkinsd' - - -class CAOM2RepoClient: - - """Client script to access the CAOM-2 repository Observations.""" - - CAOM2REPO_REGISTRY_PROP_DIR_VAR = "CADC_ROOT" - - # - # Main function for execution. This function will delegate to proper functions. - # - def main(self): - # Some constants. - parser = ArgumentParser(description="CAOM-2 Observation Repository client.") - - parser.add_argument('--version', action='version', version='%(prog)s 1.0') - parser.add_argument('-v', '--verbose', required=False, action="store_true", - dest="verbose") - parser.add_argument('-d', '--debug', required=False, action="store_true", - dest="debug") - parser.add_argument('-g', '--get', required=False, dest="get_action", - nargs=2, metavar=("", ""), - help="Get observation (in the form caom:/) from the repository and write to ") - parser.add_argument('-p', '--put', required=False, dest='create_action', - nargs=2, metavar=("", ""), - help="Create observation (in the form caom:/) in the repository using ") - parser.add_argument('-u', '--update', required=False, dest='update_action', - nargs=2, metavar=("", ""), - help="Update observation (in the form caom:/) in the repository using ") - parser.add_argument('-r', '--remove', required=False, dest='delete_action', - nargs=1, metavar="", - help="Remove observation (in the form caom:/) from the repository") - parser.add_argument('--retry', required=False, nargs='?', const=3, - metavar=(""), - help="Retry the command on transient errors. Default is 3 retries unless a value is specified") - parser.epilog = 'Environment:\n' \ - + 'CADC_ROOT: location of lib/python-2.7/site-packages [REQUIRED]\n' \ - + 'CAOM2_REPO_HOST : force a specific server for caom2 repository [OPTIONAL]\n' - - arguments = parser.parse_args(sys.argv[1:]) - - if arguments.verbose: - logging.basicConfig(level=logging.INFO) - - if arguments.debug: - logging.basicConfig(level=logging.DEBUG) - - # Doing retries? - self.retries = None - if arguments.retry: - self.retries = int(arguments.retry) - - self.SERVICE_PROTOCOL = 'https' - self.SERVICE_URL = 'https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' - repoHost = os.getenv('CAOM2_REPO_HOST') - if repoHost is not None: - url = urlparse(self.SERVICE_URL) - self.SERVICE_URL = url.scheme + '://' + repoHost + url.path - logging.info("Service URL: '%s'" % self.SERVICE_URL) - - if arguments.get_action: - logging.info("GET ACTION") - self.get(arguments.get_action[0], arguments.get_action[1]) - elif arguments.create_action: - logging.info("PUT ACTION") - self.put(arguments.create_action[0], arguments.create_action[1]) - elif arguments.update_action: - logging.info("UPDATE ACTION") - self.update(arguments.update_action[0], arguments.update_action[1]) - elif arguments.delete_action: - logging.info("REMOVE ACTION") - self.remove(arguments.delete_action[0]) - else: - parser.print_help() - print - - - # - # Obtain the CAOM-2 Observation instance from the CAOM-2 service. - # - # @param observationURI - The URI of the CAOM-2 Observation - # @param filename - The full path to the XML File to construct an - # Observation. - # - def get(self, observationURI, filename): - logging.info("GET " + observationURI) - - response = self.send_request("GET", observationURI, {}, '') - - status = response.status - - if status == 503 and self.retries: - status = self.retry("GET", observationURI, {}, '') - - if status == 404: - logging.error('No such Observation found with URI \'%s\'.\n' % observationURI) - sys.exit(errno.ENOENT) - elif status >= 400: - logging.error('Unable to retrieve Observation with URI \'%s\'.\n' % observationURI) - logging.error('Server Returned: ' + httplib.responses[status] + ' (' - + str(status) + ')\n' + response.read()) - sys.exit(errno.ENOEXEC) - else: - f = open(filename, 'w') - f.write(response.read()) - f.close() - logging.info("Successfully saved Observation at '%s'" % filename) - # - # Create a new Observation resource. - # - # @param observationURI - The URI of the CAOM-2 Observation - # @param filename - The full path to the XML File to construct an - # Observation. - # - def put(self, observationURI, filename): - logging.debug("PUT " + filename) - xmlfile = None - - try: - - xmlfile = open(filename) - response = self.send_request("PUT", observationURI, {'Content-Type': 'text/xml'}, xmlfile.read()) - status = response.status - - if status == 503 and self.retries: - status = self.retry("PUT", observationURI, {'Content-Type': 'text/xml'}, xmlfile.read()) - - if status == 404: - logging.error('No such collection found for URI \'%s\'' % observationURI) - sys.exit(errno.ENOENT) - elif status >= 400: - msg = '' - for hmsg in response.msg.headers: - msg = msg + hmsg - logging.error('Unable to create Observation from file ' + filename - + '\nServer Returned: ' + httplib.responses[status] + ' (' - + str(status) + ')\n' + msg + response.read()) - sys.exit(errno.ENOEXEC) - else: - logging.info('Successfully created Observation\n') - - except IOError as ioerr: - logging.error('\nAborting due to error!\nUnable to read file ' - + filename + '\n' + str(ioerr) + '\n') - sys.exit(errno.EIO) - finally: - if not xmlfile is None: - xmlfile.close() - - # - # Update an existing CAOM-2 Observation. - # - # @param observationURI - The URI of the Observation to update. - # @param filename - The full path to the XML File of the Observation. - # - def update(self, observationURI, filename): - logging.debug("POST " + observationURI + " with filename " + filename) - xmlfile = None - - try: - xmlfile = open(filename) - response = self.send_request("POST", observationURI, {'Content-Type': 'text/xml'}, xmlfile.read()) - status = response.status - - if status == 503 and self.retries: - status = self.retry("POST", observationURI, {'Content-Type': 'text/xml'}, xmlfile.read()) - - if status == 404: - logging.error('Observation with URI \'%s\' does not exist.\n' % observationURI) - sys.exit(errno.ENOENT) - elif status >= 400: - msg = '' - for hmsg in response.msg.headers: - msg = msg + hmsg - logging.error('Unable to update Observation from file ' + filename - + '\nServer Returned: ' + httplib.responses[status] + ' (' - + str(status) + ')\n' + msg + response.read()) - sys.exit(errno.ENOEXEC) - else: - logging.info('Successfully updated Observation\n') - - except IOError as ioerr: - logging.error('Aborting due to error!\nUnable to read file ' + filename + '\n' + str(ioerr) + '\n') - sys.exit(errno.EIO) - finally: - if not xmlfile is None: - xmlfile.close() - # - # Permanently remove an Observation resource. - # - # @param observationURI - The URI of the Observation to delete. - # - def remove(self, observationURI): - logging.debug("DELETE " + observationURI) - response = self.send_request("DELETE", observationURI, {}, '') - status = response.status - - if status == 503 and self.retries: - status = self.retry("DELETE", observationURI, {}, '') - - if status == 404: - logging.error('No such Observation found with URI \'%s\'.\n' % observationURI) - sys.exit(errno.ENOENT) - elif status >= 400: - logging.error('Unable to remove Observation with URI \'' + observationURI - + '\'.\n\n' + httplib.responses[status] + ' (' + str(status) - + ')\n' + response.read()) - sys.exit(errno.ENOEXEC) - else: - logging.info('Successfully removed Observation %s' % observationURI + '\n') - - # - # Send the HTTP(S) request. - # - # @param method - The HTTP Method to use (String). - # @param path - The path of the URL (After the host). Should begin - # with a slash ('/') (String). - # @param headers - Any custom headers. This is a dictionary. - # @param payload - The payload to send for a write operation (String). - # - # @return The httplib.HTTPResponse object. - # - def send_request(self, method, observationURI, headers, payload): - parseResult = urlparse(observationURI) - serviceURLResult = urlparse(self.SERVICE_URL) - path = parseResult.path - logging.debug("Found path: " + path) - - if self.SERVICE_PROTOCOL == 'https': - try: - with open(os.path.join(os.environ['HOME'], '.ssl/cadcproxy.pem')) as certfile: - logging.info('certfile {}'.format(certfile)) - conn = HTTPSConnection(serviceURLResult.hostname, 443, None, certfile.name) - conn.request(method, serviceURLResult.path + '/pub/' + path, payload, headers) - logging.debug("Making request to " + self.SERVICE_URL + '/pub/' + path) - return conn.getresponse() - except IOError as e: - logging.error('No usable credentials to connect to ' + self.SERVICE_URL + '/' + path + '\n') - logging.error(str(e) + "\n") - sys.exit(errno.EACCES) - elif self.SERVICE_PROTOCOL == 'http': - try: - netrcfile = netrc.netrc() - auth = netrcfile.authenticators(serviceURLResult.hostname) - except netrc.NetrcParseError as err: - logging.error('Unable to read netrc file.\n') - logging.error(str(err) + "\n") - sys.exit(errno.EIO) - - conn = HTTPConnection(serviceURLResult.hostname) - username = auth[0] - password = auth[2] - base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') - - if not headers or not len(headers): - headers = {'Authorization': 'Basic %s' % base64string} - elif not headers.has_key('Authorization'): - headers.update({'Authorization': 'Basic %s' % base64string}) - - conn.request(method, serviceURLResult.path + '/auth/' + path, payload, headers) - logging.debug('Making request to ' + self.SERVICE_URL + '/auth/' + path) - - return conn.getresponse() - else: - logging.error("Unknown protocol '%s'" % self.SERVICE_PROTOCOL) - - # - # Retry a HTTP(S) request. - # - # @param method - The HTTP Method to use (String). - # @param path - The path of the URL (After the host). Should begin - # with a slash ('/') (String). - # @param headers - Any custom headers. This is a dictionary. - # @param payload - The payload to send for a write operation (String). - # - # @return The httplib.HTTPResponse object. - # - def retry(self, method, observationURI, headers, payload): - num_retries = int(0); - sleep_time = int(1) - status = 503 - while status == 503: - num_retries += 1 - if num_retries > self.retries: - break - sleep_time = sleep_time * 2 - logging.info('Sleeping ' + str(sleep_time) + ', retry ' + str(num_retries)) - time.sleep(sleep_time) - response = self.send_request(method, observationURI, headers, payload) - status = response.status - return status diff --git a/caom2repoClient/makefile b/caom2repoClient/makefile deleted file mode 100644 index a19b032e..00000000 --- a/caom2repoClient/makefile +++ /dev/null @@ -1,298 +0,0 @@ -# -# This makefile was generated by mm. -# - - -# Project-specific definitions -PROJECT := myproject - -# Another perverted GNU make trick - recursive wildcard evaluation -# Usage is $(call rwildcard,dirpath,pattern) -# Return is a list of files matching pattern in the directory tree rooted at dirpath -# See http://blog.jgc.org/2011/07/gnu-make-recursive-wildcard-function.html -rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) - -PROJECTROOT := $(abspath $(dir $(firstword $(wildcard setup.py ../setup.py ../../setup.py ../../../setup.py)))) -LOCALROOT := $(abspath .) -THISMAKEFILE := $(abspath $(firstword $(MAKEFILE_LIST))) - -# Specific version of python to be used for the installation -# PYTHON can be over ruled from the command line, or in sub-makes -PYTHON := python -# The list of python versions can be restricted (or extended) in makestart -PYTHONLIST := python2.5 python2.6 python2.7 - -# Default style checker -CHECKSTYLE = pep8 -r - -# Checks that python modules are in allowed locations -PYTHON_MODULES = $(A)/scripts/python_modules.py --report=path - -# generates Python documentation -DOCGEN = pydoc -w >&/dev/null - -# use rsync to copy files around -RSYNC = rsync -Cqpotr - -LIB := $(PROJECTROOT)/lib.local/ -# System-specified directories -ifeq ($(T),) - # Environment does not define T, so assume a non-CADC platform - RPS := $(wildcard ~/ ) - A = $(RPS) - INSTALLSWITCH = -else - # Envirnment defines T, so assume a CADC platform - INSTALLSWITCH = --install-base=$(LIB) -endif -LOGS := $(PROJECTROOT)/logs -DOCAPI = $(PROJECTROOT)/www/doc/api/$(PROJECT) - -PACKAGEPATHLIST := $(abspath $(subst /__init__.py,,$(call rwildcard,$(PROJECTROOT)/,__init__.py))) -PACKAGENAMELIST := $(notdir $(PACKAGEPATHLIST)) - -# Mangle python path names into doc names -PYLIST := $(filter-out test% lib.local% www% logs% setup.py,$(subst $(PROJECTROOT)/,,$(call rwildcard,$(PROJECTROOT)/,*.py))) -DOCPATHLIST := $(subst /__init__.py,,$(PYLIST)) -DOCSOURCELIST := $(subst ..,,$(subst /,.,$(basename $(DOCPATHLIST)))) -DOCLIST := $(addsuffix .html,$(DOCSOURCELIST)) - -SCRIPTLIST := $(notdir $(wildcard $(PROJECTROOT)/scripts/*)) -SCRIPTDOCLIST := $(filter %.py,$(SCRIPTLIST)) - -TESTLIST := $(notdir $(wildcard $(PROJECTROOT)/test/*)) -TESTPATH := $(foreach t,$(TESTLIST),$(wildcard $(PROJECTROOT)/test/$(t)/test*.py)) - -CHECKLIST = $(addprefix check,$(notdir $(PYLIST))) - -PYTHON := python2.7 -PYTHONLIST := python2.7 - -project := caom2repoClient - -TARGETS = x86_linux -TARGET_BLACKLIST = x86_fedora5_32 -# -# makestart end -# - -CURRENT_TRANSITION=current.transition -include $(A)/compilers/$(CURRENT_TRANSITION) - -local: -L=$(RPS)/lib.$(T) -#ifndef REL_TARGETS -ifeq ($(REL_TARGETS),) - REL_TARGETS = $(TARGETS) -endif -release: -ifeq ($(STREAM),current) - @echo "Error: Cannot do make release in the \"current\" stream." - @exit 1 -endif - @$(MAKE) RELEASE_BUILD=T $(REL_TARGETS) -makemake: test_targets - -CCFLAGS += $(addprefix -I, $(INCLUDE_PATH)) -CFLAGS += $(addprefix -I, $(INCLUDE_PATH)) -FFLAGS += $(addprefix -I, $(INCLUDE_PATH)) -LINTFLAGS := $(addprefix -I, $(INCLUDE_PATH)) $(LINTFLAGS) - -.PHONY: test -test: - echo $(xx) - -buildpaths: - @echo "lib path : $(LIBPATH)" - @echo "include path : $(INCLUDE_PATH)" - -ifneq (,$(findstring -b,$(FLAGS))) -x := $(shell mkdir -p bin.$(T) obj.$(T)) -endif - -ifneq (,$(findstring -l,$(FLAGS))) -x := $(shell mkdir -p lib.$(T) obj.$(T)) -endif - -objects: $(OBJECTS) - - -T_TARGETS = $(shell echo $(REL_TARGETS) | sed -e 's/\([ ^]*[^_ ][^_ ]*_[^_ $$]*\)[^ ]*/\1/g') -test_targets: - @echo "rel targets $(REL_TARGETS)" - @echo "t targets $(T_TARGETS)" -ifneq ($(words $(TARGETS)),$(words $(sort $(TARGETS)))) - @echo "Makestart setup error:" - @echo " There are duplicate targets in the TARGETS make symbol." - @exit 1 -endif -ifneq ($(words $(TARGETS)),$(words $(sort $(TARGETS) $(REL_TARGETS)))) - @echo "Makestart setup error:" - @echo " There are targets in REL_TARGETS not in the TARGETS list." - @exit 1 -endif -# -# commented out for fedora8 testing only - SGo -# -#ifneq ($(words $(T_TARGETS)),$(words $(sort $(T_TARGETS)))) -#ifeq ($(findstring -b,$(FLAGS)),-b) -## @echo "Makestart setup error:" -# @echo " There is more than one target in REL_TARGETS that release " -# @echo " to the same architecture (or REL_TARGETS is not defined)." -# @exit 1 -#endif -#endif - - -# -# The following targets cause libraries to be built when the library -# test program is built, or cause objects files to be built when the -# program test program is built. -# - -ifeq ($(notdir $(PWD)),test) -ifeq ($(wildcard ../lib.$(T) ),../lib.$(T)) -local: buildlib -buildlib: - @cd ..; $(MAKE) local -endif -ifeq ($(wildcard ../bin.$(T) ),../bin.$(T)) -local: buildobj -buildobj: - @cd ..; $(MAKE) objects -endif -endif - -DEFAULT_TARGET=$(firstword $(TARGETS)) -DEFAULT_HOST=$(shell echo $(DEFAULT_TARGET)_HOST | tr '[a-z]' '[A-Z]') -showDepend: -ifeq (,$(findstring $(T),$(TARGETS))) - ssh -n $($(DEFAULT_HOST)) "setenv PROJECT $(PROJECT); setenv STREAM $(STREAM); source $(M)/dev.rc; cd $(shell pwd); make -nd RELEASE_ROOT=$(RELEASE_ROOT) MODULE_VERSION=$(MODULE_VERSION) T=$(DEFAULT_TARGET) local" -else - make -nd local -endif - -show_rel_targets: - @echo "$(REL_TARGETS)" - - -.PHONY: local lint all release test_targets show_rel_targets -.PHONY: local default clean init build test - -# run make on all platforms -ifeq ($(T),) -.PHONY: all -all: local -else -.PHONY: all -all: $(TARGETS) -endif - -.PNONY: $(TARGETS) -$(TARGETS): - ssh $$$(shell echo $@ | tr '[:lower:]' '[:upper:]')_HOST 'cd $(PWD); make local' - -# run make for all versions of python -local: $(PYTHONLIST) - -# By default, run make for every version of python separately -.PHONY: $(PYTHONLIST) -$(PYTHONLIST): - $(MAKE) -f $(THISMAKEFILE) PYTHON=$@ PROJECTROOT=$(PROJECTROOT) default - -default: init build - -.PHONY: show -show: - @echo PROJECTROOT = $(PROJECTROOT) - @echo LOCALROOT = $(LOCALROOT) - @echo THISMAKEFILE = $(THISMAKEFILE) - @echo PYLIST = $(PYLIST) - @echo DOCLIST = $(DOCLIST) - @echo TESTLIST = $(TESTLIST) - @echo TESTPATH = $(TESTPATH) - @echo CHECKLIST = $(CHECKLIST) - -.PHONY: init -init: clean - mkdir -p $(LIB) - mkdir -p $(LOGS) - mkdir -p $(DOCAPI) - -.PHONY: clean -clean: - /bin/rm -fr $(LIB) - /bin/rm -fr $(LOGS) - /bin/rm -fr $(DOCAPI) - -#---------------------------------- -# BUILD TARGETS -#---------------------------------- -.PHONY: build compile build_python build_doc build_scripts build_config build_dtd - -# compile is a synonym for build -compile: build - -build: build_python build_doc - -build_python: - cd $(PROJECTROOT)/; $(PYTHON) setup.py build --build-base=$(LIB) - -#---------------------------------- -# BUILD_DOC TARGETS -#---------------------------------- -#.PHONY: build_doc -build_doc: build_python $(addprefix $(DOCAPI)/,$(DOCLIST)) $(addprefix $(DOCAPI)/,$(addsuffix .html,$(basename $(SCRIPTDOCLIST)))) - -# Create document targets for each individual package and module -define doc_template -$(DOCAPI)/$(1).html: $(wildcard $(subst .,/,$(1)).py $(subst .,/,$(1))/__init__.py) - cd $(DOCAPI); export PYTHONPATH=$(abspath $(LIB)/lib); $(DOCGEN) $(1) -endef -$(foreach p,$(DOCSOURCELIST),$(eval $(call doc_template,$(p)))) - -define scriptdoc_template -$(DOCAPI)/$(2).html: $(PROJECTROOT)/scripts/$(1) - cd $(DOCAPI); export PYTHONPATH=$(abspath $(LIB)/lib); $(DOCGEN) $^ -# /bin/rm $(PROJECTROOT)/scripts/*.pyc -endef -$(foreach p,$(SCRIPTDOCLIST),$(eval $(call scriptdoc_template,$(p),$(basename $(p))))) - -#---------------------------------- -# TEST TARGETS -#---------------------------------- -.PHONY: test $(addsuffix Test,$(TESTLIST)) - -define generate_tests -$(1)Test: $(2) - -.PHONY: $(2) -$(2): - cd $(PROJECTROOT)/test/$(1); export PYTHONPATH=$(abspath $(LIB)/lib); $(PYTHON) $$@ -endef -$(foreach t,$(TESTLIST),$(eval $(call generate_tests,$(t),$(strip $(notdir $(wildcard $(PROJECTROOT)/test/$(t)/test*.py)))))) - -#---------------------------------- -# CHECKSTYLE TARGETS -#---------------------------------- -.PHONY: checkstyle $(CHECKLIST) -checkstyle: $(CHECKLIST) - -define generate_checks -.PHONY: $(2) - -$(2): - -$(CHECKSTYLE) $(1) -endef - -$(foreach c,$(PYLIST),$(eval $(call generate_checks,$(c),$(addprefix check,$(notdir $(c)))))) - -#---------------------------------- -# CLASSPATH TARGETS -#---------------------------------- -.PHONY: classpath -classpath: - export PYTHONPATH=$(LIB)/lib; \ - $(PYTHON_MODULES) $(PACKAGEPATHLIST) \ - $(addprefix $(PROJECTROOT)/scripts/,$(SCRIPTDOCLIST)) \ - $(TESTPATH) diff --git a/caom2repoClient/setup.cfg b/caom2repoClient/setup.cfg deleted file mode 100644 index e8551e6f..00000000 --- a/caom2repoClient/setup.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[global] -verbose=0 - -description = "CAOM2RepoClient Class libraries" - -[install] -install-purelib=$base/lib/python$py_version_short/site-packages -install-platlib=$base/lib/python$py_version_short/site-packages -install_headers=$base/include/python$py_version_short/$dist_name diff --git a/caom2repoClient/setup.py b/caom2repoClient/setup.py deleted file mode 100755 index 185c8628..00000000 --- a/caom2repoClient/setup.py +++ /dev/null @@ -1,63 +0,0 @@ -#/*+ -#************************************************************************ -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#* -#* (c) 2012. (c)2012. -#* National Research Council Conseil national de recherches -#* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -#* All rights reserved Tous droits reserves -#* -#* NRC disclaims any warranties, Le CNRC denie toute garantie -#* expressed, implied, or statu- enoncee, implicite ou legale, -#* tory, of any kind with respect de quelque nature que se soit, -#* to the software, including concernant le logiciel, y com- -#* without limitation any war- pris sans restriction toute -#* ranty of merchantability or garantie de valeur marchande -#* fitness for a particular pur- ou de pertinence pour un usage -#* pose. NRC shall not be liable particulier. Le CNRC ne -#* in any event for any damages, pourra en aucun cas etre tenu -#* whether direct or indirect, responsable de tout dommage, -#* special or general, consequen- direct ou indirect, particul- -#* tial or incidental, arising ier ou general, accessoire ou -#* from the use of the software. fortuit, resultant de l'utili- -#* sation du logiciel. -#* -#************************************************************************ -#* -#* Script Name: setup.py -#* -#* Purpose: -#* Distutils setup script for caom2repoClient -#* -#* Functions: -#* -#* -#* -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#************************************************************************ -#-*/ - -# Use "distribute" -from setuptools import setup, find_packages -import sys - -if sys.version_info[0] > 2: - print 'The caom2repoClient package is only compatible with Python version 2.n' - sys.exit(-1) - -setup(name="caom2repoClient", - version='0.5.2', - description='Client application to the CAOM2 Repository', - long_description='The caom2repo client allows the caller to get/put/update/delete CAOM2 Observations in a central repository.', - url='http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo', - author='Canadian Astronomy Data Centre', - author_email='cadc@hia.nrc.ca', - license='GPLv3', - packages=find_packages(), - scripts=['scripts/caom2repo.py'], - include_package_data=True, - provides=['caom2repoClient'], - install_requires = ['distribute'], - zip_safe=False -) - diff --git a/caom2repoClient/test/data/CAOM-2.0.xsd b/caom2repoClient/test/data/CAOM-2.0.xsd deleted file mode 100644 index e2d91ace..00000000 --- a/caom2repoClient/test/data/CAOM-2.0.xsd +++ /dev/null @@ -1,523 +0,0 @@ - - - - - - - - - - - - - - The metaRelease date is expected to be in IVOA date format: - yyyy-MM-dd'T'HH:mm:ss.SSS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The observationURI must be constructed as follows: - caom:{collection}/{observationID} - - TODO: formally specify the ObservationURI type - - - - - - - - - - - - - - - - - - - - - The metaRelease date is expected to be in IVOA date format: - yyyy-MM-dd'T'HH:mm:ss.SSS - - - - - - - The dataRelease date is expected to be in IVOA date format: - yyyy-MM-dd'T'HH:mm:ss.SSS - - - - - - - - - - - - - - - - - - - - - - - - - The dataRelease date is expected to be in IVOA date format: - yyyy-MM-dd'T'HH:mm:ss.SSS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The planeURI must be constructed as follows: - caom:{collection}/{observationID}/{productID} - which is based on the observationURI syntax, e.g.: - {observationURI}/{productID} - - TODO: formally specify the PlaneURI type - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/caom2repoClient/test/data/simple.xml b/caom2repoClient/test/data/simple.xml deleted file mode 100644 index 4b524d97..00000000 --- a/caom2repoClient/test/data/simple.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - TEST - TESTBOGUS_CAOM2REPOCLIENT - - exposure - - - - productIDFromXML - - - ad:foo/bar - false - - - - - diff --git a/caom2repoClient/test/scripts/test_caom2repo.sh b/caom2repoClient/test/scripts/test_caom2repo.sh deleted file mode 100755 index 96fe8e3d..00000000 --- a/caom2repoClient/test/scripts/test_caom2repo.sh +++ /dev/null @@ -1,285 +0,0 @@ -#!/bin/bash -#/*+ -#************************************************************************ -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#* -#* (c) 2012. (c) 2012. -#* National Research Council Conseil national de recherches -#* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -#* All rights reserved Tous droits reserves -#* -#* NRC disclaims any warranties, Le CNRC denie toute garantie -#* expressed, implied, or statu- enoncee, implicite ou legale, -#* tory, of any kind with respect de quelque nature que se soit, -#* to the software, including concernant le logiciel, y com- -#* without limitation any war- pris sans restriction toute -#* ranty of merchantability or garantie de valeur marchande -#* fitness for a particular pur- ou de pertinence pour un usage -#* pose. NRC shall not be liable particulier. Le CNRC ne -#* in any event for any damages, pourra en aucun cas etre tenu -#* whether direct or indirect, responsable de tout dommage, -#* special or general, consequen- direct ou indirect, particul- -#* tial or incidental, arising ier ou general, accessoire ou -#* from the use of the software. fortuit, resultant de l'utili- -#* sation du logiciel. -#* -#************************************************************************ -#* -#* Script Name: caom2repo.py -#* -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#************************************************************************ -#-*/ - -PYTHON=$(/usr/bin/which python) -TEST_SUBJECT="../../scripts/caom2repo.py -v" -VERSION_OUTPUT_1=$(${TEST_SUBJECT} --version 2>&1) - -if [[ ! $VERSION_OUTPUT_1 = 'caom2repo.py 1.0' ]] -then - echo "Failed version test." - echo "Expected 'caom2repo.py 1.0', but got '${VERSION_OUTPUT_1}'" - exit -1 -fi - -HELP_OUTPUT_1=$(${TEST_SUBJECT} 2>&1 | head -2 | tail -1) - -if [[ ! $HELP_OUTPUT_1 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed help test (1)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${HELP_OUTPUT_1}'" - exit -1 -fi - -HELP_OUTPUT_2=$(${TEST_SUBJECT} -h 2>&1 | head -1) - -if [[ ! $HELP_OUTPUT_2 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed help test (2)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${HELP_OUTPUT_2}'" - exit -1 -fi - -HELP_OUTPUT_3=$(${TEST_SUBJECT} --help 2>&1 | head -1) - -if [[ ! $HELP_OUTPUT_3 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed help test (3)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${HELP_OUTPUT_3}'" - exit -1 -fi - -# Get tests -# -GET_OUTPUT_1=$(${TEST_SUBJECT} -g 2>&1 | tail -1) - -if [[ ! $GET_OUTPUT_1 = 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)' ]] -then - echo "Failed get test (1)." - echo "Expected 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)', but got '${GET_OUTPUT_1}'" - exit -1 -fi - -GET_OUTPUT_2=$(${TEST_SUBJECT} --get 2>&1 | tail -1) - -if [[ ! $GET_OUTPUT_2 = 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)' ]] -then - echo "Failed get test (2)." - echo "Expected 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)', but got '${GET_OUTPUT_2}'" - exit -1 -fi - -GET_OUTPUT_3=$(${TEST_SUBJECT} -g caom:TEST/BOGUSOBSERVATION 2>&1 | tail -1 2>&1) - -if [[ ! $GET_OUTPUT_3 = 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)' ]] -then - echo "Failed get test (3)." - echo "Expected 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)', but got '${GET_OUTPUT_3}'" - exit -1 -fi - -${TEST_SUBJECT} -g caom:IRIS/f212h000 /tmp/out.xml - -GET_OUTPUT_4=$(cat /tmp/out.xml | sed 's/\r//' | head -1) -GET_OUTPUT_4_2=$(cat /tmp/out.xml | sed 's/\r//' | head -5 | tail -1) - -if [[ ! ${GET_OUTPUT_4} = "" ]] -then - echo "Failed get test (4)." - echo "Expected '', but got '${GET_OUTPUT_4}'" - exit -1 -else - if [[ ! ${GET_OUTPUT_4_2} = ' 2004-12-06T00:00:00.000' ]] - then - echo "Failed get test (4.2)." - echo "Expected ' 2004-12-06T00:00:00.000', but got '${GET_OUTPUT_4_2}'" - exit -1 - fi -fi - -# Quick remove before a PUT -echo "" -echo "Issuing clean up delete in case test failed before final deletion. Ignore any error message here." -${TEST_SUBJECT} -r caom:TEST/TESTBOGUS_CAOM2REPOCLIENT -echo "OK, pay attention again." - -# Create tests -# -PUT_OUTPUT_1=$(${TEST_SUBJECT} -p 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_1 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (1)." - echo "Expected caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_1}'" - exit -1 -fi - -PUT_OUTPUT_2=$(${TEST_SUBJECT} --put 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_2 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (2)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_2}'" - exit -1 -fi - -PUT_OUTPUT_3=$(${TEST_SUBJECT} -p caom:TEST/TESTOBS 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_3 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (3)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_3}'" - exit -1 -fi - -PUT_OUTPUT_4=$(${TEST_SUBJECT} --put caom:TEST/TESTOBS 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_4 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (4)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_4}'" - exit -1 -fi - -PUT_OUTPUT_5=$(${TEST_SUBJECT} -p ../data/simple.xml 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_5 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (5)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_5}'" - exit -1 -fi - -PUT_OUTPUT_6=$(${TEST_SUBJECT} --put ../data/simple.xml 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_6 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (6)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_6}'" - exit -1 -fi - -PUT_OUTPUT_7=$(${TEST_SUBJECT} -p caom:TEST/TESTBOGUS_CAOM2REPOCLIENT ../data/simple.xml 2>&1 | head -4 | tail -1) - -if [[ ! $PUT_OUTPUT_7 = 'INFO:root:Successfully created Observation' ]] -then - echo "Failed put test (7)." - echo "Expected 'INFO:root:Successfully created Observation', but got '${PUT_OUTPUT_7}'" - exit -1 -fi - -# Update tests -# -POST_OUTPUT_1=$(${TEST_SUBJECT} -u 2>&1 | head -1) - -if [[ ! $POST_OUTPUT_1 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed post test (1)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${POST_OUTPUT_1}'" - exit -1 -fi - -POST_OUTPUT_2=$(${TEST_SUBJECT} --update 2>&1 | head -1) - -if [[ ! $POST_OUTPUT_2 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed post test (2)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${POST_OUTPUT_2}'" - exit -1 -fi - -POST_OUTPUT_3=$(${TEST_SUBJECT} -u caom:TEST/TESTBOGUS_CAOM2REPOCLIENT 2>&1 | tail -1) - -if [[ ! $POST_OUTPUT_3 = 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)' ]] -then - echo "Failed post test (3)." - echo "Expected 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)', but got '${POST_OUTPUT_3}'" - exit -1 -fi - -POST_OUTPUT_4=$(${TEST_SUBJECT} --update caom:TEST/TESTOBS 2>&1 | tail -1) - -if [[ ! $POST_OUTPUT_4 = 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)' ]] -then - echo "Failed post test (4)." - echo "Expected 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)', but got '${POST_OUTPUT_4}'" - exit -1 -fi - -POST_OUTPUT_5=$(${TEST_SUBJECT} -u ../data/simple.xml 2>&1 | tail -1) - -if [[ ! $POST_OUTPUT_5 = 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)' ]] -then - echo "Failed post test (5)." - echo "Expected 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)', but got '${POST_OUTPUT_5}'" - exit -1 -fi - -POST_OUTPUT_6=$(${TEST_SUBJECT} --update ../data/simple.xml 2>&1 | tail -1) - -if [[ ! $POST_OUTPUT_6 = 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)' ]] -then - echo "Failed post test (6)." - echo "Expected 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)', but got '${POST_OUTPUT_6}'" - exit -1 -fi - -POST_OUTPUT_7=$(${TEST_SUBJECT} -u caom:TEST/TESTBOGUS_CAOM2REPOCLIENT ../data/simple.xml 2>&1 | head -4 | tail -1) - -if [[ ! $POST_OUTPUT_7 = 'INFO:root:Successfully updated Observation' ]] -then - echo "Failed post test (7)." - echo "Expected 'INFO:root:Successfully updated Observation', but got '${POST_OUTPUT_7}'" - exit -1 -fi - -# Delete tests. -# -REMOVE_OUTPUT_1=$(${TEST_SUBJECT} -r caom:TEST/NOSUCHOBS 2>&1 | head -3 | tail -1) - -if [[ ! $REMOVE_OUTPUT_1 = "ERROR:root:No such Observation found with URI 'caom:TEST/NOSUCHOBS'." ]] -then - echo "Failed remove test (1)." - echo "Expected 'ERROR:root:No such Observation found with URI 'caom:TEST/NOSUCHOBS'.', but got '${REMOVE_OUTPUT_1}'" - exit -1 -fi - -REMOVE_OUTPUT_2=$(${TEST_SUBJECT} --remove caom:TEST/NOSUCHOBS 2>&1 | head -3 | tail -1) - -if [[ ! $REMOVE_OUTPUT_2 = "ERROR:root:No such Observation found with URI 'caom:TEST/NOSUCHOBS'." ]] -then - echo "Failed remove test (2)." - echo "Expected 'ERROR:root:No such Observation found with URI 'caom:TEST/NOSUCHOBS'.', but got '${REMOVE_OUTPUT_2}'" - exit -1 -fi - -REMOVE_OUTPUT_3=$(${TEST_SUBJECT} --remove caom:TEST/TESTBOGUS_CAOM2REPOCLIENT 2>&1 | head -3 | tail -1) - -if [[ ! $REMOVE_OUTPUT_3 = "INFO:root:Successfully removed Observation caom:TEST/TESTBOGUS_CAOM2REPOCLIENT" ]] -then - echo "Failed remove test (3)." - echo "Expected 'INFO:root:Successfully removed Observation caom:TEST/TESTBOGUS_CAOM2REPOCLIEN', but got '${REMOVE_OUTPUT_3}'" - exit -1 -fi - -echo "All tests passed." diff --git a/pyCAOM2/COPYING b/pyCAOM2/COPYING deleted file mode 100644 index dba13ed2..00000000 --- a/pyCAOM2/COPYING +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/pyCAOM2/Dependencies.txt b/pyCAOM2/Dependencies.txt deleted file mode 100644 index 7923b46b..00000000 --- a/pyCAOM2/Dependencies.txt +++ /dev/null @@ -1,47 +0,0 @@ -# -# -*- coding: utf-8 -*- -#/*+ -#************************************************************************ -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#* -#* (c) 2012. (c)2012. -#* National Research Council Conseil national de recherches -#* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -#* All rights reserved Tous droits reserves -#* -#* NRC disclaims any warranties, Le CNRC denie toute garantie -#* expressed, implied, or statu- enoncee, implicite ou legale, -#* tory, of any kind with respect de quelque nature que se soit, -#* to the software, including concernant le logiciel, y com- -#* without limitation any war- pris sans restriction toute -#* ranty of merchantability or garantie de valeur marchande -#* fitness for a particular pur- ou de pertinence pour un usage -#* pose. NRC shall not be liable particulier. Le CNRC ne -#* in any event for any damages, pourra en aucun cas etre tenu -#* whether direct or indirect, responsable de tout dommage, -#* special or general, consequen- direct ou indirect, particul- -#* tial or incidental, arising ier ou general, accessoire ou -#* from the use of the software. fortuit, resultant de l'utili- -#* sation du logiciel. -#* -#************************************************************************ -#* -#* Script Name: setup.py -#* -#* Purpose: -#* Distutils setup script for caom2 -#* -#* Functions: -#* -#* -#* -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#************************************************************************ -#-*/ - -Files required for the pyCAOM2 project -==================================================== - -Name in build.xml Versioned Name Project URL ------------------ -------------------- ----------- - diff --git a/pyCAOM2/MANIFEST.in b/pyCAOM2/MANIFEST.in deleted file mode 100644 index 08f21c97..00000000 --- a/pyCAOM2/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include caom2/*.xsd -include caom2/test/data/*.xml diff --git a/pyCAOM2/build.xml b/pyCAOM2/build.xml deleted file mode 100644 index bb37ad87..00000000 --- a/pyCAOM2/build.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pyCAOM2/caom2/__init__.py b/pyCAOM2/caom2/__init__.py deleted file mode 100755 index f35cf4f0..00000000 --- a/pyCAOM2/caom2/__init__.py +++ /dev/null @@ -1,99 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Deines __init__ """ - -# from caom2_algorithm import Algorithm -# from caom2_artifact import Artifact -# from caom2_chunk import Chunk -# from caom2_composite_observation import CompositeObservation -# from caom2_energy import Energy -# from caom2_energy_transition import EnergyTransition -# from caom2_entity import AbstractCaom2Entity -# from caom2_environment import Environment -# from caom2_enums import ProductType, ReleaseType -# from caom2_exceptions import ObservationParsingException -# from caom2_instrument import Instrument -# from caom2_metrics import Metrics -# from caom2_object import Caom2Object -# from caom2_observation import Observation -# from caom2_observation_uri import ObservationURI -# from caom2_part import Part -# from caom2_plane import Plane -# from caom2_plane_uri import PlaneURI -# from caom2_polarization import Polarization -# from caom2_position import Position -# from caom2_proposal import Proposal -# from caom2_provenance import Provenance -# from caom2_simple_observation import SimpleObservation -# from caom2_target import Target -# from caom2_target_position import TargetPosition -# from caom2_telescope import Telescope -# from caom2_time import Time diff --git a/pyCAOM2/caom2/caom2_algorithm.py b/pyCAOM2/caom2/caom2_algorithm.py deleted file mode 100644 index 0fcf7d99..00000000 --- a/pyCAOM2/caom2/caom2_algorithm.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines Algorithm class""" - -from caom2_object import Caom2Object -from util.caom2_util import typeCheck - - -class Algorithm(Caom2Object): - """ - The concept of Algorithm is to provide a way for users to find all - composite observation sets that have been built using a particular - grouping algorithm (eg. the MegaPipe stacks). For simple - observations the algorithm is 'exposure'. - """ - - def __init__(self, name): - """ - Initializes an Algorithm instance - - Arguments: - name : name of the algorithm. Should be 'exposure' if this is a - simple observation, otherwise name of algorithm that selected - composite members or just 'composite' works too. - """ - typeCheck(name, str, "name", override=False) - self._name = name - - def _key(self): - return (self._name) - - def __ne__(self, y): - return not self.__eq__(y) - - # Properties - - @property - def name(self): - """ - algorithm that defines the composite grouping; 'exposure' for - simple observations - """ - return self._name diff --git a/pyCAOM2/caom2/caom2_chunk.py b/pyCAOM2/caom2/caom2_chunk.py deleted file mode 100644 index d93437b2..00000000 --- a/pyCAOM2/caom2/caom2_chunk.py +++ /dev/null @@ -1,361 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""Defines caom2.Chunk class. - -""" - -from caom2_entity import AbstractCaom2Entity -from caom2_enums import ProductType -from wcs.caom2_observable_axis import ObservableAxis -from wcs.caom2_spatial_wcs import SpatialWCS -from wcs.caom2_spectral_wcs import SpectralWCS -from wcs.caom2_polarization_wcs import PolarizationWCS -from wcs.caom2_temporal_wcs import TemporalWCS -import util.caom2_util as util - - -class Chunk(AbstractCaom2Entity): - """A caom2.Chunk object. A chunk is a peice of file part. - - eg. a column in a Table extension of a FITS file. - - The chunk is characterised by world coordinate system (WCS) - metadata plus an extra axis to describe different observables (the - measured values) stored within the data. Different chunks can be - defined which vary only on the range of coordinate values they - include. For example, if a single data array contains different - observable quantities then one can define a chunk (perhaps - representing different slices through a stored array) with each - slice having a different product type. - - Chunks can also be used to define arbitrary tiles in a large data - array; this is useful if there is no WCS solution to describe the - mapping of sky to pixel coordinates but one still wants to be able - to extract smaller sections of the data (e.g. one chunk). - - """ - - def __init__(self, product_type=None, - naxis=None, - position_axis_1=None, - position_axis_2=None, - position=None, - energy_axis=None, - energy=None, - time_axis=None, - time=None, - polarization_axis=None, - polarization=None, - observable_axis=None, - observable=None, - ): - - super(Chunk, self).__init__() - self.product_type = product_type - self.naxis = naxis - self.position_axis_1 = position_axis_1 - self.position_axis_2 = position_axis_2 - self.energy_axis = energy_axis - self.time_axis = time_axis - self.polarization_axis = polarization_axis - self.observable_axis = observable_axis - self.observable = observable - self.position = position - self.energy = energy - self.time = time - self.polarization = polarization - - @property - def product_type(self): - """A word that describes the content of the chunk. - - eg. Chunk.product_type = ProductType('SCIENCE') - - Allowed values: - """ + str(ProductType.names()) + """ - - """ - - return self._product_type - - @product_type.setter - def product_type(self, value): - if isinstance(value, str) and value in ProductType.names(): - ## be helpful - value = ProductType('value') - util.typeCheck(value, ProductType, 'product_type') - self._product_type = value - - @property - def naxis(self): - """There number of dimensions in this chunk. - - type: int - eg: 2 - - """ - return self._naxis - - @naxis.setter - def naxis(self, value): - util.typeCheck(value, int, 'naxis') - util.valueCheck(value, 0, 5, 'naxis') - self._naxis = value - - @property - def position_axis_1(self): - """The first spatial axis (nominally NAXIS1). - - This is the spatial axis whose WCS is connected to CRPIX1, CD1_1, CD2_1 - - eg: position_axis_1 = 1 - type: int - - """ - return self._position_axis_1 - - @position_axis_1.setter - def position_axis_1(self, value): - util.typeCheck(value, int, 'position_axis_1') -# util.valueCheck(value, 0, self.naxis, 'position_axis_1') - self._position_axis_1 = value - - @property - def position_axis_2(self): - """The second spatial axis (nominally NAXIS2). - - This is the spatial axis whose WCS is connected to CRPIX2, - CD2_2, CD1_2 - - eg: position_axis_2 = 2 - type: int - - """ - return self._position_axis_2 - - @position_axis_2.setter - def position_axis_2(self, value): - util.typeCheck(value, int, 'position_axis_2') -# util.valueCheck(value, 0, self.naxis, 'position_axis_2') - self._position_axis_2 = value - - @property - def energy_axis(self): - """The axis in the file that is in the energy direction. - - This should be None if the data does not contain an - energy axis. In this case the energy WCS maps to a - single pixel. - - eg: energy_axis = 3 - type: int - - """ - return self._energy_axis - - @energy_axis.setter - def energy_axis(self, value): - util.typeCheck(value, int, 'energy_axis') -# util.valueCheck(value, 0, self.naxis, 'energy_axis') - self._energy_axis = value - - @property - def time_axis(self): - """The axis in the data chunk that is in the time direction. - - Can and should be None if no time sampling axis exist. - - eg. time_axis = None - type: int - - """ - return self._time_axis - - @time_axis.setter - def time_axis(self, value): - util.typeCheck(value, int, 'polarization_axis') -# util.valueCheck(value, 0, self._naxis, 'polarization_axis') - self._time_axis = value - - @property - def polarization_axis(self): - """The axis in the data chunk that is in the polarization direction. - - Likely None... - - eg. polarization_axis = None - type: int - - """ - return self._polarization_axis - - @polarization_axis.setter - def polarization_axis(self, value): - util.typeCheck(value, int, 'polarization_axis') -# util.valueCheck(value, 0, self._naxis, 'polariztion_axis') - self._polarization_axis = value - - @property - def observable_axis(self): - """Used when on of the dimensions of the file contains?? ? - - type: int - - """ - return self._observable_axis - - @observable_axis.setter - def observable_axis(self, value): - util.typeCheck(value, int, 'obserable_axis') -# util.valueCheck(value, 0, 1E10, 'observable_axis') - self._observable_axis = value - - @property - def observable(self): - """An obserable that is contained in the chunk. - - Observables are quantities that are recorded directly?? - - """ - return self._observable - - @observable.setter - def observable(self, value): - util.typeCheck(value, ObservableAxis, 'observable_axis') - self._observable = value - - @property - def position(self): - """A SpatialWCS object associated with this chunk. - - The spatialWCS describes the relation between the position_axis - values and the world coordinate. - - type: SpatialWCS. - - """ - return self._position - - @position.setter - def position(self, value): - util.typeCheck(value, SpatialWCS, 'position') - self._position = value - - @property - def energy(self): - """A SpectralWCS object associated with this chunk. - - Even if energy_axis is None an SpectralWCS should still - be defined. The SpectalWCS in this case will be one pixel - in dimension. - - type: SpectralWCS - - """ - return self._energy - - @energy.setter - def energy(self, value): - util.typeCheck(value, SpectralWCS, 'energy') - self._energy = value - - @property - def time(self): - """The TemporalWCS object associated with this chunk. - - Even if time_axis is None you should define the TimeWCS - to convey when you observation was taken. - - type: TemporalWCS - - """ - return self._time - - @time.setter - def time(self, value): - util.typeCheck(value, TemporalWCS, 'time') - self._time = value - - @property - def polarization(self): - """The PolarizationWCS of the observation. - - ususally None - - type: PolarizationWCS - - """ - return self._polarization - - @polarization.setter - def polarization(self, value): - util.typeCheck(value, PolarizationWCS, 'polarization') - self._polarization = value diff --git a/pyCAOM2/caom2/caom2_composite_observation.py b/pyCAOM2/caom2/caom2_composite_observation.py deleted file mode 100644 index 0e8cfaf8..00000000 --- a/pyCAOM2/caom2/caom2_composite_observation.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.composite_observation class""" - -from caom2_observation import Observation -from caom2_observation_uri import ObservationURI -from caom2_simple_observation import SimpleObservation -from util.caom2_util import TypedSet - - -class CompositeObservation(Observation): - """ - Composite Observation - - A CompositeObservation is created by collecting data from multiple - SimpleObservations together. - - """ - - def __init__(self, - collection, - observation_id, - algorithm, - sequence_number=None, - intent=None, - obs_type=None, - proposal=None, - telescope=None, - instrument=None, - target=None, - meta_release=None, - planes=None, - environment=None, - target_position=None - ): - if (algorithm == SimpleObservation._ALGORITHM): - raise ValueError( - "E{0} (reserved for SimpleObservation)".format(algorithm)) - super(CompositeObservation, self).__init__(collection, - observation_id, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment, - target_position - ) - self._members = TypedSet((ObservationURI),) - - @property - def algorithm(self): - return super(CompositeObservation, self).algorithm - - @algorithm.setter - def algorithm(self, value): - if value is None: - raise ValueError - if (value == SimpleObservation._ALGORITHM): - raise ValueError("cannot set CompositeObservation.algorithm to {0}" - " (reserved for SimpleObservation)".format(value)) - self._algorithm = value - - @property - def members(self): - return self._members diff --git a/pyCAOM2/caom2/caom2_data_quality.py b/pyCAOM2/caom2/caom2_data_quality.py deleted file mode 100644 index 403350f3..00000000 --- a/pyCAOM2/caom2/caom2_data_quality.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the DataQuality class""" - -from caom2_object import Caom2Object -from caom2_enums import Quality -import caom2.util.caom2_util as util - - -class DataQuality(Caom2Object): - """ DataQuality """ - - def __init__(self, flag): - """ - Construct an DataQuality instance - - Arguments: - flag - """ - self.flag = flag - - @property - def flag(self): - """ flag """ - return self._flag - - @flag.setter - def flag(self, value): - util.typeCheck(value, Quality, "flag") - self._flag = value diff --git a/pyCAOM2/caom2/caom2_energy.py b/pyCAOM2/caom2/caom2_energy.py deleted file mode 100644 index 71f92ac7..00000000 --- a/pyCAOM2/caom2/caom2_energy.py +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""Defines the caom2.Energy object""" - -from caom2_object import Caom2Object -from caom2_energy_transition import EnergyTransition -from caom2_enums import EnergyBand -from types.caom2_interval import Interval - - -class Energy(Caom2Object): - """ Energy """ - - def __init__(self): - """ - Initialize an Energy instance. - - Arguments: - None - """ - self._value = None - self._bounds = None - self._dimension = None - self._resolving_power = None - self._sample_size = None - self._bandpass_name = None - self._em_band = None - self._transition = None - - # Properties - @property - def value(self): - """ Energy value """ - return self._value - - @value.setter - def value(self, value): - if value is not None: - assert isinstance(value, float), ( - "energy value is not a float: {0}".format(value)) - self._value = value - - @property - def bounds(self): - """ Energy bounds """ - return self._bounds - - @bounds.setter - def bounds(self, value): - if value is not None: - assert isinstance(value, Interval), ( - "energy bounds is not an Interval: {0}".format(value)) - self._bounds = value - - @property - def dimension(self): - """DIMENSION (NUMBER OF PIXELS) ALONG ENERGY AXIS.""" - return self._dimension - - @dimension.setter - def dimension(self, value): - if value is not None: - assert isinstance(value, long), ( - "energy dimension is not a long: {0}".format(value)) - self._dimension = value - - @property - def resolving_power(self): - """ Resolving power """ - return self._resolving_power - - @resolving_power.setter - def resolving_power(self, value): - if value is not None: - assert isinstance(value, float), ( - "resolving power is not a float: {0}".format(value)) - self._resolving_power = value - - @property - def sample_size(self): - """ Sample size """ - return self._sample_size - - @sample_size.setter - def sample_size(self, value): - if value is not None: - assert isinstance(value, float), ( - "sample size is not a float: {0}".format(value)) - self._sample_size = value - - @property - def bandpass_name(self): - """ Bandpass name """ - return self._bandpass_name - - @bandpass_name.setter - def bandpass_name(self, value): - if value is not None: - assert isinstance(value, str), ( - "bandpass name is not str: {0}".format(value)) - self._bandpass_name = value - - @property - def em_band(self): - """ EM Band """ - return self._em_band - - @em_band.setter - def em_band(self, value): - if value is not None: - assert isinstance(value, EnergyBand), ( - "em_Band is not an EnergyBand: {0}".format(value)) - self._em_band = value - - @property - def transition(self): - """ Energy transition """ - return self._transition - - @transition.setter - def transition(self, value): - if value is not None: - assert isinstance(value, EnergyTransition), ( - "transition is not an EnergyTransition: {0}".format(value)) - self._transition = value diff --git a/pyCAOM2/caom2/caom2_energy_transition.py b/pyCAOM2/caom2/caom2_energy_transition.py deleted file mode 100644 index 21fcf5aa..00000000 --- a/pyCAOM2/caom2/caom2_energy_transition.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the EnergyTransition class""" - -from caom2_object import Caom2Object -import util.caom2_util as util - - -class EnergyTransition(Caom2Object): - """ EnergyTransition """ - - def __init__(self, species, transition): - """ - Construct an EnergyTransition instance - - Arguments: - species - transition - """ - util.typeCheck(species, str, "species", override=False) - util.typeCheck(transition, str, "transition", override=False) - self._species = species - self._transition = transition - - @property - def species(self): - """ Species """ - return self._species - - @property - def transition(self): - """ Transition """ - return self._transition diff --git a/pyCAOM2/caom2/caom2_entity.py b/pyCAOM2/caom2/caom2_entity.py deleted file mode 100644 index 34bc3a9b..00000000 --- a/pyCAOM2/caom2/caom2_entity.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the AbstractCaom2Entity class""" - -import random -import time -import uuid -from datetime import datetime -from caom2_object import Caom2Object -from caom2.util.caom2_util import long2uuid - - -class AbstractCaom2Entity(Caom2Object): - """Class that defines the persistence unique ID and last mod date """ - - def __init__(self, fulluuid=False): - self._id = AbstractCaom2Entity._gen_id(fulluuid) - self._last_modified = AbstractCaom2Entity._gen_last_modified() - - @classmethod - def _gen_id(cls, fulluuid=False): - """Generate a 128 but UUID by default. For backwards compatibility - allow creation of a 64 bit UUID using a rand number for the - lower 64 bits. First two bytes of the random number are generated - with the random and the last 6 bytes from the current time - in microseconds. - - return: UUID - """ - - if fulluuid: - return uuid.uuid4() - else: - vmrandom = random.randint(-int(0x7fff), int(0x7fff)) << 8 * 6 - randtime = int(round(time.time() * 1000000)) - randtime = randtime & 0xffffffffffff - rand = vmrandom | randtime - if rand & 0x8000000000000000: - rand = 0x1000000000000000 + rand - return long2uuid(rand) - - @classmethod - def _gen_last_modified(cls): - """Generate a datetime with 3 digit microsecond precision. - - return: datatime - IVOA date format to millisecond precision. - """ - now = datetime.now() - return datetime(now.year, now.month, now.day, now.hour, now.minute, \ - now.second, long(str(now.microsecond)[:-3] + '000')) diff --git a/pyCAOM2/caom2/caom2_enums.py b/pyCAOM2/caom2/caom2_enums.py deleted file mode 100644 index 871a1f03..00000000 --- a/pyCAOM2/caom2/caom2_enums.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""A set of variables that describe the limited range -of allowed values for various caom2 quantities. """ - - -from enum import Enum - -CalibrationLevel = Enum('CalibrationLevel', - RAW_INSTRUMENT=0, - RAW_STANDARD=1, - CALIBRATED=2, - PRODUCT=3) - -DataProductType = Enum('DataProductType', - IMAGE="image", - CATALOG="catalog", - CUBE="cube", - EVENTLIST="eventlist", - SPECTRUM="spectrum", - TIMESERIES="timeseries", - VISIBILITY="visibility") - -EnergyBand = Enum('EnergyBand', - EUV="EUV", - GAMMARAY="Gamma-ray", - INFRARED="Infrared", - MILLIMETER="Millimeter", - OPTICAL="Optical", - RADIO="Radio", - UV="UV", - XRAY="X-ray") - -ObservationIntentType = Enum('ObservationIntentType', - CALIBRATION="calibration", - SCIENCE="science") - -PolarizationState = Enum('PolarizationState', - I="I", - Q="Q", - U="U", - V="V", - LL="LL", - LR="LR", - RL="RL", - RR="RR", - XX="XX", - XY="XY", - YX="YX", - YY="YY") - -ProductType = Enum('ProductType', - SCIENCE="science", - CALIBRATION="calibration", - PREVIEW="preview", - INFO="info", - NOISE="noise", - WEIGHT="weight", - AUXILIARY="auxiliary", - THUMBNAIL="thumbnail", - ) - -ReleaseType = Enum('ReleaseType', - DATA="data", - META="meta") - -SegmentType = Enum('SegmentType', - CLOSE=0, - LINE=1, - MOVE=2) - -TargetType = Enum('TargetType', - FIELD="field", - OBJECT="object") - -Quality = Enum('Quality', - JUNK="junk") - -Status = Enum('Status', - FAIL="fail") diff --git a/pyCAOM2/caom2/caom2_environment.py b/pyCAOM2/caom2/caom2_environment.py deleted file mode 100644 index 5cc02be1..00000000 --- a/pyCAOM2/caom2/caom2_environment.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" -Defines the caom2.Environment class, populates the caom2_environment values -""" - -from caom2_object import Caom2Object -import util.caom2_util as util - - -class Environment(Caom2Object): - """A CAOM2 Environment Object. - - This object contains the various values that can be set in the environment - table entry. Normally each Observation object will have an associate - Environment Object.""" - - def __init__(self): - """ - Initializes an Environment instance - - Arguments: - """ - self._seeing = None - self._humidity = None - self._elevation = None - self._tau = None - self._wavelength_tau = None - self._ambient_temp = None - self._photometric = None - - # Properties - @property - def seeing(self): - """atmospheric seeing (FWHM) in arcsec. - - units: arcseconds - """ - return self._seeing - - @seeing.setter - def seeing(self, value): - util.typeCheck(value, float, 'seeing') - util.valueCheck(value, 0, 360 * 3600.0, 'seeing') - self._seeing = value - - @property - def humidity(self): - """Relative humidity, expressed as a fraction between 0 and 200. - - units: fraction - """ - return self._humidity - - @humidity.setter - def humidity(self, value): - # set the humidity to value, which must be +ve fraction less than 200 - util.typeCheck(value, float, 'humidity') - util.valueCheck(value, 0, 200, 'humidity') - self._humidity = value - - @property - def elevation(self): - """ Elevation above horizon (0 to 90 deg) at which tau was measured. - - units: deg - """ - return self._elevation - - @elevation.setter - def elevation(self, value): - util.typeCheck(value, float, 'elevation') - util.valueCheck(value, 0, 90, 'elevation') - self._elevation = value - - @property - def tau(self): - """The tau at zennith at the time of observation. - - units: fraction - - This tau can be used, in combination with the elevation, - to determine the actual tau.""" - return self._tau - - @tau.setter - def tau(self, value): - util.typeCheck(value, float, 'tau') - util.valueCheck(value, 0, 1, 'tau') - self._tau = value - - @property - def wavelength_tau(self): - """Wavelength at which tau was measured - (normally 225GHz converted to wavelength). - - units: meters - - """ - return self._wavelength_tau - - @wavelength_tau.setter - def wavelength_tau(self, value): - util.typeCheck(value, float, 'wavelength_tau') - util.valueCheck(value, 0, 1E3, 'wavelength_tau') - self._wavelength_tau = value - - @property - def ambient_temp(self): - """The ambient air temperature at time of observation. - - unit: Celsius degrees - """ - return self._ambient_temp - - @ambient_temp.setter - def ambient_temp(self, value): - util.typeCheck(value, float, 'ambient_temp') - util.valueCheck(value, -100, 100, 'ambient_temp') - self._ambient_temp = value - - @property - def photometric(self): - """A boolean flag (True/False) indicating if - the observational conditions were photometric.""" - return self._photometric - - @photometric.setter - def photometric(self, value): - util.typeCheck(value, bool, 'photometric') - self._photometric = value diff --git a/pyCAOM2/caom2/caom2_exceptions.py b/pyCAOM2/caom2/caom2_exceptions.py deleted file mode 100644 index 6dad5bee..00000000 --- a/pyCAOM2/caom2/caom2_exceptions.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""A caom2 exception class for catching""" - - -class ObservationParsingException(Exception): - pass diff --git a/pyCAOM2/caom2/caom2_instrument.py b/pyCAOM2/caom2/caom2_instrument.py deleted file mode 100644 index 6b528a37..00000000 --- a/pyCAOM2/caom2/caom2_instrument.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""contains the definition of the caom2.Instrument object""" - -import util.caom2_util as util -from caom2_object import Caom2Object - - -class Instrument(Caom2Object): - """The telescopic instrument that recorded a given observation. - - Each observation should have an associated instrument. - - eg: - inst=caom2.Observation('CFHT','123456p','exposure').Instrument("MEGAPRIME") - - Each instrument can have list of keywords. - eg. - inst.keywords.append("shutter=closed") - """ - - def __init__(self, name): - """ - Initializes a Instrument instance - - Arguments: - name - name of the instrument - """ - util.typeCheck(name, str, 'name', override='none') - self._name = name - self._keywords = set() - - # Properties - @property - def name(self): - """The name of the instrument. - - type: str - """ - return self._name - - @property - def keywords(self): - """A set of strings that are keywords associated with the instrument. - - eg. keywords.append(("ccd=off","hot","shutter broken")) - - Keywords are stored as text in the database and are searched as text, - so in the above example you can search for ccd=off but that is just - matching the text 'ccd=off' and you can not do 'ccd!=on' to find that - key/value pair. - - Also, the list is concated together and inserted into the - model as a single text field, so keywords like 'shutter - broken' will match 'shutter' and 'broken'. If these keywords - appear in a pick list 'shutter' and 'broken' will be seperate - entries. So shutter_broken is a better choice. - """ - return self._keywords diff --git a/pyCAOM2/caom2/caom2_metrics.py b/pyCAOM2/caom2/caom2_metrics.py deleted file mode 100644 index 6b7ce616..00000000 --- a/pyCAOM2/caom2/caom2_metrics.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""definition of the caom2.Metrics object""" - -from caom2_object import Caom2Object -import util.caom2_util as util - - -class Metrics(Caom2Object): - """ Metrics """ - - def __init__(self): - """ - Initializes a Metrics instance - - Arguments: - None - """ - self._source_number_density = None - self._background = None - self._background_std_dev = None - self._flux_density_limit = None - self._mag_limit = None - - # Properties - @property - def source_number_density(self): - """The number of sources brighter than mag_limit (flux_density_limit) - - unit: ct/deg2 - type: float - """ - return self._source_number_density - - @source_number_density.setter - def source_number_density(self, value): - util.typeCheck(value, float, "source_number_density") - util.valueCheck(value, 0, 1E10, "source_number_density") - self._source_number_density = value - - @property - def background(self): - """The flux in the sky (background). - - units: Jy/pix - type: float - """ - return self._background - - @background.setter - def background(self, value): - util.typeCheck(value, float, "background") - util.valueCheck(value, 0, 1E10, "background") - self._background = value - - @property - def background_std_dev(self): - """the standard deviation (per pixel) in background flux. - - Likely this only makes sense to define if background is also defined. - units: Jy/pix - type: float - """ - return self._background_std_dev - - @background_std_dev.setter - def background_std_dev(self, value): - util.typeCheck(value, float, "background_std_dev") - util.valueCheck(value, 0, 1E10, "background") - self._background_std_dev = value - - @property - def flux_density_limit(self): - """flux density where S:N=5 for point source. - - this is intended to provide a measure of the limit of detection. - - units: Jy - type: float - """ - return self._flux_density_limit - - @flux_density_limit.setter - def flux_density_limit(self, value): - util.typeCheck(value, float, "flux_denisty_limit") - util.valueCheck(value, 0, 1E10, "flux_density_limit") - self._flux_density_limit = value - - @property - def mag_limit(self): - """AB magnitude limit where S:N=5 for point source. - - Likely specify just mag_limit or flux_density_limit, not both? - - units: AB mag - type: float - """ - return self._mag_limit - - @mag_limit.setter - def mag_limit(self, value): - util.typeCheck(value, float, 'mag_limit') - util.valueCheck(value, 0, 40, 'mag_limit') - self._mag_limit = value diff --git a/pyCAOM2/caom2/caom2_object.py b/pyCAOM2/caom2/caom2_object.py deleted file mode 100644 index 14011b07..00000000 --- a/pyCAOM2/caom2/caom2_object.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Caom2Object class""" - -import inspect - - -class Caom2Object(object): - """ - setup all objects with the same generic equality, str and repr methods - """ - - def __init__(self): - pass - - def __str__(self): - args = inspect.getargspec(self.__init__).args[1:] - clsName = self.__class__.__name__ - return "\n".join( - ["{}.{} : {}".format(clsName, - arg, - getattr(self, arg, None)) - for arg in args]) - - def __eq__(self, other): - if type(other) == type(self): - return self.__dict__ == other.__dict__ - else: - return False - - def __repr__(self): - args = inspect.getargspec(self.__init__).args[1:] - clsName = "" - if self.__class__.__module__ != '__main__': - clsName += self.__class__.__module__ + "." - clsName += self.__class__.__name__ - pading = " " * (len(clsName) + 1) - return clsName + "(" + ( - ",\n" + pading).join( - ["%s=%r" % (arg, getattr(self, arg, None) - ) for arg in args - ] - ) + ")" diff --git a/pyCAOM2/caom2/caom2_observation.py b/pyCAOM2/caom2/caom2_observation.py deleted file mode 100644 index 6ff2e650..00000000 --- a/pyCAOM2/caom2/caom2_observation.py +++ /dev/null @@ -1,435 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""definition of the caom2.Observation object.""" - -from datetime import datetime - -from caom2_entity import AbstractCaom2Entity -from caom2_algorithm import Algorithm -from caom2_environment import Environment -from caom2_instrument import Instrument -from caom2_plane import Plane -from caom2_proposal import Proposal -from caom2.caom2_requirements import Requirements -from caom2_target import Target -from caom2_target_position import TargetPosition -from caom2_telescope import Telescope -from caom2_observation_uri import ObservationURI -from caom2_enums import ObservationIntentType -from util.caom2_util import TypedOrderedDict -from util import caom2_util as util - - -class Observation(AbstractCaom2Entity): - """ - Observation - - An observation describes a set of empirical data. - - The CAOM2 observation is described at: - http://www.cadc.hia.nrc.gc.ca/caom2 - - The Observation object is the top level container for the - meta-data assocaited with an observation. The variaous attributes - described here provide ways of storing the complete set of - associated meta-data as well as links to the actual observation - data. - - Observation -> Target - -> Plane(s) - -> Instrument - -> Telescope - -> Proposal - -> Environment - -> TargetPosition - - Plane -> Artifact(s) - - Artifact -> Part(s) - - Part -> Chunk(s) - - The actual 'chunks' of observational data are reference by Chunk - objects. Information about the Spatial/Frequency/Time aspects of - an Observation are expressed at the Chunk level. - - The Chunk contains refernces to caom2 objects that fully describe - the circumstances of that chunk of observation. Often a 'Chunk' - is a single extension in a FITS image. But can also be a - particular column of values from a FITS Table or some other data - object. - - Chunk -> SpatialWCS - -> TemporalWCS - -> SpectralWCS - -> PolarizationWCS - -> (Observable) - """ - - def __init__(self, - collection, - observation_id, - algorithm, - sequence_number=None, - intent=None, - obs_type=None, - proposal=None, - telescope=None, - instrument=None, - target=None, - meta_release=None, - planes=None, - environment=None, - target_position=None, - requirements=None - ): - """ - Initializes an Observation instance - - Arguments: collection : where the observation is from - (eg. 'HST') - - observation_id : a unique identifier within that collection - (eg. '111') - - algorithm : the algorithm used to create the observation. For - a telescope observation this is always 'exposure' - """ - super(Observation, self).__init__() - - self.collection = collection - self.observation_id = observation_id - self.algorithm = algorithm - - self.uri = ObservationURI.get_observation_uri(collection, - observation_id) - - self.sequence_number = sequence_number - self.intent = intent - self.obs_type = obs_type - self.proposal = proposal - self.telescope = telescope - self.instrument = instrument - self.target = target - self.environment = environment - self.target_position = target_position - self.requirements = requirements - self.meta_release = meta_release - if planes is None: - planes = TypedOrderedDict((Plane),) - self.planes = planes - - # Properties - @property - def collection(self): - """The name of the collection of observations, normally a telescope - name. - - type: str - """ - return self._collection - - @collection.setter - def collection(self, value): - util.typeCheck(value, str, 'collection', override=False) - self._collection = value - - @property - def observation_id(self): - """A string that uniquely identifies this obseravtion within the given - collection. - - type: str - """ - return self._observation_id - - @observation_id.setter - def observation_id(self, value): - util.typeCheck(value, str, 'observation_id', override=False) - self._observation_id = value - - @property - def uri(self): - """A URI for this observation referenced in the caom system. - - This attribute is auto geneqrated from the other metadata. - type: str - """ - return self._uri - - @uri.setter - def uri(self, value): - util.typeCheck(value, ObservationURI, 'uri') - self._uri = value - - @property - def planes(self): - """A typed ordered dictionary containing plane objects associated with - this observations. - - see caom2.Plane for details about a creating a plane. - - type: TypedOrderDict((Plane),) - - eg. Observation.planes.add(Plane("SCIENCE")) - """ - return self._planes - - @planes.setter - def planes(self, value): - util.typeCheck(value, TypedOrderedDict, 'planes') - self._planes = value - - @property - def algorithm(self): - """The process that was used to select this observation. - - normally 'exposure' for an observation or the name of a group - process for a composite observation""" - return self._algorithm - - @algorithm.setter - def algorithm(self, value): - if isinstance(value, str): - value = Algorithm(value) - util.typeCheck(value, Algorithm, 'algorithm') - self._algorithm = value - - @property - def intent(self): - """The original intent of having this data. - - type: ObservationIntentType - - see ObservationIntentType.names() for allowed values - - """ - return self._intent - - @intent.setter - def intent(self, value): - if isinstance(value, str): - value = ObservationIntentType(value) - util.typeCheck(value, ObservationIntentType, 'intent') - self._intent = value - - @property - def sequence_number(self): - """An integer counter that reprsents this observation within a - collection. eg. EXPNUM type: int - """ - return self._sequence_number - - @sequence_number.setter - def sequence_number(self, value): - util.typeCheck(value, int, 'sequence_number') - self._sequence_number = value - - @property - def obs_type(self): - """The OBSTYPE of the observation being recorded. - - eg. OBJECT, FLAT, BIAS - type: str - """ - return self._obs_type - - @obs_type.setter - def obs_type(self, value): - util.typeCheck(value, str, 'obs_type') - self._obs_type = value - - @property - def proposal(self): - """Refence to a Proposal object that describe the science proposal - that lead to this observation. - - can be None - see caom2.Proposal for help on building a Proposal object - type: caom2.Proposal - """ - return self._proposal - - @proposal.setter - def proposal(self, value): - util.typeCheck(value, Proposal, "proposal") - self._proposal = value - - @property - def telescope(self): - """Reference to a Telescope object associated with this observation. - - can be None - type: caom2.Telescope - """ - return self._telescope - - @telescope.setter - def telescope(self, value): - util.typeCheck(value, Telescope, 'telescope') - self._telescope = value - - @property - def instrument(self): - """Reference to an Instrument object associated with this observation. - - can be None - type: caom2.Instrument - """ - return self._instrument - - @instrument.setter - def instrument(self, value): - if isinstance(value, str): - value = Instrument(str) - util.typeCheck(value, Instrument, "instrument") - self._instrument = value - - @property - def target(self): - """Reference to a Target object associted with this observation. - - can be None - type: caom2.Target - """ - return self._target - - @target.setter - def target(self, value): - if isinstance(value, str): - value = Target(str) - util.typeCheck(value, Target, 'target') - self._target = value - - @property - def environment(self): - """Reference to an Environment object associated with this - observation. - - can be None - type: caom2.Environment - """ - return self._environment - - @environment.setter - def environment(self, value): - util.typeCheck(value, Environment, 'environment') - self._environment = value - - @property - def target_position(self): - """Reference to a TargetPosition object associated - with this observation. - - can be None - type: caom2.TargetPosition - """ - return self._target_position - - @target_position.setter - def target_position(self, value): - util.typeCheck(value, TargetPosition, 'target_position') - self._target_position = value - - @property - def requirements(self): - """Reference to a Requirements object associated - with this observation. - - can be None - type: caom2.Requirements - """ - return self._requirements - - @requirements.setter - def requirements(self, value): - util.typeCheck(value, Requirements, 'requirements') - self._requirements = value - - @property - def meta_release(self): - """A datetime value indicating when the meta-data of this observation - is publicly accessible. - - This only controls access to the information about the - observation. Access to the observational data is controlled - via the Plane.data_release attribute (see the planes - attribute). - - eg. '2012/11/28 12:00:00' - type: datatime - """ - return self._meta_release - - @meta_release.setter - def meta_release(self, value): - util.typeCheck(value, datetime, 'meta_release') - self._meta_release = value diff --git a/pyCAOM2/caom2/caom2_plane.py b/pyCAOM2/caom2/caom2_plane.py deleted file mode 100644 index 23e6f182..00000000 --- a/pyCAOM2/caom2/caom2_plane.py +++ /dev/null @@ -1,360 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.Plane class""" - - -from caom2_entity import AbstractCaom2Entity -from caom2_artifact import Artifact -from caom2_metrics import Metrics -from caom2_provenance import Provenance -from caom2_data_quality import DataQuality -from caom2_enums import CalibrationLevel -from caom2_enums import DataProductType -from util.caom2_util import TypedOrderedDict -from datetime import datetime -from caom2.util import caom2_util as util - - -class Plane(AbstractCaom2Entity): - """ Plane class """ - - def __init__(self, product_id, - artifacts=None, - meta_release=None, - data_release=None, - data_product_type=None, - calibration_level=None, - provenance=None, - metrics=None, - quality=None): - """ - Initialize a Plane instance - - Arguments: - product_id : product ID - """ - super(Plane, self).__init__() - self.product_id = product_id - if artifacts is None: - artifacts = TypedOrderedDict((Artifact),) - self.artifacts = artifacts - - self.meta_release = meta_release - self.data_release = data_release - self.data_product_type = data_product_type - self.calibration_level = calibration_level - self.provenance = provenance - self.metrics = metrics - self.quality = quality - - # computed fields - # aggregated from the Chunks during ingestion - self._position = None - self._energy = None - self._time = None - self._polarization = None - - def _key(self): - return (self.product_id) - - def __hash__(self): - return hash(self._key()) - - # Properties - @property - def product_id(self): - """A string that identifies the data product, within a given - observation, that is stored in this plane. - - eg: '1234567p' - type: str - """ - return self._product_id - - @product_id.setter - def product_id(self, value): - util.typeCheck(value, str, 'product_id', override=False) - self._product_id = value - - @property - def key(self): - """ The dictionary key for a plane is product ID """ - return self._product_id - - @property - def artifacts(self): - """A TypeList of artifacts that are part of this plane. - - individual artifacts are constructed and then added to the plane. - - eg. Plane.artifacts.add(Artifact('ad:CFHT/1234567p')), see the - Arifact help for more info on making an Aritfact object return - """ - return self._artifacts - - @artifacts.setter - def artifacts(self, value): - util.typeCheck(value, TypedOrderedDict, 'artifacts', override=False) - self._artifacts = value - - @property - def meta_release(self): - """The date when the metadata describing this observation become - public. - - eg. Plane.meta_releaes=datetime.datetime(2012,1,1,0,0,0) - indicates that the metadata become public at 00:00:00 on - January 1st 2012. - - if there is no meta_release period, set value to None - - unit: calendar date - type: datetime - """ - return self._meta_release - - @meta_release.setter - def meta_release(self, value): - util.typeCheck(value, datetime, 'meta_release') - util.valueCheck(value, - datetime(1800, 1, 1, 0, 0, 0), - datetime(2050, 1, 1, 0, 0, 0), - 'meta_release') - self._meta_release = value - - @property - def data_release(self): - """The date when the data contained in this plane become public. - - eg. Plane.data_releaes=datetime.datetime(2012,1,1,0,0,0) - indicates that ar 00:00:00 on January 1st 2012 the data - assocaited with this Plane will become publicly accessible. - - If there is no data_release period, set value to None. - - unit: calendar date - type: datetime - """ - return self._data_release - - @data_release.setter - def data_release(self, value): - util.typeCheck(value, datetime, 'data_release') - util.valueCheck(value, - datetime(1800, 1, 1, 0, 0, 0), - datetime(2050, 1, 1, 0, 0, 0), - 'data_release') - self._data_release = value - - @property - def data_product_type(self): - """The type of file structure that this plane contains. - - eg. - Plane.data_product_type = 'EVENTLIST' - - see DataProductType.names() for allowed values - - """ - return self._data_product_type - - @data_product_type.setter - def data_product_type(self, value): - util.typeCheck(value, DataProductType, 'data_product_type') - self._data_product_type = value - - @property - def calibration_level(self): - """a string that represents the level of calibration (aka processing) - the data contained in this plane have received. The string - is converted to an integer during storage. - - eg. Plane.calibration_level = "RAW_STANDARD" - type: str - - Must be one of CalibrationLevel.names() - - """ - return self._calibration_level - - @calibration_level.setter - def calibration_level(self, value): - util.typeCheck(value, CalibrationLevel, "calibration_level") - self._calibration_level = value - - @property - def provenance(self): - """The process that created the data referred to by this Plane. - - eg. Plane.provenance=caom2.Provenance("Elixir") - """ - return self._provenance - - @provenance.setter - def provenance(self, value): - util.typeCheck(value, Provenance, "provenance") - self._provenance = value - - @property - def metrics(self): - """reference to an object that contains metrics of this plane. - - eg. Plane.metrics = caom2.Metrics() - """ - return self._metrics - - @metrics.setter - def metrics(self, value): - util.typeCheck(value, Metrics, 'metrics') - self._metrics = value - - @property - def quality(self): - """reference to an object that describes the quality of the data of this plane. - - eg. Plane.data_quality = caom2.DataQuality() - """ - return self._quality - - @quality.setter - def quality(self, value): - util.typeCheck(value, DataQuality, 'quality') - self._quality = value - - #@property - #def observable(self): - # """ """ - # return self._observable - - @property - def position(self): - """A caom2 Position object that is developed from - the agregation of the Chunks that are children of - the Plane. - - agregation happens during ingest and is not part - of the python module at this time. - """ - return self._position - - @property - def energy(self): - """A caom2 Energy object that is developed from - the agregation of the Chunks that are children of - the Plane. - - agregation happens during ingest and is not part - of the python module at this time. - """ - """ Energy """ - return self._energy - - @property - def time(self): - """A caom2 Time object that is developed from - the agregation of the Chunks that are children of - the Plane. - - agregation happens during ingest and is not part - of the python module at this time. - """ - """ Time """ - return self._time - - @property - def polarization(self): - """A caom2 Polarization object that is developed from - the agregation of the Chunks that are children of - the Plane. - - agregation happens during ingest and is not part - of the python module at this time. - """ - return self._polarization - - # Compute derived fields - - def compute_position(self): - raise NotImplementedError( - "Aggregation of position has not been implemented in this module") - - def compute_energy(self): - raise NotImplementedError( - "Aggregation of energy has not been implemented in this module") - - def compute_time(self): - raise NotImplementedError( - "Aggregation of time has not been implemented in this module") - - def compute_polarization(self): - raise NotImplementedError( - "Aggregation of polarization " + - "has not been implemented in this module") diff --git a/pyCAOM2/caom2/caom2_plane_uri.py b/pyCAOM2/caom2/caom2_plane_uri.py deleted file mode 100644 index a943b207..00000000 --- a/pyCAOM2/caom2/caom2_plane_uri.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.PlaneURI class""" - -from caom2_observation_uri import ObservationURI -from util.caom2_util import validate_path_component -from urlparse import urlsplit -from urlparse import SplitResult -from caom2_object import Caom2Object -import util.caom2_util as util - - -class PlaneURI(Caom2Object): - """ Plane URI """ - - def __init__(self, uri): - """ - Initializes an Plane instance - - Arguments: - uri : URI corresponding to the plane - - Throws: - TypeError : if uri is not a string - ValueError : if uri is invalid - ValueError : if the uri is valid but does not contain the expected - fields (collection, observation_id and product_id) - """ - - self.uri = uri - - def _key(self): - return (self.uri) - - def __hash__(self): - return hash(self._key()) - - @classmethod - def get_plane_uri(cls, observation_uri, product_id): - """ - Initializes an Plane URI instance - - Arguments: - observation_uri : the uri of the observation - product_id : ID of the product - """ - util.typeCheck(observation_uri, ObservationURI, "observation_uri", - override=False) - util.typeCheck(product_id, str, "observation_uri", override=False) - validate_path_component(cls, "product_id", product_id) - - path = urlsplit(observation_uri.uri).path - uri = SplitResult(ObservationURI._SCHEME, "", path + "/" + - product_id, "", "").geturl() - return cls(uri) - - # Properties - @property - def uri(self): - """A uri that locates the plane object inside caom""" - return self._uri - - @uri.setter - def uri(self, value): - - util.typeCheck(value, str, "uri", override=False) - tmp = urlsplit(value) - - if tmp.scheme != ObservationURI._SCHEME: - raise ValueError("{} doesn't have an allowed scheme".format(value)) - if tmp.geturl() != value: - raise ValueError("Failed to parse uri correctly: {}".format(value)) - - (collection, observation_id, product_id) = tmp.path.split("/") - - if product_id is None: - raise ValueError("Faield to get product ID from uri: {}" - .format(value)) - - self._product_id = product_id - self._observation_uri = \ - ObservationURI.get_observation_uri(collection, - observation_id) - self._uri = value - - @property - def product_id(self): - """the product_id associated with this plane""" - return self._product_id - - @property - def observation_uri(self): - """The uri that can be used to find the caom2 observation object that - this plane belongs to""" - return self._observation_uri diff --git a/pyCAOM2/caom2/caom2_polarization.py b/pyCAOM2/caom2/caom2_polarization.py deleted file mode 100644 index c5c97e3e..00000000 --- a/pyCAOM2/caom2/caom2_polarization.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.Polarization class""" - -from caom2_object import Caom2Object -import util.caom2_util as util - - -class Polarization(Caom2Object): - """ Polarization """ - - def __init__(self, - dimension=None, - polarization_states=None): - """ - Initialize a Polarization instance. - - Arguments: - None - """ - self.dimension = dimension - self.polarization_states = polarization_states - - # Properties - @property - def dimension(self): - """number of samples (pixels) along polarization axis. - - unit: pix - type: int - """ - return self._dimension - - @dimension.setter - def dimension(self, value): - util.typeCheck(value, int, 'dimension') - util.valueCheck(value, 0, 1E10, 'dimension') - self._dimension = value - - -# TODO implement list of PolarizationState enums diff --git a/pyCAOM2/caom2/caom2_position.py b/pyCAOM2/caom2/caom2_position.py deleted file mode 100644 index 8ca74d3b..00000000 --- a/pyCAOM2/caom2/caom2_position.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.Position class""" - -from types.caom2_box import Box -from types.caom2_circle import Circle -from types.caom2_polygon import Polygon -from wcs.caom2_dimension2d import Dimension2D -from caom2_object import Caom2Object - - -class Position(Caom2Object): - """ Position """ - - def __init__(self, bounds=None, - dimension=None, - resolution=None, - sample_size=None, - time_dependent=None - ): - """ - Initialize a Position instance. - - Arguments: - None - """ - self.bounds = bounds - self.dimension = dimension - self.resolution = resolution - self.sample_size = sample_size - self.time_dependent = time_dependent - - # Properties - - @property - def bounds(self): - """ Bounds """ - return self._bounds - - @bounds.setter - def bounds(self, value): - if value is not None: - assert isinstance(value, (Box, Circle, Polygon)), ( - "bounds is not a Shape: {0}".format(value)) - self._bounds = value - - @property - def dimension(self): - """ Dimension """ - return self._dimension - - @dimension.setter - def dimension(self, value): - if value is not None: - assert isinstance(value, Dimension2D), ( - "dimension is not a Dimension2D: {0}".format(value)) - self._dimension = value - - @property - def resolution(self): - """ Resolution """ - return self._resolution - - @resolution.setter - def resolution(self, value): - if value is not None: - assert isinstance(value, float), ( - "resolution is not a float: {0}".format(value)) - self._resolution = value - - @property - def sample_size(self): - """ Sample size """ - return self._sample_size - - @sample_size.setter - def sample_size(self, value): - if value is not None: - assert isinstance(value, float), ( - "sample size is not a float: {0}".format(value)) - self._sample_size = value - - @property - def time_dependent(self): - """ Time dependent """ - return self._time_dependent - - @time_dependent.setter - def time_dependent(self, value): - if value is not None: - assert isinstance(value, bool), ( - "time dependent is not a bool: {0}".format(value)) - self._time_dependent = value diff --git a/pyCAOM2/caom2/caom2_proposal.py b/pyCAOM2/caom2/caom2_proposal.py deleted file mode 100644 index 083e09be..00000000 --- a/pyCAOM2/caom2/caom2_proposal.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Proposal class""" - -from caom2_object import Caom2Object -from util.caom2_util import TypedList -import util.caom2_util as util - - -class Proposal(Caom2Object): - """ Proposal """ - - def __init__(self, - proposal_id, - pi_name=None, - project=None, - title=None): - """ - Initializes a Proposal instance - - Arguments: - myId : id of the proposal - """ - - self.proposal_id = proposal_id - self.pi_name = pi_name - self.project = project - self.title = title - - self.keywords = set() - - # Properties - - @property - def id(self): - """The proposal ID. Sometimes also called a RUNID. - - type: str - """ - return self._proposal_id - - @id.setter - def proposal_id(self, value): - util.typeCheck(value, str, 'id') - self._proposal_id = value - - @property - def keywords(self): - """A Set of keywords connected to this proposal. - - keywords are stored as a string of words and do not need to be - key/value pairs. - - eg. Proposal.keywords.add('galaxies') - - type: set - """ - return self._keywords - - @keywords.setter - def keywords(self, value): - util.typeCheck(value, set, 'keywords', override=False) - self._keywords = value - - @property - def pi_name(self): - """The name (First Last) of the Principle Investigator of the - Proposal. - - type: str - """ - return self._pi_name - - @pi_name.setter - def pi_name(self, value): - util.typeCheck(value, str, 'pi_name') - self._pi_name = value - - @property - def project(self): - """The name of a project associated with this proposal. - - type: str - """ - return self._project - - @project.setter - def project(self, value): - util.typeCheck(value, str, 'project') - self._project = value - - @property - def title(self): - """The title of the proposal. - - type: str - """ - return self._title - - @title.setter - def title(self, value): - util.typeCheck(value, str, 'title') - self._title = value diff --git a/pyCAOM2/caom2/caom2_provenance.py b/pyCAOM2/caom2/caom2_provenance.py deleted file mode 100644 index 6869d94e..00000000 --- a/pyCAOM2/caom2/caom2_provenance.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Provenance class""" - -from datetime import datetime -from urlparse import urlsplit - -from caom2_object import Caom2Object -from caom2_plane_uri import PlaneURI -from util.caom2_util import TypedSet -from util.caom2_util import typeCheck - - -class Provenance(Caom2Object): - """ Provenance """ - - def __init__(self, name, - version=None, - project=None, - producer=None, - run_id=None, - reference=None, - last_executed=None): - """ - Initializes a Provenance instance - - Arguments: - name - name of the provenance - """ - - assert name is not None, "No name provided" - assert isinstance(name, str), "name is not a str: {0}".format(name) - self._name = name - - self.version = version - self.project = project - self.producer = producer - self.run_id = run_id - self.reference = reference - self.last_executed = last_executed - - self._keywords = set() - self._inputs = TypedSet((PlaneURI),) - - # Properties - - @property - def name(self): - """ Name """ - return self._name - - @property - def version(self): - """ Version """ - return self._version - - @version.setter - def version(self, value): - typeCheck(value, str, 'version') - self._version = value - - @property - def project(self): - """ Project """ - return self._project - - @project.setter - def project(self, value): - typeCheck(value, str, 'project') - self._project = value - - @property - def producer(self): - """ Producer """ - return self._producer - - @producer.setter - def producer(self, value): - typeCheck(value, str, 'producer') - self._producer = value - - @property - def run_id(self): - """ Run ID """ - return self._run_id - - @run_id.setter - def run_id(self, value): - typeCheck(value, str, 'run_id') - self._run_id = value - - @property - def reference(self): - """ Reference """ - return self._reference - - @reference.setter - def reference(self, value): - typeCheck(value, str, 'version') - if value is not None: - tmp = urlsplit(value) - assert tmp.geturl() == value, "Invalid URI: " + value - self._reference = value - - @property - def last_executed(self): - """ Version """ - return self._last_executed - - @last_executed.setter - def last_executed(self, value): - typeCheck(value, datetime, 'last_executed') - self._last_executed = value - - @property - def keywords(self): - """ Set of keywords as str""" - return self._keywords - - @property - def inputs(self): - """ Set of inputs as PlaneURI""" - return self._inputs diff --git a/pyCAOM2/caom2/caom2_requirements.py b/pyCAOM2/caom2/caom2_requirements.py deleted file mode 100644 index dc68ee73..00000000 --- a/pyCAOM2/caom2/caom2_requirements.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the Requirements class""" - -from caom2_object import Caom2Object -from caom2_enums import Status -import caom2.util.caom2_util as util - - -class Requirements(Caom2Object): - """ Requirements """ - - def __init__(self, flag): - """ - Construct an Requirements instance - - Arguments: - flag - """ - self.flag = flag - - @property - def flag(self): - """ flag """ - return self._flag - - @flag.setter - def flag(self, value): - util.typeCheck(value, Status, "flag") - self._flag = value \ No newline at end of file diff --git a/pyCAOM2/caom2/caom2_simple_observation.py b/pyCAOM2/caom2/caom2_simple_observation.py deleted file mode 100644 index cb791b2f..00000000 --- a/pyCAOM2/caom2/caom2_simple_observation.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the SimpleObservation class""" - - -from caom2_algorithm import Algorithm -from caom2_observation import Observation -import util.caom2_util as util - - -class SimpleObservation(Observation): - """A convenience class for biuld Observations where - algorithm='exposure'. - - Simple Observation : an object to store the metadata associated - with a telescopic observation. - - Simple Observations are the basic package for the CAOM2 - model. Each simple observation refers to an observation by a - telescope. - - The metadata content is stored in a variety of objects, see the - caom2_observtion class for details. - - The algorithm value for a simple observation is forced set to - "exposure" - - """ - - _ALGORITHM = Algorithm("exposure") - - def __init__(self, - collection, - observation_id, - algorithm=None, - sequence_number=None, - intent=None, - obs_type=None, - proposal=None, - telescope=None, - instrument=None, - target=None, - meta_release=None, - planes=None, - environment=None, - target_position=None - ): - """ - collection - A name that describes a collection of data, - nominally the name of a telescope - - observation_id - A UNIQUE identifier with in that collection - """ - if (algorithm == None): - algorithm = SimpleObservation._ALGORITHM - if (algorithm != SimpleObservation._ALGORITHM): - raise ValueError( - "E{0} (required for SimpleObservation)".format(algorithm)) - super(SimpleObservation, self).__init__(collection, - observation_id, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment, - target_position - ) - - @property - def algorithm(self): - """The algorithm that built the observation, for SimpleObservation - this is always 'exposure'""" - - return super(SimpleObservation, self).algorithm - - @algorithm.setter - def algorithm(self, value=_ALGORITHM): - # build an Algorithm type if passed a string... - if isinstance(value, str): - value = Algorithm(value) - util.typeCheck(value, Algorithm, 'algorithm', override=False) - util.valueCheck(value, None, None, - 'algorithm', - override=self._ALGORITHM) - self._algorithm = value diff --git a/pyCAOM2/caom2/caom2_target.py b/pyCAOM2/caom2/caom2_target.py deleted file mode 100644 index 4bc05f37..00000000 --- a/pyCAOM2/caom2/caom2_target.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.Target class""" - -import util.caom2_util as util -from caom2_enums import TargetType -from caom2_object import Caom2Object - - -class Target(Caom2Object): - """ Target """ - - def __init__(self, name, - target_type=None, - standard=None, - redshift=None, - keywords=None, - moving=None): - """ - Initializes a Target instance - - Arguments: - name : name of the target - type : type of the target - """ - - self.name = name - self.target_type = target_type - self.standard = standard - self.redshift = redshift - if keywords is None: - keywords = set() - self.keywords = keywords - self.moving = moving - - # Properties - - @property - def name(self): - """A name for the target - - eg 'NGC 3115' - type: str - - """ - return self._name - - @name.setter - def name(self, value): - util.typeCheck(value, str, "name", override=False) - self._name = value - - @property - def target_type(self): - """A keyword describing the type of target. - - must be from the list - """ + ",".join(TargetType.names()) + """ - type: TargetType - - """ - return self._type - - @target_type.setter - def target_type(self, value): - if isinstance(value, str): - value = TargetType(value) - util.typeCheck(value, TargetType, "target_type") - self._type = value - - @property - def keywords(self): - """A set of keywords associated with this target. - - eg. keywords.add('galaxy') - type: set - - """ - return self._keywords - - @keywords.setter - def keywords(self, value): - util.typeCheck(value, set, 'keywords', override=False) - self._keywords = value - - @property - def standard(self): - """Is this a standard field? - - eg True - type: bool - - """ - return self._standard - - @standard.setter - def standard(self, value): - util.typeCheck(value, bool, 'standard') - self._standard = value - - @property - def redshift(self): - """The redshift of the observed target. - - eg 1.2 (can be None) - type: float - - """ - return self._redshift - - @redshift.setter - def redshift(self, value): - util.typeCheck(value, float, 'redshift') - util.valueCheck(value, -0.5, 1200, 'redshift') - self._redshift = value - - @property - def moving(self): - """Is this a moving target? - - eg True - type: bool - - """ - return self._moving - - @moving.setter - def moving(self, value): - util.typeCheck(value, bool, 'moving') - self._moving = value diff --git a/pyCAOM2/caom2/caom2_target_position.py b/pyCAOM2/caom2/caom2_target_position.py deleted file mode 100644 index 681f3598..00000000 --- a/pyCAOM2/caom2/caom2_target_position.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.TargetPosition class""" - -from caom2_object import Caom2Object -from types.caom2_point import Point -import caom2.util.caom2_util as util - - -class TargetPosition(Caom2Object): - """ TargetPosition """ - - def __init__(self, coordinates, coordsys, equinox=None): - """ - Initialize a TargetPosition instance. - - Arguments: - coordinates : target position as a Point. - coordsys: target coordsys - equinox: target equinox - """ - self.coordinates = coordinates - self.coordsys = coordsys - self.equinox = equinox - - # Properties - - @property - def coordinates(self): - """ Coordinates """ - return self._coordinates - - @coordinates.setter - def coordinates(self, value): - util.typeCheck(value, Point, "coordinates") - self._coordinates = value - - @property - def coordsys(self): - """ Coordsys """ - return self._coordsys - - @coordsys.setter - def coordsys(self, value): - util.typeCheck(value, str, "coordsys") - self._coordsys = value - - @property - def equinox(self): - """ Equinox """ - return self._equinox - - @equinox.setter - def equinox(self, value): - util.typeCheck(value, float, "equinox") - self._equinox = value diff --git a/pyCAOM2/caom2/caom2_telescope.py b/pyCAOM2/caom2/caom2_telescope.py deleted file mode 100644 index 508d6354..00000000 --- a/pyCAOM2/caom2/caom2_telescope.py +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""Definition of the caom2.telescope class""" - -import util.caom2_util as util -from caom2_object import Caom2Object - - -class Telescope(Caom2Object): - """ Telescope """ - - def __init__(self, name, - geo_location_x=None, - geo_location_y=None, - geo_location_z=None, - keywords=None - ): - """ - Initializes a Telescope instance - - Arguments: - name : name of the telescope - """ - - assert name is not None, "No telescope name provided" - assert isinstance(name, str), "name is not a str: {0}".format(name) - self.name = name - self.geo_location_x = geo_location_x - self.geo_location_y = geo_location_y - self.geo_location_z = geo_location_z - if keywords is None: - keywords = set() - self.keywords = keywords - - # Properties - - @property - def name(self): - """a name for this facility. - - eg. CFHT - type: str - - """ - return self._name - - @name.setter - def name(self, value): - util.typeCheck(value, str, 'name', override=False) - self._name = value - - @property - def keywords(self): - """A set that contains keywords associated with this telescope - - eg. keywords.add('big') - type: set - - """ - return self._keywords - - @keywords.setter - def keywords(self, value): - util.typeCheck(value, set, 'keywords', override=False) - self._keywords = value - - @property - def geo_location_x(self): - """The x geocentric location of the telescope. - - This should be valid at time of MJD-OBS. - - These coordinates should be in the ITRS reference, - basically whatever a GPS device is saying. - - The directions of the x/y/z follow the - Earth Centred Rotation frame. - - units: m - type: float - - """ - return self._geo_location_x - - @geo_location_x.setter - def geo_location_x(self, value): - util.typeCheck(value, float, 'geo_location_x') - self._geo_location_x = value - - @property - def geo_location_y(self): - """the y geocentric (ECR) location of the telescope. - - This should be valid at time of MJD-OBS. - - These coordinates should be in the ITRS reference, - basically whatever a GPS device is saying. - - The directions of the x/y/z follow the - Earth Centred Rotation frame. - - units: m - type: float - - """ - return self._geo_location_y - - @geo_location_y.setter - def geo_location_y(self, value): - util.typeCheck(value, float, 'geo_location_y') - self._geo_location_y = value - - @property - def geo_location_z(self): - """the z geocentric (ECR) location of the telescope. - This should be valid at time of MJD-OBS. - - These coordinates should be in the ITRS reference, - basically whatever a GPS device is saying. - - The directions of the x/y/z follow the - Earth Centred Rotation frame. - - units: m - type: float - - """ - return self._geo_location_z - - @geo_location_z.setter - def geo_location_z(self, value): - util.typeCheck(value, float, 'geo_location_z') - self._geo_location_z = value diff --git a/pyCAOM2/caom2/caom2_time.py b/pyCAOM2/caom2/caom2_time.py deleted file mode 100644 index dfec3e84..00000000 --- a/pyCAOM2/caom2/caom2_time.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the time class""" - -from caom2_object import Caom2Object -from types.caom2_interval import Interval -import util.caom2_util as util - - -class Time(Caom2Object): - """ Time """ - - def __init__(self, - value=None, - bounds=None, - dimension=None, - resolution=None, - sample_size=None, - exposure=None): - """ - Initialize a Time instance. - - Arguments: - None - """ - self.value = value - self.bounds = bounds - self.dimension = dimension - self.resolution = resolution - self.sample_size = sample_size - self.exposure = exposure - - # Properties - - @property - def value(self): - """ Actual time value, seconds since epoch. - - quesion is, what epoch? - - units: s - """ - return self._value - - @value.setter - def value(self, value): - util.typeCheck(value, float, 'value') - self._value = value - - @property - def bounds(self): - """an interval object that gives start and end of an time interval - - Not actually implemented yet. Likely you want a TemporalWCS - instead - - type: Interval(lower_mjd, upper_mjd) - unit: mjd - - """ - return self._bounds - - @bounds.setter - def bounds(self, value): - util.typeCheck(value, Interval, 'bounds') - self._bounds = value - - @property - def dimension(self): - """Number of pixel in the time direction, normally 1. - - eg 1 - type: long - - """ - return self._dimension - - @dimension.setter - def dimension(self, value): - util.typeCheck(value, long, 'dimension') - self._dimension = value - - @property - def resolution(self): - """Time resolution of the samples, in seconds. - - normally this is the same as the exposure time, - but in a stack you might have a larger resolution value than - exposure time. - - eg. 1000 - unit: s - type: float - - """ - return self._resolution - - @resolution.setter - def resolution(self, value): - util.typeCheck(value, float, 'resolution') - self._resolution = value - - @property - def sample_size(self): - """nominally the exposure time, in seconds. - - """ - return self._sample_size - - @sample_size.setter - def sample_size(self, value): - util.typeCheck(value, float, 'sample_size') - self._sample_size = value - - @property - def exposure(self): - """Duration of the exposure, in seconds""" - return self._exposure - - @exposure.setter - def exposure(self, value): - util.typeCheck(value, float, 'exposure') - self._exposure = value diff --git a/pyCAOM2/caom2/enum.py b/pyCAOM2/caom2/enum.py deleted file mode 100644 index f3893b71..00000000 --- a/pyCAOM2/caom2/enum.py +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/env python - -""" -Copyright (C) 2011 Cameron Hayne (macdev@hayne.net) -This is published under the MIT Licence: ----------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -from operator import attrgetter - - -class EnumClass(object): - """ - EnumClass is the superclass of all enum classes created by - the 'Enum' function below. - Each such subclass represents a set of named values. - """ - - def __new__(cls, name, value=None): - # I presume that 'value' is an immutable object - # but not sure how to enforce this - existingObj = cls.get(name) - if existingObj: - if value is None or value == existingObj.value: - return existingObj - else: - raise TypeError("can't overwrite an existing enum") - else: - if value is None: # e.g. MyEnumType('foo') - existingNames = cls.names() - if existingNames: - # probably trying to refer to an existing enum object - # but got the name wrong - raise ValueError(("'%s' is not a valid enum name" - + " (Must be one of: %s)") - % (name, str(existingNames))) - else: - # probably trying to create an enum object - # without specifying a value, just a name - raise ValueError("must supply value for enum") - # create a new instance of 'cls' - obj = super(EnumClass, cls).__new__(cls) - # and assign 'name' & 'value' (via the superclass) - super(EnumClass, obj).__setattr__('name', name) - super(EnumClass, obj).__setattr__('value', value) - # assign 'obj' as a class attribute for 'name' in 'cls' - setattr(cls, name, obj) - return obj - - def __copy__(self): - return self - - def __deepcopy__(self, memo): - # I presume that the 'value' is not a mutable object - return self - - def __setattr__(self, name, value): - raise TypeError("can't modify an enum") - - def __delattr__(self, name): - raise TypeError("can't modify an enum") - - # no need for __cmp__ or __hash__ since above methods ensure immutability - - def __str__(self): - return self.name - - def __list__(self): - return self.names() - - @classmethod - def addAlias(cls, name, existingName): - """ - Add 'name' as an alias for 'existingName'. - 'name' is a string. - 'existingName' is the name of one of the existing enum objects. - This is intended as a way to maintain backward compatibility - when the enum names get changed. - Example of use: - Vehicles.addAlias('horselessCarriage', 'car') - # Now old code referring to Vehicles.horselessCarriage - # will get the same object as Vehicles.car - # i.e. Vehicles.horselessCarriage.name is 'car' - # But Vehicles.names() does not include 'horselessCarriage' - """ - existingNames = cls.names() - if name in existingNames: - raise ValueError("The name '%s' is already in use." % name) - if existingName not in existingNames: - raise ValueError(("'%s' is not one of the existing enum names." - + " (Must be one of: %s)") - % (existingName, str(existingNames))) - existingObj = cls.get(existingName) - setattr(cls, name, existingObj) - - @classmethod - def get(cls, name): - """ - Return the enum instance with the specified name. - Return None if there is no such instance. - """ - return getattr(cls, name.strip(), None) - - @classmethod - def getByValue(cls, value): - """ - Return an enum instance that has the specified value. - Return None if there is no such instance. - Note that there may be more than one enum instance with the same value - and in that case this method returns whichever one it finds first. - """ - for obj in cls.objects(): - if obj.value == value: - return obj - return None - - @classmethod - def listOfNamesToListOfEnums(cls, listOfNames): - """ - Convert a list of strings (names of enums of this class) - into a list of enum instances. - Example of use: - listOfNames = ['red', 'blue'] - listOfEnums = Colours.listOfNamesToListOfEnums(listOfNames) - # would give [Colours.red, Colours.blue] - """ - listOfEnums = [cls(name) for name in listOfNames] - return listOfEnums - - @classmethod - def commaSepStrToEnumList(cls, commaSepNamesStr): - enumList = list() - commaSepNamesStr = commaSepNamesStr.lstrip('[ ') - commaSepNamesStr = commaSepNamesStr.rstrip(' ]') - names = commaSepNamesStr.split(',') - for name in names: - name = name.strip() - enumObj = cls.get(name) - if enumObj is not None: - enumList.append(enumObj) - return enumList - - @classmethod - def objects(cls): - objs = set() # need to use set since might have aliases - for obj in cls.__dict__.values(): - if isinstance(obj, cls): - objs.add(obj) - objList = sorted(objs, key=attrgetter('value')) - return objList - - @classmethod - def names(cls): - objList = cls.objects() - nameList = [obj.name for obj in objList] - return nameList -# ----------------------------------------------------------------------------- - - -def Enum(classname, **kargs): - """ - Create a new class named as specifed in the first argument, - and then create instances of this class with the name/value pairs of - the subsequent (keyword) arguments. - Return the newly created class object. - The values can be anything (not necessarily integers) - but should be immutable objects (e.g. shouldn't be a list). - Examples of use: - >>> Colours = Enum('Colours', red=1, green=2, blue=3) - >>> Colours.green.name - 'green' - - >>> print Colours.green - green - - >>> Colours.green.value - 2 - - >>> Colours.names() - ['red', 'green', 'blue'] - - >>> Colours.get('blue').value - 3 - - >>> Colours.getByValue(3).name - 'blue' - - >>> Colours('blue').value - 3 - - >>> Colours.addAlias('bleu', 'blue') - >>> Colours.names() - ['red', 'green', 'blue'] - - >>> Colours.bleu.value - 3 - - >>> [x.name for x in Colours.objects()] - ['red', 'green', 'blue'] - - >>> listOfNames = ['red', 'blue'] - >>> [x.name for x in Colours.listOfNamesToListOfEnums(listOfNames)] - ['red', 'blue'] - - >>> commaSepStr = "red, blue" - >>> [x.name for x in Colours.commaSepStrToEnumList(commaSepStr)] - ['red', 'blue'] - - - >>> Numbers = Enum('Numbers', pi=3.1415926, e=2.71828) - >>> isinstance(Numbers, type) - True - - >>> Numbers.names() - ['e', 'pi'] - - >>> round(Numbers.e.value, 3) - 2.718 - - >>> x = Numbers.pi - >>> x is Numbers('pi') - True - - >>> Numbers('phi') - Traceback (most recent call last): - ... - - ValueError: 'phi' is not a valid enum name - (Must be one of: ['e', 'pi']) - - - >>> Numbers.e.value = 42 - Traceback (most recent call last): - ... - TypeError: can't modify an enum - """ - - # create a new class derived from EnumClass - cls = type(classname, (EnumClass,), dict()) - for name in kargs.keys(): - # create an instance of 'cls' for each keyword arg - obj = cls(name, kargs[name]) - # return the newly created class to the caller - return cls - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/pyCAOM2/caom2/test/test_algorithm.py b/pyCAOM2/caom2/test/test_algorithm.py deleted file mode 100644 index 09d5cd19..00000000 --- a/pyCAOM2/caom2/test/test_algorithm.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestAlgorithm class """ - -import unittest - -from caom2.caom2_algorithm import Algorithm - - -class TestAlgorithm(unittest.TestCase): - - def testAll(self): - algorithm = Algorithm("myAlgorithm") - self.assertEqual("myAlgorithm", algorithm.name, "Algorithm name") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_axis.py b/pyCAOM2/caom2/test/test_axis.py deleted file mode 100644 index c36dcb1f..00000000 --- a/pyCAOM2/caom2/test/test_axis.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestAxis class """ -import unittest - -from caom2.wcs.caom2_axis import Axis - - -class TestAxis(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, Axis, None, None) - self.assertRaises(TypeError, Axis, None, "cunit") - self.assertRaises(TypeError, Axis, "ctype", int(1)) - self.assertRaises(TypeError, Axis, int(1), "cunit") - - axis = Axis("ctype", "cunit") - self.assertEqual(axis.ctype, "ctype") - self.assertEqual(axis.cunit, "cunit") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_caom2_entity.py b/pyCAOM2/caom2/test/test_caom2_entity.py deleted file mode 100644 index 4e85cc11..00000000 --- a/pyCAOM2/caom2/test/test_caom2_entity.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCaom2IdGenerator class """ - -import unittest - -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_artifact import Artifact -from caom2.caom2_chunk import Chunk -from caom2.caom2_entity import AbstractCaom2Entity -from caom2.caom2_enums import ProductType, ReleaseType -from caom2.caom2_observation import Observation -from caom2.caom2_part import Part -from caom2.caom2_plane import Plane - - -class TestCaom2IdGenerator(unittest.TestCase): - - def testAll(self): - #Not much for now. Just to make sure that all the clients work - entity = AbstractCaom2Entity() - print entity._id, entity._last_modified - artifact = Artifact("caom2:/blah/blah", ProductType.SCIENCE, ReleaseType.DATA) - print artifact._id, artifact._last_modified - chunk = Chunk() - print chunk._id, chunk._last_modified - algorithm = Algorithm("myAlg") - obs = Observation("colect", "obs", algorithm) - print obs._id, obs._last_modified - part = Part("part") - print part._id, part._last_modified - plane = Plane("prodid") - print plane._id, plane._last_modified - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_caom2_enums.py b/pyCAOM2/caom2/test/test_caom2_enums.py deleted file mode 100644 index 075a3462..00000000 --- a/pyCAOM2/caom2/test/test_caom2_enums.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCaom2Enums class """ - -import unittest - -from caom2.caom2_enums import EnergyBand, CalibrationLevel, ProductType - - -class TestCaom2Enums(unittest.TestCase): - - # EnergyBand and CalibrationLevel are used to test the open source - # Enum package that the Caom2Enums use. Caom2Enums only use a subset - # of the features provided by the Enum package. Only these subset - # features are tested. - def testToOBject(self): - # test for invalid value - self.assertEqual(EnergyBand.get("no_such_string"), None) - self.assertEqual(EnergyBand.get("g"), None) - self.assertEqual(EnergyBand.get("no_such_string"), None) - self.assertRaises(AttributeError, EnergyBand.get, None) - self.assertRaises(AttributeError, EnergyBand.get, 1) - # test that we can get the object for each enum by name - self.assertEqual(CalibrationLevel.CALIBRATED.name, "CALIBRATED", - "incorrect enum name") - self.assertEqual(CalibrationLevel.get(CalibrationLevel.CALIBRATED.name) - .name, "CALIBRATED") - self.assertEqual(CalibrationLevel.get('CALIBRATED').value, 2) - self.assertEqual(CalibrationLevel.get(CalibrationLevel.CALIBRATED.name) - .value, 2) - self.assertEqual(CalibrationLevel. - getByValue(CalibrationLevel.CALIBRATED.value) - .value, 2) - self.assertEqual(CalibrationLevel. - getByValue(CalibrationLevel.CALIBRATED.value).name, - "CALIBRATED") - self.assertEqual(EnergyBand.get('RADIO').value, "Radio") - self.assertEqual(EnergyBand.get('MILLIMETER').value, "Millimeter") - self.assertEqual(EnergyBand.get('INFRARED').value, "Infrared") - self.assertEqual(EnergyBand.get('OPTICAL').value, "Optical") - self.assertEqual(EnergyBand.get('UV').value, "UV") - self.assertEqual(EnergyBand.get('EUV').value, "EUV") - self.assertEqual(EnergyBand.get('XRAY').value, "X-ray") - self.assertEqual(EnergyBand.get('GAMMARAY').value, "Gamma-ray") - # test that we can get the object for each enum by value - self.assertEqual(EnergyBand.getByValue(EnergyBand.RADIO.value).value, - "Radio") - self.assertEqual(EnergyBand.getByValue(EnergyBand.MILLIMETER.value) - .value, "Millimeter") - self.assertEqual(EnergyBand.getByValue(EnergyBand.INFRARED.value) - .value, "Infrared") - self.assertEqual(EnergyBand.getByValue(EnergyBand.OPTICAL.value) - .value, "Optical") - self.assertEqual(EnergyBand.getByValue(EnergyBand.UV.value).value, - "UV") - self.assertEqual(EnergyBand.getByValue(EnergyBand.EUV.value).value, - "EUV") - self.assertEqual(EnergyBand.getByValue(EnergyBand.XRAY.value).value, - "X-ray") - self.assertEqual(EnergyBand.getByValue(EnergyBand.GAMMARAY.value) - .value, "Gamma-ray") - - def testGetValue(self): - # test that we can get each enum value - self.assertEqual(EnergyBand.RADIO.value, "Radio") - self.assertEqual(EnergyBand.MILLIMETER.value, "Millimeter") - self.assertEqual(EnergyBand.INFRARED.value, "Infrared") - self.assertEqual(EnergyBand.OPTICAL.value, "Optical") - self.assertEqual(EnergyBand.UV.value, "UV") - self.assertEqual(EnergyBand.EUV.value, "EUV") - self.assertEqual(EnergyBand.XRAY.value, "X-ray") - self.assertEqual(EnergyBand.GAMMARAY.value, "Gamma-ray") - - def testSetValue(self): - # test that we cannot change an enum value - self.assertRaises(TypeError, EnergyBand.RADIO.value, "InvalidValue") - self.assertRaises(TypeError, EnergyBand.RADIO.name, "InvalidName") - - def testProductType(self): - # test that we can get each enum value - self.assertEqual(ProductType.AUXILIARY.value, "auxiliary") - self.assertEqual(ProductType.CALIBRATION.value, "calibration") - self.assertEqual(ProductType.INFO.value, "info") - self.assertEqual(ProductType.PREVIEW.value, "preview") - self.assertEqual(ProductType.SCIENCE.value, "science") - self.assertEqual(ProductType.THUMBNAIL.value, "thumbnail") - self.assertEqual(ProductType.NOISE.value, "noise") - self.assertEqual(ProductType.WEIGHT.value, "weight") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_caom2instances.py b/pyCAOM2/caom2/test/test_caom2instances.py deleted file mode 100644 index 75043ec1..00000000 --- a/pyCAOM2/caom2/test/test_caom2instances.py +++ /dev/null @@ -1,458 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines Caom2TestInstances class """ - -import collections -from datetime import datetime - -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_artifact import Artifact -from caom2.caom2_chunk import Chunk -from caom2.caom2_composite_observation import CompositeObservation -from caom2.caom2_data_quality import DataQuality -from caom2.caom2_energy_transition import EnergyTransition -from caom2.caom2_enums import CalibrationLevel -from caom2.caom2_enums import DataProductType -from caom2.caom2_enums import ObservationIntentType -from caom2.caom2_enums import ProductType -from caom2.caom2_enums import Quality -from caom2.caom2_enums import Status -from caom2.caom2_enums import TargetType -from caom2.caom2_enums import ReleaseType -from caom2.caom2_environment import Environment -from caom2.caom2_instrument import Instrument -from caom2.caom2_metrics import Metrics -from caom2.caom2_observation_uri import ObservationURI -from caom2.caom2_part import Part -from caom2.caom2_plane import Plane -from caom2.caom2_plane_uri import PlaneURI -from caom2.caom2_proposal import Proposal -from caom2.caom2_provenance import Provenance -from caom2.caom2_requirements import Requirements -from caom2.caom2_simple_observation import SimpleObservation -from caom2.caom2_target import Target -from caom2.caom2_target_position import TargetPosition -from caom2.caom2_telescope import Telescope -from caom2.types.caom2_point import Point -from caom2.util.caom2_util import TypedList, TypedSet -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -from caom2.wcs.caom2_coord_bounds1d import CoordBounds1D -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_coord_error import CoordError -from caom2.wcs.caom2_coord_function1d import CoordFunction1D -from caom2.wcs.caom2_coord_function2d import CoordFunction2D -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.wcs.caom2_coord_range1d import CoordRange1D -from caom2.wcs.caom2_coord_range2d import CoordRange2D -from caom2.wcs.caom2_dimension2d import Dimension2D -from caom2.wcs.caom2_observable_axis import ObservableAxis -from caom2.wcs.caom2_polarization_wcs import PolarizationWCS -from caom2.wcs.caom2_ref_coord import RefCoord -from caom2.wcs.caom2_slice import Slice -from caom2.wcs.caom2_spatial_wcs import SpatialWCS -from caom2.wcs.caom2_spectral_wcs import SpectralWCS -from caom2.wcs.caom2_temporal_wcs import TemporalWCS -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class Caom2TestInstances(object): - - _collection = "collection" - _observation_id = "observationID" - _product_id = "productId" - _keywords = {"keyword1", "keyword2"} - _ivoa_date = datetime(2012, 07, 11, 13, 26, 37, 0) - - def __init__(self): - self.depth = 5 - self.complete = True - self.bounds_is_circle = True - self.caom_version = 20 - - @property - def depth(self): - return self._depth - - @depth.setter - def depth(self, v): - self._depth = v - - @property - def complete(self): - return self._complete - - @complete.setter - def complete(self, v): - self._complete = v - - @property - def bounds_is_circle(self): - return self._bounds_is_circle - - @bounds_is_circle.setter - def bounds_is_circle(self, v): - self._bounds_is_circle = v - - @property - def caom_version(self): - return self._caom_version - - @caom_version.setter - def caom_version(self, v): - self._caom_version = v - - def get_simple_observation(self): - observation = SimpleObservation(Caom2TestInstances._collection, - Caom2TestInstances._observation_id) - if self.complete: - observation.sequence_number = int(5) - observation.obs_type = "flat" - observation.intent = ( - ObservationIntentType.CALIBRATION) - observation.meta_release = Caom2TestInstances._ivoa_date - observation.proposal = self.get_proposal() - observation.target = self.get_target() - observation.target_position = self.get_target_position() - if self.caom_version == 21: - observation.requirements = self.get_requirements() - observation.telescope = self.get_telescope() - observation.instrument = self.get_instrument() - observation.environment = self.get_environment() - if self.depth > 1: - observation.planes.update(self.get_planes()) - return observation - - def get_composite_observation(self): - observation = CompositeObservation(Caom2TestInstances._collection, - Caom2TestInstances._observation_id, - self.get_algorithm()) - if self.complete: - observation.sequence_number = int(10) - observation.obs_type = "filed" - observation.intent = ( - ObservationIntentType.SCIENCE) - observation.meta_release = Caom2TestInstances._ivoa_date - observation.proposal = self.get_proposal() - observation.target = self.get_target() - observation.target_position = self.get_target_position() - if self.caom_version == 21: - observation.requirements = self.get_requirements() - observation.telescope = self.get_telescope() - observation.instrument = self.get_instrument() - observation.environment = self.get_environment() - if self.depth > 1: - observation.planes.update(self.get_planes()) - observation.members.update(self.get_members()) - return observation - - def get_algorithm(self): - return Algorithm("algorithmName") - - def get_proposal(self): - proposal = Proposal("proposalId") - proposal.pi_name = "proposalPi" - proposal.project = "proposalProject" - proposal.title = "proposalTitle" - proposal.keywords.update(Caom2TestInstances._keywords) - return proposal - - def get_target(self): - target = Target("targetName") - target.target_type = TargetType.OBJECT - target.standard = False - target.redshift = 1.5 - target.keywords.update(Caom2TestInstances._keywords) - return target - - def get_target_position(self): - point = Point(1.0, 2.0) - target_position = TargetPosition(point, "coordsys") - target_position.equinox = 3.0 - return target_position - - def get_requirements(self): - return Requirements(Status.FAIL) - - def get_telescope(self): - telescope = Telescope("telescopeName") - telescope.geo_location_x = 1.0 - telescope.geo_location_y = 2.0 - telescope.geo_location_z = 3.0 - telescope.keywords.update(Caom2TestInstances._keywords) - return telescope - - def get_instrument(self): - instrument = Instrument("instrumentName") - instrument.keywords.update(Caom2TestInstances._keywords) - return instrument - - def get_environment(self): - env = Environment() - env.seeing = 0.08 - env.humidity = 0.35 - env.elevation = 2.7 - env.tau = 0.7 - env.wavelength_tau = 450e-6 - env.ambient_temp = 20.0 - env.photometric = True - return env - - def get_members(self): - members = TypedSet( - ObservationURI, ObservationURI("caom:foo/bar")) - return members - - def get_planes(self): - planes = collections.OrderedDict() - plane = Plane("productID") - if self.complete: - plane.meta_release = Caom2TestInstances._ivoa_date - plane.data_release = Caom2TestInstances._ivoa_date - plane.data_product_type = DataProductType.IMAGE - plane.calibration_level = CalibrationLevel.PRODUCT - plane.provenance = self.get_provenance() - plane.metrics = self.get_metrics() - if self.caom_version == 21: - plane.quality = self.get_quality() - - if self.depth > 2: - for k, v in self.get_artifacts().iteritems(): - plane.artifacts[k] = v - planes["productID"] = plane - return planes - - def get_provenance(self): - provenance = Provenance("name") - provenance.version = "version" - provenance.product = "product" - provenance.producer = "producer" - provenance.run_id = "run_id" - provenance.reference = "http://foo/bar" - provenance.last_executed = Caom2TestInstances._ivoa_date - provenance.keywords.update(Caom2TestInstances._keywords) - provenance.inputs.update(self.get_inputs()) - return provenance - - def get_inputs(self): - return TypedSet(PlaneURI, PlaneURI("caom:foo/bar/plane1"), - PlaneURI("caom:foo/bar/plane2")) - - def get_metrics(self): - metrics = Metrics() - metrics.source_number_density = float(1.0) - metrics.background = float(2.0) - metrics.background_std_dev = float(3.0) - metrics.flux_density_limit = float(4.0) - metrics.mag_limit = float(5.0) - return metrics - - def get_quality(self): - return DataQuality(Quality.JUNK) - - def get_artifacts(self): - artifacts = collections.OrderedDict() - artifact = Artifact("ad:foo/bar1", ProductType.SCIENCE, ReleaseType.META) - if self.complete: - artifact.content_type = "application/fits" - artifact.content_length = 12345L - if self.depth > 3: - for k, v in self.get_parts().iteritems(): - artifact.parts[k] = v - artifacts["ad:foo/bar1"] = artifact - return artifacts - - def get_parts(self): - parts = collections.OrderedDict() - part = Part("x") - if self.complete: - part.product_type = ProductType.SCIENCE - if self.depth > 4: - for chunk in self.get_chunks(): - part.chunks.append(chunk) - parts["x"] = part - return parts - - def get_chunks(self): - chunks = TypedList(Chunk,) - chunk = Chunk() - if self.complete: - chunk.product_type = ProductType.SCIENCE - chunk.naxis = 5 - chunk.observable_axis = 1 - chunk.position_axis_1 = 1 - chunk.position_axis_2 = 2 - chunk.energy_axis = 3 - chunk.time_axis = 4 - chunk.polarization_axis = 5 - chunk.observable = self.get_observable_axis() - chunk.position = self.get_spatial_wcs() - chunk.energy = self.get_spectral_wcs() - chunk.time = self.get_temporal_wcs() - chunk.polarization = self.get_polarization_wcs() - chunks.append(chunk) - return chunks - - def get_observable_axis(self): - observable = ObservableAxis(self.get_slice()) - if self.complete: - observable.independent = self.get_slice() - return observable - - def get_spatial_wcs(self): - coord_axis_2d = self.get_coord_axis_2d() - position = SpatialWCS(coord_axis_2d) - if self.complete: - position.coordsys = "position coordsys" - position.equinox = 2000.0 - position.resolution = 0.5 - return position - - def get_spectral_wcs(self): - axis = self.get_coord_axis_1d() - energy = SpectralWCS(axis, "energy specsys") - if self.complete: - energy.ssysobs = "energy ssysobs" - energy.ssyssrc = "energy ssyssrc" - energy.restfrq = 1.0 - energy.restwav = 2.0 - energy.velosys = 3.0 - energy.zsource = 4.0 - energy.velang = 5.0 - energy.bandpassName = "energy bandpassName" - energy.resolvingPower = 6.0 - energy.transition = EnergyTransition("H", "21cm") - return energy - - def get_temporal_wcs(self): - axis = self.get_coord_axis_1d() - time = TemporalWCS(axis) - if self.complete: - time.exposure = 1.0 - time.resolution = 2.0 - time.timesys = "UTC" - time.trefpos = "TOPOCENTER" - time.mjdref = 3.0 - return time - - def get_polarization_wcs(self): - axis = Axis('STOKES') - axis_1d = CoordAxis1D(axis) - #IQUV - axis_1d.function = CoordFunction1D(4L, 1.0, RefCoord(1.0, 1.0)) - pol = PolarizationWCS(axis_1d) - return pol - - def get_slice(self): - return Slice(Axis("sliceCtype", "sliceCunit"), 1L) - - def get_coord_axis_1d(self): - coord_axis_1d = CoordAxis1D(Axis("axisCtype", "axisCunit")) - if self.complete: - coord_axis_1d.error = CoordError(1.0, 1.5) - coord_axis_1d.range = CoordRange1D(RefCoord(2.0, 2.5), - RefCoord(3.0, 3.5)) - coord_axis_1d.function = ( - CoordFunction1D(4L, 4.5, RefCoord(5.0, 5.5))) - bounds = CoordBounds1D() - bounds.samples.append(CoordRange1D(RefCoord(6.0, 6.5), - RefCoord(7.0, 7.5))) - bounds.samples.append(CoordRange1D(RefCoord(8.0, 8.5), - RefCoord(9.0, 9.5))) - coord_axis_1d.bounds = bounds - return coord_axis_1d - - def get_coord_axis_2d(self): - axis1 = Axis("axis1Ctype", "axis1Cunit") - axis2 = Axis("axis2Ctype", "axis2Cunit") - coord_axis_2d = CoordAxis2D(axis1, axis2) - if self.complete: - coord_axis_2d.error1 = CoordError(1.0, 1.5) - coord_axis_2d.error2 = CoordError(2.0, 2.5) - start = Coord2D(RefCoord(3.0, 3.5), RefCoord(4.0, 4.5)) - end = Coord2D(RefCoord(5.0, 5.5), RefCoord(6.0, 6.5)) - coord_axis_2d.range = CoordRange2D(start, end) - dimension = Dimension2D(7L, 8L) - ref_coord = Coord2D(RefCoord(9.0, 9.5), RefCoord(10.0, 10.5)) - coord_axis_2d.function = (CoordFunction2D(dimension, ref_coord, - 11.0, 12.0, 13.0, 14.0)) - if self.bounds_is_circle: - center = ValueCoord2D(15.0, 16.0) - coord_axis_2d.bounds = CoordCircle2D(center, 17.0) - else: - polygon = CoordPolygon2D() - polygon.vertices.append(ValueCoord2D(15.0, 16.0)) - polygon.vertices.append(ValueCoord2D(17.0, 18.0)) - polygon.vertices.append(ValueCoord2D(19.0, 20.0)) - coord_axis_2d.bounds = polygon - return coord_axis_2d diff --git a/pyCAOM2/caom2/test/test_chunk.py b/pyCAOM2/caom2/test/test_chunk.py deleted file mode 100644 index 47a17db1..00000000 --- a/pyCAOM2/caom2/test/test_chunk.py +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestChunk class """ - -import unittest - -from caom2.caom2_chunk import Chunk -from caom2.caom2_enums import ProductType -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -from caom2.caom2_enums import ProductType -from caom2.wcs.caom2_observable_axis import ObservableAxis -from caom2.wcs.caom2_polarization_wcs import PolarizationWCS -from caom2.wcs.caom2_slice import Slice -from caom2.wcs.caom2_spatial_wcs import SpatialWCS -from caom2.wcs.caom2_spectral_wcs import SpectralWCS -from caom2.wcs.caom2_temporal_wcs import TemporalWCS - - -class TestChunk(unittest.TestCase): - - def testInit(self): - - chunk = Chunk() - self.assertIsNone(chunk.product_type) - self.assertIsNone(chunk.naxis) - #self.assertIsNone(chunk.observable_axis) - self.assertIsNone(chunk.position_axis_1) - self.assertIsNone(chunk.position_axis_2) - self.assertIsNone(chunk.energy_axis) - self.assertIsNone(chunk.time_axis) - self.assertIsNone(chunk.polarization_axis) - self.assertIsNone(chunk.observable) - self.assertIsNone(chunk.position) - self.assertIsNone(chunk.energy) - self.assertIsNone(chunk.time) - self.assertIsNone(chunk.polarization) - - def testAttributes(self): - - chunk = Chunk() - with self.assertRaises(TypeError): - chunk.product_type = float(1.0) - chunk.naxis = float(1.0) - #chunk.observable_axis = float(1.0) - chunk.position_axis_1 = float(1.0) - chunk.position_axis_2 = float(1.0) - chunk.energy_axis = float(1.0) - chunk.time_axis = float(1.0) - chunk.polarization_axis = float(1.0) - chunk.observable = float(1.0) - chunk.position = float(1.0) - chunk.energy = float(1.0) - chunk.time = float(1.0) - chunk.polarization = float(1.0) - - chunk.product_type = ProductType.SCIENCE - self.assertEqual(ProductType.SCIENCE, chunk.product_type) - - chunk.naxis = int(5) - self.assertEqual(int(5), chunk.naxis) - - #chunk.observable_axis = int(2) - #self.assertEqual(int(2), chunk.observable_axis) - - chunk.position_axis_1 = int(1) - self.assertEqual(int(1), chunk.position_axis_1) - - chunk.position_axis_2 = int(2) - self.assertEqual(int(2), chunk.position_axis_2) - - chunk.energy_axis = int(3) - self.assertEqual(int(3), chunk.energy_axis) - - chunk.time_axis = int(4) - self.assertEqual(int(4), chunk.time_axis) - - chunk.polarization_axis = int(5) - self.assertEqual(int(5), chunk.polarization_axis) - - axis = Axis("ctype", "cunit") - dependent = Slice(axis, long(1)) - observable = ObservableAxis(dependent) - chunk.observable = observable - self.assertEqual(observable, chunk.observable) - - axis1 = Axis("ctype1", "cunit1") - axis2 = Axis("ctype2", "cunit2") - axis_2d = CoordAxis2D(axis1, axis2) - position = SpatialWCS(axis_2d) - chunk.position = position - self.assertEqual(position, chunk.position) - - axis_1d = CoordAxis1D(axis) - energy = SpectralWCS(axis_1d, "specsys") - chunk.energy = energy - self.assertEqual(energy, chunk.energy) - - time = TemporalWCS(axis_1d) - chunk.time = time - self.assertEqual(time, chunk.time) - - polarization = PolarizationWCS(CoordAxis1D(Axis('STOKES'))) - chunk.polarization = polarization - self.assertEqual(polarization, chunk.polarization) - -# def testCompareTo(self): -# # test for chunk1 == chunk2 -# chunk1 = Chunk() -# chunk1.naxis = 1 -# chunk1.observableAxis = 2 -# chunk1.positionAxis1 = 3 -# chunk1.positionAxis2 = 4 -# chunk1.energyAxis = 5 -# chunk1.timeAxis = 6 -# chunk1.polarizationAxis = 7 -# chunk1.observable = ObservableAxis() -# chunk1.position = SpatialWCS() -# chunk1.energy = SpectralWCS() -# chunk1.time = TemporalWCS() -# chunk1.polarization = PolarizationWCS() - -# chunk2 = Chunk() -# chunk2.naxis = 1 -# chunk2.observableAxis = 2 -# chunk2.positionAxis1 = 3 -# chunk2.positionAxis2 = 4 -# chunk2.energyAxis = 5 -# chunk2.timeAxis = 6 -# chunk2.polarizationAxis = 7 -# chunk2.observable = ObservableAxis() -# chunk2.position = SpatialWCS() -# chunk2.energy = SpectralWCS() -# chunk2.time = TemporalWCS() -# chunk2.polarization = PolarizationWCS() - - # test for chunk1 < chunk2 -# chunk1 = Chunk() -# chunk1.naxis = 1 -# chunk1.observableAxis = 2 -# chunk1.positionAxis1 = 3 -# chunk1.positionAxis2 = 4 -# chunk1.energyAxis = 5 -# chunk1.timeAxis = 6 -# chunk1.polarizationAxis = 7 -# chunk1.observable = ObservableAxis() -# chunk1.position = SpatialWCS() -# chunk1.energy = SpectralWCS() -# chunk1.time = TemporalWCS() -# chunk1.polarization = PolarizationWCS() - -# chunk2 = Chunk() -# chunk2.naxis = 2 -# chunk2.observableAxis = 2 -# chunk2.positionAxis1 = 3 -# chunk2.positionAxis2 = 4 -# chunk2.energyAxis = 5 -# chunk2.timeAxis = 6 -# chunk2.polarizationAxis = 7 -# chunk2.observable = ObservableAxis() -# chunk2.position = SpatialWCS() -# chunk2.energy = SpectralWCS() -# chunk2.time = TemporalWCS() -# chunk2.polarization = PolarizationWCS() -# -# self.assertEqual(chunk1.compareTo(chunk2), -1, -# "compareTo equal failed") -# - # test for chunk1 > chunk2 -# chunk1 = Chunk() -# chunk1.naxis = 2 -# chunk1.observableAxis = 2 -# chunk1.positionAxis1 = 3 -# chunk1.positionAxis2 = 4 -# chunk1.energyAxis = 5 -# chunk1.timeAxis = 6 -# chunk1.polarizationAxis = 7 -# chunk1.observable = ObservableAxis() -# chunk1.position = SpatialWCS() -# chunk1.energy = SpectralWCS() -# chunk1.time = TemporalWCS() -# chunk1.polarization = PolarizationWCS() -# -# chunk2 = Chunk() -# chunk2.naxis = 1 -# chunk2.observableAxis = 2 -# chunk2.positionAxis1 = 3 -# chunk2.positionAxis2 = 4 -# chunk2.energyAxis = 5 -# chunk2.timeAxis = 6 -# chunk2.polarizationAxis = 7 -# chunk2.observable = ObservableAxis() -# chunk2.position = SpatialWCS() -# chunk2.energy = SpectralWCS() -# chunk2.time = TemporalWCS() -# chunk2.polarization = PolarizationWCS() - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_composite_observation.py b/pyCAOM2/caom2/test/test_composite_observation.py deleted file mode 100644 index 06d96cd1..00000000 --- a/pyCAOM2/caom2/test/test_composite_observation.py +++ /dev/null @@ -1,278 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCompositeObservation class """ - -import unittest -from datetime import datetime - -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_composite_observation import CompositeObservation -from caom2.caom2_enums import ObservationIntentType -from caom2.caom2_enums import Status -from caom2.caom2_environment import Environment -from caom2.caom2_instrument import Instrument -from caom2.caom2_observation_uri import ObservationURI -from caom2.caom2_plane import Plane -from caom2.caom2_proposal import Proposal -from caom2.caom2_requirements import Requirements -from caom2.caom2_simple_observation import SimpleObservation -from caom2.caom2_target import Target -from caom2.caom2_target_position import TargetPosition -from caom2.caom2_telescope import Telescope -from caom2.types.caom2_point import Point -from caom2.util.caom2_util import TypedOrderedDict - - -class TestCompositeObservation(unittest.TestCase): - - def testAll(self): - algorithm = Algorithm("mozaic") - obs = CompositeObservation("GSA", "A12345", algorithm) - self.assertEqual("GSA", obs.collection, "Collection") - self.assertEqual("A12345", obs.observation_id, "Observation ID") - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - obs.algorithm = algorithm - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - # try to set algorithm to an invalid value - exception = False - try: - obs.algorithm = SimpleObservation._ALGORITHM - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - # try to set algorithm to None - exception = False - try: - obs.algorithm = None - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - self.assertEqual(0, len(obs.members), "Members") - observationURI1 = ObservationURI("caom:collection/obsID") - obs.members.add(observationURI1) - self.assertEqual(1, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) - - observationURI2 = ObservationURI("caom:collection/obsID2") - obs.members.add(observationURI2) - self.assertEqual(2, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) - self.assertTrue(observationURI2 in obs.members) - - #duplicates - observationURI3 = ObservationURI("caom:collection/obsID") - obs.members.add(observationURI3) - self.assertEqual(2, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) - self.assertTrue(observationURI2 in obs.members) - - # run the rest of the Observation tests - self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, - obs.intent, "Observation intent") - - self.assertIsNone(obs.obs_type, "Default obs_type") - obs.obs_type = "obstype1" - self.assertEqual("obstype1", - obs.obs_type, "obs type") - - self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") - obs.proposal = proposal - self.assertEqual(proposal, - obs.proposal, "Proposal") - - self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") - obs.telescope = telescope - self.assertEqual(telescope, - obs.telescope, "Telescope") - - self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") - obs.instrument = instrument - self.assertEqual(instrument, - obs.instrument, "Instrument") - - self.assertIsNone(obs.target, "Default target") - target = Target("TGT") - obs.target = target - self.assertEqual(target, - obs.target, "Target") - - self.assertIsNone(obs.environment, "Default environment") - environment = Environment() - obs.environment = environment - self.assertEqual(environment, - obs.environment, "Environment") - - self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - obs.target_position = target_position - self.assertEqual(target_position, - obs.target_position, "TargetPosition") - - self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) - obs.requirements = requirements - self.assertEquals(requirements, obs.requirements, "requirements") - - self.assertIsNone(obs.meta_release, "Default metadata release") - date_now = datetime.now() - obs.meta_release = date_now - self.assertEqual(date_now, - obs.meta_release, "Metadata release") - - # Test the complete constructor - def testCompleteInit(self): - collection = str("CFHT") - observationID = str("543210") - algorithm = str("algo") - sequence_number = int(3) - intent = ObservationIntentType.SCIENCE - obs_type = str("foo") - proposal = Proposal("123") - telescope = Telescope("TEL") - instrument = Instrument("INST") - target = Target("LMC") - meta_release = datetime.now() - planes = TypedOrderedDict((Plane),) - environment = Environment() - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - - obs = CompositeObservation(collection, - observationID, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment, - target_position) - - self.assertIsNotNone(obs.collection, "Collection") - self.assertEqual(collection, obs.collection, "Collection") - - self.assertIsNotNone(obs.observation_id, "Observation ID") - self.assertEqual(observationID, obs.observation_id, "Observation ID") - - self.assertIsNotNone(obs.algorithm, "Algorithm") - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - self.assertIsNotNone(obs.intent, "Observation intent") - self.assertEqual(intent, obs.intent, "Observation intent") - - self.assertIsNotNone(obs.obs_type, "obs type") - self.assertEqual(obs_type, obs.obs_type, "obs type") - - self.assertIsNotNone(obs.proposal, "Proposal") - self.assertEqual(proposal, obs.proposal, "Proposal") - - self.assertIsNotNone(obs.telescope, "Telescope") - self.assertEqual(telescope, obs.telescope, "Telescope") - - self.assertIsNotNone(obs.instrument, "Instrument") - self.assertEqual(instrument, obs.instrument, "Instrument") - - self.assertIsNotNone(obs.target, "Target") - self.assertEqual(target, obs.target, "Target") - - self.assertIsNotNone(obs.meta_release, "Metadata release") - self.assertEqual(meta_release, obs.meta_release, "Metadata release") - - self.assertIsNotNone(obs.planes, "Planes") - self.assertEqual(planes, obs.planes, "Planes") - - self.assertIsNotNone(obs.environment, "Environment") - self.assertEqual(environment, obs.environment, "Environment") - - self.assertIsNotNone(obs.target_position, "TargetPosition") - self.assertEqual(target_position, obs.target_position, - "TargetPosition") - - # Try changing the algorithm - algorithm2 = str("new algo") - obs.algorithm = algorithm2 - self.assertIsNotNone(obs.algorithm, "Algorithm") - self.assertNotEqual(algorithm, obs.algorithm, "Algorithm") - self.assertEqual(algorithm2, obs.algorithm, "Algorithm") - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_coord2d.py b/pyCAOM2/caom2/test/test_coord2d.py deleted file mode 100644 index df3c2eef..00000000 --- a/pyCAOM2/caom2/test/test_coord2d.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoord2D class """ - -import unittest - -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoord2D(unittest.TestCase): - - def testInit(self): - - coord1 = RefCoord(float(1.0), float(2.0)) - coord2 = RefCoord(float(3.0), float(4.0)) - - self.assertRaises(TypeError, Coord2D, None, None) - self.assertRaises(TypeError, Coord2D, None, coord2) - self.assertRaises(TypeError, Coord2D, coord1, None) - self.assertRaises(TypeError, Coord2D, str("s"), coord2) - self.assertRaises(TypeError, Coord2D, coord1, str("s")) - - coord_2d = Coord2D(coord1, coord2) - self.assertEqual(coord_2d.coord1, coord1) - self.assertEqual(coord_2d.coord2, coord2) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_coord_axis1d.py b/pyCAOM2/caom2/test/test_coord_axis1d.py deleted file mode 100644 index e8bd5a21..00000000 --- a/pyCAOM2/caom2/test/test_coord_axis1d.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordAxis1D class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_coord_bounds1d import CoordBounds1D -from caom2.wcs.caom2_coord_error import CoordError -from caom2.wcs.caom2_coord_function1d import CoordFunction1D -from caom2.wcs.caom2_coord_range1d import CoordRange1D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordAxis1D(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, CoordAxis1D, None) - self.assertRaises(TypeError, CoordAxis1D, int(1)) - - axis = Axis("ctype", "cunit") - axis_1d = CoordAxis1D(axis) - self.assertEqual(axis_1d.axis, axis) - with self.assertRaises(TypeError): - axis_1d.error = str("s") - axis_1d.bounds = str("s") - axis_1d.function = str("s") - axis_1d.range = str("s") - - error = CoordError(float(1.0), float(2.0)) - axis_1d.error = error - self.assertEqual(axis_1d.error, error) - - start = RefCoord(float(1.0), float(2.0)) - end = RefCoord(float(3.0), float(4.0)) - coordRange = CoordRange1D(start, end) - axis_1d.range = coordRange - self.assertEqual(axis_1d.range, coordRange) - - bounds = CoordBounds1D() - axis_1d.bounds = bounds - self.assertEqual(axis_1d.bounds, bounds) - - naxis = long(1) - delta = float(2.5) - ref_coord = RefCoord(float(1.0), float(2.0)) - function = CoordFunction1D(naxis, delta, ref_coord) - axis_1d.function = function - self.assertEqual(axis_1d.function, function) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_coord_axis2d.py b/pyCAOM2/caom2/test/test_coord_axis2d.py deleted file mode 100644 index 141e25a6..00000000 --- a/pyCAOM2/caom2/test/test_coord_axis2d.py +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordAxis2D class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_coord_error import CoordError -from caom2.wcs.caom2_coord_function2d import CoordFunction2D -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.wcs.caom2_coord_range2d import CoordRange2D -from caom2.wcs.caom2_dimension2d import Dimension2D -from caom2.wcs.caom2_ref_coord import RefCoord -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestCoordAxis2D(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, CoordAxis2D, None, None) - self.assertRaises(TypeError, CoordAxis2D, None, int(1)) - self.assertRaises(TypeError, CoordAxis2D, int(1), None) - - axis1 = Axis("ctype1", "cunit1") - axis2 = Axis("ctype2", "cunit2") - axis_2d = CoordAxis2D(axis1, axis2) - self.assertEqual(axis_2d.axis1, axis1) - self.assertEqual(axis_2d.axis2, axis2) - with self.assertRaises(TypeError): - axis_2d.error1 = str("s") - axis_2d.error2 = str("s") - axis_2d.bounds = str("s") - axis_2d.function = str("s") - axis_2d.range = str("s") - - error1 = CoordError(float(1.0), float(2.0)) - axis_2d.error1 = error1 - self.assertEqual(axis_2d.error1, error1) - - error2 = CoordError(float(3.0), float(4.0)) - axis_2d.error2 = error2 - self.assertEqual(axis_2d.error2, error2) - - start = Coord2D(RefCoord(float(1.0), float(2.0)), - RefCoord(float(3.0), float(4.0))) - end = Coord2D(RefCoord(float(5.0), float(6.0)), - RefCoord(float(7.0), float(8.0))) - coordRange = CoordRange2D(start, end) - axis_2d.range = coordRange - self.assertEqual(axis_2d.range, coordRange) - - center = ValueCoord2D(float(1.0), float(2.0)) - radius = float(1.5) - circle = CoordCircle2D(center, radius) - axis_2d.bounds = circle - self.assertEqual(axis_2d.bounds, circle) - - polygon = CoordPolygon2D() - axis_2d.bounds = polygon - self.assertEqual(axis_2d.bounds, polygon) - - dimension = Dimension2D(long(1), long(2)) - ref_coord = Coord2D(RefCoord(float(9.0), float(10.0)), - RefCoord(float(11.0), float(12.0))) - cd11 = float(1.1) - cd12 = float(1.2) - cd21 = float(2.1) - cd22 = float(2.2) - function = CoordFunction2D(dimension, ref_coord, - cd11, cd12, cd21, cd22) - axis_2d.function = function - self.assertEqual(axis_2d.function, function) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_coord_bounds1d.py b/pyCAOM2/caom2/test/test_coord_bounds1d.py deleted file mode 100644 index 000ee8b0..00000000 --- a/pyCAOM2/caom2/test/test_coord_bounds1d.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordBounds1D class """ - -import unittest - -from caom2.wcs.caom2_coord_bounds1d import CoordBounds1D -from caom2.wcs.caom2_coord_range1d import CoordRange1D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordBounds1D(unittest.TestCase): - - def testInit(self): - - start = RefCoord(float(1.0), float(2.0)) - end = RefCoord(float(3.0), float(4.0)) - coordRange = CoordRange1D(start, end) - - bounds = CoordBounds1D() - bounds.samples.append(coordRange) - self.assertTrue(bounds.samples.count(coordRange) == 1) - self.assertEqual(bounds.samples.pop(), coordRange) - - with self.assertRaises(TypeError): - bounds.samples = [str("s")] - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_coord_bounds2d.py b/pyCAOM2/caom2/test/test_coord_bounds2d.py deleted file mode 100644 index d19f8f5f..00000000 --- a/pyCAOM2/caom2/test/test_coord_bounds2d.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordBounds2D class """ - -import unittest - -from caom2.wcs.caom2_coord_bounds2d import CoordBounds2D -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestCoordBounds2D(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, CoordBounds2D, None) - self.assertRaises(TypeError, CoordBounds2D, float(1.0)) - - center = ValueCoord2D(float(1.0), float(2.0)) - radius = float(1.5) - circle = CoordCircle2D(center, radius) - - polygon = CoordPolygon2D() - polygon.vertices.append(ValueCoord2D(float(1.0), float(2.0))) - - bounds = CoordBounds2D(circle) - self.assertEqual(bounds.bounds, circle) - - bounds = CoordBounds2D(polygon) - self.assertEqual(bounds.bounds, polygon) - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_coord_circle2d.py b/pyCAOM2/caom2/test/test_coord_circle2d.py deleted file mode 100644 index 940763da..00000000 --- a/pyCAOM2/caom2/test/test_coord_circle2d.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordCircle2D class """ - -import unittest - -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestCoordCircle2D(unittest.TestCase): - - def testInit(self): - - center = ValueCoord2D(float(1.0), float(2.0)) - radius = float(1.5) - - self.assertRaises(TypeError, CoordCircle2D, None, None) - self.assertRaises(TypeError, CoordCircle2D, None, radius) - self.assertRaises(TypeError, CoordCircle2D, center, None) - self.assertRaises(TypeError, CoordCircle2D, int(1), radius) - self.assertRaises(TypeError, CoordCircle2D, center, int(1)) - - circle = CoordCircle2D(center, radius) - self.assertEqual(circle.center, center) - self.assertEqual(circle.radius, radius) - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_coord_error.py b/pyCAOM2/caom2/test/test_coord_error.py deleted file mode 100644 index ea7d3b12..00000000 --- a/pyCAOM2/caom2/test/test_coord_error.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordError class """ - -import unittest - -from caom2.wcs.caom2_coord_error import CoordError - - -class TestCoordError(unittest.TestCase): - - def testInit(self): - self.assertRaises(TypeError, CoordError, None, None) - self.assertRaises(TypeError, CoordError, None, float(1.0)) - self.assertRaises(TypeError, CoordError, float(1.0), None) - self.assertRaises(TypeError, CoordError, int(1), float(1.0)) - self.assertRaises(TypeError, CoordError, float(1.0), int(1)) - - error = CoordError(float(1), float(2)) - print error.rnder - self.assertIsNotNone(error) - self.assertEqual(error.syser, float(1)) - self.assertEqual(error.rnder, float(2)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_coord_function1d.py b/pyCAOM2/caom2/test/test_coord_function1d.py deleted file mode 100644 index f945084d..00000000 --- a/pyCAOM2/caom2/test/test_coord_function1d.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordFunction1D class """ - -import unittest - -from caom2.wcs.caom2_coord_function1d import CoordFunction1D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordFunction1D(unittest.TestCase): - - def testInit(self): - - naxis = long(1) - delta = float(2.5) - ref_coord = RefCoord(float(1.0), float(2.0)) - - self.assertRaises(TypeError, CoordFunction1D, None, None, - None) - self.assertRaises(TypeError, CoordFunction1D, None, delta, - ref_coord) - self.assertRaises(TypeError, CoordFunction1D, naxis, None, - ref_coord) - self.assertRaises(TypeError, CoordFunction1D, naxis, delta, - None) - self.assertRaises(TypeError, CoordFunction1D, int(1), delta, - ref_coord) - self.assertRaises(TypeError, CoordFunction1D, naxis, int(1), - ref_coord) - self.assertRaises(TypeError, CoordFunction1D, naxis, delta, - int(1)) - - function = CoordFunction1D(naxis, delta, ref_coord) - self.assertEqual(function.naxis, naxis) - self.assertEqual(function.delta, delta) - self.assertEqual(function.ref_coord, ref_coord) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_coord_function2d.py b/pyCAOM2/caom2/test/test_coord_function2d.py deleted file mode 100644 index 3115d93d..00000000 --- a/pyCAOM2/caom2/test/test_coord_function2d.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordFunction2D class """ - -import unittest - -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_coord_function2d import CoordFunction2D -from caom2.wcs.caom2_dimension2d import Dimension2D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordFunction2D(unittest.TestCase): - - def testInit(self): - - dimension = Dimension2D(long(1), long(2)) - ref_coord = Coord2D(RefCoord(float(9.0), float(10.0)), - RefCoord(float(11.0), float(12.0))) - cd11 = float(1.1) - cd12 = float(1.2) - cd21 = float(2.1) - cd22 = float(2.2) - - self.assertRaises(TypeError, CoordFunction2D, None, - ref_coord, cd11, cd12, cd21, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - None, cd11, cd12, cd21, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - ref_coord, None, cd12, cd21, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - ref_coord, cd11, None, cd21, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - ref_coord, cd11, cd12, None, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - ref_coord, cd11, cd12, cd21, None) - - function = CoordFunction2D(dimension, ref_coord, - cd11, cd12, cd21, cd22) - self.assertEqual(function.dimension, dimension) - self.assertEqual(function.ref_coord, ref_coord) - self.assertEqual(function.cd11, cd11) - self.assertEqual(function.cd12, cd12) - self.assertEqual(function.cd21, cd21) - self.assertEqual(function.cd22, cd22) - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_coord_polygon2d.py b/pyCAOM2/caom2/test/test_coord_polygon2d.py deleted file mode 100644 index 53218dbd..00000000 --- a/pyCAOM2/caom2/test/test_coord_polygon2d.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordPolygon2D class """ - -import unittest - -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestCoordPolygon2D(unittest.TestCase): - - def testInit(self): - - value_coord2d = ValueCoord2D(float(1.0), float(2.0)) - - polygon = CoordPolygon2D() - polygon.vertices.append(value_coord2d) - self.assertTrue(polygon.vertices.count(value_coord2d) == 1) - self.assertEqual(polygon.vertices.pop(), value_coord2d) - - with self.assertRaises(TypeError): - polygon.vertices = [str("s")] - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_coord_range1d.py b/pyCAOM2/caom2/test/test_coord_range1d.py deleted file mode 100644 index e057a2c9..00000000 --- a/pyCAOM2/caom2/test/test_coord_range1d.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordRange1D class """ - -import unittest - -from caom2.wcs.caom2_coord_range1d import CoordRange1D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordRange1D(unittest.TestCase): - - def testInit(self): - - start = RefCoord(float(1.0), float(2.0)) - end = RefCoord(float(3.0), float(4.0)) - - self.assertRaises(TypeError, CoordRange1D, None, None) - self.assertRaises(TypeError, CoordRange1D, None, end) - self.assertRaises(TypeError, CoordRange1D, start, None) - self.assertRaises(TypeError, CoordRange1D, int(1), end) - self.assertRaises(TypeError, CoordRange1D, start, int(1)) - - coordRange = CoordRange1D(start, end) - self.assertEqual(coordRange.start, start) - self.assertEqual(coordRange.end, end) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_coord_range2d.py b/pyCAOM2/caom2/test/test_coord_range2d.py deleted file mode 100644 index ab88709a..00000000 --- a/pyCAOM2/caom2/test/test_coord_range2d.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordRange2D class """ - -import unittest - -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_coord_range2d import CoordRange2D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordRange2D(unittest.TestCase): - - def testInit(self): - - start = Coord2D(RefCoord(float(1.0), float(2.0)), - RefCoord(float(3.0), float(4.0))) - end = Coord2D(RefCoord(float(5.0), float(6.0)), - RefCoord(float(7.0), float(8.0))) - - self.assertRaises(TypeError, CoordRange2D, None, None) - self.assertRaises(TypeError, CoordRange2D, None, end) - self.assertRaises(TypeError, CoordRange2D, start, None) - self.assertRaises(TypeError, CoordRange2D, int(1), end) - self.assertRaises(TypeError, CoordRange2D, start, int(1)) - - coordRange = CoordRange2D(start, end) - self.assertEqual(coordRange.start, start) - self.assertEqual(coordRange.end, end) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_data_quality.py b/pyCAOM2/caom2/test/test_data_quality.py deleted file mode 100644 index b4ebdb4b..00000000 --- a/pyCAOM2/caom2/test/test_data_quality.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestDataQuality class """ - -import unittest - -from caom2.caom2_data_quality import DataQuality -from caom2.caom2_enums import Quality - - -class TestDataQuality(unittest.TestCase): - - def testAll(self): - - self.assertRaises(TypeError, DataQuality, "string") - quality = DataQuality(Quality.JUNK) - self.assertEqual(Quality.JUNK, quality.flag, - "DataQuality flag") - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_dimension2d.py b/pyCAOM2/caom2/test/test_dimension2d.py deleted file mode 100644 index d666e2b1..00000000 --- a/pyCAOM2/caom2/test/test_dimension2d.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestDimension2D class """ - -import unittest - -from caom2.wcs.caom2_dimension2d import Dimension2D - - -class TestDimension2D(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, Dimension2D, None, None) - self.assertRaises(TypeError, Dimension2D, long(1), None) - self.assertRaises(TypeError, Dimension2D, None, long(1)) - self.assertRaises(TypeError, Dimension2D, int(1), long(1)) - self.assertRaises(TypeError, Dimension2D, long(1), int(1)) - - dimension = Dimension2D(long(1), long(2)) - self.assertEqual(dimension.naxis1, long(1)) - self.assertEqual(dimension.naxis2, long(2)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_energy.py b/pyCAOM2/caom2/test/test_energy.py deleted file mode 100644 index b233c1d8..00000000 --- a/pyCAOM2/caom2/test/test_energy.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestEnergy class """ - -import unittest - -from caom2.caom2_energy import Energy -from caom2.caom2_enums import EnergyBand - - -class TestEnergy(unittest.TestCase): - - def testAll(self): - energy = Energy() - self.assertIsNone(energy.value, "Default energy value") - energy.value = 33.33 - self.assertEqual(33.33, energy.value, "Energy value") - self.assertIsNone(energy.bounds, "Default energy bounds") - #TODO switch to Interval - #energy.bounds = 22 - self.assertIsNone(energy.dimension, "Default energy dimension") - energy.dimension = 1000L - self.assertEqual(1000L, energy.dimension, "Energy dimension") - self.assertIsNone(energy.resolving_power, - "Default energy resolving power") - energy.resolving_power = 123.12 - self.assertEqual(123.12, energy.resolving_power, - "Energy resolving power") - self.assertIsNone(energy.sample_size, "Default energy sample size") - energy.sample_size = 123.321 - self.assertEqual(123.321, energy.sample_size, "Energy sample size") - self.assertIsNone(energy.bandpass_name, "Default energy band pass") - energy.bandpass_name = "EBN" - self.assertEqual("EBN", energy.bandpass_name, "Energy bandpass name") - self.assertIsNone(energy.em_band, "Default energy em band") - energy.em_band = EnergyBand.OPTICAL - self.assertEqual(EnergyBand.OPTICAL, energy.em_band, "Energy band") - self.assertIsNone(energy.transition, "Default energy transition") - #TODO replace with EnergyTransistion - #energy.transition = "BLAH" - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_energy_transition.py b/pyCAOM2/caom2/test/test_energy_transition.py deleted file mode 100644 index 495e220e..00000000 --- a/pyCAOM2/caom2/test/test_energy_transition.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestEnergyTransition class """ - -import unittest - -from caom2.caom2_energy_transition import EnergyTransition - - -class TestEnergyTransition(unittest.TestCase): - - def test__init__(self): - # test for invalid values - self.assertRaises(TypeError, EnergyTransition, None, None) - self.assertRaises(TypeError, EnergyTransition, 'aString', None) - self.assertRaises(TypeError, EnergyTransition, None, 'aString') - self.assertRaises(TypeError, EnergyTransition, 1, 'aString') - self.assertRaises(TypeError, EnergyTransition, 'aString', 2) - # test for happy path - transition = EnergyTransition("aSpecies", "aTransition") - self.assertEqual(transition._species, "aSpecies") - self.assertEqual(transition._transition, "aTransition") - - def test_setters(self): - # test that we cannot change the attribute values - transition = EnergyTransition("aSpecies", "aTransition") - try: - transition.species = "newSpecies" - transition.transition = "newTransition" - except AttributeError: - pass - else: - raise AttributeError("at least one attribute was changed") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_environment.py b/pyCAOM2/caom2/test/test_environment.py deleted file mode 100644 index 7a6a045f..00000000 --- a/pyCAOM2/caom2/test/test_environment.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestEnvironment class """ - -import unittest - -from caom2.caom2_environment import Environment - - -class TestEnvironment(unittest.TestCase): - - def testAll(self): - environment = Environment() - - self.assertIsNone(environment.seeing, "Default seeing") - environment.seeing = 123.321 - self.assertEqual(123.321, environment.seeing, "Seeing") - self.assertIsNone(environment.humidity, "Default humidity") - environment.humidity = 0.333 - self.assertEqual(0.333, environment.humidity, "humidity") - self.assertIsNone(environment.elevation, "Default elevation") - environment.elevation = 12.12 - self.assertEqual(12.12, environment.elevation, "Elevation") - self.assertIsNone(environment.tau, "Default tau") - environment.tau = 0.456 - self.assertEqual(0.456, environment.tau, "Tau") - self.assertIsNone(environment.wavelength_tau, "Default wavelength tau") - environment.wavelength_tau = 200.02 - self.assertEqual(200.02, environment.wavelength_tau, "Wavelength tau") - self.assertIsNone(environment.ambient_temp, - "Default ambient temperature") - environment.ambient_temp = 12.44 - self.assertEqual(12.44, environment.ambient_temp, - "Ambient temperature") - self.assertIsNone(environment.photometric, "Default photometric") - environment.photometric = True - self.assertTrue(environment.photometric, "Photometric") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_instrument.py b/pyCAOM2/caom2/test/test_instrument.py deleted file mode 100644 index ec60ed05..00000000 --- a/pyCAOM2/caom2/test/test_instrument.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPlane class """ - -import unittest - -from caom2.caom2_instrument import Instrument - - -class TestPlane(unittest.TestCase): - - def testAll(self): - instrument = Instrument("myInstrument") - self.assertEqual("myInstrument", instrument.name, "Instrument name") - self.assertEqual(0, len(instrument.keywords), "Default number of keywords") - - instrument.keywords.add("optical") - self.assertEqual(1, len(instrument.keywords), "Number of keywords") - self.assertTrue("optical" in instrument.keywords, "Keyword not found") - - instrument.keywords.add("radio") - self.assertEqual(2, len(instrument.keywords), "Number of keywords") - self.assertTrue("radio" in instrument.keywords, "Keyword not found") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_metrics.py b/pyCAOM2/caom2/test/test_metrics.py deleted file mode 100644 index 048c32bd..00000000 --- a/pyCAOM2/caom2/test/test_metrics.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestMetrics class """ - -import unittest - -from caom2.caom2_metrics import Metrics - - -class TestMetrics(unittest.TestCase): - - def testAll(self): - metrics = Metrics() - - self.assertIsNone(metrics.source_number_density, - "Default source number density") - metrics.source_number_density = 22.22 - self.assertEquals(22.22, metrics.source_number_density, - "Source number density") - self.assertIsNone(metrics.background, "Default background") - metrics.background = 12.34 - self.assertEquals(12.34, metrics.background, "Background") - self.assertIsNone(metrics.background_std_dev, - "Default background standard deviation") - metrics.background_std_dev = 34.34 - self.assertEquals(34.34, metrics.background_std_dev, - "Background standard deviation") - self.assertIsNone(metrics.flux_density_limit, - "Default flux density limit") - metrics.flux_density_limit = 55.55 - self.assertEquals(55.55, metrics.flux_density_limit, - "Flux density limit") - self.assertIsNone(metrics.mag_limit, "Default mag limit") - metrics.mag_limit = 20.08 - self.assertEquals(20.08, metrics.mag_limit, "Mag limit") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_observable_axis.py b/pyCAOM2/caom2/test/test_observable_axis.py deleted file mode 100644 index 6d9f50f6..00000000 --- a/pyCAOM2/caom2/test/test_observable_axis.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestObservableAxis class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_observable_axis import ObservableAxis -from caom2.wcs.caom2_slice import Slice - - -class TestObservableAxis(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, ObservableAxis, None) - self.assertRaises(TypeError, ObservableAxis, int(1)) - - dependent = Slice(Axis("ctype1", "cunit1"), long(1)) - independent = Slice(Axis("ctype2", "cunit2"), long(2)) - - observable = ObservableAxis(dependent) - self.assertEqual(observable.dependent, dependent) - - observable.independent = independent - self.assertEqual(observable.independent, independent) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_observation.py b/pyCAOM2/caom2/test/test_observation.py deleted file mode 100644 index 6fb59459..00000000 --- a/pyCAOM2/caom2/test/test_observation.py +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestObservation class """ - -import unittest -from datetime import datetime - -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_enums import ObservationIntentType -from caom2.caom2_enums import Status -from caom2.caom2_environment import Environment -from caom2.caom2_instrument import Instrument -from caom2.caom2_observation import Observation -from caom2.caom2_plane import Plane -from caom2.caom2_proposal import Proposal -from caom2.caom2_requirements import Requirements -from caom2.caom2_target import Target -from caom2.caom2_target_position import TargetPosition -from caom2.caom2_telescope import Telescope -from caom2.types.caom2_point import Point - - -class TestObservation(unittest.TestCase): - - def testAll(self): - algorithm = Algorithm("myAlg") - obs = Observation("GSA", "A12345", algorithm) - self.assertEqual("GSA", obs.collection, "Collection") - self.assertEqual("A12345", obs.observation_id, "Observation ID") - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - new_algorithm = Algorithm("myNewAlg") - obs.algorithm = new_algorithm - self.assertEquals(new_algorithm, obs.algorithm, "New algorithm") - - self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, - obs.intent, "Observation intent") - - self.assertIsNone(obs.obs_type, "Default obs_type") - obs.obs_type = "obstype1" - self.assertEqual("obstype1", - obs.obs_type, "obs type") - - self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") - obs.proposal = proposal - self.assertEqual(proposal, - obs.proposal, "Proposal") - - self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") - obs.telescope = telescope - self.assertEqual(telescope, obs.telescope, "Telescope") - - self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") - obs.instrument = instrument - self.assertEqual(instrument, obs.instrument, "Instrument") - - self.assertIsNone(obs.target, "Default target") - target = Target("TGT") - obs.target = target - self.assertEqual(target, obs.target, "Target") - - self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - obs.target_position = target_position - self.assertEqual(target_position, - obs.target_position, "TargetPosition") - - self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) - obs.requirements = requirements - self.assertEqual(requirements, - obs.requirements, "Requirements") - - self.assertIsNone(obs.environment, "Default environment") - environment = Environment() - obs.environment = environment - self.assertEqual(environment, - obs.environment, "Environment") - - self.assertIsNone(obs.meta_release, "Default metadata release") - date_now = datetime.now() - obs.meta_release = date_now - self.assertEqual(date_now, - obs.meta_release, "Metadata release") - - self.assertEqual(0, len(obs.planes), "Default planes") - plane1 = Plane("myPlaneID") - obs.planes["myPlaneID"] = plane1 - self.assertEqual(1, len(obs.planes), "Planes") - self.assertTrue("myPlaneID" in obs.planes.keys()) - - plane2 = Plane("myPlaneID2") - obs.planes["myPlaneID2"] = plane2 - self.assertEqual(2, len(obs.planes), "Planes") - self.assertTrue("myPlaneID" in obs.planes) - self.assertTrue("myPlaneID2" in obs.planes.keys()) - - # test duplicates - plane3 = Plane("myPlaneID2") - obs.planes["myPlaneID2"] = plane3 - self.assertEqual(2, len(obs.planes), "Planes") - self.assertTrue("myPlaneID" in obs.planes) - self.assertTrue("myPlaneID2" in obs.planes.keys()) - - obs2 = Observation(obs.collection, - obs.observation_id, - obs.algorithm, - planes=obs.planes, - sequence_number=obs.sequence_number, - intent=obs.intent, - obs_type=obs.obs_type, - proposal=obs.proposal, - telescope=obs.telescope, - instrument=obs.instrument, - target=obs.target, - meta_release=obs.meta_release, - environment=obs.environment, - target_position=obs.target_position) - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_observation_reader_writer.py b/pyCAOM2/caom2/test/test_observation_reader_writer.py deleted file mode 100644 index db4c14a0..00000000 --- a/pyCAOM2/caom2/test/test_observation_reader_writer.py +++ /dev/null @@ -1,862 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestObservationReaderWriter class """ - -import StringIO -import unittest - -from caom2.xml.caom2_xml_constants import CAOM20_NAMESPACE, CAOM21_NAMESPACE, CAOM22_NAMESPACE -from caom2.caom2_composite_observation import CompositeObservation -from caom2.caom2_simple_observation import SimpleObservation -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.xml.caom2_observation_reader import ObservationReader -from caom2.xml.caom2_observation_writer import ObservationWriter -from test_caom2instances import Caom2TestInstances - - -class TestObservationReaderWriter(unittest.TestCase): - - def test_invalid_long_id(self): - print "Test Invalid long id " - observation = minimal_simple(1, False, 20) - writer = ObservationWriter( - False, False, "caom2", CAOM20_NAMESPACE) - output = StringIO.StringIO() - writer.write(observation, output) - xml = output.getvalue() - output.close() - xml = xml.replace("caom2:id=\"", "caom2:id=\"x") - f = open('/tmp/test.xml', 'w') - f.write(xml) - f.close() - reader = ObservationReader(False) - try: - reader.read('/tmp/test.xml') - self.fail("invalid long id should throw ValueError") - except ValueError: - pass - - def test_invalid_uuid(self): - print "Test Invalid UUID id" - observation = minimal_simple(1, False, 21) - writer = ObservationWriter(False, False) # default writer is 2.1 - output = StringIO.StringIO() - writer.write(observation, output) - xml = output.getvalue() - output.close() - xml = xml.replace("0000", "xxxx", 1) - f = open('/tmp/test.xml', 'w') - f.write(xml) - f.close() - reader = ObservationReader(False) - try: - reader.read('/tmp/test.xml') - self.fail("invalid uuid id should throw ValueError") - except ValueError: - pass - - def test_minimal_simple(self): - - for version in (20, 21): - for i in range(1, 6): - print "Test Minimal Simple {} version {}".format(i, version) - # CoordBounds2D as CoordCircle2D - observation = minimal_simple(i, True, version) - # write empty elements - test_observation(self, observation, True, True, version) - # do not write empty elements - test_observation(self, observation, True, False, version) - # CoordBounds2D as CoordPolygon2D - observation = minimal_simple(i, False, version) - # write empty elements - test_observation(self, observation, True, True, version) - # do not write empty elements - test_observation(self, observation, True, False, version) - - def test_complete_simple(self): - - for version in (20, 21, 22): - for i in range(1, 6): - print "Test Complete Simple {} version {}".format(i, version) - # CoordBounds2D as CoordCircle2D - observation = complete_simple(i, True, version) - # write empty elements - test_observation(self, observation, True, True, version) - # do not write empty elements - test_observation(self, observation, True, False, version) - # CoordBounds2D as CoordPolygon2D - observation = complete_simple(i, False, version) - # write empty elements - test_observation(self, observation, True, True, version) - # do not write empty elements - test_observation(self, observation, True, False, version) - - def test_minimal_composite(self): - - for version in (20, 21, 22): - for i in range(1, 6): - print "Test Minimal Composite {} version {}".format(i, version) - # CoordBounds2D as CoordCircle2D - observation = minimal_composite(i, True, version) - # write empty elements - test_observation(self, observation, True, True, version) - # do not write empty elements - test_observation(self, observation, True, False, version) - # CoordBounds2D as CoordPolygon2D - observation = minimal_composite(i, False, version) - # write empty elements - test_observation(self, observation, True, True, version) - # do not write empty elements - test_observation(self, observation, True, False, version) - - def test_complete_composite(self): - - for version in (20, 21, 22): - for i in range(1, 6): - print "Test Complete Composite {} version {}".format(i, version) - # CoordBounds2D as CoordCircle2D - observation = complete_composite(i, True, version) - # write empty elements - test_observation(self, observation, True, True, version) - # do not write empty elements - test_observation(self, observation, True, False, version) - # CoordBounds2D as CoordPolygon2D - observation = complete_composite(i, False, version) - # write empty elements - test_observation(self, observation, True, True, version) - # do not write empty elements - test_observation(self, observation, True, False, version) - - def test_versions(self): - observation = complete_composite(6, True, 20) - test_observation(self, observation, True, True, 20) - test_observation(self, observation, True, True, 21) - test_observation(self, observation, True, True, 22) - - observation = complete_composite(6, True, 21) - test_observation(self, observation, True, True, 20) - test_observation(self, observation, True, True, 21) - test_observation(self, observation, True, True, 22) - - observation = complete_composite(6, True, 22) - test_observation(self, observation, True, True, 20) - test_observation(self, observation, True, True, 21) - test_observation(self, observation, True, True, 22) - - -def minimal_simple(depth, bounds_is_circle, version): - instances = Caom2TestInstances() - instances.complete = False - instances.depth = depth - instances.bounds_is_circle = bounds_is_circle - instances.caom_version = version - return instances.get_simple_observation() - - -def complete_simple(depth, bounds_is_circle, version): - instances = Caom2TestInstances() - instances.complete = True - instances.depth = depth - instances.bounds_is_circle = bounds_is_circle - instances.caom_version = version - return instances.get_simple_observation() - - -def minimal_composite(depth, bounds_is_circle, version): - instances = Caom2TestInstances() - instances.complete = False - instances.depth = depth - instances.bounds_is_circle = bounds_is_circle - instances.caom_version = version - return instances.get_composite_observation() - - -def complete_composite(depth, bounds_is_circle, version): - instances = Caom2TestInstances() - instances.complete = True - instances.depth = depth - instances.bounds_is_circle = bounds_is_circle - instances.caom_version = version - return instances.get_composite_observation() - - -def test_observation(self, observation, validate, write_empty_collections, version): - if version == 20: - writer = ObservationWriter( - validate, write_empty_collections, "caom2", CAOM20_NAMESPACE) - elif version == 21: - writer = ObservationWriter( - validate, write_empty_collections, "caom2", CAOM21_NAMESPACE) - else: - writer = ObservationWriter(validate, write_empty_collections) - xmlfile = open('/tmp/test.xml', 'w') - writer.write(observation, xmlfile) - xmlfile.close() - reader = ObservationReader(True) - returned = reader.read('/tmp/test.xml') - compareObservations(self, observation, returned, version) - - -def compareObservations(self, expected, actual, version): - - assert ((isinstance(expected, SimpleObservation) and - isinstance(actual, SimpleObservation)) or - (isinstance(expected, CompositeObservation) and - isinstance(actual, CompositeObservation))), ( - "Observation types do not match 0 vs 1". - format(expected.__class__.__name__, actual.__class__.__name__)) - - self.assertIsNotNone(expected.collection) - self.assertIsNotNone(actual.collection) - self.assertEqual(expected.collection, actual.collection) - - self.assertIsNotNone(expected.observation_id) - self.assertIsNotNone(actual.observation_id) - self.assertEqual(expected.observation_id, actual.observation_id) - - self.assertIsNotNone(expected._id) - self.assertIsNotNone(actual._id) - self.assertEqual(expected._id, actual._id) - - self.assertIsNotNone(expected._last_modified) - self.assertIsNotNone(actual._last_modified) - self.assertEqual(expected._last_modified, actual._last_modified) - - self.assertIsNotNone(expected.algorithm) - self.assertIsNotNone(actual.algorithm) - self.assertEqual(expected.algorithm.name, actual.algorithm.name) - - self.assertEqual(expected.sequence_number, actual.sequence_number) - self.assertEqual(expected.intent, actual.intent) - self.assertEqual(expected.meta_release, actual.meta_release) - compareProposal(self, expected.proposal, actual.proposal) - compareTarget(self, expected.target, actual.target) - compareTargetPosition(self, expected.target_position, actual.target_position) - compareTelescope(self, expected.telescope, actual.telescope) - compareInstrument(self, expected.instrument, actual.instrument) - compareEnvironment(self, expected.environment, actual.environment) - if version == 21: - compareRequirements(self, expected.requirements, actual.requirements) - - comparePlanes(self, expected.planes, actual.planes, version) - - if (isinstance(expected, CompositeObservation) and - isinstance(actual, CompositeObservation)): - compareMembers(self, expected.members, actual.members) - - -def compareProposal(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.proposal_id, actual.proposal_id) - self.assertEqual(expected.pi_name, actual.pi_name) - self.assertEqual(expected.project, actual.project) - self.assertEqual(expected.title, actual.title) - self.assertEqual(len(expected.keywords), len(actual.keywords)) - for keyword in expected.keywords: - self.assertTrue(keyword in actual.keywords) - - -def compareTarget(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.name, actual.name) - self.assertEqual(expected.target_type, actual.target_type) - self.assertEqual(expected.redshift, actual.redshift) - for keyword in expected.keywords: - self.assertTrue(keyword in actual.keywords) - - - -def compareTargetPosition(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.coordinates) - self.assertIsNotNone(actual.coordsys) - comparePoint(self, expected.coordinates, actual.coordinates) - self.assertEqual(expected.coordsys, actual.coordsys) - self.assertEqual(expected.equinox, actual.equinox) - - -def compareTelescope(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.name, actual.name) - self.assertEqual(expected.geo_location_x, actual.geo_location_x) - self.assertEqual(expected.geo_location_y, actual.geo_location_y) - self.assertEqual(expected.geo_location_z, actual.geo_location_z) - for keyword in expected.keywords: - self.assertTrue(keyword in actual.keywords) - - - -def compareInstrument(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.name, actual.name) - for keyword in expected.keywords: - self.assertTrue(keyword in actual.keywords) - - -def compareEnvironment(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.seeing, actual.seeing) - self.assertEqual(expected.humidity, actual.humidity) - self.assertEqual(expected.elevation, actual.elevation) - self.assertEqual(expected.tau, actual.tau) - self.assertEqual(expected.wavelength_tau, actual.wavelength_tau) - self.assertEqual(expected.ambient_temp, actual.ambient_temp) - self.assertEqual(expected.photometric, actual.photometric) - - -def compareMembers(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for expected_member, actual_member in zip(expected, actual): - compareObservationURI(self, expected_member, actual_member) - - -def compareObservationURI(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEquals(expected.uri, actual.uri) - self.assertEquals(expected.collection, actual.collection) - self.assertEquals(expected.observation_id, actual.observation_id) - - -def compareRequirements(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEquals(expected.flag, actual.flag) - - -def comparePlanes(self, expected, actual, version): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for key in expected: - self.assertTrue(key in actual) - expected_plane = expected[key] - actual_plane = actual[key] - self.assertIsNotNone(expected_plane) - self.assertIsNotNone(actual_plane) - self.assertEqual(expected_plane.product_id, actual_plane.product_id) - self.assertIsNotNone(expected_plane._id) - self.assertIsNotNone(actual_plane._id) - self.assertEqual(expected_plane._id, actual_plane._id) - self.assertIsNotNone(expected_plane._last_modified) - self.assertIsNotNone(actual_plane._last_modified) - self.assertEqual(expected_plane._last_modified, - actual_plane._last_modified) - self.assertEqual(expected_plane.meta_release, - actual_plane.meta_release) - self.assertEqual(expected_plane.data_release, - actual_plane.data_release) - self.assertEqual(expected_plane.data_product_type, - actual_plane.data_product_type) - self.assertEqual(expected_plane.calibration_level, - actual_plane.calibration_level) - compareProvenance(self, expected_plane.provenance, - actual_plane.provenance) - compareMetrics(self, expected_plane.metrics, actual_plane.metrics) - if version == 21: - compareQuality(self, expected_plane.quality, actual_plane.quality) - - compareArtifacts(self, expected_plane.artifacts, actual_plane.artifacts, version) - - -def compareProvenance(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.version, actual.version) - self.assertEqual(expected.project, actual.project) - self.assertEqual(expected.producer, actual.producer) - self.assertEqual(expected.run_id, actual.run_id) - self.assertEqual(expected.reference, actual.reference) - self.assertEqual(expected.last_executed, actual.last_executed) - compareInputs(self, expected.inputs, actual.inputs) - - -def compareMetrics(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.source_number_density, actual.source_number_density) - self.assertEqual(expected.background, actual.background) - self.assertEqual(expected.background_std_dev, actual.background_std_dev) - self.assertEqual(expected.flux_density_limit, actual.flux_density_limit) - self.assertEqual(expected.mag_limit, actual.mag_limit) - - -def compareQuality(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.flag, actual.flag) - - -def compareInputs(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for expected_plane_uri, actual_plane_uri in zip(expected, actual): - self.assertEqual(expected_plane_uri, actual_plane_uri) - - -def compareArtifacts(self, expected, actual, version): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for key in expected: - self.assertTrue(key in actual) - expected_artifact = expected[key] - actual_artifact = actual[key] - self.assertIsNotNone(expected_artifact) - self.assertIsNotNone(actual_artifact) - self.assertIsNotNone(expected_artifact._id) - self.assertIsNotNone(actual_artifact._id) - self.assertEqual(expected_artifact._id, actual_artifact._id) - self.assertIsNotNone(expected_artifact._last_modified) - self.assertIsNotNone(actual_artifact._last_modified) - self.assertEqual(expected_artifact._last_modified, actual_artifact._last_modified) - self.assertEqual(expected_artifact.uri, actual_artifact.uri) - self.assertEqual(expected_artifact.content_type, actual_artifact.content_type) - self.assertEqual(expected_artifact.content_length, actual_artifact.content_length) - self.assertEqual(expected_artifact.product_type, actual_artifact.product_type) - if version > 21: - self.assertEqual(expected_artifact.release_type, actual_artifact.release_type) - compareParts(self, expected_artifact.parts, actual_artifact.parts, version) - - -def compareParts(self, expected, actual, version): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for key in expected: - self.assertTrue(key in actual) - expected_part = expected[key] - actual_part = actual[key] - self.assertIsNotNone(expected_part) - self.assertIsNotNone(actual_part) - self.assertIsNotNone(expected_part._id) - self.assertIsNotNone(actual_part._id) - self.assertEqual(expected_part._id, actual_part._id) - self.assertIsNotNone(expected_part._last_modified) - self.assertIsNotNone(actual_part._last_modified) - self.assertEqual(expected_part._last_modified, - actual_part._last_modified) - self.assertEqual(expected_part.name, actual_part.name) - self.assertEqual(expected_part.product_type, actual_part.product_type) - compareChunks(self, expected_part.chunks, actual_part.chunks) - - -def compareChunks(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for expected_chunk, actual_chunk in zip(expected, actual): - self.assertIsNotNone(expected_chunk) - self.assertIsNotNone(actual_chunk) - self.assertIsNotNone(expected_chunk._id) - self.assertIsNotNone(actual_chunk._id) - self.assertEqual(expected_chunk._id, actual_chunk._id) - self.assertIsNotNone(expected_chunk._last_modified) - self.assertIsNotNone(actual_chunk._last_modified) - self.assertEqual(expected_chunk._last_modified, - actual_chunk._last_modified) - self.assertEqual(expected_chunk.product_type, - actual_chunk.product_type) - self.assertEqual(expected_chunk.naxis, actual_chunk.naxis) - self.assertEqual(expected_chunk.observable_axis, - actual_chunk.observable_axis) - self.assertEqual(expected_chunk.position_axis_1, - actual_chunk.position_axis_1) - self.assertEqual(expected_chunk.position_axis_2, - actual_chunk.position_axis_2) - self.assertEqual(expected_chunk.energy_axis, actual_chunk.energy_axis) - self.assertEqual(expected_chunk.time_axis, actual_chunk.time_axis) - self.assertEqual(expected_chunk.polarization_axis, - actual_chunk.polarization_axis) - compareObservableAxis(self, expected_chunk.observable, - actual_chunk.observable) - compareSpatialWCS(self, expected_chunk.position, actual_chunk.position) - compareSpectralWCS(self, expected_chunk.energy, actual_chunk.energy) - compareTemporalWCS(self, expected_chunk.time, actual_chunk.time) - comparePolarizationWCS(self, expected_chunk.polarization, - actual_chunk.polarization) - - -def compareObservableAxis(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compareSlice(self, expected.dependent, actual.dependent) - compareSlice(self, expected.independent, actual.independent) - - -def compareSpatialWCS(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compareCoordAxis2D(self, expected.axis, actual.axis) - self.assertEqual(expected.coordsys, actual.coordsys) - self.assertEqual(expected.equinox, actual.equinox) - self.assertEqual(expected.resolution, actual.resolution) - - -def compareSpectralWCS(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compareCoordAxis1D(self, expected.axis, actual.axis) - self.assertEqual(expected.bandpass_name, actual.bandpass_name) - self.assertEqual(expected.resolving_power, actual.resolving_power) - self.assertEqual(expected.restfrq, actual.restfrq) - self.assertEqual(expected.restwav, actual.restwav) - self.assertEqual(expected.specsys, actual.specsys) - self.assertEqual(expected.ssysobs, actual.ssysobs) - self.assertEqual(expected.ssyssrc, actual.ssyssrc) - self.assertEqual(expected.velang, actual.velang) - self.assertEqual(expected.velosys, actual.velosys) - self.assertEqual(expected.zsource, actual.zsource) - - -def compareTemporalWCS(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compareCoordAxis1D(self, expected.axis, actual.axis) - self.assertEqual(expected.exposure, actual.exposure) - self.assertEqual(expected.resolution, actual.resolution) - self.assertEqual(expected.timesys, actual.timesys) - self.assertEqual(expected.trefpos, actual.trefpos) - self.assertEqual(expected.mjdref, actual.mjdref) - - -def comparePolarizationWCS(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compareCoordAxis1D(self, expected.axis, actual.axis) - - -def compareAxis(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.ctype) - self.assertIsNotNone(actual.cunit) - self.assertEqual(expected.ctype, actual.ctype) - self.assertEqual(expected.cunit, actual.cunit) - - -def compareCoord2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - compareRefCoord(self, expected.coord1, actual.coord1) - compareRefCoord(self, expected.coord2, actual.coord2) - - -def compareValueCoord2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertEqual(expected.coord1, actual.coord1) - self.assertEqual(expected.coord2, actual.coord2) - - -def compareCoordAxis1D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - compareCoordError(self, expected.error, actual.error) - compareCoordRange1D(self, expected.range, actual.range) - compareCoordBounds1D(self, expected.bounds, actual.bounds) - compareCoordFunction1D(self, expected.function, actual.function) - - -def compareCoordAxis2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.axis1) - self.assertIsNotNone(actual.axis2) - compareAxis(self, expected.axis1, actual.axis1) - compareAxis(self, expected.axis2, actual.axis2) - compareCoordError(self, expected.error1, actual.error1) - compareCoordError(self, expected.error2, actual.error2) - compareCoordRange2D(self, expected.range, actual.range) - compareCoordBounds2D(self, expected.bounds, actual.bounds) - compareCoordFunction2D(self, expected.function, actual.function) - - -def compareCoordBounds1D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(expected.samples) - self.assertIsNotNone(actual.samples) - self.assertEqual(len(expected.samples), len(actual.samples)) - for expected_range, actual_range in zip(expected.samples, actual.samples): - compareCoordRange1D(self, expected_range, actual_range) - - -def compareCoordBounds2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - if (isinstance(expected, CoordCircle2D) and - isinstance(actual, CoordCircle2D)): - compareCoordCircle2D(self, expected, actual) - elif (isinstance(expected, CoordPolygon2D) and - isinstance(actual, CoordPolygon2D)): - compareCoordPolygon2D(self, expected, actual) - else: - self.fail("CoordBounds2D expected and actual are different types.") - - -def compareCoordCircle2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.center) - self.assertIsNotNone(actual.radius) - compareValueCoord2D(self, expected.center, actual.center) - self.assertEqual(expected.radius, actual.radius) - - -def compareCoordError(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - - self.assertIsNotNone(actual) - if expected.syser: - self.assertIsNotNone(actual.syser) - self.assertEqual(expected.syser, actual.syser) - if expected.rnder: - self.assertIsNotNone(actual.rnder) - self.assertEqual(expected.rnder, actual.rnder) - - -def compareCoordFunction1D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertEqual(expected.naxis, actual.naxis) - self.assertEqual(expected.delta, actual.delta) - compareRefCoord(self, expected.ref_coord, actual.ref_coord) - - -def compareCoordFunction2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.dimension) - self.assertIsNotNone(actual.ref_coord) - self.assertIsNotNone(actual.cd11) - self.assertIsNotNone(actual.cd12) - self.assertIsNotNone(actual.cd21) - self.assertIsNotNone(actual.cd22) - compareDimension2D(self, expected.dimension, actual.dimension) - compareCoord2D(self, expected.ref_coord, actual.ref_coord) - self.assertEqual(expected.cd11, actual.cd11, 0.0) - self.assertEqual(expected.cd12, actual.cd12, 0.0) - self.assertEqual(expected.cd21, actual.cd21, 0.0) - self.assertEqual(expected.cd22, actual.cd22, 0.0) - - -def compareCoordPolygon2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(expected.vertices) - self.assertIsNotNone(actual.vertices) - self.assertEqual(len(expected.vertices), len(actual.vertices)) - for expected_coord_2d, actual_coord_2d in zip(expected.vertices, - actual.vertices): - compareValueCoord2D(self, expected_coord_2d, actual_coord_2d) - - -def compareCoordRange1D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - compareRefCoord(self, expected.start, actual.start) - compareRefCoord(self, expected.end, actual.end) - - -def compareCoordRange2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.start) - self.assertIsNotNone(actual.end) - compareCoord2D(self, expected.start, actual.start) - compareCoord2D(self, expected.end, actual.end) - - -def compareDimension2D(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertEqual(expected.naxis1, actual.naxis1) - self.assertEqual(expected.naxis2, actual.naxis2) - - -def compareRefCoord(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertEqual(expected.pix, actual.pix) - self.assertEqual(expected.val, actual.val) - - -def compareSlice(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.bin) - self.assertIsNotNone(actual.axis) - self.assertEqual(expected.bin, actual.bin) - compareAxis(self, expected.axis, actual.axis) - - -def comparePoint(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.cval1) - self.assertIsNotNone(actual.cval2) - self.assertEqual(expected.cval1, actual.cval1) - self.assertEqual(expected.cval2, actual.cval2) - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_plane.py b/pyCAOM2/caom2/test/test_plane.py deleted file mode 100644 index 974f1384..00000000 --- a/pyCAOM2/caom2/test/test_plane.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPlane class """ - -import unittest -from datetime import datetime - -from caom2.caom2_artifact import Artifact -from caom2.caom2_data_quality import DataQuality -from caom2.caom2_enums import CalibrationLevel -from caom2.caom2_enums import DataProductType -from caom2.caom2_enums import Quality -from caom2.caom2_metrics import Metrics -from caom2.caom2_plane import Plane -from caom2.caom2_provenance import Provenance -from caom2.caom2_enums import ProductType, ReleaseType - - -class TestPlane(unittest.TestCase): - - def testAll(self): - plane = Plane("ProdID") - self.assertEqual("ProdID", plane.product_id, "Product ID") - self.assertEqual(0, len(plane.artifacts), - "Default number of artifacts") - self.assertIsNone(plane.meta_release, "Default meta release date") - date_now = datetime.now() - plane.meta_release = date_now - self.assertEqual(date_now, plane.meta_release, "Metadata release date") - self.assertIsNone(plane.data_release, "Default data release date") - date_now = datetime.now() - plane.data_release = date_now - self.assertEqual(date_now, plane.data_release, "Data release date") - self.assertIsNone(plane.data_product_type, "Default data product type") - plane.data_product_type = DataProductType.IMAGE - self.assertEqual(DataProductType.IMAGE, plane.data_product_type, - "Data product type") - self.assertIsNone(plane.calibration_level, - "Default calibration level") - plane.calibration_level = CalibrationLevel.CALIBRATED - self.assertEqual(CalibrationLevel.CALIBRATED, - plane.calibration_level, "CalibrationLevel") - self.assertIsNone(plane.quality, - "Default quality") - quality = DataQuality(Quality.JUNK) - plane.quality = quality - self.assertEqual(quality, - plane.quality, "Quality") - self.assertIsNone(plane.provenance, "Default provenance") - provenance = Provenance("myProv") - plane.provenance = provenance - self.assertEqual("myProv", plane.provenance.name, "Provenance - name") - self.assertIsNone(plane.metrics, "Default metrics") - metrics = Metrics() - plane.metrics = metrics - self.assertEqual(metrics, plane.metrics, "Provenance - metrics") - #self.assertIsNone(plane.observable, "Default observable") - self.assertIsNone(plane.position, "Default position") - self.assertIsNone(plane.energy, "Default energy") - self.assertIsNone(plane.time, "Default time") - self.assertIsNone(plane.polarization, "Default polarization") - - artifact1 = Artifact("caom:GEMINI/222/333", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:GEMINI/222/333"] = artifact1 - self.assertEquals(1, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - - artifact2 = Artifact("caom:CFHT/55/66", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:CFHT/55/66"] = artifact2 - self.assertEquals(2, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - self.assertTrue("caom:CFHT/55/66" in plane.artifacts.keys()) - - #try to append a duplicate artifact - artifact3 = Artifact("caom:GEMINI/222/333", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:GEMINI/222/333"] = artifact3 - self.assertEquals(2, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - self.assertTrue("caom:CFHT/55/66" in plane.artifacts.keys()) - - #Error cases - exception = False - try: - plane = Plane(None) - except TypeError: - exception = True - self.assertTrue(exception, "Null argument in initialize") - - #exception = False - #try: - # plane.compute_observable() - #except TypeError: - # exception = True - #self.assertTrue(exception, - # "compute_observable implemented - Testing needed") - - #exception = False - #try: - # plane.compute_position() - #except TypeError: - # exception = True - #self.assertTrue(exception, - # "compute_position implemented - Testing needed") - - exception = False - try: - plane.compute_energy() - except NotImplementedError: - exception = True - self.assertTrue(exception, - "compute_energy implemented - Testing needed") - - exception = False - try: - plane.compute_time() - except NotImplementedError: - exception = True - self.assertTrue(exception, "compute_time implemented - Testing needed") - - exception = False - try: - plane.compute_polarization() - except NotImplementedError: - exception = True - self.assertTrue(exception, "compute_polarization implemented" - " - Testing needed") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_plane_uri.py b/pyCAOM2/caom2/test/test_plane_uri.py deleted file mode 100644 index 25eef54b..00000000 --- a/pyCAOM2/caom2/test/test_plane_uri.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPlaneURI class """ - -import unittest - -from caom2.caom2_observation_uri import ObservationURI -from caom2.caom2_plane_uri import PlaneURI - - -class TestPlaneURI(unittest.TestCase): - - def testAll(self): - planeURI = PlaneURI("caom:GEMINI/12345/3333") - self.assertEqual("caom:GEMINI/12345/3333", planeURI.uri, - "Plane URI") - self.assertEqual("GEMINI", planeURI.observation_uri.collection, - "Collection") - self.assertEqual("12345", planeURI.observation_uri.observation_id, - "Observation ID") - self.assertEqual("3333", planeURI.product_id, "Product ID") - - planeURI = PlaneURI.get_plane_uri(ObservationURI("caom:CFHT/654321"), - "555") - self.assertEqual("caom:CFHT/654321/555", planeURI.uri, - "Observation URI") - self.assertEqual("CFHT", planeURI.observation_uri.collection, - "Collection") - self.assertEqual("654321", planeURI.observation_uri.observation_id, - "Observation ID") - self.assertEqual("555", planeURI.product_id, "Product ID") - - exception = False - try: - planeURI = PlaneURI.get_plane_uri(None, "123") - except TypeError: - exception = True - self.assertTrue(exception, "Missing exception") - - exception = False - try: - planeURI = PlaneURI.get_plane_uri("GEMINI", None) - except TypeError: - exception = True - self.assertTrue(exception, "Missing exception") - - #wrong scheme - exception = False - try: - planeURI = PlaneURI("somescheme:GEMINI/12345/3333") - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - exception = False - try: - planeURI = PlaneURI("caom:GEMINI/12345") - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_polarization.py b/pyCAOM2/caom2/test/test_polarization.py deleted file mode 100644 index 0d22864f..00000000 --- a/pyCAOM2/caom2/test/test_polarization.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPolarizaton class """ - -import unittest - -from caom2.caom2_energy import Energy -from caom2.caom2_polarization import Polarization - - -class TestPolarizaton(unittest.TestCase): - - def testAll(self): - polarization = Polarization() - - self.assertIsNone(polarization.dimension, - "Default polarization dimension") - energy = Energy() - energy.bandpass_name = '123' - self.assertEqual('123', energy.bandpass_name, "Polarization dimension") - - #TODO add test for state - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_polarization_wcs.py b/pyCAOM2/caom2/test/test_polarization_wcs.py deleted file mode 100644 index 8cc7426a..00000000 --- a/pyCAOM2/caom2/test/test_polarization_wcs.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPolarizationWCS class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_polarization_wcs import PolarizationWCS - - -class TestPolarizationWCS(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, PolarizationWCS, None) - self.assertRaises(TypeError, PolarizationWCS, int(1)) - - axis = Axis('STOKES') - axis_1d = CoordAxis1D(axis) - polarization = PolarizationWCS(axis_1d) - self.assertEqual(polarization.axis, axis_1d) - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_position.py b/pyCAOM2/caom2/test/test_position.py deleted file mode 100644 index ae3c2bae..00000000 --- a/pyCAOM2/caom2/test/test_position.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPosition class """ - -import unittest - -from caom2.caom2_position import Position - - -class TestPosition(unittest.TestCase): - - def testAll(self): - position = Position() - - self.assertIsNone(position.bounds, "Default bounds") - #position.bounds = 123 - #self.assertEqual(123, position.bounds, "Bounds") - self.assertIsNone(position.dimension, "Default dimension") - #position.dimension = 123 - #self.assertEqual(123, position.dimension, "Dimension") - self.assertIsNone(position.resolution, "Default resolution") - position.resolution = 123.321 - self.assertEqual(123.321, position.resolution, "Resolution") - self.assertIsNone(position.sample_size, "Default sample size") - position.sample_size = 321.123 - self.assertEqual(321.123, position.sample_size, "Sample size") - self.assertFalse(position.time_dependent, "Default time dependent") - position.time_dependent = True - self.assertTrue(position.time_dependent, "Time dependent") - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_proposal.py b/pyCAOM2/caom2/test/test_proposal.py deleted file mode 100644 index 300ac24d..00000000 --- a/pyCAOM2/caom2/test/test_proposal.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestProposal class """ - -import unittest - -from caom2.caom2_proposal import Proposal - - -class TestProposal(unittest.TestCase): - - def testAll(self): - proposal = Proposal("myProposal") - self.assertEqual("myProposal", proposal.proposal_id, "Proposal ID") - self.assertEqual(0, len(proposal.keywords), "Default number of keywords") - proposal.keywords.add("optical") - self.assertEqual(1, len(proposal.keywords), "Number of keywords") - self.assertTrue("optical" in proposal.keywords, "Keyword not found") - self.assertIsNone(proposal.pi_name, "Default PI") - proposal.pi_name = "John Doe" - self.assertEqual("John Doe", proposal.pi_name, "PI") - self.assertIsNone(proposal.project, "Default PI") - proposal.project = "Project A" - self.assertEqual("Project A", proposal.project, "Project") - self.assertIsNone(proposal.title, "Default title") - proposal.title = "Something Interesting" - self.assertEqual("Something Interesting", proposal.title, "Title") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_provenance.py b/pyCAOM2/caom2/test/test_provenance.py deleted file mode 100644 index bbfe4a65..00000000 --- a/pyCAOM2/caom2/test/test_provenance.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestProvenance class """ - -import unittest -from datetime import datetime - -from caom2.caom2_plane_uri import PlaneURI -from caom2.caom2_provenance import Provenance - - -class TestProvenance(unittest.TestCase): - - def testAll(self): - provenance = Provenance("MyProvenance") - self.assertEqual("MyProvenance", provenance.name, "Name") - - self.assertIsNone(provenance.version, "Default version") - provenance.version = "XII" - self.assertEquals("XII", provenance.version, "Version") - self.assertIsNone(provenance.project, "Default project") - provenance.project = "CFHTLS" - self.assertEquals("CFHTLS", provenance.project, "Project") - self.assertIsNone(provenance.producer, "Default producer") - provenance.producer = "prod" - self.assertEquals("prod", provenance.producer, "Producer") - self.assertIsNone(provenance.run_id, "Default run ID") - provenance.run_id = "A23" - self.assertEquals("A23", provenance.run_id, "Run ID") - self.assertIsNone(provenance.reference, "Default reference") - - self.assertEqual(0, len(provenance.inputs), "Default inputs") - planeURI1 = PlaneURI("caom:HST/11/00") - provenance.inputs.add(planeURI1) - self.assertEqual(1, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) - - planeURI2 = PlaneURI("caom:HST/22/00") - provenance.inputs.add(planeURI2) - self.assertEqual(2, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) - self.assertTrue(planeURI2 in provenance.inputs) - - # testing duplicates - planeURI3 = PlaneURI("caom:HST/22/00") - provenance.inputs.add(planeURI3) - self.assertEqual(2, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) - self.assertTrue(planeURI2 in provenance.inputs) - - self.assertIsNone(provenance.last_executed, "Default last executed") - now_date = datetime.now() - provenance.last_executed = now_date - self.assertEquals(now_date, provenance.last_executed, "Last executed") - - self.assertEquals(0, len(provenance.keywords), "0 default keywords") - provenance.keywords.add("keyword1") - self.assertEquals(1, len(provenance.keywords), "1 keyword") - self.assertTrue("keyword1" in provenance.keywords, "Keyword not found") - - provenance.keywords.add("keyword2") - self.assertEquals(2, len(provenance.keywords), "2 keyword") - self.assertTrue("keyword2" in provenance.keywords, "Keyword not found") - - # test the full constructor - provenance = Provenance("MyOtherProvenance", - "Version2.0", - "JCMT", - "Mutt Lang", - "b32", - "caom:JCMT/33/00", - now_date) - - self.assertIsNotNone(provenance.name) - self.assertIsNotNone(provenance.version) - self.assertIsNotNone(provenance.project) - self.assertIsNotNone(provenance.producer) - self.assertIsNotNone(provenance.run_id) - self.assertIsNotNone(provenance.reference) - self.assertIsNotNone(provenance.last_executed) - - self.assertEquals("MyOtherProvenance", provenance.name, "name") - self.assertEquals("Version2.0", provenance.version, "version") - self.assertEquals("JCMT", provenance.project, "project") - self.assertEquals("Mutt Lang", provenance.producer, "producer") - self.assertEquals("b32", provenance.run_id, "run_id") - self.assertEquals("caom:JCMT/33/00", provenance.reference, "reference") - self.assertEquals(now_date, provenance.last_executed, "last_executed") - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_ref_coord.py b/pyCAOM2/caom2/test/test_ref_coord.py deleted file mode 100644 index ee12da9e..00000000 --- a/pyCAOM2/caom2/test/test_ref_coord.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestRefCoord class """ - -import unittest - -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestRefCoord(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, RefCoord, None, None) - self.assertRaises(TypeError, RefCoord, None, float(1.0)) - self.assertRaises(TypeError, RefCoord, float(1.0), None) - self.assertRaises(TypeError, RefCoord, int(1), float(1.0)) - self.assertRaises(TypeError, RefCoord, float(1.0), int(1)) - - ref_coord = RefCoord(float(1), float(2)) - self.assertIsNotNone(ref_coord) - self.assertEqual(ref_coord.pix, float(1)) - self.assertEqual(ref_coord.val, float(2)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_requirements.py b/pyCAOM2/caom2/test/test_requirements.py deleted file mode 100644 index 7b238d95..00000000 --- a/pyCAOM2/caom2/test/test_requirements.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestRequirements class """ - -import unittest - -from caom2.caom2_enums import Status -from caom2.caom2_requirements import Requirements - - -class TestRequirements(unittest.TestCase): - - def testAll(self): - - self.assertRaises(TypeError, Requirements, "string") - requirements = Requirements(Status.FAIL) - self.assertEqual(Status.FAIL, requirements.flag, - "Requirements flag") - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_simple_observation.py b/pyCAOM2/caom2/test/test_simple_observation.py deleted file mode 100644 index a9706b61..00000000 --- a/pyCAOM2/caom2/test/test_simple_observation.py +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestSimpleObservation class """ - -import unittest -from datetime import datetime - -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_enums import ObservationIntentType -from caom2.caom2_enums import Status -from caom2.caom2_environment import Environment -from caom2.caom2_instrument import Instrument -from caom2.caom2_plane import Plane -from caom2.caom2_proposal import Proposal -from caom2.caom2_requirements import Requirements -from caom2.caom2_simple_observation import SimpleObservation -from caom2.caom2_target import Target -from caom2.caom2_target_position import TargetPosition -from caom2.caom2_telescope import Telescope -from caom2.types.caom2_point import Point -from caom2.util.caom2_util import TypedOrderedDict - - -class TestSimpleObservation(unittest.TestCase): - - def testAll(self): - algorithm = SimpleObservation._ALGORITHM - obs = SimpleObservation("GSA", "A12345") - self.assertEqual("GSA", obs.collection, "Collection") - self.assertEqual("A12345", obs.observation_id, "Observation ID") - - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - obs.algorithm = algorithm - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - # try to set algorithm - exception = False - try: - obs.algorithm = Algorithm("myAlg") - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - # run the rest of the Observation tests - self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, - obs.intent, "Observation intent") - - self.assertIsNone(obs.obs_type, "Default obs_type") - obs.obs_type = "obstype1" - self.assertEqual("obstype1", - obs.obs_type, "obs type") - - self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") - obs.proposal = proposal - self.assertEqual(proposal, - obs.proposal, "Proposal") - - self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") - obs.telescope = telescope - self.assertEqual(telescope, - obs.telescope, "Telescope") - - self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") - obs.instrument = instrument - self.assertEqual(instrument, - obs.instrument, "Instrument") - - self.assertIsNone(obs.target, "Default target") - target = Target("TGT") - obs.target = target - self.assertEqual(target, - obs.target, "Target") - - self.assertIsNone(obs.environment, "Default environment") - environment = Environment() - obs.environment = environment - self.assertEqual(environment, - obs.environment, "Environment") - - self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - obs.target_position = target_position - self.assertEqual(target_position, - obs.target_position, "TargetPosition") - - self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) - obs.requirements = requirements - self.assertEquals(requirements, obs.requirements, "requirements") - - self.assertIsNone(obs.meta_release, "Default metadata release") - date_now = datetime.now() - obs.meta_release = date_now - self.assertEqual(date_now, - obs.meta_release, "Metadata release") - - # Test the complete constructor - def testCompleteInit(self): - collection = str("CFHT") - observationID = str("543210") - algorithm = SimpleObservation._ALGORITHM - sequence_number = int(3) - intent = ObservationIntentType.SCIENCE - obs_type = str("foo") - proposal = Proposal("123") - telescope = Telescope("TEL") - instrument = Instrument("INST") - target = Target("LMC") - meta_release = datetime.now() - planes = TypedOrderedDict((Plane),) - environment = Environment() - - obs = SimpleObservation(collection, - observationID, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment) - - self.assertIsNotNone(obs.collection, "Collection") - self.assertEqual(collection, obs.collection, "Collection") - - self.assertIsNotNone(obs.observation_id, "Observation ID") - self.assertEqual(observationID, obs.observation_id, "Observation ID") - - self.assertIsNotNone(obs.algorithm, "Algorithm") - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - self.assertIsNotNone(obs.intent, "Observation intent") - self.assertEqual(intent, obs.intent, "Observation intent") - - self.assertIsNotNone(obs.obs_type, "obs type") - self.assertEqual(obs_type, obs.obs_type, "obs type") - - self.assertIsNotNone(obs.proposal, "Proposal") - self.assertEqual(proposal, obs.proposal, "Proposal") - - self.assertIsNotNone(obs.telescope, "Telescope") - self.assertEqual(telescope, obs.telescope, "Telescope") - - self.assertIsNotNone(obs.instrument, "Instrument") - self.assertEqual(instrument, obs.instrument, "Instrument") - - self.assertIsNotNone(obs.target, "Target") - self.assertEqual(target, obs.target, "Target") - - self.assertIsNotNone(obs.meta_release, "Metadata release") - self.assertEqual(meta_release, obs.meta_release, "Metadata release") - - self.assertIsNotNone(obs.planes, "Planes") - self.assertEqual(planes, obs.planes, "Planes") - - self.assertIsNotNone(obs.environment, "Environment") - self.assertEqual(environment, obs.environment, "Environment") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_slice.py b/pyCAOM2/caom2/test/test_slice.py deleted file mode 100644 index 8bf7ac20..00000000 --- a/pyCAOM2/caom2/test/test_slice.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestSlice class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_slice import Slice - - -class TestSlice(unittest.TestCase): - - def testInit(self): - - axis = Axis("ctype", "cunit") - myBin = long(1) - - self.assertRaises(TypeError, Slice, None, None) - self.assertRaises(TypeError, Slice, None, myBin) - self.assertRaises(TypeError, Slice, axis, None) - self.assertRaises(TypeError, Slice, str("s"), myBin) - self.assertRaises(TypeError, Slice, axis, int(1)) - - mySlice = Slice(axis, myBin) - self.assertEqual(mySlice.axis, axis) - self.assertEqual(mySlice.bin, long(1)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_spatial_wcs.py b/pyCAOM2/caom2/test/test_spatial_wcs.py deleted file mode 100644 index 3aac4c67..00000000 --- a/pyCAOM2/caom2/test/test_spatial_wcs.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestSpatialWCS class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -from caom2.wcs.caom2_spatial_wcs import SpatialWCS - - -class TestSpatialWCS(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, SpatialWCS, None) - self.assertRaises(TypeError, SpatialWCS, int(1)) - - axis1 = Axis("ctype1", "cunit1") - axis2 = Axis("ctype2", "cunit2") - axis_2d = CoordAxis2D(axis1, axis2) - position = SpatialWCS(axis_2d) - self.assertEqual(position.axis, axis_2d) - with self.assertRaises(TypeError): - position.coordsys = float(1.0) - position.bounds = str("s") - position.function = str("s") - - position.coordsys = "coordsys" - self.assertEqual(position.coordsys, "coordsys") - - self.assertRaises(ValueError, position.equinox, float(1.0)) - position.equinox = float(2000.0) - self.assertEqual(position.equinox, float(2000.0)) - - position.resolution = float(2.0) - self.assertEqual(position.resolution, float(2.0)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_spectral_wcs.py b/pyCAOM2/caom2/test/test_spectral_wcs.py deleted file mode 100644 index 0db774e2..00000000 --- a/pyCAOM2/caom2/test/test_spectral_wcs.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestSpectralWCS class """ - -import unittest - -from caom2.caom2_energy_transition import EnergyTransition -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_spectral_wcs import SpectralWCS - - -class TestSpectralWCS(unittest.TestCase): - - def testInit(self): - - axis = Axis("ctype", "cunit") - axis_1d = CoordAxis1D(axis) - - self.assertRaises(TypeError, SpectralWCS, None, None) - self.assertRaises(TypeError, SpectralWCS, None, str("s")) - self.assertRaises(TypeError, SpectralWCS, axis_1d, None) - self.assertRaises(TypeError, SpectralWCS, int(1), str("s")) - self.assertRaises(TypeError, SpectralWCS, axis_1d, int(1)) - - energy = SpectralWCS(axis_1d, "specsys") - self.assertEqual(energy.axis, axis_1d) - self.assertEqual(energy.specsys, "specsys") - with self.assertRaises(TypeError): - energy.ssysobs = int(1) - energy.ssyssrc = int(1) - energy.restfrq = int(1) - energy.restwav = int(1) - energy.velosys = int(1) - energy.zsource = int(1) - energy.velang = int(1) - energy.bandpass_name = int(1) - energy.transition = int(1) - energy.resolving_power = int(1) - - with self.assertRaises(ValueError): - energy.zsource = float(-1) - energy.zsource = float(1201) - energy.resolving_power = float(-1) - energy.resolving_power = float(1.1e8) - - - energy.ssysobs = "ssysobs" - self.assertEqual(energy.ssysobs, "ssysobs") - - energy.ssyssrc = "ssyssrc" - self.assertEqual(energy.ssyssrc, "ssyssrc") - - energy.restfrq = float(1.0) - self.assertEqual(energy.restfrq, float(1.0)) - - energy.restwav = float(2.0) - self.assertEqual(energy.restwav, float(2.0)) - - energy.velosys = float(3.0) - self.assertEqual(energy.velosys, float(3.0)) - - energy.zsource = float(4.0) - self.assertEqual(energy.zsource, float(4.0)) - - energy.velang = float(5.0) - self.assertEqual(energy.velang, float(5.0)) - - energy.bandpass_name = "bandpass_name" - self.assertEqual(energy.bandpass_name, "bandpass_name") - - transition = EnergyTransition("species", "transition") - energy.transition = transition - self.assertEqual(energy.transition, transition) - - energy.resolving_power = float(6.0) - self.assertEqual(energy.resolving_power, float(6.0)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_target.py b/pyCAOM2/caom2/test/test_target.py deleted file mode 100644 index aacf9051..00000000 --- a/pyCAOM2/caom2/test/test_target.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTarget class """ - -import unittest - -from caom2.caom2_enums import TargetType -from caom2.caom2_target import Target -from caom2.util.caom2_util import TypedList - - -class TestTarget(unittest.TestCase): - - def testAll(self): - - target = Target("myTarget") - self.assertEqual("myTarget", target.name, "target name") - - target.target_type = TargetType.FIELD - self.assertEqual(TargetType.FIELD, target.target_type, "target type") - - self.assertEqual(0, len(target.keywords), "Default number of keywords") - target.keywords.add("optical") - self.assertEqual(1, len(target.keywords), "Number of keywords") - self.assertTrue("optical" in target.keywords, "Keyword not found") - - self.assertIsNone(target.redshift, "Default redshift") - target.redshift = 123.321 - self.assertEqual(123.321, target.redshift, "Redshift") - - self.assertIsNone(target.standard, "Default standard") - target.standard = True - self.assertTrue(target.standard, "Standard") - - self.assertIsNone(target.moving, "Default moving") - target.moving = True - self.assertTrue(target.moving, "Moving") - - target = Target("myOtherTarget", TargetType.OBJECT, False, 1.2, {"radio"}, False) - self.assertEquals("myOtherTarget", target.name, "target name") - self.assertEquals(TargetType.OBJECT, target.target_type, "target type") - self.assertFalse(target.standard, "Standard") - self.assertEquals(1.2, target.redshift, "Redshift") - self.assertEquals(1, len(target.keywords), "Keywords") - self.assertTrue("radio" in target.keywords, "Keywords") - self.assertFalse(target.moving, "Moving") - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_target_position.py b/pyCAOM2/caom2/test/test_target_position.py deleted file mode 100644 index 5815c259..00000000 --- a/pyCAOM2/caom2/test/test_target_position.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTargetPosition class """ - -import unittest - -from caom2.caom2_target_position import TargetPosition -from caom2.types.caom2_point import Point - - -class TestTargetPosition(unittest.TestCase): - - def testAll(self): - - self.assertRaises(TypeError, TargetPosition, "string") - point = Point(1.0, 2.0) - target_position = TargetPosition(point, "coordsys") - self.assertIsNotNone(target_position.coordinates, - "target position coordinates") - self.assertEqual(point.cval1, target_position.coordinates.cval1, - "coordinates cval1") - self.assertEqual(point.cval2, target_position.coordinates.cval2, - "coordinates cval2") - self.assertIsNotNone(target_position.coordsys, - "target position coordsys") - self.assertEqual("coordsys", target_position.coordsys, "coordsys") - self.assertIsNone(target_position.equinox, - "target position equinox") - - target_position = TargetPosition(point, "coordsys", 1.0) - self.assertIsNotNone(target_position.equinox, - "target position equinox") - self.assertEqual(1.0, target_position.equinox, - "equinox") - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/test/test_telescope.py b/pyCAOM2/caom2/test/test_telescope.py deleted file mode 100644 index 8ccfeda0..00000000 --- a/pyCAOM2/caom2/test/test_telescope.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTelescope class """ - -import unittest - -from caom2.caom2_telescope import Telescope - - -class TestTelescope(unittest.TestCase): - - def testAll(self): - telescope = Telescope("myTelescope") - self.assertEqual("myTelescope", telescope.name, "telescope name") - self.assertEqual(0, len(telescope.keywords), "Default number of keywords") - - telescope.keywords.add("optical") - self.assertEqual(1, len(telescope.keywords), "Number of keywords") - self.assertTrue("optical" in telescope.keywords, "Keyword not found") - - self.assertIsNone(telescope.geo_location_x, "Default geo location x") - telescope.geo_location_x = 123.321 - self.assertEqual(123.321, telescope.geo_location_x, "Geo location x") - - self.assertIsNone(telescope.geo_location_y, "Default geo location y") - telescope.geo_location_y = 333.33 - self.assertEqual(333.33, telescope.geo_location_y, "Geo location y") - - self.assertIsNone(telescope.geo_location_z, "Default geo location z") - telescope.geo_location_z = 12.12 - self.assertEqual(12.12, telescope.geo_location_z, "Geo location z") - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_temporal_wcs.py b/pyCAOM2/caom2/test/test_temporal_wcs.py deleted file mode 100644 index 5b83fb4f..00000000 --- a/pyCAOM2/caom2/test/test_temporal_wcs.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTemporalWCS class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_temporal_wcs import TemporalWCS - - -class TestTemporalWCS(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, TemporalWCS, None) - self.assertRaises(TypeError, TemporalWCS, int(1)) - - axis = Axis("ctype", "cunit") - axis_1d = CoordAxis1D(axis) - time = TemporalWCS(axis_1d) - self.assertEqual(time.axis, axis_1d) - with self.assertRaises(TypeError): - time.exposure = str("s") - time.resolution = str("s") - - time.exposure = float(1.0) - self.assertEqual(time.exposure, float(1.0)) - - time.resolution = float(2.0) - self.assertEqual(time.resolution, float(2.0)) - - time.timesys = str("timesys") - self.assertEqual(time.timesys, "timesys") - - time.trefpos = str("trefpos") - self.assertEqual(time.trefpos, "trefpos") - - time.mjdref = float(3.0) - self.assertEqual(time.mjdref, float(3.0)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_time.py b/pyCAOM2/caom2/test/test_time.py deleted file mode 100644 index 37d545e4..00000000 --- a/pyCAOM2/caom2/test/test_time.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTime class """ - -import unittest - -from caom2.caom2_time import Time - - -class TestTime(unittest.TestCase): - - def testAll(self): - time = Time() - self.assertIsNone(time.value, "Default value") - self.assertIsNone(time.bounds, "Default bounds") - self.assertIsNone(time.dimension, "Default dimension") - self.assertIsNone(time.resolution, "Default resolution") - self.assertIsNone(time.sample_size, "Default sample size") - self.assertIsNone(time.exposure, "Default exposure") - - time.value = 34.34 - self.assertEqual(34.34, time.value, "Value") - time.dimension = 777L - self.assertEqual(777L, time.dimension, "Dimension") - time.resolution = 77.777 - self.assertEqual(77.777, time.resolution, "Resolution") - time.sample_size = 12.34 - self.assertEqual(12.34, time.sample_size, "Sample size") - time.exposure = 55.55 - self.assertEqual(55.55, time.exposure, "Exposure") - -if __name__ == '__main__': - unittest.main() - diff --git a/pyCAOM2/caom2/test/test_value_coord2d.py b/pyCAOM2/caom2/test/test_value_coord2d.py deleted file mode 100644 index d4cc94c1..00000000 --- a/pyCAOM2/caom2/test/test_value_coord2d.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestValueCoord2d class """ - -import unittest - -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestValueCoord2d(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, ValueCoord2D, None, None) - self.assertRaises(TypeError, ValueCoord2D, None, float(1.0)) - self.assertRaises(TypeError, ValueCoord2D, float(1.0), None) - self.assertRaises(TypeError, ValueCoord2D, int(1), float(1.0)) - self.assertRaises(TypeError, ValueCoord2D, float(1.0), int(1)) - - value_coord2d = ValueCoord2D(float(1), float(2)) - self.assertIsNotNone(value_coord2d) - self.assertEqual(value_coord2d.coord1, float(1)) - self.assertEqual(value_coord2d.coord2, float(2)) - - -if __name__ == '__main__': - unittest.main() diff --git a/pyCAOM2/caom2/types/__init__.py b/pyCAOM2/caom2/types/__init__.py deleted file mode 100755 index 4afe65c3..00000000 --- a/pyCAOM2/caom2/types/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines __init__ """ - -from caom2_point import Point diff --git a/pyCAOM2/caom2/types/caom2_box.py b/pyCAOM2/caom2/types/caom2_box.py deleted file mode 100644 index aa2d45d6..00000000 --- a/pyCAOM2/caom2/types/caom2_box.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines Box class""" - - -class Box(object): - - def __init__(self): - pass diff --git a/pyCAOM2/caom2/types/caom2_circle.py b/pyCAOM2/caom2/types/caom2_circle.py deleted file mode 100644 index bbb9f9dc..00000000 --- a/pyCAOM2/caom2/types/caom2_circle.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Circle class """ - - -class Circle(object): - - def __init__(self): - pass diff --git a/pyCAOM2/caom2/types/caom2_interval.py b/pyCAOM2/caom2/types/caom2_interval.py deleted file mode 100644 index 443a54f2..00000000 --- a/pyCAOM2/caom2/types/caom2_interval.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Interval class """ - - -class Interval(object): - - def __init__(self): - pass diff --git a/pyCAOM2/caom2/types/caom2_polygon.py b/pyCAOM2/caom2/types/caom2_polygon.py deleted file mode 100644 index 70c367b6..00000000 --- a/pyCAOM2/caom2/types/caom2_polygon.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Polygon class """ - - -class Polygon(object): - - def __init__(self): - pass diff --git a/pyCAOM2/caom2/types/caom2_vertex.py b/pyCAOM2/caom2/types/caom2_vertex.py deleted file mode 100644 index f8ec1471..00000000 --- a/pyCAOM2/caom2/types/caom2_vertex.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Vertex class """ - - -class Vertex(object): - - def __init__(self): - pass diff --git a/pyCAOM2/caom2/util/caom2_validator.py b/pyCAOM2/caom2/util/caom2_validator.py deleted file mode 100644 index f315a4a1..00000000 --- a/pyCAOM2/caom2/util/caom2_validator.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Validator class """ - - -from ..caom2_observation import Observation -from ..caom2_plane import Plane -from ..caom2_artifact import Artifact -from ..caom2_part import Part -from ..caom2_chunk import Chunk - - -class Validator(object): - - def __init__(self): - self.errors = {} - - def validate(self, obs): - if not isinstance(obs, Observation): - self.errors.append("") - return - self._validatePlanes(obs.planes) - if (len(self.errors) > 0): - return False - return True - - def _validatePlanes(self, planes): - for product_id, plane in planes.iteritems(): - if not isinstance(plane, Plane): - self.errors.append("") - continue - if (product_id != plane.product_id): - self.errors.append("") - self._validateArtifacts(plane.artifacts) - - def _validateArtifacts(self, artifacts): - for uri, artifact in artifacts.iteritems(): - if not isinstance(artifact, Artifact): - self.errors.append("") - continue - if (uri != artifact.uri): - self.errors.append("") - self._validateParts(artifact.parts) - - def _validateParts(self, parts): - for name, part in parts.iteritems(): - if not isinstance(part, Part): - self.errors.append("") - continue - if (name != part.name): - self.errors.append("") - self._validateChunks(parts.chunks) - - def _validateChunks(self, chunks): - for chunk in chunks: - if not isinstance(chunk, Chunk): - self.errors.append("") diff --git a/pyCAOM2/caom2/wcs/__init__.py b/pyCAOM2/caom2/wcs/__init__.py deleted file mode 100755 index 6851d8cf..00000000 --- a/pyCAOM2/caom2/wcs/__init__.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines __init__ """ - - -from caom2_axis import Axis -from caom2_coord2d import Coord2D -from caom2_value_coord2d import ValueCoord2D -from caom2_coord_axis1d import CoordAxis1D -from caom2_coord_axis2d import CoordAxis2D -from caom2_coord_bounds1d import CoordBounds1D -from caom2_coord_bounds2d import CoordBounds2D -from caom2_coord_circle2d import CoordCircle2D -from caom2_coord_error import CoordError -from caom2_coord_function1d import CoordFunction1D -from caom2_coord_function2d import CoordFunction2D -from caom2_coord_polygon2d import CoordPolygon2D -from caom2_coord_range1d import CoordRange1D -from caom2_coord_range2d import CoordRange2D -from caom2_dimension2d import Dimension2D - -from caom2_observable_axis import ObservableAxis -from caom2_polarization_wcs import PolarizationWCS -from caom2_ref_coord import RefCoord -from caom2_slice import Slice -from caom2_spatial_wcs import SpatialWCS -from caom2_spectral_wcs import SpectralWCS -from caom2_temporal_wcs import TemporalWCS diff --git a/pyCAOM2/caom2/wcs/caom2_axis.py b/pyCAOM2/caom2/wcs/caom2_axis.py deleted file mode 100644 index 559aac1a..00000000 --- a/pyCAOM2/caom2/wcs/caom2_axis.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" -Defines the Axis class -""" - -import caom2.util.caom2_util as util -from caom2.caom2_object import Caom2Object - - -class Axis(Caom2Object): - """the Axis class holds the definition of the axis type and units""" - - def __init__(self, ctype, cunit=None): - - self.ctype = ctype - self.cunit = cunit - - @property - def ctype(self): - """The Coordinate Type value for this axis. - - eg. DEC - type: str - - """ - return self._ctype - - @ctype.setter - def ctype(self, value): - util.typeCheck(value, str, 'ctype', override=False) - self._ctype = value - - @property - def cunit(self): - """The unit of the coordinate that results after transform. - - eg. deg - type: str - - """ - return self._cunit - - @cunit.setter - def cunit(self, value): - util.typeCheck(value, str, 'cunit') - self._cunit = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord2d.py b/pyCAOM2/caom2/wcs/caom2_coord2d.py deleted file mode 100644 index 1ca28c65..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord2d.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""definition of 2D coord object""" - -from caom2_ref_coord import RefCoord -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class Coord2D(Caom2Object): - """Represents the reference point. - - eg: Coord2D(RefCoord(crpix1,crval1),RefCoord(crpix2,crval2)) - """ - - def __init__(self, coord1, coord2): - self.coord1 = coord1 - self.coord2 = coord2 - - @property - def coord1(self): - """A coordinate axis1 coordinate/pix pair, crpix1, crval1. - - eg. RefCoord(crpix1, crval1) - """ - return self._coord1 - - @coord1.setter - def coord1(self, value): - util.typeCheck(value, RefCoord, 'coord1', override=False) - self._coord1 = value - - @property - def coord2(self): - """The axis2 coordinate reference pair (ei. crpix2/crval2. - - eg. RefCorrd(crpix2, crval2) - """ - return self._coord2 - - @coord2.setter - def coord2(self, value): - util.typeCheck(value, RefCoord, 'coord2', override=False) - self._coord2 = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_axis1d.py b/pyCAOM2/caom2/wcs/caom2_coord_axis1d.py deleted file mode 100644 index a9c1bbe5..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_axis1d.py +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""Definition of the CoordAxis1D class""" - -from caom2_axis import Axis -from caom2_coord_error import CoordError -from caom2_coord_range1d import CoordRange1D -from caom2_coord_bounds1d import CoordBounds1D -from caom2_coord_function1d import CoordFunction1D -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class CoordAxis1D(Caom2Object): - """Holds the metadata needed to transform a 1D pixel value into a - World Coordinate value. - - """ - - def __init__(self, axis, error=None, range=None, - bounds=None, function=None): - - self.axis = axis - self.error = error - self.range = range - self.bounds = bounds - self.function = function - - @property - def axis(self): - """An axis object which describes the type and units of this - coordinate axis. - - eg. Axis(ctype1,cunit1) - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, Axis, "Axis", override=False) - self._axis = value - - @property - def error(self): - """A CoordError object that describes the uncertainty in the. - - eg. CoordError(syser=0.1, rnder=0.1) - unit: cunit1 [of axis] - - """ - return self._error - - @error.setter - def error(self, value): - util.typeCheck(value, CoordError, 'error') - self._error = value - - @property - def range(self): - """A range that defines a coordinate transformation. - - the transform is a linear interpolation over the range - given which is a specified as a set of two pix/val reference pair. - eg. CoordRange1D(start=RefCoord(pix1,val1),end=RefCoord(pix2,val2)) - unit: same as the axis you are defining. - - """ - return self._range - - @range.setter - def range(self, value): - util.typeCheck(value, CoordRange1D, 'range') - self._range = value - - @property - def bounds(self): - """A polygon that defines the boundary of this axis, in 1D. - - eg. CoordBounds1D(ListOfRanges()) - The ranges are like those given for the range attribute. - - """ - return self._bounds - - @bounds.setter - def bounds(self, value): - util.typeCheck(value, CoordBounds1D, "bounds") - self._bounds = value - - @property - def function(self): - """A linear function that describes the tranformation between pixel - and world coordinate value. - - Since this is a 1D object and linear, the function is - y = m*x + b. - eg. CoordFunction1D(naxis, delta, RefCoord) - - """ - return self._function - - @function.setter - def function(self, value): - util.typeCheck(value, CoordFunction1D, 'function') - self._function = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_axis2d.py b/pyCAOM2/caom2/wcs/caom2_coord_axis2d.py deleted file mode 100644 index 197dac94..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_axis2d.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the CoordAxis2D class""" - -from caom2_axis import Axis -from caom2_coord_error import CoordError -from caom2_coord_range2d import CoordRange2D -from caom2_coord_circle2d import CoordCircle2D -from caom2_coord_polygon2d import CoordPolygon2D -from caom2_coord_function2d import CoordFunction2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordAxis2D(Caom2Object): - """This object hold the metadata need to transform a 2D pixel - array (say an image) into a World position, say RA/DEC - - """ - - def __init__(self, axis1, axis2, - error1=None, error2=None, - range=None, bounds=None, - function=None): - - self.axis1 = axis1 - self.axis2 = axis2 - self.error1 = error1 - self.error2 = error2 - self.range = range - self.bounds = bounds - self.function = function - - @property - def axis1(self): - """An axis object that desciribes the first dimension - of this 2d system. - - eg. axis1=Axis("RA","deg") - - """ - return self._axis1 - - @axis1.setter - def axis1(self, value): - util.typeCheck(value, Axis, "axis1", override=False) - self._axis1 = value - - @property - def axis2(self): - """An axis objet that describes the 2nd dimensiotn of this 2d coord - system. - - eg. axis2=Axis("DEG","deg") - - """ - return self._axis2 - - @axis2.setter - def axis2(self, value): - util.typeCheck(value, Axis, "axis2", override=False) - self._axis2 = value - - @property - def error1(self): - """An object that descibes the uncertainty in the pix/world transform. - - eg. CoordError() - type: CoordError - - """ - return self._error1 - - @error1.setter - def error1(self, value): - util.typeCheck(value, CoordError, 'error1') - self._error1 = value - - @property - def error2(self): - """An object that describes the uncertainty in the pix/world transform - for the 2nd axis - - type: CoordError - - """ - return self._error2 - - @error2.setter - def error2(self, value): - util.typeCheck(value, CoordError, "error2") - self._error2 = value - - @property - def range(self): - """Coordinate range defined by this CoordAxis2d object. - - type: CoordRange2D - """ - return self._range - - @range.setter - def range(self, value): - util.typeCheck(value, CoordRange2D, 'range') - self._range = value - - @property - def bounds(self): - """The Coordinate boundary mapped by this CoordAxis2D object. - - ag. CoordPolygon2d((234,10),(234,11),(233,11),(234,11),(234,10)) - type: CoordPolygon2D or CoordCircle2D - """ - return self._bounds - - @bounds.setter - def bounds(self, value): - util.typeCheck(value, (CoordCircle2D, CoordPolygon2D), 'bounds') - self._bounds = value - - @property - def function(self): - """A function object that describes the relation - between pixels and wcs. - - ag. CoordFunction2D (see the help for that puppy) - type: CoordFunction2D - """ - return self._function - - @function.setter - def function(self, value): - util.typeCheck(value, CoordFunction2D, 'function') - self._function = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_bounds1d.py b/pyCAOM2/caom2/wcs/caom2_coord_bounds1d.py deleted file mode 100644 index d034f9d1..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_bounds1d.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordBounds1D class""" - -from caom2_coord_range1d import CoordRange1D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordBounds1D(Caom2Object): - """Contains the bounds for a 1D axis, a list of ranges - - """ - - def __init__(self, samples=None): - - if samples is None: - samples = util.TypedList((CoordRange1D),) - self.samples = samples - - @property - def samples(self): - """A list of CoordRange1D objects that define the - boundary of a 1D axis. - - see also caom2.util.TypedList and caom2.wcs.CoordRange1D - - eg. - samples.add(CoordRange1D(RefCoord(pix,val),RefCoord(pix,val))) - - """ - return self._samples - - @samples.setter - def samples(self, value): - util.typeCheck(value, - util.TypedList, - 'samples', - override=False) - self._samples = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_bounds2d.py b/pyCAOM2/caom2/wcs/caom2_coord_bounds2d.py deleted file mode 100644 index cb72b1b3..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_bounds2d.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the CoordBounds2D class""" - -from caom2_coord_circle2d import CoordCircle2D -from caom2_coord_polygon2d import CoordPolygon2D -from caom2.caom2_object import Caom2Object - - -class CoordBounds2D(Caom2Object): - """Contains the bounds for a 2D axis - - """ - - def __init__(self, bounds): - if (isinstance(bounds, CoordCircle2D) or - isinstance(bounds, CoordPolygon2D)): - self.bounds = bounds - else: - raise TypeError( - "Expected CoordCircle2D or CoordPolygon2D, received {}" - .format(type(bounds))) - - @property - def bounds(self): - """The bounds expressed as a circle or polygon. - - eg CoordBounds2D(CoordCircle2D()) - type: CoordCircle2D or CoordPolygon2D - """ - return self._bounds - - @bounds.setter - def bounds(self, value): - self._bounds = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_circle2d.py b/pyCAOM2/caom2/wcs/caom2_coord_circle2d.py deleted file mode 100644 index ffd7dac2..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_circle2d.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the CoordCircle2D class""" - -from caom2_value_coord2d import ValueCoord2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordCircle2D(Caom2Object): - """A circle expressed in both pixel and WCS value coordinates. - - These objects are used to map out the bounds of spatial WCS. - - Currently radius is only given in WCS units.. should be both. - - """ - - def __init__(self, center, radius): - self.center = center - self.radius = radius - - @property - def center(self): - """The pixel/world coordinate location of the centre. - - eg ValueCoord2D(coord1, coord2) - type: ValueCoord2D - """ - return self._center - - @center.setter - def center(self, value): - util.typeCheck(value, ValueCoord2D, 'center', override=False) - self._center = value - - @property - def radius(self): - """The radius of the circle. - - NOTE::: This should likely be a RefCoord too... - - unit: same as centre which is pix/cunit - type: float - """ - return self._radius - - @radius.setter - def radius(self, value): - util.typeCheck(value, float, 'radius', override=False) - util.valueCheck(value, 0, 1E10, 'radius') - self._radius = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_error.py b/pyCAOM2/caom2/wcs/caom2_coord_error.py deleted file mode 100644 index 4d711051..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_error.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordError class - -""" - - -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordError(Caom2Object): - """Holds the systematic (syser) and random (rnder) error on a - coordinate. - - The concept is that these values are functions of the coordinate - transformation but likely be expressed with sufficient precision - (for a query model) using a systematic and random component. Both - are taken to be symetric. - - Likely either of these could be 'None', but best set to '0' if - that's what you really want to express. - - """ - - def __init__(self, syser, rnder): - - self.syser = syser - self.rnder = rnder - - # Properties - @property - def syser(self): - """the systematic uncertainty in a coordinate transform. - - units: should be the same as the CoordAxis (s, arcsec, deg?) - - """ - return self._syser - - @syser.setter - def syser(self, value): - util.typeCheck(value, float, "syser", override=False) - self._syser = value - - @property - def rnder(self): - """the random uncertainty in a coordinate transform. - - units: should be the same as the CoordAxis transform. - - """ - return self._rnder - - @rnder.setter - def rnder(self, value): - util.typeCheck(value, float, "rnder", override=False) - self._rnder = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_function1d.py b/pyCAOM2/caom2/wcs/caom2_coord_function1d.py deleted file mode 100644 index 5565ce7c..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_function1d.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordFunction1D class - -""" - -from caom2_ref_coord import RefCoord -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class CoordFunction1D(Caom2Object): - """Defines a linear function that transforms from pixel to WCS - values. - - """ - - def __init__(self, naxis, delta, ref_coord): - """ - Need to define the length of the axis, the slope of the - conversion and a reference coordinate. All are needed for a - valid 1D function. - - """ - - self.naxis = naxis - self.delta = delta - self.ref_coord = ref_coord - - @property - def naxis(self): - """The length of the axis. - - unit: pix - type: long - - """ - return self._naxis - - @naxis.setter - def naxis(self, value): - util.typeCheck(value, long, 'naxis', override=False) - self._naxis = value - - @property - def delta(self): - """The step in WCS between pixels. - - unit: WCS/pix (days if this is a timeWCS) - type: float - - """ - return self._delta - - @delta.setter - def delta(self, value): - util.typeCheck(value, float, 'delta', override=False) - self._delta = value - - @property - def ref_coord(self): - """the (pix,val) reference for this transformtion. - - eg. ref_coord=RefCoord(pix,val) - type: RefCoord - - """ - return self._ref_coord - - @ref_coord.setter - def ref_coord(self, value): - util.typeCheck(value, RefCoord, 'ref_coord', override=False) - self._ref_coord = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_function2d.py b/pyCAOM2/caom2/wcs/caom2_coord_function2d.py deleted file mode 100644 index ca64e16d..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_function2d.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines a 'CoordFunction2D' class - -""" - -from caom2_dimension2d import Dimension2D -from caom2_coord2d import Coord2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordFunction2D(Caom2Object): - """Describes the parameters needed for the standard CD matrix. - - defines a linear translation between pixel and WCS. - - """ - - def __init__(self, dimension, ref_coord, cd11, cd12, cd21, cd22): - self.dimension = dimension - self.ref_coord = ref_coord - self.cd11 = cd11 - self.cd12 = cd12 - self.cd21 = cd21 - self.cd22 = cd22 - - @property - def dimension(self): - """A Dimension2D object that holds the lengths of the axis - - eg. Diemnsion2D(naxis1=1024,naxis2=2048) - type: Dimension2D - - """ - return self._dimension - - @dimension.setter - def dimension(self, value): - util.typeCheck(value, Dimension2D, 'dimension', override=False) - self._dimension = value - - @property - def ref_coord(self): - """A Coord2D object that holds the reference pixel location - - eg. Coord2D((crpix1,crval1),(crpix2,crval2)) - type: Coord2D - - """ - return self._ref_coord - - @ref_coord.setter - def ref_coord(self, value): - util.typeCheck(value, Coord2D, 'ref_coord', override=False) - self._ref_coord = value - - @property - def cd11(self): - """The CD1_1 value (depenence of RA scale on x-pixel value) - - eg. cd11 = 5E-5 - unit: deg/pix - type: float - - """ - return self._cd11 - - @cd11.setter - def cd11(self, value): - util.typeCheck(value, float, 'cd11', override=False) - self._cd11 = value - - @property - def cd12(self): - """The CD1_2 value (depenence of RA scale on y-pixel value) - - eg. cd12 = 5E-10 - unit: deg/pix - type: float - - """ - return self._cd12 - - @cd12.setter - def cd12(self, value): - util.typeCheck(value, float, 'cd12', override=False) - self._cd12 = value - - @property - def cd21(self): - """The CD1_1 value (depenence of DEC scale on x-pixel value) - - eg. cd11 = 5E-10 - unit: deg/pix - type: float - - """ - return self._cd21 - - @cd21.setter - def cd21(self, value): - util.typeCheck(value, float, 'cd21', override=False) - self._cd21 = value - - @property - def cd22(self): - """The CD2_2 value (depenence of DEC scale on y-pixel value) - - eg. cd12 = 5E-5 - unit: deg/pix - type: float - - """ - return self._cd22 - - @cd22.setter - def cd22(self, value): - util.typeCheck(value, float, 'cd22', override=False) - self._cd22 = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_polygon2d.py b/pyCAOM2/caom2/wcs/caom2_coord_polygon2d.py deleted file mode 100644 index 56d8572a..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_polygon2d.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordPolygon2D class - -""" - -from caom2_value_coord2d import ValueCoord2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordPolygon2D(Caom2Object): - """A object to contain a TypeList ValueCoord2D vertices that are a - polygon. The vertices are given as ValueCoord2D objects, which are - coordinate pairs. - - eg. vertices.add(ValueCoord2D(coord1,coord2)) - - """ - - def __init__(self, vertices=None): - if vertices is None: - vertices = util.TypedList((ValueCoord2D),) - self.vertices = vertices - - @property - def vertices(self): - """A TypedList of ValueCoord2D objects that layout the vertices of a - polygon. - - A vertices can be added using the 'add' method.. - eg: vertices.add(ValueCoord2D()) - - see the caom2.wcs.ValueCoord2D help for details on making a - coordinate pair. - - type: TypedList((ValueCoord2D),) - - """ - return self._vertices - - @vertices.setter - def vertices(self, value): - util.typeCheck(value, util.TypedList, 'vertices', override=False) - self._vertices = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_range1d.py b/pyCAOM2/caom2/wcs/caom2_coord_range1d.py deleted file mode 100644 index 75afc2f9..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_range1d.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines CoordRange1D class - -""" - -from caom2_ref_coord import RefCoord -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordRange1D(Caom2Object): - """a CoordRange1D object contains the start and end of - a range of values, expressed in both pixel and WCS units. - - """ - - def __init__(self, start, end): - self.start = start - self.end = end - - @property - def start(self): - """The pixel and world coordinate of the start of a range. - - eg. RefCoord(pix,val) - type: RefCoord - - """ - return self._start - - @start.setter - def start(self, value): - util.typeCheck(value, RefCoord, "start", override=False) - self._start = value - - @property - def end(self): - """The pixel and world coordinate of the end of a range. - - eg. RefCoord(pix,val) - type: RefCoord - - """ - return self._end - - @end.setter - def end(self, value): - util.typeCheck(value, RefCoord, "end", override=False) - self._end = value diff --git a/pyCAOM2/caom2/wcs/caom2_coord_range2d.py b/pyCAOM2/caom2/wcs/caom2_coord_range2d.py deleted file mode 100644 index 5f54f3c8..00000000 --- a/pyCAOM2/caom2/wcs/caom2_coord_range2d.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordRange2D class - -""" - -from caom2_coord2d import Coord2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordRange2D(Caom2Object): - """A range (x1,y1) to (x2,y2) in two dimenstions. - - The range object should know the coordinate in both - pixels and WCS units. - - """ - - def __init__(self, start, end): - self.start = start - self.end = end - - @property - def start(self): - """The starting coordinate pair of a range, in wcs units. - - eg: Coord2D(RefCoord(crpix1,crval1), RefCoord(crpix2,crval2)) - """ - return self._start - - @start.setter - def start(self, value): - util.typeCheck(value, Coord2D, 'start', override=False) - self._start = value - - @property - def end(self): - """The reference for the ending coordinate of a range. - - eg: Coord2D(RefCoord(crpix1,crval1), RefCoord(crpix2,crval2)) - """ - return self._end - - @end.setter - def end(self, value): - util.typeCheck(value, Coord2D, 'end', override=False) - self._end = value diff --git a/pyCAOM2/caom2/wcs/caom2_dimension2d.py b/pyCAOM2/caom2/wcs/caom2_dimension2d.py deleted file mode 100644 index eed92ee8..00000000 --- a/pyCAOM2/caom2/wcs/caom2_dimension2d.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Dimension2d class - -""" - - -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class Dimension2D(Caom2Object): - """Hey, how big is this thing? What are its dimensions. That's what - Dimension2D will tell you. - - """ - - def __init__(self, naxis1, naxis2): - self.naxis1 = naxis1 - self.naxis2 = naxis2 - - @property - def naxis1(self): - """The length of the first (x) dimension. - - eg. naxis1=1024 - unit: pix - type: long - - """ - return self._naxis1 - - @naxis1.setter - def naxis1(self, value): - util.typeCheck(value, long, 'naxis1', override=False) - util.valueCheck(value, 0, 1E10, 'naxis1', override=False) - self._naxis1 = value - - @property - def naxis2(self): - """The length of the second (y) dimension. - - eg. naxis2=2048 - unit: pix - type: long - - """ - return self._naxis2 - - @naxis2.setter - def naxis2(self, value): - util.typeCheck(value, long, 'naxis2', override=False) - util.valueCheck(value, 0, 1E10, 'naxis2', override=False) - self._naxis2 = value diff --git a/pyCAOM2/caom2/wcs/caom2_observable_axis.py b/pyCAOM2/caom2/wcs/caom2_observable_axis.py deleted file mode 100644 index be61ed98..00000000 --- a/pyCAOM2/caom2/wcs/caom2_observable_axis.py +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the ObservableAxis class - -""" - -from caom2_slice import Slice -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class ObservableAxis(Caom2Object): - """The slice through the data structure that provides the thing being - described by this Axis. - - this data structure is used when a file contains data that has set - of measured values (the dependent variable) and might also have - the coordinate at which those values are measured in another Slice - of the file. - - The Slice refers to a column in a FITS image. The bin is the - column index and ctype/cunit for the axis describe what the column - contiains. - - eg. - - NAXIS=2 - NAXIS1=3 - NAXIS2=N - l1 f1 s1 - l2 f2 s2 - l3 f3 s3 - . - . - lN fN sN - - where l? is the wavelength at which a measure of flux f? has been - made and l is the first column of a FITS data structure that is - 3,N in size. s? is a third slice that would be used to define - another observable. When defining the s? obserable the independent - variable must be defined for that ObservableAxis too. - - The l/f obserable would be recorded as - - dependent=Slice(Axis('wave','nm'),bin=1) - independent=Slice(Axis('flux','Jy'),bin=2) - Chunk.observable_axis=ObservableAxis(dependent, independent) - - - """ - def __init__(self, dependent, independent=None): - - self.dependent = dependent - self.independent = independent - - @property - def dependent(self): - """The dependent (y) variable slice. - - A slice provides the bin and the type/unit of the observable axis - """ - - return self._dependent - - @dependent.setter - def dependent(self, value): - util.typeCheck(value, Slice, 'dependent', override=False) - self._dependent = value - - @property - def independent(self): - """The dependent (y) variable slice. - - A slice that provides the pixel value and the type/unit for - conversion - - """ - return self._independent - - @independent.setter - def independent(self, value): - util.typeCheck(value, Slice, "independent") - self._independent = value diff --git a/pyCAOM2/caom2/wcs/caom2_polarization_wcs.py b/pyCAOM2/caom2/wcs/caom2_polarization_wcs.py deleted file mode 100644 index 30be5b86..00000000 --- a/pyCAOM2/caom2/wcs/caom2_polarization_wcs.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the PolarizationWCS class""" - -from caom2_coord_axis1d import CoordAxis1D -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class PolarizationWCS(Caom2Object): - """A WCS structure that describes the relation ship between a pixel - location and the polarization value. - - """ - - def __init__(self, axis): - """Set up a CoordAxis1D object to represent the Polariation. - - """ - - self.axis = axis - - @property - def axis(self): - """A CoordAxis1D object that describes the pixel/value relation ship - for polarization of the data. - - type: CoordAxis1D - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, CoordAxis1D, 'axis', override=False) - if value.axis.ctype != 'STOKES': - raise ValueError('CTYPE must be STOKES') - self._axis = value diff --git a/pyCAOM2/caom2/wcs/caom2_ref_coord.py b/pyCAOM2/caom2/wcs/caom2_ref_coord.py deleted file mode 100644 index cbdc9e3e..00000000 --- a/pyCAOM2/caom2/wcs/caom2_ref_coord.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the RefCoord class - -""" - - -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class RefCoord(Caom2Object): - """A refernce coordinate object, maps pixel value to wcs value - - """ - - def __init__(self, pix, val): - """maps a pixel location to a wcs value, as a reference spot. - - eg. RefCoord(crpix1, crval1) - - """ - self.pix = pix - self.val = val - - @property - def pix(self): - """The pixel location of a reference position. - - units: pix - type: float - - """ - return self._pix - - @pix.setter - def pix(self, value): - util.typeCheck(value, float, 'pix', override=False) - self._pix = value - - @property - def val(self): - """The WCS value at the reference position. - - units: CUNIT - type: float - - """ - return self._val - - @val.setter - def val(self, value): - util.typeCheck(value, float, 'val', override=False) - self._val = value diff --git a/pyCAOM2/caom2/wcs/caom2_slice.py b/pyCAOM2/caom2/wcs/caom2_slice.py deleted file mode 100644 index 7f33eebe..00000000 --- a/pyCAOM2/caom2/wcs/caom2_slice.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Slice class - -""" - - -from caom2_axis import Axis -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class Slice(Caom2Object): - """defines a slice in a set of data contains values. - - The slice keeps track of the type/unit and values. - - ctype and cunit are stored in the axis variable. - values are stored in the bins - - """ - def __init__(self, axis, bin_): - self.axis = axis - self.bin = bin_ - - @property - def axis(self): - """A ctype/cunit pair for this slice of data. - - type: Axis(ctype,cunit) - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, Axis, 'axis', override=False) - self._axis = value - - @property - def bin(self): - """The pixel value on the axis. - - This value is use to transform to the WCS for this axis. - unit: pixel - type: long - """ - return self._bin - - @bin.setter - def bin(self, value): - util.typeCheck(value, long, 'long', override=False) - self._bin = value diff --git a/pyCAOM2/caom2/wcs/caom2_spatial_wcs.py b/pyCAOM2/caom2/wcs/caom2_spatial_wcs.py deleted file mode 100644 index 95e37bb0..00000000 --- a/pyCAOM2/caom2/wcs/caom2_spatial_wcs.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the SpatialWCS class - -""" - - -from caom2_coord_axis2d import CoordAxis2D -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class SpatialWCS(Caom2Object): - """this object contains the WCS information needed to convert an - astronomical spatial location (ie. RA/DEC) into a pixel location - in the image. - - During ingestion a variety of extra information is created. - - """ - - def __init__(self, - axis, - coordsys=None, - equinox=None, - resolution=None): - - self.axis = axis - self.coordsys = coordsys - self.equinox = equinox - self.resolution = resolution - - @property - def axis(self): - """A CoordAxis2D object that contains - the actual WCS values (crpix etc.) - - type: CoordAxis2D - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, CoordAxis2D, 'axis', override=False) - self._axis = value - - @property - def coordsys(self): - """The Coordinate system of the transformation, likely ICRS or FK5. - - eg. SpatialWCS.coordsys="ICRS" - - type: str - - """ - return self._coordsys - - @coordsys.setter - def coordsys(self, value): - util.typeCheck(value, str, 'coordsys') - self._coordsys = value - - @property - def equinox(self): - """The Equinox of the coordinate system. - - You might think J2000, but must be expressed as a float, so in years - - unit: years - type: float - - """ - return self._equinox - - @equinox.setter - def equinox(self, value): - util.typeCheck(value, float, 'equinox') - util.valueCheck(value, 1800, 2500, 'equinox') - self._equinox = value - - @property - def resolution(self): - """The spatial resolution of the image data (account for seeing/beem). - - unit: arcsec - type: float - - """ - return self._resolution - - @resolution.setter - def resolution(self, value): - util.typeCheck(value, float, 'resolution') - util.valueCheck(value, 0, 360 * 3600.0, 'resolution') - self._resolution = value diff --git a/pyCAOM2/caom2/wcs/caom2_spectral_wcs.py b/pyCAOM2/caom2/wcs/caom2_spectral_wcs.py deleted file mode 100644 index 1e90ada3..00000000 --- a/pyCAOM2/caom2/wcs/caom2_spectral_wcs.py +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the SpectralWCS class""" - -from caom2.caom2_energy_transition import EnergyTransition -from caom2_coord_axis1d import CoordAxis1D -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class SpectralWCS(Caom2Object): - """A transformation that maps pixel coordinates to spectral ones. - - Note that a 2D image has implicit 'spectral' (and temporal) - dimension that is one pixel in size. Basically pixels are really - multidimensional voxels. - - Due to FITS standards this pixel starts at 0.5 and runs to 1.5 - with the centre being at 1.0 - - """ - - def __init__(self, - axis, - specsys, - ssysobs=None, - ssyssrc=None, - restfrq=None, - restwav=None, - velosys=None, - zsource=None, - velang=None, - bandpass_name=None, - transition=None, - resolving_power=None - ): - """The SpectralWCS can be defined in a number of different ways, to - define one you must provide a CoordAxis1D object that maps the - pixels to WCS values and a reference specsys. After that the - user can add what ever parts seam useful. More info is more - helpful for searching. - - """ - - self.axis = axis - self.specsys = specsys - self.ssysobs = ssysobs - self.ssyssrc = ssyssrc - self.restfrq = restfrq - self.restwav = restwav - self.velosys = velosys - self.zsource = zsource - self.velang = velang - self.bandpass_name = bandpass_name - self.transition = transition - self.resolving_power = resolving_power - - @property - def axis(self): - """A 1D coordinate axis object that contains the pix/wcs - transformation values. - - eg. CoordAxis1D(Axis('wave','flux'),...) - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, CoordAxis1D, 'axis', override=False) - self._axis = value - - @property - def specsys(self): - """describes the reference frame in use for the spectral-axis - coordinate(s). - - eg. BARYCENT - - type: str - """ - return self._specsys - - @specsys.setter - def specsys(self, value): - util.typeCheck(value, str, 'specsys', override=False) - self._specsys = value - - @property - def ssysobs(self): - """describes the spectral reference frame that is constant over the - range of the non-spectral world coordinates - - For example, for a large image the the wavelength at the edges - is different from the centres. This refernce frame is one where they - are not different. - - Nominally 'TOPOCENT' - - type: str - """ - return self._ssysobs - - @ssysobs.setter - def ssysobs(self, value): - util.typeCheck(value, str, 'ssysobs') - self._ssysobs = value - - @property - def ssyssrc(self): - """The reference frame in which zsource is expressed. - - eg. BARYCENT - type: string - """ - return self._ssyssrc - - @ssyssrc.setter - def ssyssrc(self, value): - util.typeCheck(value, str, 'ssyssrc') - self._ssyssrc = value - - @property - def restfrq(self): - """The frequency of the spectal feature being observed. - - unit: Hz - type: float - """ - return self._restfrq - - @restfrq.setter - def restfrq(self, value): - util.typeCheck(value, float, 'restfrq') - self._restfrq = value - - @property - def restwav(self): - """The wavelength of spectral feature being observed, - not the wavelength observed but the wavelength of the - feature when at rest.. - - unit: m - type: float - """ - return self._restwav - - @restwav.setter - def restwav(self, value): - util.typeCheck(value, float, 'restwav') - self._restwav = value - - @property - def velosys(self): - """Relative radial velocity between the observer and the selected - standard of rest in the direction of the celestial reference - coordinate. - - eg. 26000 m/s - - - unit: m/s - type: float - """ - return self._velosys - - @velosys.setter - def velosys(self, value): - util.typeCheck(value, float, 'velosys') - self._velosys = value - - @property - def zsource(self): - """The redshift of the source emitting the photons. - - almost always None - - unit: z - type: float - """ - return self._zsource - - @zsource.setter - def zsource(self, value): - util.typeCheck(value, float, 'zsource') - util.valueCheck(value, -0.5, 1200, 'zsource') - self._zsource = value - - @property - def velang(self): - """I don't know what this is... angle of the velocity ??? """ - return self._velang - - @velang.setter - def velang(self, value): - util.typeCheck(value, float, 'velang') - self._velang = value - - @property - def bandpass_name(self): - """string the represent the bandpass of the observation. - - eg. r' - type: str - """ - return self._bandpass_name - - @bandpass_name.setter - def bandpass_name(self, value): - util.typeCheck(value, str, 'bandpass_name') - self._bandpass_name = value - - @property - def transition(self): - """which molecular transition has been observed. - - type: EnergyTransition object (see caom2.EnergyTransition for help) - """ - return self._transition - - @transition.setter - def transition(self, value): - util.typeCheck(value, EnergyTransition, "transition") - self._transition = value - - @property - def resolving_power(self): - """The R value of the spectal coverage. - - Normally this is something like dlamda/lamda - - unit: RATIO - type: float - """ - return self._resolving_power - - @resolving_power.setter - def resolving_power(self, value): - util.typeCheck(value, float, 'resolving_power') - util.valueCheck(value, 0, 1E8, 'resolving_power') - self._resolving_power = value diff --git a/pyCAOM2/caom2/wcs/caom2_temporal_wcs.py b/pyCAOM2/caom2/wcs/caom2_temporal_wcs.py deleted file mode 100644 index 02338aeb..00000000 --- a/pyCAOM2/caom2/wcs/caom2_temporal_wcs.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""The definition of the TemporalWCS class""" - - -from caom2_coord_axis1d import CoordAxis1D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class TemporalWCS(Caom2Object): - """Describes the Time variation within the data. - - In the case of a single exposure, define the center of the first - pixel (0.5) as the MJD of the exposure and size of the pixel - as the exposure time.""" - - def __init__(self, - axis, - timesys=None, - trefpos=None, - mjdref=None, - exposure=None, - resolution=None - ): - - self.axis = axis - self.timesys = timesys - self.trefpos = trefpos - self.mjdref = mjdref - self.exposure = exposure - self.resolution = resolution - - @property - def axis(self): - """A CoordAxis1D object that describes the TemporalWCS transform. - - eg. CoordAxis1D(Axis) """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, CoordAxis1D, 'axis', override=False) - self._axis = value - - @property - def timesys(self): - """The time scale that you are using, almost alwasy UTC. - - eg. timesys = "UTC" - type: str - """ - return self._timesys - - @timesys.setter - def timesys(self, value): - util.typeCheck(value, str, 'timesys') - self._timesys = value - - @property - def trefpos(self): - """ specifies the spatial location at which the time is valid, either - where the observation was made or the point in space for which - light-time corrections have been applied. - - eg. trefpos = "TOPOCENTER" - type: str - """ - return self._trefpos - - @trefpos.setter - def trefpos(self, value): - util.typeCheck(value, str, 'trefpos') - self._trefpos = value - - @property - def mjdref(self): - """The Modified Julian Date of the at the reference location of the - location of the TimeWCS (aka. pixel 0.5). Nominally this the start - of the exposure. - - Why 0.5? FITS: the middle of the first pixel - is defined as pixel value 1.0 so, the start of that pixel - is location 0.5 - - eg. mjdref = 567643.1234 - unit: d - type: float - """ - return self._mjdref - - @mjdref.setter - def mjdref(self, value): - util.typeCheck(value, float, 'mjdref') - ### set the limits to be after 1800 but before year 2050 - util.valueCheck(value, -22000, 70000, 'mjdref') - self._mjdref = value - - @property - def exposure(self): - """The median exposure time per pixel. - - The exposure time if this not a time cube you are describing. - - eg. exposure = 100.0 - unit: s - type: float - """ - return self._exposure - - @exposure.setter - def exposure(self, value): - util.typeCheck(value, float, "exposure") - util.valueCheck(value, 0, 30 * 24 * 3600.0, "exposure") - self._exposure = value - - @property - def resolution(self): - """the resolution of the time sampling available. - - Normally this is going to be the same as the exposure above, - but a stack of exposures taken over many months has a very - large value for resolution while the exposure value is just - the sum of the individual exposure times. - - - eg. resolution = 100.0s - unit: s - type: float - """ - return self._resolution - - @resolution.setter - def resolution(self, value): - util.typeCheck(value, float, 'resolution') - util.valueCheck(value, 0, 100 * 365 * 24 * 3600.0, "resolution") - self._resolution = value diff --git a/pyCAOM2/caom2/wcs/caom2_value_coord2d.py b/pyCAOM2/caom2/wcs/caom2_value_coord2d.py deleted file mode 100644 index 0467cd1f..00000000 --- a/pyCAOM2/caom2/wcs/caom2_value_coord2d.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""definition of value 2D coord object""" - -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class ValueCoord2D(Caom2Object): - """Represents the reference point.""" - - def __init__(self, coord1, coord2): - self.coord1 = coord1 - self.coord2 = coord2 - - @property - def coord1(self): - """Coordinate 1""" - return self._coord1 - - @coord1.setter - def coord1(self, value): - util.typeCheck(value, float, 'coord1', override=False) - self._coord1 = value - - @property - def coord2(self): - """Coordinate 2""" - return self._coord2 - - @coord2.setter - def coord2(self, value): - util.typeCheck(value, float, 'coord2', override=False) - self._coord2 = value diff --git a/pyCAOM2/caom2/xml/__init__.py b/pyCAOM2/caom2/xml/__init__.py deleted file mode 100644 index d3720208..00000000 --- a/pyCAOM2/caom2/xml/__init__.py +++ /dev/null @@ -1,77 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines __init__ """ - -# from caom2_observation_reader import ObservationReader -# from caom2_observation_writer import ObservationWriter -# from caom2_xml_constants import CAOM20_NAMESPACE -# from caom2_xml_constants import CAOM21_NAMESPACE -# from caom2_xml_constants import CAOM22_NAMESPACE diff --git a/pyCAOM2/caom2/xml/caom2_observation_reader.py b/pyCAOM2/caom2/xml/caom2_observation_reader.py deleted file mode 100644 index 35140e5b..00000000 --- a/pyCAOM2/caom2/xml/caom2_observation_reader.py +++ /dev/null @@ -1,1394 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines ObservationReader class """ - -import uuid - -import pkg_resources -from lxml import etree - -import caom2_xml_constants -from .. caom2_algorithm import Algorithm -from .. caom2_artifact import Artifact -from .. caom2_chunk import Chunk -from .. caom2_composite_observation import CompositeObservation -from .. caom2_data_quality import DataQuality -from .. caom2_energy_transition import EnergyTransition -from .. caom2_enums import CalibrationLevel -from .. caom2_enums import DataProductType -from .. caom2_enums import ObservationIntentType -from .. caom2_enums import ProductType -from .. caom2_enums import Quality -from .. caom2_enums import Status -from .. caom2_enums import TargetType -from .. caom2_enums import ReleaseType -from .. caom2_composite_observation import CompositeObservation -from .. caom2_data_quality import DataQuality -from .. caom2_energy_transition import EnergyTransition -from .. caom2_environment import Environment -from .. caom2_exceptions import ObservationParsingException -from .. caom2_instrument import Instrument -from .. caom2_metrics import Metrics -from .. caom2_observation_uri import ObservationURI -from .. caom2_part import Part -from .. caom2_plane import Plane -from .. caom2_plane_uri import PlaneURI -from .. caom2_proposal import Proposal -from .. caom2_provenance import Provenance -from .. caom2_requirements import Requirements -from .. caom2_simple_observation import SimpleObservation -from .. caom2_target import Target -from .. caom2_target_position import TargetPosition -from .. caom2_telescope import Telescope -from .. types.caom2_point import Point -from .. util.caom2_util import long2uuid -from .. util.caom2_util import str2ivoa -from .. wcs.caom2_axis import Axis -from .. wcs.caom2_coord2d import Coord2D -from .. wcs.caom2_coord_axis1d import CoordAxis1D -from .. wcs.caom2_coord_axis2d import CoordAxis2D -from .. wcs.caom2_coord_bounds1d import CoordBounds1D -from .. wcs.caom2_coord_circle2d import CoordCircle2D -from .. wcs.caom2_coord_error import CoordError -from .. wcs.caom2_coord_function1d import CoordFunction1D -from .. wcs.caom2_coord_function2d import CoordFunction2D -from .. wcs.caom2_coord_polygon2d import CoordPolygon2D -from .. wcs.caom2_coord_range1d import CoordRange1D -from .. wcs.caom2_coord_range2d import CoordRange2D -from .. wcs.caom2_dimension2d import Dimension2D -from .. wcs.caom2_observable_axis import ObservableAxis -from .. wcs.caom2_polarization_wcs import PolarizationWCS -from .. wcs.caom2_ref_coord import RefCoord -from .. wcs.caom2_slice import Slice -from .. wcs.caom2_spatial_wcs import SpatialWCS -from .. wcs.caom2_spectral_wcs import SpectralWCS -from .. wcs.caom2_temporal_wcs import TemporalWCS -from .. wcs.caom2_value_coord2d import ValueCoord2D - - -class ObservationReader(object): - """ObservationReader """ - - def __init__(self, valididate=False): - """Constructor. XML Schema validation may be disabled, in which case - the client is likely to fail in horrible ways if it received invalid - documents. However, performance may be improved. - - Arguments: - validate : If True enable schema validation, False otherwise - """ - self._validate = valididate - - if self._validate: - caom20_schema_path = pkg_resources.resource_filename( - caom2_xml_constants.CAOM2_PKG, caom2_xml_constants.CAOM20_SCHEMA_FILE) - - parser = etree.XMLParser(remove_blank_text=True) - xsd = etree.parse(caom20_schema_path, parser) - - caom21_schema = etree.Element( - '{http://www.w3.org/2001/XMLSchema}import', - namespace=caom2_xml_constants.CAOM21_NAMESPACE, - schemaLocation=caom2_xml_constants.CAOM21_SCHEMA_FILE) - xsd.getroot().insert(1, caom21_schema) - - caom22_schema = etree.Element( - '{http://www.w3.org/2001/XMLSchema}import', - namespace=caom2_xml_constants.CAOM22_NAMESPACE, - schemaLocation=caom2_xml_constants.CAOM22_SCHEMA_FILE) - xsd.getroot().insert(2, caom22_schema) - - self._xmlschema = etree.XMLSchema(xsd) - - def _set_entity_attributes(self, element, ns, caom2_entity): - expect_uuid = True - if caom2_xml_constants.CAOM20_NAMESPACE == ns: - expect_uuid = False - - element_id = element.get("{" + ns + "}id") - element_last_modified = element.get("{" + ns + "}lastModified") - - if expect_uuid: - uid = uuid.UUID(element_id) - else: - uid = long2uuid(long(element_id)) - caom2_entity._id = uid - - if element_last_modified: - caom2_entity._last_modified = str2ivoa(element_last_modified) - - def _getChildElement(self, elTag, parent, ns, required): - for element in list(parent): - if element.tag == "{" + ns + "}" + elTag: - if not element.keys() and not element.text: - # element is empty, return None - return None - else: - # element has content, return it - return element - - if required: - error = elTag + " element not found in " + parent.tag - raise ObservationParsingException(error) - else: - return None - - def _getChildText(self, elTag, parent, ns, required): - childElement = self._getChildElement(elTag, parent, ns, required) - if childElement is None: - return None - else: - return childElement.text - - def _getChildTextAsInt(self, elTag, parent, ns, required): - childElement = self._getChildElement(elTag, parent, ns, required) - if childElement is None: - return None - else: - return int(childElement.text) - - def _getChildTextAsLong(self, elTag, parent, ns, required): - childElement = self._getChildElement(elTag, parent, ns, required) - if childElement is None: - return None - else: - return long(childElement.text) - - def _getChildTextAsFloat(self, elTag, parent, ns, required): - childElement = self._getChildElement(elTag, parent, ns, required) - if childElement is None: - return None - else: - return float(childElement.text) - - def _getAlgorithm(self, elTag, parent, ns, required): - """Build an Algorithm object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the algorithm element - ns : namespace of the document - required : indicates whether the element is required - return : an Algorithm object or - None if the document does not contain an algorithm element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Algorithm(self._getChildText("name", el, ns, True)) - - def _getMetaRelease(self, elTag, parent, ns, required): - """Build a MetaRelease object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the MetaRelease element - ns : namespace of the document - required : indicates whether the element is required - return : a MetaRelease object or - None if the document does not contain a MetaRelease element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - # TODO: need to catch exceptions, - # what kind of exceptions are thrown? - return str2ivoa(el.text) - - def _getProposal(self, elTag, parent, ns, required): - """Build a Proposal object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Proposal element - ns : namespace of the document - required : indicates whether the element is required - return : a Proposal object or - None if the document does not contain a Proposal element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - proposal = Proposal(self._getChildText("id", el, ns, True)) - proposal.pi_name = self._getChildText("pi", el, ns, False) - proposal.project = self._getChildText("project", el, ns, False) - proposal.title = self._getChildText("title", el, ns, False) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - proposal.keywords.add(keyword) - return proposal - - def _getTarget(self, elTag, parent, ns, required): - """Build a Target object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Target element - ns : namespace of the document - required : indicates whether the element is required - return : a Target object or - None if the document does not contain a Target element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - target = Target(self._getChildText("name", el, ns, True)) - targetType = self._getChildText("type", el, ns, False) - if targetType: - target.target_type = TargetType.getByValue(targetType) - target.standard = ("true" == - self._getChildText("standard", el, ns, False)) - target.redshift = ( - self._getChildTextAsFloat("redshift", el, ns, False)) - target.moving = ("true" == - self._getChildText("moving", el, ns, False)) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - target.keywords.add(keyword) - return target - - def _getTargetPosition(self, elTag, parent, ns, required): - """Build a TargetPosition object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Target element - ns : namespace of the document - required : indicates whether the element is required - return : a TargetPosition object or - None if the document does not contain a TargetPosition element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - target_position = TargetPosition( - self._getPoint("coordinates", el, ns, True), - self._getChildText("coordsys", el, ns, True)) - target_position.equinox = ( - self._getChildTextAsFloat("equinox", el, ns, False)) - return target_position - - def _getRequirements(self, elTag, parent, ns, required): - """Build an Requirements object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Requirements element - ns : namespace of the document - required : indicates whether the element is required - return : a Requirements object or - None if the document does not contain an Requirements element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - flag = self._getChildText("flag", el, ns, True) - requirements = Requirements(Status.getByValue(flag)) - return requirements - - def _getTelescope(self, elTag, parent, ns, required): - """Build a Telescope object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Telescope element - ns : namespace of the document - required : indicates whether the element is required - return : a Telescope object or - None if the document does not contain a Telescope element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - telescope = Telescope(self._getChildText("name", el, ns, True)) - telescope.geo_location_x = ( - self._getChildTextAsFloat("geoLocationX", el, ns, False)) - telescope.geo_location_y = ( - self._getChildTextAsFloat("geoLocationY", el, ns, False)) - telescope.geo_location_z = ( - self._getChildTextAsFloat("geoLocationZ", el, ns, False)) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - telescope.keywords.add(keyword) - return telescope - - def _getInstrument(self, elTag, parent, ns, required): - """Build an Instrument object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Instrument element - ns : namespace of the document - required : indicates whether the element is required - return : a Instrument object or - None if the document does not contain an Instrument element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - instrument = Instrument(self._getChildText("name", el, ns, True)) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - instrument.keywords.add(keyword) - return instrument - - def _getEnvironment(self, elTag, parent, ns, required): - """Build an Environment object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Environment element - ns : namespace of the document - required : indicates whether the element is required - return : a Environment object or - None if the document does not contain an Environment element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - environment = Environment() - environment.seeing = ( - self._getChildTextAsFloat("seeing", el, ns, False)) - environment.humidity = ( - self._getChildTextAsFloat("humidity", el, ns, False)) - environment.elevation = ( - self._getChildTextAsFloat("elevation", el, ns, False)) - environment.tau = ( - self._getChildTextAsFloat("tau", el, ns, False)) - environment.wavelength_tau = ( - self._getChildTextAsFloat("wavelengthTau", el, ns, False)) - environment.ambient_temp = ( - self._getChildTextAsFloat("ambientTemp", el, ns, False)) - environment.photometric = ("true" == - self._getChildText("photometric", el, ns, False)) - return environment - - def _addMembers(self, members, parent, ns): - """Create ObservationURI objects from an XML representation of - ObservationURI elements found in members element, and add them to the - set of ObservationURI's - - Arguments: - members : Set of member's from the parent Observation object - parent : element containing the Environment element - ns : namespace of the document - return : an Environment object or - None if the document does not contain an Environment element - raise : ObservationParsingException - """ - el = self._getChildElement("members", parent, ns, False) - if el is not None: - for memberEl in el.iterchildren("{" + ns + "}observationURI"): - members.add(ObservationURI(memberEl.text)) - - if not members: - error = "No observationURI element found in members" - raise ObservationParsingException(error) - - def _addInputs(self, inputs, parent, ns): - """Create PlaneURI objects from an XML representation of the planeURI - elements and add them to the set of PlaneURIs. - - Arguments: - inputs : set of PlaneURI from the Provenance - parent : element containing the PlaneURI elements - ns : namespace of the document - raise : ObservationParsingException - """ - el = self._getChildElement("inputs", parent, ns, False) - if el is not None: - for uriEl in el.iterchildren("{" + ns + "}planeURI"): - inputs.add(PlaneURI(uriEl.text)) - - if not inputs: - error = "No planeURI element found in members" - raise ObservationParsingException(error) - - def _getProvenance(self, elTag, parent, ns, required): - """Build a Provenance object from an XML representation of a - Provenance element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Provenance element - ns : namespace of the document - required : indicates whether the element is required - return : a Provenance object or - None if the document does not contain a Provenance element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - prov = Provenance(self._getChildText("name", el, ns, True)) - prov.version = self._getChildText("version", el, ns, False) - prov.project = self._getChildText("project", el, ns, False) - prov.producer = self._getChildText("producer", el, ns, False) - prov.run_id = self._getChildText("runID", el, ns, False) - reference = self._getChildText("reference", el, ns, False) - if reference: - prov.reference = reference - prov.last_executed = str2ivoa( - self._getChildText("lastExecuted", el, ns, False)) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - prov.keywords.add(keyword) - self._addInputs(prov.inputs, el, ns) - return prov - - def _getMetrics(self, elTag, parent, ns, required): - """Build a Metrics object from an XML representation of a - Metrics element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Metrics element - ns : namespace of the document - required : indicates whether the element is required - return : a Metrics object or - None if the document does not contain a Metrics element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - metrics = Metrics() - metrics.source_number_density = \ - self._getChildTextAsFloat("sourceNumberDensity", el, ns, False) - metrics.background = \ - self._getChildTextAsFloat("background", el, ns, False) - metrics.background_std_dev = \ - self._getChildTextAsFloat("backgroundStddev", el, ns, False) - metrics.flux_density_limit = \ - self._getChildTextAsFloat("fluxDensityLimit", el, ns, False) - metrics.mag_limit = \ - self._getChildTextAsFloat("magLimit", el, ns, False) - return metrics - - def _getQuality(self, elTag, parent, ns, required): - """Build an Quality object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Quality element - ns : namespace of the document - required : indicates whether the element is required - return : a Quality object or - None if the document does not contain an Quality element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - flag = self._getChildText("flag", el, ns, True) - dataQuality = DataQuality(Quality.getByValue(flag)) - return dataQuality - - def _getPoint(self, elTag, parent, ns, required): - """Build an Point object from an XML representation - of an Point element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Point element - ns : namespace of the document - required : indicate whether the element is required - return : an Point object or - None if the document does not contain an Point element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Point(self._getChildTextAsFloat("cval1", el, ns, True), - self._getChildTextAsFloat("cval2", el, ns, True)) - - def _getAxis(self, elTag, parent, ns, required): - """Build an Axis object from an XML representation of an Axis element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Axis element - ns : namespace of the document - required : indicate whether the element is required - return : an Axis object or - None if the document does not contain an Axis element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Axis(self._getChildText("ctype", el, ns, True), - self._getChildText("cunit", el, ns, False)) - - def _getSlice(self, elTag, parent, ns, required): - """Build a Slice object from an XML representation of a Slice element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Slice element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a Slice object or - None if the document does not contain a Slice element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Slice(self._getAxis("axis", el, ns, True), - self._getChildTextAsLong("bin", el, ns, True)) - - def _getObservableAxis(self, elTag, parent, ns, required): - """Build an ObservableAxis object from an XML representation of an - observable element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Observable element - ns : namespace of the document - required : boolean indicating whether the element is required - return : an ObservableAxis object or - None if the document does not contain an Observable element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - observable = ObservableAxis( - self._getSlice("dependent", el, ns, True)) - observable.independent = \ - self._getSlice("independent", el, ns, False) - return observable - - def _getCoordError(self, elTag, parent, ns, required): - """Build a CoordError object from an XML representation of an error - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the error element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordError object or - None if the document does not contain an error element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordError( - self._getChildTextAsFloat("syser", el, ns, True), - self._getChildTextAsFloat("rnder", el, ns, True)) - - def _getRefCoord(self, elTag, parent, ns, required): - """Build a RefCoord object from an XML representation of a coord - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the coord element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a RefCoord object or - None if the document does not contain a coord element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return RefCoord( - self._getChildTextAsFloat("pix", el, ns, True), - self._getChildTextAsFloat("val", el, ns, True)) - - def _getCoord2D(self, elTag, parent, ns, required): - """Build a Coord2D object from an XML representation of a coord - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the coord element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a Coord2D object or - None if the document does not contain a coord element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Coord2D( - self._getRefCoord("coord1", el, ns, True), - self._getRefCoord("coord2", el, ns, True)) - - def _getValueCoord2D(self, elTag, parent, ns, required): - """Build a ValueCoord2D object from an XML representation of a - value coord element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the coord element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a ValueCoord2D object or - None if the document does not contain a coord element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return ValueCoord2D( - self._getChildTextAsFloat("coord1", el, ns, True), - self._getChildTextAsFloat("coord2", el, ns, True)) - - def _getCoordRange2D(self, elTag, parent, ns, required): - """Build a CoordRange2D object from an XML representation of a range - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the range element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordRange2D object or - None if the document does not contain a range element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordRange2D( - self._getCoord2D("start", el, ns, True), - self._getCoord2D("end", el, ns, True)) - - def _getCoordCircle2D(self, elTag, parent, ns, required): - """Build a CoordCircle2D object from an XML representation of a circle - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the circle element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordCircle2D object or - None if the document does not contain a circle element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordCircle2D( - self._getValueCoord2D("center", el, ns, True), - self._getChildTextAsFloat("radius", el, ns, True)) - - def _getCoordPolygon2D(self, elTag, parent, ns, required): - """Build a CoordPolygon2D object from an XML representation - of a polygon element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the polygon element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordPolygon2D object or - None if the document does not contain a polygon element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - verticeEl = self._getChildElement("vertices", el, ns, True) - childrenVertices = list( - verticeEl.iterchildren(tag=("{" + ns + "}vertex"))) - if len(childrenVertices) < 3: - error = ("CoordPolygon2D must have a minimum of 3 vertices, " - "found " + len(childrenVertices)) - raise ObservationParsingException(error) - else: - polygon = CoordPolygon2D() - for childVertexEl in childrenVertices: - polygon.vertices.append(ValueCoord2D( - self._getChildTextAsFloat( - "coord1", childVertexEl, ns, True), - self._getChildTextAsFloat( - "coord2", childVertexEl, ns, True))) - return polygon - - def _getCoordBounds2D(self, elTag, parent, ns, required): - """Build a CoordBounds2D object from an XML representation of a bounds - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the bounds element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordBounds2D object or - None if the document does not contain a bounds element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - circle = self._getCoordCircle2D("circle", el, ns, False) - if circle is not None: - return circle - else: - polygon = self._getCoordPolygon2D("polygon", el, ns, False) - if polygon is not None: - return polygon - else: - error = "Unsupported element not found in " + elTag + \ - ": " + el.getText() - raise ObservationParsingException(error) - - def _getDimension2D(self, elTag, parent, ns, required): - """Build a Dimension2D object from an XML representation of a dimension - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the dimension element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a Dimention2D object or - None if the document does not contain a dimension element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Dimension2D( - self._getChildTextAsLong("naxis1", el, ns, True), - self._getChildTextAsLong("naxis2", el, ns, True)) - - def _getCoordFunction2D(self, elTag, parent, ns, required): - """Build a CoordFunction2D object from an XML representation of a - function element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the function element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordFunction2D object or - None if the document does not contain a function element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordFunction2D( - self._getDimension2D("dimension", el, ns, True), - self._getCoord2D("refCoord", el, ns, True), - self._getChildTextAsFloat("cd11", el, ns, True), - self._getChildTextAsFloat("cd12", el, ns, True), - self._getChildTextAsFloat("cd21", el, ns, True), - self._getChildTextAsFloat("cd22", el, ns, True)) - - def _getCoordAxis2D(self, elTag, parent, ns, required): - """Build a CoordAxis2D object from an XML representation of an axis - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the axis element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordAxis2D object or - None if the document does not contain an axis element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - axis = CoordAxis2D(self._getAxis("axis1", el, ns, True), - self._getAxis("axis2", el, ns, True)) - axis.error1 = self._getCoordError("error1", el, ns, False) - axis.error2 = self._getCoordError("error2", el, ns, False) - axis.range = self._getCoordRange2D("range", el, ns, False) - axis.bounds = self._getCoordBounds2D("bounds", el, ns, False) - axis.function = self._getCoordFunction2D("function", el, ns, False) - return axis - - def _getSpatialWCS(self, elTag, parent, ns, required): - """Build a SpatialWCS object from an XML representation of a position - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the position element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a SpatialWCS object or - None if the document does not contain a position element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - position = SpatialWCS(self._getCoordAxis2D("axis", el, ns, False)) - position.coordsys = self._getChildText("coordsys", el, ns, False) - position.equinox = \ - self._getChildTextAsFloat("equinox", el, ns, False) - position.resolution = \ - self._getChildTextAsFloat("resolution", el, ns, False) - return position - - def _addChildrenToCoordRange1DList(self, elTag, ranges, parent, ns, - required): - """Create CoordRange1D objects from an XML representation of the - range elements and add them to the set of ranges. - - Arguments: - elTag : element tag which identifies the element - ranges : reference to set of ranges - parent : element containing the ranges elements - ns : namespace of the document - required : boolean indicating whether the element is required - """ - for rangeEl in parent.iterchildren("{" + ns + "}" + elTag): - ranges.append(CoordRange1D( - self._getRefCoord("start", rangeEl, ns, True), - self._getRefCoord("end", rangeEl, ns, True))) - - def _getCoordBounds1D(self, elTag, parent, ns, required): - """Build a CoordBounds1D object from an XML representation of a bounds - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the bounds element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordBounds1D object or - None if the document does not contain a bounds element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - coordBounds1D = CoordBounds1D() - samplesEl = self._getChildElement("samples", el, ns, False) - if samplesEl is not None: - self._addChildrenToCoordRange1DList( - "range", coordBounds1D.samples, samplesEl, ns, False) - return coordBounds1D - - def _getCoordRange1D(self, elTag, parent, ns, required): - """Build a CoordRange1D object from an XML representation of a range - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the range element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordRange1D object or - None if the document does not contain a range element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordRange1D( - self._getRefCoord("start", el, ns, True), - self._getRefCoord("end", el, ns, True)) - - def _getCoordFunction1D(self, elTag, parent, ns, required): - """Build a CoordFunction1D object from an XML representation of a - function element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the function element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordFunction1D object or - None if the document does not contain a function element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordFunction1D( - self._getChildTextAsLong("naxis", el, ns, True), - self._getChildTextAsFloat("delta", el, ns, True), - self._getRefCoord("refCoord", el, ns, True)) - - def _getCoordAxis1D(self, elTag, parent, ns, required): - """Build a CoordAxis1D object from an XML representation of an axis - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the axis element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordAxis1D object or - None if the document does not contain an axis element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - axis = CoordAxis1D(self._getAxis("axis", el, ns, True)) - axis.error = self._getCoordError("error", el, ns, False) - axis.range = self._getCoordRange1D("range", el, ns, False) - axis.bounds = self._getCoordBounds1D("bounds", el, ns, False) - axis.function = self._getCoordFunction1D("function", el, ns, False) - return axis - - def _getTransition(self, elTag, parent, ns, required): - """Build an EnergyTransition object from an XML representation of - a transition element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the transition element - ns : namespace of the document - required : boolean indicating whether the element is reuiqred - return : an EnergyTransition object or - None if the document does not contain a transition element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return EnergyTransition( - self._getChildText("species", el, ns, True), - self._getChildText("transition", el, ns, True)) - - def _getSpectralWCS(self, elTag, parent, ns, required): - """Build a SpectralWCS object from an XML representation of an energy - element. - - Arguments: - elTag : element tag which indentifies the element - parent : element containing the position element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a SpectralWCS object or - None if the document does not contain an energy element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - energy = SpectralWCS( - self._getCoordAxis1D("axis", el, ns, True), - self._getChildText("specsys", el, ns, True)) - energy.ssysobs = \ - self._getChildText("ssysobs", el, ns, False) - energy.ssyssrc = \ - self._getChildText("ssyssrc", el, ns, False) - energy.restfrq = \ - self._getChildTextAsFloat("restfrq", el, ns, False) - energy.restwav = \ - self._getChildTextAsFloat("restwav", el, ns, False) - energy.velosys = \ - self._getChildTextAsFloat("velosys", el, ns, False) - energy.zsource = \ - self._getChildTextAsFloat("zsource", el, ns, False) - energy.velang = \ - self._getChildTextAsFloat("velang", el, ns, False) - energy.bandpass_name = \ - self._getChildText("bandpassName", el, ns, False) - energy.resolving_power = \ - self._getChildTextAsFloat("resolvingPower", el, ns, False) - energy.transition = \ - self._getTransition("transition", el, ns, False) - return energy - - def _getTemporalWCS(self, elTag, parent, ns, required): - """Build a TemporalWCS object from an XML representation of an time - element. - - Arguments: - elTag : element tag which indentifies the element - parent : element containing the position element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a TemporalWCS object or - None if the document does not contain an time element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - time = TemporalWCS( - self._getCoordAxis1D("axis", el, ns, True)) - time.timesys = \ - self._getChildText("timesys", el, ns, False) - time.trefpos = \ - self._getChildText("trefpos", el, ns, False) - time.mjdref = \ - self._getChildTextAsFloat("mjdref", el, ns, False) - time.exposure = \ - self._getChildTextAsFloat("exposure", el, ns, False) - time.resolution = \ - self._getChildTextAsFloat("resolution", el, ns, False) - return time - - def _getPolarizationWCS(self, elTag, parent, ns, required): - """Build a PolarizationWCS object from an XML representation of a - polarization element. - - Arguments: - elTag : element tag which indentifies the element - parent : element containing the position element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a PolarizationWCS object or - None if the document does not contain an polarization element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return PolarizationWCS( - self._getCoordAxis1D("axis", el, ns, False)) - - def _addChunks(self, chunks, parent, ns): - """Build Chunk objects from an XML representation of Chunk elements - and add them to the set of Chunks. - - Argument: - chunks : set of Chunk objects from the Part - parent : element containing the Chunk elements - ns : namespace of the document - raise : ObservationParsingException - """ - el = self._getChildElement("chunks", parent, ns, False) - if el is None: - return None - else: - for chunkEl in el.iterchildren("{" + ns + "}chunk"): - tempChunk = Chunk() - productType = \ - self._getChildText("productType", chunkEl, ns, False) - if productType: - tempChunk.product_type = \ - ProductType.getByValue(productType) - tempChunk.naxis = \ - self._getChildTextAsInt("naxis", chunkEl, ns, False) - tempChunk.observable_axis = \ - self._getChildTextAsInt("observableAxis", chunkEl, ns, - False) - tempChunk.position_axis_1 = \ - self._getChildTextAsInt("positionAxis1", chunkEl, ns, - False) - tempChunk.position_axis_2 = \ - self._getChildTextAsInt("positionAxis2", chunkEl, ns, - False) - tempChunk.energy_axis = \ - self._getChildTextAsInt("energyAxis", chunkEl, ns, False) - tempChunk.time_axis = \ - self._getChildTextAsInt("timeAxis", chunkEl, ns, False) - tempChunk.polarization_axis = \ - self._getChildTextAsInt("polarizationAxis", chunkEl, ns, - False) - tempChunk.observable = \ - self._getObservableAxis("observable", chunkEl, ns, False) - tempChunk.position = \ - self._getSpatialWCS("position", chunkEl, ns, False) - tempChunk.energy = \ - self._getSpectralWCS("energy", chunkEl, ns, False) - tempChunk.time = \ - self._getTemporalWCS("time", chunkEl, ns, False) - tempChunk.polarization = \ - self._getPolarizationWCS("polarization", chunkEl, ns, - False) - self._set_entity_attributes(chunkEl, ns, tempChunk) - chunks.append(tempChunk) - - def _addParts(self, parts, parent, ns): - """Build Part objects from an XML representation of Part elements and - add them to the set of Parts. - - Argument: - parts : set of Part objects from the Artifact - parent : element containing the Part elements - ns : namespace of the document - raise : ObservationParsingException - """ - el = self._getChildElement("parts", parent, ns, False) - if el is None: - return None - else: - for partEl in el.iterchildren("{" + ns + "}part"): - tempPart = \ - Part(self._getChildText("name", partEl, ns, True)) - productType = \ - self._getChildText("productType", partEl, ns, False) - if productType: - tempPart.product_type = \ - ProductType.getByValue(productType) - self._addChunks(tempPart.chunks, partEl, ns) - self._set_entity_attributes(partEl, ns, tempPart) - parts[tempPart.name] = tempPart - - def _addArtifacts(self, artifacts, parent, ns): - """Build artifacts from an XML representation of the artifact elements - and add them to the set of Artifacts. - - Arguments: - artifacts : set of Artifacts from the Plane - parent : element containing the Artifact elements - ns : namespace fo the document - raise : ObservationParsingException - """ - el = self._getChildElement("artifacts", parent, ns, False) - if el is None: - return None - else: - for artifactEl in el.iterchildren("{" + ns + "}artifact"): - uri = self._getChildText("uri", artifactEl, ns, True) - - product_type = self._getChildText("productType", artifactEl, ns, False) - if product_type is None: - product_type = ProductType.SCIENCE - print "Using default Artifact.productType value {0}".format(str(ProductType.SCIENCE)) - else: - product_type = ProductType.getByValue(product_type) - - release_type = self._getChildText("releaseType", artifactEl, ns, False) - if release_type is None: - release_type = ReleaseType.DATA - print "Using default Artifact.releaseType value {0}".format(str(ReleaseType.DATA)) - else: - release_type = ReleaseType.getByValue(release_type) - - tempArtifact = Artifact(uri, product_type, release_type) - tempArtifact.content_type = self._getChildText("contentType", artifactEl, ns, False) - tempArtifact.content_length = ( - self._getChildTextAsLong("contentLength", artifactEl, ns, False)) - self._addParts(tempArtifact.parts, artifactEl, ns) - self._set_entity_attributes(artifactEl, ns, tempArtifact) - artifacts[tempArtifact.uri] = tempArtifact - - def _addPlanes(self, planes, parent, ns): - """Create Planes object from XML representation of Plane elements - and add them to the set of Planes. - - Arguments: - planes : Set of planes from the parent Observation object - parent : element containing the Plane elements - ns : namespace of the document - raise : ObservationParsingException - """ - el = self._getChildElement("planes", parent, ns, False) - if el is None: - return None - else: - for planeEl in el.iterchildren("{" + ns + "}plane"): - tempPlane = Plane( - self._getChildText("productID", planeEl, ns, True)) - tempPlane.meta_release = str2ivoa( - self._getChildText("metaRelease", planeEl, ns, False)) - tempPlane.data_release = str2ivoa( - self._getChildText("dataRelease", planeEl, ns, False)) - dataProductType = \ - self._getChildText("dataProductType", planeEl, ns, False) - if dataProductType: - tempPlane.data_product_type = \ - DataProductType.getByValue(dataProductType) - calibrationLevel = \ - self._getChildText("calibrationLevel", planeEl, ns, False) - if calibrationLevel: - tempPlane.calibration_level = \ - CalibrationLevel.getByValue(int(calibrationLevel)) - tempPlane.provenance = \ - self._getProvenance("provenance", planeEl, ns, False) - tempPlane.metrics = \ - self._getMetrics("metrics", planeEl, ns, False) - tempPlane.quality = \ - self._getQuality("quality", planeEl, ns, False) - self._addArtifacts(tempPlane.artifacts, planeEl, ns) - self._set_entity_attributes(planeEl, ns, tempPlane) - planes[tempPlane.product_id] = tempPlane - - if not planes: - error = "No plane element found in planes" - raise ObservationParsingException(error) - - def read(self, source): - """Build an Observation object from an XML document located in source. - Source an be a file name/path, a file object, a file-like object or a - URL using the HTTP or FTP protocol. - - Arguments: - source : source of XML document containing an Observation element - return : an Observation object - raise : ObservationParsingException - """ - doc = etree.parse(source) - if self._validate and self._xmlschema: - self._xmlschema.assertValid(doc) - root = doc.getroot() - ns = root.nsmap["caom2"] - collection = self._getChildElement("collection", root, ns, True).text - observationID = \ - self._getChildElement("observationID", root, ns, True).text - # Instantiate Algorithm - algorithm = self._getAlgorithm("algorithm", root, ns, True) - # Instantiate Observation - if root.get("{http://www.w3.org/2001/XMLSchema-instance}type") \ - == "caom2:SimpleObservation": - observation = SimpleObservation(collection, observationID) - observation.algorithm = algorithm - else: - observation = \ - CompositeObservation(collection, observationID, algorithm) - # Instantiate children of Observation - observation.sequence_number = \ - self._getChildTextAsInt("sequenceNumber", root, ns, False) - observation.obs_type = \ - self._getChildText("type", root, ns, False) - intent = self._getChildText("intent", root, ns, False) - if intent: - observation.intent = ObservationIntentType.getByValue(intent) - observation.meta_release = \ - self._getMetaRelease("metaRelease", root, ns, False) - observation.proposal = \ - self._getProposal("proposal", root, ns, False) - observation.target = \ - self._getTarget("target", root, ns, False) - observation.target_position = \ - self._getTargetPosition("targetPosition", root, ns, False) - observation.telescope = \ - self._getTelescope("telescope", root, ns, False) - observation.instrument = \ - self._getInstrument("instrument", root, ns, False) - observation.environment = \ - self._getEnvironment("environment", root, ns, False) - observation.requirements = \ - self._getRequirements("requirements", root, ns, False) - self._addPlanes(observation.planes, root, ns) - if isinstance(observation, CompositeObservation): - self._addMembers(observation.members, root, ns) - - self._set_entity_attributes(root, ns, observation) - return observation - -if __name__ == '__main__': - reader = ObservationReader(True) - reader.read('../../../../test/data/CompleteCompositePolygon.xml') diff --git a/pyCAOM2/caom2/xml/caom2_observation_writer.py b/pyCAOM2/caom2/xml/caom2_observation_writer.py deleted file mode 100644 index 4a53e2c0..00000000 --- a/pyCAOM2/caom2/xml/caom2_observation_writer.py +++ /dev/null @@ -1,737 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines ObservationWriter class """ - -from lxml import etree -import pkg_resources -import caom2_xml_constants -from .. caom2_observation import Observation -from .. caom2_composite_observation import CompositeObservation -from .. caom2_simple_observation import SimpleObservation -from .. wcs.caom2_coord_circle2d import CoordCircle2D -from .. wcs.caom2_coord_polygon2d import CoordPolygon2D -from .. caom2_enums import CalibrationLevel -from .. caom2_enums import DataProductType -from .. caom2_enums import ObservationIntentType -from .. caom2_enums import ProductType -from .. caom2_enums import Quality -from .. caom2_enums import Status -from .. caom2_enums import TargetType -from .. caom2_enums import ReleaseType -from .. util.caom2_util import date2ivoa -from .. util.caom2_util import uuid2long - - -class ObservationWriter(object): - """ ObservationWriter """ - - def __init__(self, validate=False, write_empty_collections=False, - namespace_prefix="caom2", namespace=None): - """ - Arguments: - validate : If True enable schema validation, False otherwise - write_empty_collections : if True write empty elements for empty collections - namespace_prefix : a CAOM-2.x namespace prefix - namespace : a valid CAOM-2.x target namespace - """ - self._validate = validate - self._write_empty_collections = write_empty_collections - - if namespace_prefix is None or not namespace_prefix: - raise RuntimeError('null or empty namespace_prefix not allowed') - - if namespace is None or namespace == caom2_xml_constants.CAOM22_NAMESPACE: - self._output_version = 22 - self._caom2_namespace = caom2_xml_constants.CAOM22 - self._namespace = caom2_xml_constants.CAOM22_NAMESPACE - elif namespace == caom2_xml_constants.CAOM21_NAMESPACE: - self._output_version = 21 - self._caom2_namespace = caom2_xml_constants.CAOM21 - self._namespace = caom2_xml_constants.CAOM21_NAMESPACE - elif namespace == caom2_xml_constants.CAOM20_NAMESPACE: - self._output_version = 20 - self._caom2_namespace = caom2_xml_constants.CAOM20 - self._namespace = caom2_xml_constants.CAOM20_NAMESPACE - else: - raise RuntimeError('invalid namespace {}'.format(namespace)) - - if self._validate: - if self._output_version == 20: - schema_file = caom2_xml_constants.CAOM20_SCHEMA_FILE - elif self._output_version == 21: - schema_file = caom2_xml_constants.CAOM21_SCHEMA_FILE - else: - schema_file = caom2_xml_constants.CAOM22_SCHEMA_FILE - schema_path = pkg_resources.resource_filename( - caom2_xml_constants.CAOM2_PKG, schema_file) - xmlschema_doc = etree.parse(schema_path) - self._xmlschema = etree.XMLSchema(xmlschema_doc) - - self._nsmap = {namespace_prefix: self._namespace, "xsi": caom2_xml_constants.XSI_NAMESPACE} - - def write(self, observation, out): - assert isinstance(observation, Observation), ( - "observation is not an Observation") - - obs = etree.Element(self._caom2_namespace + "Observation", nsmap=self._nsmap) - if isinstance(observation, SimpleObservation): - obs.set(caom2_xml_constants.XSI + "type", "caom2:SimpleObservation") - else: - obs.set(caom2_xml_constants.XSI + "type", "caom2:CompositeObservation") - - self._addEnityAttributes(observation, obs) - - self._addElement("collection", observation.collection, obs) - self._addElement("observationID", observation.observation_id, obs) - self._addDatetimeElement("metaRelease", observation.meta_release, obs) - self._addElement("sequenceNumber", observation.sequence_number, obs) - self._addAlgorithmElement(observation.algorithm, obs) - self._addElement("type", observation.obs_type, obs) - if observation.intent is not None: - self._addElement( - "intent", ObservationIntentType.get(str(observation.intent)).value, obs) - - self._addProposalElement(observation.proposal, obs) - self._addTargetElement(observation.target, obs) - self._addTargetPositionElement(observation.target_position, obs) - self._addRequirementsElement(observation.requirements, obs) - self._addTelescopeElement(observation.telescope, obs) - self._addInstrumentElement(observation.instrument, obs) - self._addEnvironmentElement(observation.environment, obs) - self._addPlanesElement(observation.planes, obs) - - if isinstance(observation, CompositeObservation): - self._addMembersElement(observation.members, obs) - - if self._validate and self._xmlschema: - self._xmlschema.assertValid(obs) - - out.write(etree.tostring(obs, xml_declaration=True, encoding='UTF-8', - pretty_print=True)) - - def _addEnityAttributes(self, entity, element): - if self._output_version == 20: - uid = uuid2long(entity._id) - self._addAttribute("id", str(uid), element) - else: - self._addAttribute("id", str(entity._id), element) - - if entity._last_modified is not None: - self._addAttribute( - "lastModified", date2ivoa(entity._last_modified), element) - - def _addAlgorithmElement(self, algorithm, parent): - if algorithm is None: - return - - element = self._getCaom2Element("algorithm", parent) - self._addElement("name", algorithm.name, element) - - def _addProposalElement(self, proposal, parent): - if proposal is None: - return - - element = self._getCaom2Element("proposal", parent) - self._addElement("id", proposal.proposal_id, element) - self._addElement("pi", proposal.pi_name, element) - self._addElement("project", proposal.project, element) - self._addElement("title", proposal.title, element) - self._addListElement("keywords", proposal.keywords, element) - - def _addTargetElement(self, target, parent): - if target is None: - return - - element = self._getCaom2Element("target", parent) - self._addElement("name", target.name, element) - if target.target_type is not None: - self._addElement( - "type", TargetType.get(str(target.target_type)).value, element) - if target.standard is not None: - self._addElement("standard", str(target.standard).lower(), element) - self._addElement("redshift", target.redshift, element) - if target.moving is not None: - self._addElement("moving", str(target.moving).lower(), element) - self._addListElement("keywords", target.keywords, element) - - def _addTargetPositionElement(self, target_position, parent): - if target_position is None: - return - - element = self._getCaom2Element("targetPosition", parent) - self._addElement("coordsys", target_position.coordsys, element) - if target_position.equinox is not None: - self._addElement("equinox", target_position.equinox, element) - self._addPointElement("coordinates", target_position.coordinates, - element) - - def _addRequirementsElement(self, requirements, parent): - if self._output_version < 21: - return # Requirements added in CAOM-2.1 - if requirements is None: - return - - element = self._getCaom2Element("requirements", parent) - self._addElement( - "flag", Status.get(str(requirements.flag)).value, element) - - def _addTelescopeElement(self, telescope, parent): - if telescope is None: - return - - element = self._getCaom2Element("telescope", parent) - self._addElement("name", telescope.name, element) - self._addElement("geoLocationX", telescope.geo_location_x, element) - self._addElement("geoLocationY", telescope.geo_location_y, element) - self._addElement("geoLocationZ", telescope.geo_location_z, element) - self._addListElement("keywords", telescope.keywords, element) - - def _addInstrumentElement(self, instrument, parent): - if instrument is None: - return - - element = self._getCaom2Element("instrument", parent) - self._addElement("name", instrument.name, element) - self._addListElement("keywords", instrument.keywords, element) - - def _addEnvironmentElement(self, environment, parent): - if environment is None: - return - - element = self._getCaom2Element("environment", parent) - self._addElement("seeing", environment.seeing, element) - self._addElement("humidity", environment.humidity, element) - self._addElement("elevation", environment.elevation, element) - self._addElement("tau", environment.tau, element) - self._addElement("wavelengthTau", environment.wavelength_tau, element) - self._addElement("ambientTemp", environment.ambient_temp, element) - if environment.photometric is not None: - self._addElement("photometric", - str(environment.photometric).lower(), element) - - def _addMembersElement(self, members, parent): - if members is None or \ - (len(members) == 0 and not self._write_empty_collections): - return - - element = self._getCaom2Element("members", parent) - for member in members: - memberElement = self._getCaom2Element("observationURI", element) - memberElement.text = member.uri - - def _addPlanesElement(self, planes, parent): - if planes is None or \ - (len(planes) == 0 and not self._write_empty_collections): - return - - element = self._getCaom2Element("planes", parent) - for plane in planes.itervalues(): - planeElement = self._getCaom2Element("plane", element) - self._addEnityAttributes(plane, planeElement) - self._addElement("productID", plane.product_id, planeElement) - self._addDatetimeElement("metaRelease", plane.meta_release, - planeElement) - self._addDatetimeElement("dataRelease", plane.data_release, - planeElement) - if plane.data_product_type is not None: - self._addElement("dataProductType", - DataProductType.get(str(plane.data_product_type)).value, - planeElement) - if plane.calibration_level is not None: - self._addElement("calibrationLevel", - CalibrationLevel(str(plane.calibration_level)).value, - planeElement) - self._addProvenanceElement(plane.provenance, planeElement) - self._addMetricsElement(plane.metrics, planeElement) - self._addQualityElement(plane.quality, planeElement) - self._addArtifactsElement(plane.artifacts, planeElement) - - def _addProvenanceElement(self, provenance, parent): - if provenance is None: - return - - element = self._getCaom2Element("provenance", parent) - self._addElement("name", provenance.name, element) - self._addElement("version", provenance.version, element) - self._addElement("project", provenance.project, element) - self._addElement("producer", provenance.producer, element) - self._addElement("runID", provenance.run_id, element) - self._addElement("reference", provenance.reference, element) - self._addDatetimeElement("lastExecuted", provenance.last_executed, - element) - self._addListElement("keywords", provenance.keywords, element) - self._addInputsElement("inputs", provenance.inputs, element) - - def _addMetricsElement(self, metrics, parent): - if metrics is None: - return - - element = self._getCaom2Element("metrics", parent) - self._addElement("sourceNumberDensity", metrics.source_number_density, - element) - self._addElement("background", metrics.background, element) - self._addElement("backgroundStddev", metrics.background_std_dev, - element) - self._addElement("fluxDensityLimit", metrics.flux_density_limit, - element) - self._addElement("magLimit", metrics.mag_limit, element) - - def _addQualityElement(self, quality, parent): - if self._output_version < 21: - return # Requirements added in CAOM-2.1 - if quality is None: - return - - element = self._getCaom2Element("quality", parent) - self._addElement( - "flag", Quality.get(str(quality.flag)).value, element) - - def _addTransitionElement(self, transition, parent): - if transition is None: - return - - element = self._getCaom2Element("transition", parent) - self._addElement("species", transition.species, element) - self._addElement("transition", transition.transition, element) - - def _addArtifactsElement(self, artifacts, parent): - if artifacts is None: - return - - element = self._getCaom2Element("artifacts", parent) - for artifact in artifacts.itervalues(): - artifactElement = self._getCaom2Element("artifact", element) - self._addEnityAttributes(artifact, artifactElement) - self._addElement("uri", artifact.uri, artifactElement) - if self._output_version > 21: - self._addElement("productType", ProductType.get(str(artifact.product_type)).value, artifactElement) - self._addElement("releaseType", ReleaseType.get(str(artifact.release_type)).value, artifactElement) - self._addElement("contentType", artifact.content_type, artifactElement) - self._addElement("contentLength", artifact.content_length, artifactElement) - if self._output_version < 22: - self._addElement("productType", ProductType.get(str(artifact.product_type)).value, artifactElement) - self._addPartsElement(artifact.parts, artifactElement) - - def _addPartsElement(self, parts, parent): - if parts is None: - return - - element = self._getCaom2Element("parts", parent) - for part in parts.itervalues(): - partElement = self._getCaom2Element("part", element) - self._addEnityAttributes(part, partElement) - self._addElement("name", part.name, partElement) - if part.product_type is not None: - self._addElement("productType", - ProductType.get(str(part.product_type)).value, partElement) - self._addChunksElement(part.chunks, partElement) - - def _addChunksElement(self, chunks, parent): - if chunks is None: - return - - element = self._getCaom2Element("chunks", parent) - for chunk in chunks: - chunkElement = self._getCaom2Element("chunk", element) - self._addEnityAttributes(chunk, chunkElement) - if chunk.product_type is not None: - self._addElement("productType", - ProductType.get(str(chunk.product_type)).value, - chunkElement) - self._addElement("naxis", chunk.naxis, chunkElement) - self._addElement("observableAxis", chunk.observable_axis, - chunkElement) - self._addElement("positionAxis1", chunk.position_axis_1, - chunkElement) - self._addElement("positionAxis2", chunk.position_axis_2, - chunkElement) - self._addElement("energyAxis", chunk.energy_axis, chunkElement) - self._addElement("timeAxis", chunk.time_axis, chunkElement) - self._addElement("polarizationAxis", chunk.polarization_axis, - chunkElement) - - self._addObservableAxisElement(chunk.observable, chunkElement) - self._addSpatialWCSElement(chunk.position, chunkElement) - self._addSpectralWCSElement(chunk.energy, chunkElement) - self._addTemporalWCSElement(chunk.time, chunkElement) - self._addPolarizationWCSElement(chunk.polarization, chunkElement) - - def _addObservableAxisElement(self, observable, parent): - if observable is None: - return - - element = self._getCaom2Element("observable", parent) - self._addSliceElement("dependent", observable.dependent, element) - self._addSliceElement("independent", observable.independent, element) - - def _addSpatialWCSElement(self, position, parent): - """ Builds a representation of a SpatialWCS and adds it to the - parent element. """ - if position is None: - return - - element = self._getCaom2Element("position", parent) - self._addCoordAxis2DElement("axis", position.axis, element) - self._addElement("coordsys", position.coordsys, element) - self._addElement("equinox", position.equinox, element) - self._addElement("resolution", position.resolution, element) - - def _addSpectralWCSElement(self, energy, parent): - """ Builds a representation of a SpectralWCS and adds it to the - parent element.""" - if energy is None: - return - - element = self._getCaom2Element("energy", parent) - self._addCoordAxis1DElement("axis", energy.axis, element) - self._addElement("specsys", energy.specsys, element) - self._addElement("ssysobs", energy.ssysobs, element) - self._addElement("ssyssrc", energy.ssyssrc, element) - self._addElement("restfrq", energy.restfrq, element) - self._addElement("restwav", energy.restwav, element) - self._addElement("velosys", energy.velosys, element) - self._addElement("zsource", energy.zsource, element) - self._addElement("velang", energy.velang, element) - self._addElement("bandpassName", energy.bandpass_name, element) - self._addElement("resolvingPower", energy.resolving_power, element) - self._addTransitionElement(energy.transition, element) - - def _addTemporalWCSElement(self, time, parent): - """ Builds a representation of a TemporalWCS and adds it to the - parent element. """ - if time is None: - return - - element = self._getCaom2Element("time", parent) - self._addCoordAxis1DElement("axis", time.axis, element) - self._addElement("timesys", time.timesys, element) - self._addElement("trefpos", time.trefpos, element) - self._addElement("mjdref", time.mjdref, element) - self._addElement("exposure", time.exposure, element) - self._addElement("resolution", time.resolution, element) - - def _addPolarizationWCSElement(self, polarization, parent): - """ Builds a representation of a PolarizationWCS and adds it to the - parent element. """ - if polarization is None: - return - - element = self._getCaom2Element("polarization", parent) - self._addCoordAxis1DElement("axis", polarization.axis, element) - -#/*+ CAOM2 Types #-*/ - - def _addPointElement(self, name, point, parent): - """ Builds a representation of a Point and adds it to the - parent element. """ - if point is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("cval1", point.cval1, element) - self._addElement("cval2", point.cval2, element) - -#/*+ WCS Types #-*/ - - def _addAxisElement(self, name, axis, parent): - """ Builds a representation of a Axis and adds it to the - parent element. """ - if axis is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("ctype", axis.ctype, element) - if axis.cunit: - self._addElement("cunit", axis.cunit, element) - - def _addCoord2DElement(self, name, coord, parent): - """ Builds a representation of a Coord2D and adds it to the - parent element. """ - if coord is None: - return - - element = self._getCaom2Element(name, parent) - self._addRefCoordElement("coord1", coord.coord1, element) - self._addRefCoordElement("coord2", coord.coord2, element) - - def _addValueCoord2DElement(self, name, coord, parent): - """ Builds a representation of a ValueCoord2D and adds it to the - parent element. """ - if coord is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("coord1", coord.coord1, element) - self._addElement("coord2", coord.coord2, element) - - def _addCoordAxis1DElement(self, name, axis, parent): - """ Builds a representation of a CoordAxis1D and adds it to the - parent element. """ - if axis is None: - return - - element = self._getCaom2Element(name, parent) - self._addAxisElement("axis", axis.axis, element) - self._addCoordErrorElement("error", axis.error, element) - self._addCoordRange1DElement("range", axis.range, element) - self._addCoordBounds1DElement("bounds", axis.bounds, element) - self._addCoordFunction1DElement("function", axis.function, element) - - def _addCoordAxis2DElement(self, name, axis, parent): - """ Builds a representation of a CoordAxis2D and adds it to the - parent element. """ - if axis is None: - return - - element = self._getCaom2Element(name, parent) - self._addAxisElement("axis1", axis.axis1, element) - self._addAxisElement("axis2", axis.axis2, element) - self._addCoordErrorElement("error1", axis.error1, element) - self._addCoordErrorElement("error2", axis.error2, element) - self._addCoordRange2DElement("range", axis.range, element) - self._addCoordBounds2DElement("bounds", axis.bounds, element) - self._addCoordFunction2DElement("function", axis.function, element) - - def _addCoordBounds1DElement(self, name, bounds, parent): - """ Builds a representation of a CoordBounds1D and adds it to the - parent element. """ - if bounds is None: - return - - element = self._getCaom2Element(name, parent) - self._addCoordRange1DListElement("samples", bounds.samples, element) - - def _addCoordBounds2DElement(self, name, bounds, parent): - """Builds a representation of a CoordBounds2D and adds it to the - parent element. """ - if bounds is None: - return - - element = self._getCaom2Element(name, parent) - if isinstance(bounds, CoordCircle2D): - self._addCoordCircle2DElement("circle", - CoordCircle2D(bounds.center, - bounds.radius), element) - elif isinstance(bounds, CoordPolygon2D): - self._addCoordPolygon2DElement("polygon", bounds, element) - else: - raise TypeError("BUG: unsupported CoordBounds2D type " - + bounds.__class__.__name__) - - def _addCoordCircle2DElement(self, name, circle, parent): - """ Builds a representation of a CoordCircle2D and adds it to the - parent element. """ - if circle is None: - return - - element = self._getCaom2Element(name, parent) - self._addValueCoord2DElement("center", circle.center, element) - self._addElement("radius", circle.radius, element) - - def _addCoordErrorElement(self, name, error, parent): - """ Builds a representation of a CoordError and adds it to the - parent element. """ - if error is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("syser", error.syser, element) - self._addElement("rnder", error.rnder, element) - - def _addCoordFunction1DElement(self, name, function, parent): - """ Builds a representation of a CoordFunction1D and adds it to the - parent element. """ - if function is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("naxis", function.naxis, element) - self._addElement("delta", function.delta, element) - self._addRefCoordElement("refCoord", function.ref_coord, element) - - def _addCoordFunction2DElement(self, name, function, parent): - """ Builds a representation of a CoordFunction2D and adds it to the - parent element. """ - if function is None: - return - - element = self._getCaom2Element(name, parent) - self._addDimension2DElement("dimension", function.dimension, element) - self._addCoord2DElement("refCoord", function.ref_coord, element) - self._addElement("cd11", function.cd11, element) - self._addElement("cd12", function.cd12, element) - self._addElement("cd21", function.cd21, element) - self._addElement("cd22", function.cd22, element) - - def _addCoordPolygon2DElement(self, name, polygon, parent): - """ Builds a representation of a CoordPolygon2D and adds it to the - parent element. """ - if polygon is None: - return - - element = self._getCaom2Element(name, parent) - if (len(polygon.vertices) > 0): - verticesElement = self._getCaom2Element("vertices", element) - for vertex in polygon.vertices: - self._addValueCoord2DElement("vertex", vertex, verticesElement) - - def _addCoordRange1DElement(self, name, _range, parent): - """ Builds a representation of a CoordRange1D and adds it to the - parent element. """ - if _range is None: - return - - element = self._getCaom2Element(name, parent) - self._addRefCoordElement("start", _range.start, element) - self._addRefCoordElement("end", _range.end, element) - - def _addCoordRange2DElement(self, name, _range, parent): - """ Builds a representation of a CoordRange2D and adds it to the - parent element. """ - if _range is None: - return - - element = self._getCaom2Element(name, parent) - self._addCoord2DElement("start", _range.start, element) - self._addCoord2DElement("end", _range.end, element) - - def _addDimension2DElement(self, name, dimension, parent): - """ Builds a representation of a Dimension2D and adds it to the - parent element. """ - if dimension is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("naxis1", dimension.naxis1, element) - self._addElement("naxis2", dimension.naxis2, element) - - def _addRefCoordElement(self, name, refCoord, parent): - """ Builds a representation of a RefCoord and adds it to the - parent element. """ - if refCoord is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("pix", refCoord.pix, element) - self._addElement("val", refCoord.val, element) - - def _addSliceElement(self, name, _slice, parent): - """ Builds a representation of a Slice and adds it to the - parent element. """ - if _slice is None: - return - - element = self._getCaom2Element(name, parent) - self._addAxisElement("axis", _slice.axis, element) - self._addElement("bin", _slice.bin, element) - - def _addAttribute(self, name, value, element): - element.set(self._caom2_namespace + name, value) - - def _addElement(self, name, text, parent): - if text is None: - return - element = self._getCaom2Element(name, parent) - if isinstance(text, str): - element.text = text - else: - element.text = str(text) - - def _addDatetimeElement(self, name, value, parent): - if value is None: - return - element = self._getCaom2Element(name, parent) - element.text = date2ivoa(value) - - def _addListElement(self, name, collection, parent): - if collection is None or \ - (len(collection) == 0 and not self._write_empty_collections): - return - element = self._getCaom2Element(name, parent) - element.text = ' '.join(collection) - - def _addCoordRange1DListElement(self, name, values, parent): - if values is None: - return - element = self._getCaom2Element(name, parent) - for v in values: - self._addCoordRange1DElement("range", v, element) - - def _addInputsElement(self, name, collection, parent): - if collection is None or \ - (len(collection) == 0 and not self._write_empty_collections): - return - element = self._getCaom2Element(name, parent) - for plane_uri in collection: - self._addElement("planeURI", plane_uri.uri, element) - - def _getCaom2Element(self, tag, parent): - return etree.SubElement(parent, self._caom2_namespace + tag) diff --git a/pyCAOM2/requirements.txt b/pyCAOM2/requirements.txt deleted file mode 100644 index dc67614a..00000000 --- a/pyCAOM2/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -lxml -requests -urllib3 diff --git a/pyCAOM2/setup.cfg b/pyCAOM2/setup.cfg deleted file mode 100644 index 2216d825..00000000 --- a/pyCAOM2/setup.cfg +++ /dev/null @@ -1,10 +0,0 @@ -[global] -verbose=0 - -version = 0.6.3 -description = "CAOM2 Class libraries" - -[install] -install-purelib=$base/lib/python$py_version_short/site-packages -install-platlib=$base/lib/python$py_version_short/site-packages -install_headers=$base/include/python$py_version_short/$dist_name diff --git a/pyCAOM2/setup.py b/pyCAOM2/setup.py deleted file mode 100755 index 1fe26e7c..00000000 --- a/pyCAOM2/setup.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#/*+ -#************************************************************************ -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#* -#* (c) 2012. (c)2012. -#* National Research Council Conseil national de recherches -#* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -#* All rights reserved Tous droits reserves -#* -#* NRC disclaims any warranties, Le CNRC denie toute garantie -#* expressed, implied, or statu- enoncee, implicite ou legale, -#* tory, of any kind with respect de quelque nature que se soit, -#* to the software, including concernant le logiciel, y com- -#* without limitation any war- pris sans restriction toute -#* ranty of merchantability or garantie de valeur marchande -#* fitness for a particular pur- ou de pertinence pour un usage -#* pose. NRC shall not be liable particulier. Le CNRC ne -#* in any event for any damages, pourra en aucun cas etre tenu -#* whether direct or indirect, responsable de tout dommage, -#* special or general, consequen- direct ou indirect, particul- -#* tial or incidental, arising ier ou general, accessoire ou -#* from the use of the software. fortuit, resultant de l'utili- -#* sation du logiciel. -#* -#************************************************************************ -#* -#* Script Name: setup.py -#* -#* Purpose: -#* Distutils setup script for caom2 -#* -#* Functions: -#* -#* -#* -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#************************************************************************ -#-*/ - -# Use "distribute" -from setuptools import setup, find_packages -import sys - -if sys.version_info[0] > 2: - print 'The caom2 package is only compatible with Python version 2.n' - sys.exit(-1) - -setup(name='pyCAOM2', - version='2.2.1', - description='CAOM-2.2 library', - url='This is a Home-page.', - author='Canadian Astronomy Data Centre', - author_email='cadc@nrc.ca', - license='GPLv3', - long_description='Python library for the CAOM-2.2 data model', - packages=find_packages(exclude=['caom2.test']), - package_data={'caom2': ['CAOM-2.0.xsd', 'CAOM-2.1.xsd', 'CAOM-2.2.xsd'], 'caom2.test.data': ['*.xml']}, - include_package_data=True, - requires=['distribute', 'lxml'], - provides=['caom2'], - zip_safe=False -) - diff --git a/pyCAOM2/test/test_roundtrip.py b/pyCAOM2/test/test_roundtrip.py deleted file mode 100644 index 4098f841..00000000 --- a/pyCAOM2/test/test_roundtrip.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestRoundTrip class """ - -import errno -import filecmp -import glob -import os -import shutil -import unittest - -import caom2.xml.caom2_xml_constants -from caom2.xml.caom2_observation_reader import ObservationReader -from caom2.xml.caom2_observation_writer import ObservationWriter - - -class TestRoundTrip(unittest.TestCase): - - TEST_FILE_SOURCE_DIR = '../caom2/test/data' - XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' - XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/pyCAOM2' - - def makeTestDir(self): - try: - os.makedirs(TestRoundTrip.XML_FILE_SOURCE_DIR) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise - - def copyFiles(self): - for filename in glob.glob(os.path.join(TestRoundTrip. - TEST_FILE_SOURCE_DIR, '*.xml')): - shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) - - def init(self): - self.makeTestDir() - self.copyFiles() - - def cleanup(self): - shutil.rmtree(TestRoundTrip.XML_FILE_SOURCE_DIR) - - def get_file_list(self): - return [f for f in os.listdir(TestRoundTrip.XML_FILE_SOURCE_DIR)\ - if f.endswith('.xml')] - - def do_test(self, reader, writer, filename): - sourceFilePath = (TestRoundTrip.XML_FILE_SOURCE_DIR + - '/' + filename) - print "test file: " + sourceFilePath - sourceXMLfp = open(sourceFilePath, 'r') - observation = reader.read(sourceFilePath) - sourceXMLfp.close() - destFilePath = TestRoundTrip.XML_FILE_DEST_DIR + '/' + filename - destXMLfp = open(destFilePath, 'w') - writer.write(observation, destXMLfp) - destXMLfp.close() - self.assertTrue(filecmp.cmp(sourceFilePath, destFilePath), - 'files are different, ' + - 'file from Java was: ' + sourceFilePath + ' ' - 'file from Python was: ' + destFilePath) - - # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 - # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 - # objects. The two XML files are then compared to ensure that they - # are the same. The test fails if the files are not the same. The - # test/data/*.xml files can be used in this test. - - def test_round_trip(self): - print "Test Round Trip" - - try: - self.init() - files = self.get_file_list() - self.assertTrue(len(files) > 0, 'No XML files in ' + - TestRoundTrip.XML_FILE_SOURCE_DIR) - try: - os.makedirs(TestRoundTrip.XML_FILE_DEST_DIR) - except OSError as e: - if e.errno != errno.EEXIST: - raise - - reader = ObservationReader(True) - writer20 = ObservationWriter(True, False, "caom2", caom2.xml.caom2_xml_constants.CAOM20_NAMESPACE) - writer21 = ObservationWriter(True, False, "caom2", caom2.xml.caom2_xml_constants.CAOM21_NAMESPACE) - writer22 = ObservationWriter(True, False, "caom2") - for filename in files: - if filename.endswith("CAOM-2.2.xml"): - self.do_test(reader, writer22, filename) - elif filename.endswith("CAOM-2.1.xml"): - self.do_test(reader, writer21, filename) - else: - self.do_test(reader, writer20, filename) - - #finally: - # self.cleanup() - except Exception as e: - #if e.errno != errno.EEXIST: - raise - -suite = unittest.TestLoader().loadTestsFromTestCase(TestRoundTrip) -unittest.TextTestRunner(verbosity=2).run(suite)