Metadata-Version: 2.4
Name: rms-opus
Version: 3.23.0
Summary: OPUS: the Outer Planets Unified Search tool for the PDS Ring-Moon Systems Node
Author-email: "Robert S. French" <rfrench@seti.org>
Maintainer-email: "Robert S. French" <rfrench@seti.org>
License: Apache-2.0
Project-URL: Homepage, https://github.com/SETI/rms-opus
Project-URL: Documentation, https://rms-opus.readthedocs.io/en/latest
Project-URL: Repository, https://github.com/SETI/rms-opus
Project-URL: Source, https://github.com/SETI/rms-opus
Project-URL: Issues, https://github.com/SETI/rms-opus/issues
Keywords: pds,planetary,astronomy,rings,search,opus
Classifier: Development Status :: 5 - Production/Stable
Classifier: Natural Language :: English
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: django<6,>=5.2
Requires-Dist: jinja2
Requires-Dist: markupsafe
Requires-Dist: mysqlclient
Requires-Dist: numpy>=1.26
Requires-Dist: pdfkit
Requires-Dist: pillow>=10.1
Requires-Dist: pyparsing
Requires-Dist: pytz
Requires-Dist: pyyaml>=6.0.1
Requires-Dist: qrcode
Requires-Dist: regex
Requires-Dist: requests
Requires-Dist: rms-julian>=3.0.2
Requires-Dist: rms-pdsfile>=1.0.0
Requires-Dist: rms-pdslogger
Requires-Dist: rms-pdstable
Requires-Dist: rms-translator
Provides-Extra: dev
Requires-Dist: rms-opus; extra == "dev"
Requires-Dist: coverage>=7.6; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: django-stubs[compatible-mypy]>=5.1; extra == "dev"
Requires-Dist: types-mysqlclient; extra == "dev"
Requires-Dist: types-requests; extra == "dev"
Requires-Dist: types-pytz; extra == "dev"
Requires-Dist: types-regex; extra == "dev"
Requires-Dist: types-qrcode; extra == "dev"
Requires-Dist: types-docutils; extra == "dev"
Requires-Dist: pymarkdownlnt>=0.9.35; extra == "dev"
Requires-Dist: pytest>=9.0.3; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: pytest-django>=4.5; extra == "dev"
Requires-Dist: pytest-xdist>=3.8.0; extra == "dev"
Requires-Dist: djangorestframework; extra == "dev"
Requires-Dist: ruff>=0.9; extra == "dev"
Requires-Dist: bandit[toml]>=1.8; extra == "dev"
Requires-Dist: pyroma>=4.2; extra == "dev"
Requires-Dist: vulture>=2.14; extra == "dev"
Requires-Dist: rms-opus[docs]; extra == "dev"
Provides-Extra: docs
Requires-Dist: myst-parser; extra == "docs"
Requires-Dist: sphinx>=7; extra == "docs"
Requires-Dist: sphinxcontrib-mermaid>=0.9.2; extra == "docs"
Requires-Dist: sphinx-rtd-theme; extra == "docs"
Dynamic: license-file

# rms-opus

| Release | Test Status | Documentation | Coverage |
| ------- | ----------- | ------------- | -------- |
| [![Release](https://img.shields.io/github/v/release/SETI/rms-opus?logo=github)](https://github.com/SETI/rms-opus/releases) [![Release date](https://img.shields.io/github/release-date/SETI/rms-opus)](https://github.com/SETI/rms-opus/releases) | [![Tests](https://img.shields.io/github/actions/workflow/status/SETI/rms-opus/run-tests.yml?branch=main&label=tests)](https://github.com/SETI/rms-opus/actions/workflows/run-tests.yml) [![Integration](https://img.shields.io/github/actions/workflow/status/SETI/rms-opus/run-integration.yml?branch=main&label=integration)](https://github.com/SETI/rms-opus/actions/workflows/run-integration.yml) | [![Documentation](https://img.shields.io/readthedocs/rms-opus/latest?logo=readthedocs)](https://rms-opus.readthedocs.io/en/latest/) | [![Code coverage](https://img.shields.io/codecov/c/github/SETI/rms-opus/main?logo=codecov)](https://codecov.io/gh/SETI/rms-opus) |

| PyPI | Python | Downloads | License |
| ---- | ------ | --------- | ------- |
| [![PyPI version](https://img.shields.io/pypi/v/rms-opus?logo=pypi&logoColor=white)](https://pypi.org/project/rms-opus) | [![Python versions](https://img.shields.io/pypi/pyversions/rms-opus?logo=python&logoColor=white)](https://pypi.org/project/rms-opus) | [![Downloads](https://img.shields.io/pypi/dm/rms-opus)](https://pypi.org/project/rms-opus) | [![License](https://img.shields.io/github/license/SETI/rms-opus)](https://github.com/SETI/rms-opus/blob/main/LICENSE) |

| Issues | Pull requests | Activity |
| ------ | ------------- | -------- |
| [![Open issues](https://img.shields.io/github/issues/SETI/rms-opus)](https://github.com/SETI/rms-opus/issues) [![Closed issues](https://img.shields.io/github/issues-closed/SETI/rms-opus)](https://github.com/SETI/rms-opus/issues?q=is%3Aissue+is%3Aclosed) | [![Open pull requests](https://img.shields.io/github/issues-pr/SETI/rms-opus)](https://github.com/SETI/rms-opus/pulls) [![Closed pull requests](https://img.shields.io/github/issues-pr-closed/SETI/rms-opus)](https://github.com/SETI/rms-opus/pulls?q=is%3Apr+is%3Aclosed) | [![Commit activity](https://img.shields.io/github/commit-activity/m/SETI/rms-opus)](https://github.com/SETI/rms-opus/commits) [![Last commit](https://img.shields.io/github/last-commit/SETI/rms-opus)](https://github.com/SETI/rms-opus/commits) |

<!-- start-after-point -->

## Introduction

OPUS is the Outer Planets Unified Search tool of the Ring-Moon Systems Node of NASA's
Planetary Data System. It lets a researcher search the Ring-Moon Systems Node's
archive by what an
observation *is* -- when it was taken, what instrument took it, what it was pointed at,
what ring or surface geometry it covers -- and then retrieve the matching data files.
A public instance runs at [opus.pds-rings.seti.org](https://opus.pds-rings.seti.org).

This distribution holds everything that instance is made of: the pipeline that reads
PDS3 volumes and PDS4 bundles and populates the search database, the Django application
that serves the web interface and the public API, and the log analyzer that reports on
how the site is used. It is published so that the Ring-Moon Systems Node can deploy
it and so that the
software behind a public archive is inspectable, not because OPUS is a library to build
on: the packages carry no API stability guarantees.

## Features

- **Search by metadata, not by file name** -- observation time, target, instrument,
  wavelength, ring and surface geometry, and hundreds of other fields.
- **A public HTTP API** returning JSON, CSV or HTML, documented in the
  [API guide](https://rms-opus.readthedocs.io/en/latest/api_guide.html), with stable
  per-observation identifiers meant to stay valid indefinitely.
- **An import pipeline** that reads PDS3 and PDS4 archives, computes every metadata
  field, and writes the whole database in one piece: nothing a run produces becomes
  visible until the run succeeds.
- **A schema-driven database** -- every table, column, search widget and tooltip comes
  from checked-in JSON, so adding a metadata field is a schema change rather than a
  migration.
- **A cart and bulk download**, building ZIP or TAR archives of the products a search
  selected.
- **A log analyzer** that turns Apache access logs into per-session reports of what
  users actually did.

## Installation

`rms-opus` requires **Python 3.12 or later** and **MySQL 8.0.19 or later**. It also
needs the MySQL client development headers, because its MySQL driver has no Linux
wheel and is compiled during the install:

```bash
sudo apt-get install pkg-config default-libmysqlclient-dev build-essential
```

Then:

```bash
pip install rms-opus
```

OPUS reads one TOML configuration file and has **no default location for it**: the
`OPUS_CONFIG` environment variable must name the file in the environment of every OPUS
process. The installation writes the template to start from, with a comment on every key:

```bash
opus_config_template                          # writes ./opus.toml.template
install -m 600 opus.toml.template opus.toml   # then fill in every <PLACEHOLDER>
export OPUS_CONFIG=$PWD/opus.toml
```

Running the import pipeline needs the PDS holdings mounted. `memcached` and its
`pymemcache` client are optional and are not installed by `pip install rms-opus` --
without them OPUS falls back to Django's per-process local-memory cache. The
[deployment guide](https://rms-opus.readthedocs.io/en/latest/user_guide_deployment.html)
covers both.

## Quick Start

Import a volume into a fresh database:

```bash
export OPUS_CONFIG=/path/to/opus.toml
opus_import --do-it-all COISS_2002
```

Serve the site against it, from a checkout:

```bash
python manage.py migrate     # Django's own tables; OPUS's come from the import
python manage.py runserver   # then open http://127.0.0.1:8000/opus/
```

From a `pip install` there is no `manage.py`; `opus_manage` is the same program, and
`OPUS_CONFIG` stays the only variable it needs:

```bash
opus_manage migrate
opus_manage runserver
```

Ask the public API how many Cassini ISS observations of Pan there are:

```bash
curl 'https://opus.pds-rings.seti.org/opus/api/meta/result_count.json?target=Pan&instrument=Cassini+ISS'
```

Summarize a day of access logs:

```bash
opus_log_analyzer --batch /var/log/apache2/access_log-2026-08-01
```

Each command has a `--help` describing the rest of its surface.

## Documentation

The full documentation is at
[rms-opus.readthedocs.io](https://rms-opus.readthedocs.io/en/latest/): the
[public web API guide](https://rms-opus.readthedocs.io/en/latest/api_guide.html) for
people querying an OPUS server, and the
[developer guide](https://rms-opus.readthedocs.io/en/latest/dev_guide.html) for people
working on OPUS itself.

To build it locally, install the docs extra and run Sphinx:

```bash
pip install -e ".[docs]"
cd docs && make html
```

## Contributing

See [CONTRIBUTING.md](https://github.com/SETI/rms-opus/blob/main/CONTRIBUTING.md),
and the [code of conduct](https://github.com/SETI/rms-opus/blob/main/docs/code_of_conduct.md)
it points at.

## License

Apache License 2.0. See [LICENSE](https://github.com/SETI/rms-opus/blob/main/LICENSE).

## Supported by BrowserStack

Thanks to BrowserStack for their support of this open-source project.

<a href="https://www.browserstack.com">
  <img src="https://raw.githubusercontent.com/SETI/rms-opus/main/browserstack-logo-600x315.png" alt="BrowserStack" width="250">
</a>
