diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..0e2522dd
--- /dev/null
+++ b/.github/CODE_OF_CONDUCT.md
@@ -0,0 +1,46 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+- The use of sexualized language or imagery and unwelcome sexual attention or advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 00000000..b58b5b32
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1 @@
+See the following [contributing guide](../docs/contributing.md).
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..6c4b3695
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+version: 2
+updates:
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ groups:
+ actions:
+ patterns:
+ - "*"
diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 00000000..9d1e0987
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,5 @@
+changelog:
+ exclude:
+ authors:
+ - dependabot
+ - pre-commit-ci
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
new file mode 100644
index 00000000..79c2dbd1
--- /dev/null
+++ b/.github/workflows/cd.yml
@@ -0,0 +1,57 @@
+name: CD
+
+on:
+ workflow_dispatch:
+ pull_request:
+ push:
+ branches:
+ - main
+ release:
+ types:
+ - published
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ # Many color libraries just need this to be set to any value, but at least
+ # one distinguishes color depth, where "3" -> "256-bit color".
+ FORCE_COLOR: 3
+
+jobs:
+ dist:
+ name: Distribution build
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - uses: hynek/build-and-inspect-python-package@v2
+
+ publish:
+ needs: [dist]
+ name: Publish to PyPI
+ environment: pypi
+ permissions:
+ id-token: write
+ attestations: write
+ contents: read
+ runs-on: ubuntu-latest
+ if: github.event_name == 'release' && github.event.action == 'published'
+
+ steps:
+ - uses: actions/download-artifact@v4
+ with:
+ name: Packages
+ path: dist
+
+ - name: Generate artifact attestation for sdist and wheel
+ uses: actions/attest-build-provenance@v1.4.1
+ with:
+ subject-path: "dist/*"
+
+ - name: Publish to PyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..4cf39a99
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,61 @@
+name: CI
+
+on:
+ workflow_dispatch:
+ pull_request:
+ push:
+ branches:
+ - main
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+defaults:
+ run:
+ shell: bash -el {0}
+
+env:
+ # Many color libraries just need this to be set to any value, but at least
+ # one distinguishes color depth, where "3" -> "256-bit color".
+ FORCE_COLOR: 3
+
+jobs:
+ # pylint:
+ # name: Format
+ # runs-on: ubuntu-latest
+ # steps:
+ # - name: Run PyLint
+ # run: pipx run nox -s pylint -- --output-format=github
+
+ tests:
+ name: tests (${{ matrix.runs-on }} | Python ${{ matrix.python-version }})
+ runs-on: ${{ matrix.runs-on }}
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: ["3.10", "3.12"]
+ runs-on: [ubuntu-latest, windows-latest, macos-14]
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - uses: mamba-org/setup-micromamba@v1
+ with:
+ environment-name: ship
+ environment-file: environment.yml
+ create-args: >-
+ python=${{matrix.python-version}}
+
+ - run: pip install . --no-deps --no-build-isolation
+
+ - name: Test package
+ run: >-
+ python -m pytest -ra --cov --cov-report=xml --cov-report=term
+ --durations=20
+
+ - name: Upload coverage report
+ uses: codecov/codecov-action@v4.5.0
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/codetools.yml b/.github/workflows/codetools.yml
deleted file mode 100644
index 7027fec2..00000000
--- a/.github/workflows/codetools.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-name: ci
-
-on: [push, pull_request]
-
-env:
- PACKAGE: virtual_ship
- TESTS: tests
-
-jobs:
- codetools:
- runs-on: ubuntu-20.04
- strategy:
- matrix:
- python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5.1.0
- with:
- python-version: ${{ matrix.python-version }}
- - name: install
- run: pip install ".[dev]"
- - name: flake8
- run: flake8 ./$PACKAGE ./$TESTS
- - name: pydocstyle
- run: pydocstyle ./$PACKAGE
- - name: sort-all
- run: |
- find ./$PACKAGE -type f -name '__init__.py' -print0 | xargs -0 sort-all
- [[ -z $(git status -s) ]]
- git checkout -- .
- - name: black
- run: black --diff --check ./$PACKAGE ./$TESTS
- - name: isort
- run: isort --check-only --diff ./$PACKAGE ./$TESTS
-
- tests:
- runs-on: ubuntu-20.04
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5.1.0
- with:
- python-version: 3.12
- - name: install
- run: pip install ".[dev]"
- - name: run_tests
- run: pytest --cov=virtual_ship tests
diff --git a/.gitignore b/.gitignore
index 924a28fe..ca9a1bd7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,6 +81,7 @@ instance/
# Sphinx documentation
docs/_build/
+docs/api/
# PyBuilder
.pybuilder/
@@ -171,6 +172,6 @@ cython_debug/
#.idea/
# Auto generated by setuptools scm
-virtual_ship/_version_setup.py
+src/virtualship/_version_setup.py
.vscode/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..38daed3b
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,27 @@
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.6.0
+ hooks:
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ exclude: .*\.zarr/
+ - id: check-yaml
+ - id: check-ast
+ - id: check-json
+ types: [text]
+ files: \.(json|ipynb)$
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.6.5
+ hooks:
+ - id: ruff
+ args: [--fix, --show-fixes]
+ - id: ruff
+ name: ruff (isort jupyter)
+ args: [--select, I, --fix]
+ types_or: [jupyter]
+ - id: ruff-format
+ types_or: [python, jupyter]
+ - repo: https://github.com/rbubley/mirrors-prettier # Update mirror as official mirror is deprecated
+ rev: v3.3.3
+ hooks:
+ - id: prettier
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 00000000..8bbb0d95
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,16 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+version: 2
+
+build:
+ os: ubuntu-22.04
+ tools:
+ python: mambaforge-22.9
+ jobs:
+ pre_build:
+ - sphinx-build -b linkcheck docs/ _build/linkcheck
+ - sphinx-apidoc -o docs/api/ --module-first --no-toc --force src/virtualship
+
+conda:
+ environment: environment.yml
diff --git a/README.md b/README.md
index b78bfb6b..17846c1e 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,105 @@
-# Virtual_ship_classroom
-Emma's work for the MSc student material
-Please contact me at e.e.daniels1@uu.nl with any questions.
+
+
+
+
+
+
-This is a python tool that will allow students to virtually sample the ocean as if the measurements were coming from an actual oceanographic mission. At the moment we mimic ADCP, CTD, and simple underwaydata measurements and allow surface drifters and argo float deployments. We might add gliders and meteorological data in the future.
+
-### Requirements
-To use the material please create an environment called Parcels with the command
-`conda env create -f environment.yml
+---
-### Input data
-The scripts are written to work with A-grid ocean data, specifically that from CMEMS.
-Data can be downloaded with the download_data.py script. For now a different conda env is needed for downloading, see comments in the script.
+
+
+
+
Project Owner
+
Emma Daniels (e.e.daniels1@uu.nl)
+
+
+
+
Development status
+
Alpha
+
+
-### Sailing the ship
-Fill in the accompanying JSON file and run virtualship.py to start measuring. You can also use Sail_the_ship.ipynb
+
-### Ideas for improvements to be made
-- ACDP #bins instead of max_depth
-- bug when argo(/drifter?) deployed at final location? depth=(len(time))
-- documentation that ships sails great circle path
-- CTDs op land?
-- Argo's/drifters that collide with land. Chance to break?
\ No newline at end of file
+VirtualShipParcels is a command line simulator allowing students to plan and conduct a virtual research expedition, receiving measurements as if they were coming from actual oceanographic instruments including:
+
+- ADCP (for currents)
+- CTD (for conductivity, and temperature)
+- underwater measurements (salinity and temperature)
+- surface drifters
+- argo float deployments
+
+
+
+## Installation
+
+For a normal installation do:
+
+```bash
+conda create -n ship -c conda-forge virtualship
+conda activate ship
+```
+
+which creates an environment named `ship` with the latest version of `virtualship`. You can replace `ship` with any name you like.
+
+For a development installation, please follow the instructions detailed in the [contributing page](.github/CONTRIBUTING.md).
+
+## Usage
+
+```console
+$ virtualship --help
+Usage: virtualship [OPTIONS] COMMAND [ARGS]...
+
+Options:
+ --version Show the version and exit.
+ --help Show this message and exit.
+
+Commands:
+ fetch Download the relevant data specified in an expedition directory...
+ init Initialize a directory for a new expedition, with an example...
+ run Do the expedition.
+```
+
+```console
+$ virtualship init --help
+Usage: virtualship init [OPTIONS] PATH
+
+ Initialize a directory for a new expedition, with an example configuration.
+
+Options:
+ --help Show this message and exit.
+```
+
+```console
+
+$ virtualship fetch --help
+Usage: virtualship fetch [OPTIONS] PATH
+
+ Download the relevant data specified in an expedition directory (i.e., by
+ the expedition config).
+
+Options:
+ --help Show this message and exit.
+```
+
+```console
+$ virtualship run --help
+Usage: virtualship run [OPTIONS] PATH
+
+ Do the expedition.
+
+Options:
+ --help Show this message and exit.
+
+```
+
+For examples, see LINK_TO_TURORIALS.
+
+
+
+## Input data
+
+The scripts are written to work with [A-grid ocean data from the Copernicus Marine Service](https://data.marine.copernicus.eu/product/GLOBAL_ANALYSISFORECAST_PHY_001_024/description).
diff --git a/codetools.sh b/codetools.sh
deleted file mode 100755
index 8e0a4acc..00000000
--- a/codetools.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-
-# Runs all codetools and attempts to apply fixes wherever possible.
-# Not suitable for the CI as that should not make any changes.
-
-set -e
-
-# Set working directory to the directory of this script.
-cd "$(dirname "$0")"
-
-PACKAGE=virtual_ship
-TESTS=tests
-
-echo "--------------"
-echo "flake8"
-echo "--------------"
-flake8 ./$PACKAGE ./$TESTS
-# darglint is ran as a plugin for flake8.
-
-echo "--------------"
-echo "pydocstyle"
-echo "--------------"
-pydocstyle ./$PACKAGE ./$TESTS
-
-echo "--------------"
-echo "sort-all"
-echo "--------------"
-find ./$PACKAGE -type f -name '__init__.py' -print0 | xargs -0 sort-all
-
-echo "--------------"
-echo "black"
-echo "--------------"
-black ./$PACKAGE ./$TESTS
-
-echo "--------------"
-echo "isort"
-echo "--------------"
-isort ./$PACKAGE ./$TESTS
-
diff --git a/docs/_static/virtual_ship_logo.png b/docs/_static/virtual_ship_logo.png
new file mode 100644
index 00000000..23c68c32
Binary files /dev/null and b/docs/_static/virtual_ship_logo.png differ
diff --git a/docs/_static/virtual_ship_logo_inverted.png b/docs/_static/virtual_ship_logo_inverted.png
new file mode 100644
index 00000000..d3334a12
Binary files /dev/null and b/docs/_static/virtual_ship_logo_inverted.png differ
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 00000000..d9cfa43f
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,72 @@
+from __future__ import annotations
+
+import importlib.metadata
+from typing import Any
+
+project = "Virtual Ship Parcels"
+copyright = "2024, Emma Daniëls"
+author = "Emma Daniëls"
+version = release = importlib.metadata.version("virtualship")
+
+extensions = [
+ "myst_parser",
+ "nbsphinx",
+ "sphinx.ext.autodoc",
+ "sphinx.ext.intersphinx",
+ "sphinx.ext.mathjax",
+ "sphinx.ext.napoleon",
+ "sphinx_autodoc_typehints",
+ "sphinx_copybutton",
+]
+
+source_suffix = [".rst", ".md"]
+exclude_patterns = [
+ "_build",
+ "**.ipynb_checkpoints",
+ "Thumbs.db",
+ ".DS_Store",
+ ".env",
+ ".venv",
+]
+
+html_theme = "furo"
+
+html_theme_options: dict[str, Any] = {
+ "footer_icons": [
+ {
+ "name": "GitHub",
+ "url": "https://github.com/OceanParcels/virtualship",
+ "html": """
+
+ """,
+ "class": "",
+ },
+ ],
+ "source_repository": "https://github.com/OceanParcels/virtualship",
+ "source_branch": "main",
+ "source_directory": "docs/",
+}
+
+html_static_path = ["_static"]
+html_theme_options = {
+ "light_logo": "virtual_ship_logo.png",
+ "dark_logo": "virtual_ship_logo_inverted.png",
+ "sidebar_hide_name": True,
+}
+
+myst_enable_extensions = [
+ "colon_fence",
+]
+
+intersphinx_mapping = {
+ "python": ("https://docs.python.org/3", None),
+}
+
+nitpick_ignore = [
+ ("py:class", "_io.StringIO"),
+ ("py:class", "_io.BytesIO"),
+]
+
+always_document_param_types = True
diff --git a/docs/contributing.md b/docs/contributing.md
new file mode 100644
index 00000000..fe57599d
--- /dev/null
+++ b/docs/contributing.md
@@ -0,0 +1,54 @@
+# Contributing
+
+All contributions are welcome no matter your background or experience! We collaborate on GitHub using issues to track bugs, features, and discuss future development. We use pull requests to collaborate on changes to the codebase (and modifications to the tutorials).
+
+## For developers
+
+### Development installation
+
+We use `conda` to manage our development installation. Make sure you have `conda` installed by following [the instructions here](https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html) and then run the following commands:
+
+```bash
+conda create -n ship python=3.10
+conda activate ship
+conda env update --file environment.yml
+pip install -e . --no-deps --no-build-isolation
+```
+
+This creates an environment, and installs all the dependencies that you need for development, including:
+
+- core dependencies
+- development dependencies (e.g., for testing)
+- documentation dependencies
+
+then installs the package in editable mode.
+
+### Useful commands
+
+The following commands are useful for local development:
+
+- `pytest` to run tests
+- `pre-commit run --all-files` to run pre-commit checks
+- `pre-commit install` (optional) to install pre-commit hooks
+ - this means that every time you commit, pre-commit checks will run on the files you changed
+- `sphinx-autobuild docs docs/_build` to build and serve the documentation
+- `sphinx-apidoc -o docs/api/ --module-first --no-toc --force src/virtualship` (optional) to generate the API documentation
+- `sphinx-build -b linkcheck docs/ _build/linkcheck` to check for broken links in the documentation
+
+The running of these commands is useful for local development and quick iteration, but not _vital_ as they will be run automatically in the CI pipeline (`pre-commit` by pre-commit.ci, `pytest` by GitHub Actions, and `sphinx` by ReadTheDocs).
+
+## For maintainers
+
+### Release checklist
+
+- Go to GitHub, draft new release. Enter name of version and "create new tag" if it doesn't already exist. Click "Generate Release Notes". Currate release notes as needed. Look at a previous version release to match the format (title, header, section organisation etc.)
+- Go to [conda-forge/virtualship-feedstock](https://github.com/conda-forge/virtualship-feedstock), create a new issue (select the "Bot Commands" issue from the menu) with title `@conda-forge-admin, please update version`. This will prompt a build, otherwise there can be a delay in the build.
+ - Approve PR and merge on green
+- Check "publish to PyPI" workflow succeeded
+
+### Adding dependencies
+
+When adding a dependency, make sure to modify the following files where relevant:
+
+- `environment.yml` for core and development dependencies (important for the development environment, and CI)
+- `pyproject.toml` for core dependencies (important for the pypi package, this should propogate through automatically to `recipe/meta.yml` in the conda-forge feedstock)
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..63c04ec4
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,21 @@
+# Virtual Ship Parcels
+
+```{toctree}
+:maxdepth: 1
+:hidden:
+
+Home
+quickstart
+tutorials/index
+contributing
+```
+
+```{include} ../README.md
+:start-after:
+```
+
+## Indices and tables
+
+- {ref}`genindex`
+- {ref}`modindex`
+- {ref}`search`
diff --git a/docs/quickstart.md b/docs/quickstart.md
new file mode 100644
index 00000000..cc947599
--- /dev/null
+++ b/docs/quickstart.md
@@ -0,0 +1,5 @@
+# Quickstart
+
+```{note}
+We don't yet have a quickstart guide. Please refer to the tutorials. If you would like to work on a quickstart guide, please [open an Issue](https://github.com/OceanParcels/virtualship/issues/new) to discuss.
+```
diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md
new file mode 100644
index 00000000..2fb50d36
--- /dev/null
+++ b/docs/tutorials/index.md
@@ -0,0 +1,5 @@
+# Tutorials
+
+```{nbgallery}
+my_tutorial.ipynb
+```
diff --git a/docs/tutorials/my_tutorial.ipynb b/docs/tutorials/my_tutorial.ipynb
new file mode 100644
index 00000000..10167fd3
--- /dev/null
+++ b/docs/tutorials/my_tutorial.ipynb
@@ -0,0 +1,33 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Awesome Example Tutorial"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"Still a work in progress\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "ship",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python",
+ "version": "3.12.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/environment.yml b/environment.yml
new file mode 100644
index 00000000..14389240
--- /dev/null
+++ b/environment.yml
@@ -0,0 +1,33 @@
+name: ship
+channels:
+ - defaults
+ - conda-forge
+dependencies:
+ - click
+ - parcels >= 3, < 4
+ - pyproj >= 3, < 4
+ - sortedcontainers == 2.4.0
+ - opensimplex == 0.4.5
+ - numpy >=1, < 2
+ - pydantic >=2, <3
+
+ # linting
+ - pre-commit
+
+ # Testing
+ - pytest
+ - pytest-cov
+ - codecov
+ - seabird
+ - setuptools
+
+ # Docs
+ - sphinx>=7.0
+ - myst-parser>=0.13
+ - nbsphinx
+ - ipykernel
+ - pandoc
+ - sphinx-copybutton
+ - sphinx-autodoc-typehints
+ - furo
+ - sphinx-autobuild
diff --git a/meta.yaml b/meta.yaml
index 6073e7c7..21df09f1 100644
--- a/meta.yaml
+++ b/meta.yaml
@@ -1,17 +1,17 @@
package:
- name: virtual_ship
+ name: virtualship
version: 0.0.2
source:
- path: virtual_ship
+ path: virtualship
build:
entry_points:
- - do_expedition = virtual_ship.cli.do_expedition:main
+ - do_expedition = virtualship.cli.do_expedition:main
requirements:
run:
- - python >=3.8
+ - python >=3.10
- parcels >=3,<4
- pyproj >=3,<4
- sortedcontainers ==2.4.0
diff --git a/pyproject.toml b/pyproject.toml
index f585c3f7..e99c5b22 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -3,19 +3,19 @@ requires = ["setuptools >= 61.0", "setuptools_scm[toml]>=6.2"]
build-backend = "setuptools.build_meta"
[project]
-name = "virtual_ship"
+name = "virtualship"
description = "Code for the Virtual Ship Classroom, where Marine Scientists can combine Copernicus Marine Data with an OceanParcels ship to go on a virtual expedition."
readme = "README.md"
dynamic = ["version"]
authors = [{ name = "oceanparcels.org team" }]
-requires-python = ">=3.8"
+requires-python = ">=3.10"
license = { file = "LICENSE" }
classifiers = [
"Development Status :: 3 - Alpha",
"License :: OSI Approved :: MIT License",
+ "Programming Language :: Python",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.8",
- "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
@@ -25,6 +25,7 @@ classifiers = [
"Intended Audience :: Education",
]
dependencies = [
+ "click",
"parcels >= 3, < 4",
"pyproj >= 3, < 4",
"sortedcontainers == 2.4.0",
@@ -34,41 +35,71 @@ dependencies = [
]
[project.urls]
-homepage = "https://oceanparcels.org/"
-repository = "https://github.com/OceanParcels/Virtual_ship_classroom"
-tracker = "https://github.com/OceanParcels/Virtual_ship_classroom/issues"
+Homepage = "https://oceanparcels.org/" # TODO: Update this to just be repo?
+Repository = "https://github.com/OceanParcels/virtualship"
+"Bug Tracker" = "https://github.com/OceanParcels/virtualship/issues"
+Changelog = "https://github.com/OceanParcels/virtualship/releases"
+
+[tool.setuptools.packages.find]
+where = ["src"]
-[tool.setuptools]
-packages = ["virtual_ship"]
[tool.setuptools_scm]
-write_to = "virtual_ship/_version_setup.py"
+version_file = "src/virtualship/_version_setup.py"
local_scheme = "no-local-version"
-[project.optional-dependencies]
-dev = [
- "black == 24.4.0",
- "darglint == 1.8.1",
- "flake8 == 7.0.0",
- "Flake8-pyproject == 1.2.3",
- "isort == 5.13.2",
- "pydocstyle == 6.3.0",
- "sort-all == 1.2.0",
- "pytest == 8.2.0",
- "pytest-cov == 5.0.0",
- "codecov == 2.1.13",
- "seabird == 0.12.0",
- "setuptools == 70.0.0",
- "sortedcontainers-stubs == 2.4.2",
+[project.scripts]
+virtualship = "virtualship.cli.main:cli"
+
+
+[tool.pytest.ini_options]
+minversion = "6.0"
+addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"]
+xfail_strict = true
+filterwarnings = [
+ "error",
+ "default::DeprecationWarning",
+ "error::DeprecationWarning:virtualship",
+ "ignore:ParticleSet is empty.*:RuntimeWarning" # TODO: Probably should be ignored in the source code
+]
+log_cli_level = "INFO"
+testpaths = [
+ "tests",
]
-[project.scripts]
-do_expedition = "virtual_ship.cli.do_expedition:main"
-[tool.isort]
-profile = "black"
-skip_gitignore = true
+[tool.coverage]
+run.source = ["virtualship"]
+report.exclude_also = [
+ '\.\.\.',
+ 'if typing.TYPE_CHECKING:',
+]
+
+[tool.ruff.lint]
+exclude = ["*.ipynb"]
-[tool.flake8]
-extend-ignore = "E501" # Don't check line length.
-docstring_style = "sphinx" # Use sphinx docstring style for darglint plugin.
+select = [
+ "E", # Error
+ "F", # pyflakes
+ "I", # isort
+ "D", # pydocstyle
+ "DOC", # pydoclint
+ "B", # Bugbear
+ "UP", # pyupgrade
+ "ICN", # import conventions
+ "RUF", # ruff
+ "ISC001", # single-line-implicit-string-concatenation
+]
+ignore = [
+ # line too long (82 > 79 characters)
+ "E501",
+ # consider `[meta, header, *data]` instead of concatenation
+ "RUF005",
+ # multi-line-summary-first-line
+ "D212",
+ # one-blank-line-before-class
+ "D203",
+
+ # TODO: Remove later
+ "D100", "D103"
+]
diff --git a/scripts/download_data.py b/scripts/download_data.py
index d89edba8..d3034ee7 100644
--- a/scripts/download_data.py
+++ b/scripts/download_data.py
@@ -4,9 +4,10 @@
This is a very crude script, here just as long as we do not properly incorporate it into the library.
"""
-import copernicusmarine
import datetime
+import copernicusmarine
+
if __name__ == "__main__":
datadir = "input_data"
username = input("username: ")
diff --git a/virtual_ship/__init__.py b/src/virtualship/__init__.py
similarity index 55%
rename from virtual_ship/__init__.py
rename to src/virtualship/__init__.py
index 6e74f1c8..877fe4e1 100644
--- a/virtual_ship/__init__.py
+++ b/src/virtualship/__init__.py
@@ -1,9 +1,18 @@
"""Code for the Virtual Ship Classroom, where Marine Scientists can combine Copernicus Marine Data with an OceanParcels ship to go on a virtual expedition."""
+from importlib.metadata import version as _version
+
from .location import Location
from .spacetime import Spacetime
+try:
+ __version__ = _version("virtualship")
+except Exception:
+ # Local copy or not installed with setuptools
+ __version__ = "unknown"
+
__all__ = [
"Location",
"Spacetime",
+ "__version__",
]
diff --git a/virtual_ship/cli/__init__.py b/src/virtualship/cli/__init__.py
similarity index 100%
rename from virtual_ship/cli/__init__.py
rename to src/virtualship/cli/__init__.py
diff --git a/src/virtualship/cli/commands.py b/src/virtualship/cli/commands.py
new file mode 100644
index 00000000..0764bb3a
--- /dev/null
+++ b/src/virtualship/cli/commands.py
@@ -0,0 +1,40 @@
+from pathlib import Path
+
+import click
+
+from virtualship.expedition.do_expedition import do_expedition
+
+
+@click.command(
+ help="Initialize a directory for a new expedition, with an example configuration."
+)
+@click.argument(
+ "path",
+ type=click.Path(exists=False, file_okay=False, dir_okay=True),
+ # help="Expedition directory",
+)
+def init(path):
+ """Entrypoint for the tool."""
+ raise NotImplementedError("Not implemented yet.")
+
+
+@click.command(
+ help="Download the relevant data specified in an expedition directory (i.e., by the expedition config)."
+)
+@click.argument(
+ "path",
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, readable=True),
+)
+def fetch(path):
+ """Entrypoint for the tool."""
+ raise NotImplementedError("Not implemented yet.")
+
+
+@click.command(help="Do the expedition.")
+@click.argument(
+ "path",
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, readable=True),
+)
+def run(path):
+ """Entrypoint for the tool."""
+ do_expedition(Path(path))
diff --git a/src/virtualship/cli/main.py b/src/virtualship/cli/main.py
new file mode 100644
index 00000000..6d0aa258
--- /dev/null
+++ b/src/virtualship/cli/main.py
@@ -0,0 +1,17 @@
+import click
+
+from . import commands
+
+
+@click.group()
+@click.version_option()
+def cli():
+ pass
+
+
+cli.add_command(commands.init)
+cli.add_command(commands.fetch)
+cli.add_command(commands.run)
+
+if __name__ == "__main__":
+ cli()
diff --git a/virtual_ship/expedition/__init__.py b/src/virtualship/expedition/__init__.py
similarity index 100%
rename from virtual_ship/expedition/__init__.py
rename to src/virtualship/expedition/__init__.py
diff --git a/virtual_ship/expedition/checkpoint.py b/src/virtualship/expedition/checkpoint.py
similarity index 96%
rename from virtual_ship/expedition/checkpoint.py
rename to src/virtualship/expedition/checkpoint.py
index d3bb08a4..27a85657 100644
--- a/virtual_ship/expedition/checkpoint.py
+++ b/src/virtualship/expedition/checkpoint.py
@@ -46,6 +46,6 @@ def from_yaml(cls, file_path: str | Path) -> Checkpoint:
:param file_path: Path to the file to load from.
:returns: The checkpoint.
"""
- with open(file_path, "r") as file:
+ with open(file_path) as file:
data = yaml.safe_load(file)
return Checkpoint(**data)
diff --git a/virtual_ship/expedition/do_expedition.py b/src/virtualship/expedition/do_expedition.py
similarity index 100%
rename from virtual_ship/expedition/do_expedition.py
rename to src/virtualship/expedition/do_expedition.py
diff --git a/virtual_ship/expedition/expedition_cost.py b/src/virtualship/expedition/expedition_cost.py
similarity index 100%
rename from virtual_ship/expedition/expedition_cost.py
rename to src/virtualship/expedition/expedition_cost.py
diff --git a/virtual_ship/expedition/input_data.py b/src/virtualship/expedition/input_data.py
similarity index 100%
rename from virtual_ship/expedition/input_data.py
rename to src/virtualship/expedition/input_data.py
diff --git a/virtual_ship/expedition/instrument_type.py b/src/virtualship/expedition/instrument_type.py
similarity index 100%
rename from virtual_ship/expedition/instrument_type.py
rename to src/virtualship/expedition/instrument_type.py
diff --git a/virtual_ship/expedition/schedule.py b/src/virtualship/expedition/schedule.py
similarity index 95%
rename from virtual_ship/expedition/schedule.py
rename to src/virtualship/expedition/schedule.py
index a92ba55b..d3865483 100644
--- a/virtual_ship/expedition/schedule.py
+++ b/src/virtualship/expedition/schedule.py
@@ -39,6 +39,6 @@ def from_yaml(cls, file_path: str | Path) -> Schedule:
:param file_path: Path to the file to load from.
:returns: The schedule.
"""
- with open(file_path, "r") as file:
+ with open(file_path) as file:
data = yaml.safe_load(file)
return Schedule(**data)
diff --git a/virtual_ship/expedition/ship_config.py b/src/virtualship/expedition/ship_config.py
similarity index 99%
rename from virtual_ship/expedition/ship_config.py
rename to src/virtualship/expedition/ship_config.py
index 8e4564fc..73a040e6 100644
--- a/virtual_ship/expedition/ship_config.py
+++ b/src/virtualship/expedition/ship_config.py
@@ -151,6 +151,6 @@ def from_yaml(cls, file_path: str | Path) -> ShipConfig:
:param file_path: Path to the file to load from.
:returns: The config.
"""
- with open(file_path, "r") as file:
+ with open(file_path) as file:
data = yaml.safe_load(file)
return ShipConfig(**data)
diff --git a/virtual_ship/expedition/simulate_measurements.py b/src/virtualship/expedition/simulate_measurements.py
similarity index 100%
rename from virtual_ship/expedition/simulate_measurements.py
rename to src/virtualship/expedition/simulate_measurements.py
diff --git a/virtual_ship/expedition/simulate_schedule.py b/src/virtualship/expedition/simulate_schedule.py
similarity index 100%
rename from virtual_ship/expedition/simulate_schedule.py
rename to src/virtualship/expedition/simulate_schedule.py
diff --git a/virtual_ship/expedition/verify_schedule.py b/src/virtualship/expedition/verify_schedule.py
similarity index 97%
rename from virtual_ship/expedition/verify_schedule.py
rename to src/virtualship/expedition/verify_schedule.py
index 55c34587..fcc77217 100644
--- a/virtual_ship/expedition/verify_schedule.py
+++ b/src/virtualship/expedition/verify_schedule.py
@@ -1,5 +1,6 @@
"""verify_schedule function and supporting classes."""
+import itertools
from datetime import timedelta
import pyproj
@@ -38,10 +39,7 @@ def verify_schedule(
# check waypoint times are in ascending order
timed_waypoints = [wp for wp in schedule.waypoints if wp.time is not None]
if not all(
- [
- next.time >= cur.time
- for cur, next in zip(timed_waypoints, timed_waypoints[1:])
- ]
+ [next.time >= cur.time for cur, next in itertools.pairwise(timed_waypoints)]
):
raise PlanningError(
"Each waypoint should be timed after all previous waypoints"
@@ -90,7 +88,7 @@ def verify_schedule(
# check that ship will arrive on time at each waypoint (in case no unexpected event happen)
time = schedule.waypoints[0].time
for wp_i, (wp, wp_next) in enumerate(
- zip(schedule.waypoints, schedule.waypoints[1:])
+ zip(schedule.waypoints, schedule.waypoints[1:], strict=False)
):
if wp.instrument is InstrumentType.CTD:
time += timedelta(minutes=20)
diff --git a/virtual_ship/expedition/waypoint.py b/src/virtualship/expedition/waypoint.py
similarity index 100%
rename from virtual_ship/expedition/waypoint.py
rename to src/virtualship/expedition/waypoint.py
diff --git a/virtual_ship/instruments/__init__.py b/src/virtualship/instruments/__init__.py
similarity index 100%
rename from virtual_ship/instruments/__init__.py
rename to src/virtualship/instruments/__init__.py
diff --git a/virtual_ship/instruments/adcp.py b/src/virtualship/instruments/adcp.py
similarity index 97%
rename from virtual_ship/instruments/adcp.py
rename to src/virtualship/instruments/adcp.py
index bca4ab94..5563bdd2 100644
--- a/virtual_ship/instruments/adcp.py
+++ b/src/virtualship/instruments/adcp.py
@@ -1,7 +1,8 @@
"""ADCP instrument."""
+from pathlib import Path
+
import numpy as np
-import py
from parcels import FieldSet, ParticleSet, ScipyParticle, Variable
from ..spacetime import Spacetime
@@ -24,7 +25,7 @@ def _sample_velocity(particle, fieldset, time):
def simulate_adcp(
fieldset: FieldSet,
- out_path: str | py.path.LocalPath,
+ out_path: str | Path,
max_depth: float,
min_depth: float,
num_bins: int,
diff --git a/virtual_ship/instruments/argo_float.py b/src/virtualship/instruments/argo_float.py
similarity index 99%
rename from virtual_ship/instruments/argo_float.py
rename to src/virtualship/instruments/argo_float.py
index ad4a4871..91b1e752 100644
--- a/virtual_ship/instruments/argo_float.py
+++ b/src/virtualship/instruments/argo_float.py
@@ -3,9 +3,9 @@
import math
from dataclasses import dataclass
from datetime import datetime, timedelta
+from pathlib import Path
import numpy as np
-import py
from parcels import (
AdvectionRK4,
FieldSet,
@@ -117,7 +117,7 @@ def _check_error(particle, fieldset, time):
def simulate_argo_floats(
fieldset: FieldSet,
- out_path: str | py.path.LocalPath,
+ out_path: str | Path,
argo_floats: list[ArgoFloat],
outputdt: timedelta,
endtime: datetime | None,
diff --git a/virtual_ship/instruments/ctd.py b/src/virtualship/instruments/ctd.py
similarity index 98%
rename from virtual_ship/instruments/ctd.py
rename to src/virtualship/instruments/ctd.py
index 0d017fa7..6f76b408 100644
--- a/virtual_ship/instruments/ctd.py
+++ b/src/virtualship/instruments/ctd.py
@@ -2,9 +2,9 @@
from dataclasses import dataclass
from datetime import timedelta
+from pathlib import Path
import numpy as np
-import py
from parcels import FieldSet, JITParticle, ParticleSet, Variable
from ..spacetime import Spacetime
@@ -55,7 +55,7 @@ def _ctd_cast(particle, fieldset, time):
def simulate_ctd(
fieldset: FieldSet,
- out_path: str | py.path.LocalPath,
+ out_path: str | Path,
ctds: list[CTD],
outputdt: timedelta,
) -> None:
diff --git a/virtual_ship/instruments/drifter.py b/src/virtualship/instruments/drifter.py
similarity index 98%
rename from virtual_ship/instruments/drifter.py
rename to src/virtualship/instruments/drifter.py
index 7854d4cb..b4db3b9a 100644
--- a/virtual_ship/instruments/drifter.py
+++ b/src/virtualship/instruments/drifter.py
@@ -2,9 +2,9 @@
from dataclasses import dataclass
from datetime import datetime, timedelta
+from pathlib import Path
import numpy as np
-import py
from parcels import AdvectionRK4, FieldSet, JITParticle, ParticleSet, Variable
from ..spacetime import Spacetime
@@ -42,7 +42,7 @@ def _check_lifetime(particle, fieldset, time):
def simulate_drifters(
fieldset: FieldSet,
- out_path: str | py.path.LocalPath,
+ out_path: str | Path,
drifters: list[Drifter],
outputdt: timedelta,
dt: timedelta,
diff --git a/virtual_ship/instruments/ship_underwater_st.py b/src/virtualship/instruments/ship_underwater_st.py
similarity index 98%
rename from virtual_ship/instruments/ship_underwater_st.py
rename to src/virtualship/instruments/ship_underwater_st.py
index 3d2050d8..407055ad 100644
--- a/virtual_ship/instruments/ship_underwater_st.py
+++ b/src/virtualship/instruments/ship_underwater_st.py
@@ -1,7 +1,8 @@
"""Ship salinity and temperature."""
+from pathlib import Path
+
import numpy as np
-import py
from parcels import FieldSet, ParticleSet, ScipyParticle, Variable
from ..spacetime import Spacetime
@@ -28,7 +29,7 @@ def _sample_temperature(particle, fieldset, time):
def simulate_ship_underwater_st(
fieldset: FieldSet,
- out_path: str | py.path.LocalPath,
+ out_path: str | Path,
depth: float,
sample_points: list[Spacetime],
) -> None:
diff --git a/virtual_ship/location.py b/src/virtualship/location.py
similarity index 100%
rename from virtual_ship/location.py
rename to src/virtualship/location.py
diff --git a/virtual_ship/make_realistic/__init__.py b/src/virtualship/make_realistic/__init__.py
similarity index 100%
rename from virtual_ship/make_realistic/__init__.py
rename to src/virtualship/make_realistic/__init__.py
diff --git a/virtual_ship/make_realistic/adcp_make_realistic.py b/src/virtualship/make_realistic/adcp_make_realistic.py
similarity index 77%
rename from virtual_ship/make_realistic/adcp_make_realistic.py
rename to src/virtualship/make_realistic/adcp_make_realistic.py
index 69c24790..9dbcbea9 100644
--- a/virtual_ship/make_realistic/adcp_make_realistic.py
+++ b/src/virtualship/make_realistic/adcp_make_realistic.py
@@ -1,15 +1,16 @@
"""adcp_make_realistic function."""
+from pathlib import Path
+
import numpy as np
-import py
import xarray as xr
def adcp_make_realistic(
- zarr_path: str | py.path.LocalPath,
- out_dir: str | py.path.LocalPath,
+ zarr_path: str | Path,
+ out_dir: str | Path,
prefix: str,
-) -> py.path.LocalPath:
+) -> Path:
"""
Take simulated ADCP data, add noise, then save in (an inconvenient educational) CSV format.
@@ -30,11 +31,8 @@ def adcp_make_realistic(
all_us, all_vs = _add_noise(times, depths, all_us, all_vs)
csv = _to_csv(times, depths, lats, lons, all_us, all_vs)
- out_file = (
- out_dir.join(f"{prefix}.csv")
- if isinstance(out_dir, py.path.LocalPath)
- else f"{out_dir}/{prefix}.csv"
- )
+ out_file = Path(out_dir) / f"{prefix}.csv"
+
with open(out_file, "w") as out_cnv:
out_cnv.write(csv)
@@ -58,8 +56,10 @@ def _to_csv(
meta = "# depths (m): " + ",".join([str(d) for d in depths])
header = f"time,lat,lon,{','.join(['u' + str(n) + ',v' + str(n) for n in range(len(depths))])}"
data = [
- f"{str(time)},{lat},{lon},{','.join([str(u) + ',' + str(v) for u, v in zip(us, vs)])}"
- for time, lat, lon, us, vs in zip(times, lats, lons, all_us.T, all_vs.T)
+ f"{time!s},{lat},{lon},{','.join([str(u) + ',' + str(v) for u, v in zip(us, vs, strict=False)])}"
+ for time, lat, lon, us, vs in zip(
+ times, lats, lons, all_us.T, all_vs.T, strict=False
+ )
]
lines = [meta, header] + data
diff --git a/virtual_ship/make_realistic/ctd_make_realistic.py b/src/virtualship/make_realistic/ctd_make_realistic.py
similarity index 94%
rename from virtual_ship/make_realistic/ctd_make_realistic.py
rename to src/virtualship/make_realistic/ctd_make_realistic.py
index 8b7bee24..aeae2ab7 100644
--- a/virtual_ship/make_realistic/ctd_make_realistic.py
+++ b/src/virtualship/make_realistic/ctd_make_realistic.py
@@ -1,18 +1,18 @@
"""ctd_make_realistic function."""
import random
+from pathlib import Path
import numpy as np
import opensimplex
-import py
import xarray as xr
def ctd_make_realistic(
- zarr_path: str | py.path.LocalPath,
- out_dir: str | py.path.LocalPath,
+ zarr_path: str | Path,
+ out_dir: str | Path,
prefix: str,
-) -> list[py.path.LocalPath]:
+) -> list[Path]:
"""
Take simulated CTD data, add noise, then save in CNV format (1 file per CTD).
@@ -36,11 +36,8 @@ def ctd_make_realistic(
temperature = _add_temperature_noise(temperature, depth)
salinity = _add_salinity_noise(salinity, depth)
- out_file = (
- out_dir.join(f"{prefix}{ctd_i}.cnv")
- if isinstance(out_dir, py.path.LocalPath)
- else f"{out_dir}/{prefix}{ctd_i}.cnv"
- )
+ out_file = Path(out_dir) / f"{prefix}{ctd_i}.cnv"
+
files.append(out_file)
cnv = _to_cnv(
@@ -196,7 +193,15 @@ def _to_cnv(
rows = [
f"{_i_col(13 + 24 * n)}{_f_col(time + random_time_offset, 3)}{_f_col(lat, 5)}{_f_col(lon, 5)}{_f_col(-depth, 3)}{_f_col(temp, 4)}{_f_col(sal, 4)}"
for n, (time, temp, lat, lon, depth, sal) in enumerate(
- zip(times, temperatures, latitudes, longitudes, depths, salinities)
+ zip(
+ times,
+ temperatures,
+ latitudes,
+ longitudes,
+ depths,
+ salinities,
+ strict=False,
+ )
)
]
diff --git a/virtual_ship/spacetime.py b/src/virtualship/spacetime.py
similarity index 100%
rename from virtual_ship/spacetime.py
rename to src/virtualship/spacetime.py
diff --git a/tests.sh b/tests.sh
deleted file mode 100755
index a6203336..00000000
--- a/tests.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-# Runs the tests and creates a code coverage report.
-
-pytest --cov=virtual_ship --cov-report=html tests
diff --git a/tests/expedition/expedition_dir/schedule.yaml b/tests/expedition/expedition_dir/schedule.yaml
index 6d55f6c5..0db1d2af 100644
--- a/tests/expedition/expedition_dir/schedule.yaml
+++ b/tests/expedition/expedition_dir/schedule.yaml
@@ -1,16 +1,16 @@
waypoints:
-- instrument: CTD
- location:
- latitude: 0
- longitude: 0
- time: 2023-01-01 00:00:00
-- instrument: DRIFTER
- location:
- latitude: 0.01
- longitude: 0.01
- time: 2023-01-01 01:00:00
-- instrument: ARGO_FLOAT
- location:
- latitude: 0.02
- longitude: 0.02
- time: 2023-01-01 02:00:00
+ - instrument: CTD
+ location:
+ latitude: 0
+ longitude: 0
+ time: 2023-01-01 00:00:00
+ - instrument: DRIFTER
+ location:
+ latitude: 0.01
+ longitude: 0.01
+ time: 2023-01-01 01:00:00
+ - instrument: ARGO_FLOAT
+ location:
+ latitude: 0.02
+ longitude: 0.02
+ time: 2023-01-01 02:00:00
diff --git a/tests/expedition/test_do_expedition.py b/tests/expedition/test_do_expedition.py
index 11e6b862..055764af 100644
--- a/tests/expedition/test_do_expedition.py
+++ b/tests/expedition/test_do_expedition.py
@@ -1,6 +1,6 @@
from pytest import CaptureFixture
-from virtual_ship.expedition import do_expedition
+from virtualship.expedition import do_expedition
def test_do_expedition(capfd: CaptureFixture) -> None:
diff --git a/tests/expedition/test_schedule.py b/tests/expedition/test_schedule.py
index 37ee4a47..fd1ed959 100644
--- a/tests/expedition/test_schedule.py
+++ b/tests/expedition/test_schedule.py
@@ -1,12 +1,10 @@
from datetime import datetime, timedelta
-import py
+from virtualship import Location
+from virtualship.expedition import Schedule, Waypoint
-from virtual_ship import Location
-from virtual_ship.expedition import Schedule, Waypoint
-
-def test_schedule(tmpdir: py.path.LocalPath) -> None:
+def test_schedule(tmpdir) -> None:
out_path = tmpdir.join("schedule.yaml")
# arbitrary time for testing
diff --git a/tests/expedition/test_simulate_schedule.py b/tests/expedition/test_simulate_schedule.py
index e27fed3f..8f92c678 100644
--- a/tests/expedition/test_simulate_schedule.py
+++ b/tests/expedition/test_simulate_schedule.py
@@ -2,9 +2,9 @@
import pyproj
-from virtual_ship import Location
-from virtual_ship.expedition import Schedule, ShipConfig, Waypoint
-from virtual_ship.expedition.simulate_schedule import (
+from virtualship import Location
+from virtualship.expedition import Schedule, ShipConfig, Waypoint
+from virtualship.expedition.simulate_schedule import (
ScheduleOk,
ScheduleProblem,
simulate_schedule,
diff --git a/tests/instruments/test_adcp.py b/tests/instruments/test_adcp.py
index d119f3e2..118ac21f 100644
--- a/tests/instruments/test_adcp.py
+++ b/tests/instruments/test_adcp.py
@@ -3,15 +3,14 @@
import datetime
import numpy as np
-import py
import xarray as xr
from parcels import FieldSet
-from virtual_ship import Location, Spacetime
-from virtual_ship.instruments.adcp import simulate_adcp
+from virtualship import Location, Spacetime
+from virtualship.instruments.adcp import simulate_adcp
-def test_simulate_adcp(tmpdir: py.path.LocalPath) -> None:
+def test_simulate_adcp(tmpdir) -> None:
# maximum depth the ADCP can measure
MAX_DEPTH = -1000 # -1000
# minimum depth the ADCP can measure
diff --git a/tests/instruments/test_argo_float.py b/tests/instruments/test_argo_float.py
index b25e80e7..31aafe53 100644
--- a/tests/instruments/test_argo_float.py
+++ b/tests/instruments/test_argo_float.py
@@ -3,15 +3,14 @@
from datetime import datetime, timedelta
import numpy as np
-import py
import xarray as xr
from parcels import FieldSet
-from virtual_ship import Location, Spacetime
-from virtual_ship.instruments.argo_float import ArgoFloat, simulate_argo_floats
+from virtualship import Location, Spacetime
+from virtualship.instruments.argo_float import ArgoFloat, simulate_argo_floats
-def test_simulate_argo_floats(tmpdir: py.path.LocalPath) -> None:
+def test_simulate_argo_floats(tmpdir) -> None:
# arbitrary time offset for the dummy fieldset
base_time = datetime.strptime("1950-01-01", "%Y-%m-%d")
diff --git a/tests/instruments/test_ctd.py b/tests/instruments/test_ctd.py
index eab53bf2..12619edf 100644
--- a/tests/instruments/test_ctd.py
+++ b/tests/instruments/test_ctd.py
@@ -8,15 +8,14 @@
from datetime import timedelta
import numpy as np
-import py
import xarray as xr
from parcels import Field, FieldSet
-from virtual_ship import Location, Spacetime
-from virtual_ship.instruments.ctd import CTD, simulate_ctd
+from virtualship import Location, Spacetime
+from virtualship.instruments.ctd import CTD, simulate_ctd
-def test_simulate_ctds(tmpdir: py.path.LocalPath) -> None:
+def test_simulate_ctds(tmpdir) -> None:
# arbitrary time offset for the dummy fieldset
base_time = datetime.datetime.strptime("1950-01-01", "%Y-%m-%d")
diff --git a/tests/instruments/test_drifter.py b/tests/instruments/test_drifter.py
index b7e03d6b..b49b510b 100644
--- a/tests/instruments/test_drifter.py
+++ b/tests/instruments/test_drifter.py
@@ -4,15 +4,14 @@
from datetime import timedelta
import numpy as np
-import py
import xarray as xr
from parcels import FieldSet
-from virtual_ship import Location, Spacetime
-from virtual_ship.instruments.drifter import Drifter, simulate_drifters
+from virtualship import Location, Spacetime
+from virtualship.instruments.drifter import Drifter, simulate_drifters
-def test_simulate_drifters(tmpdir: py.path.LocalPath) -> None:
+def test_simulate_drifters(tmpdir) -> None:
# arbitrary time offset for the dummy fieldset
base_time = datetime.datetime.strptime("1950-01-01", "%Y-%m-%d")
diff --git a/tests/instruments/test_ship_underwater_st.py b/tests/instruments/test_ship_underwater_st.py
index 54b8bdf0..89a37227 100644
--- a/tests/instruments/test_ship_underwater_st.py
+++ b/tests/instruments/test_ship_underwater_st.py
@@ -3,15 +3,14 @@
import datetime
import numpy as np
-import py
import xarray as xr
from parcels import FieldSet
-from virtual_ship import Location, Spacetime
-from virtual_ship.instruments.ship_underwater_st import simulate_ship_underwater_st
+from virtualship import Location, Spacetime
+from virtualship.instruments.ship_underwater_st import simulate_ship_underwater_st
-def test_simulate_ship_underwater_st(tmpdir: py.path.LocalPath) -> None:
+def test_simulate_ship_underwater_st(tmpdir) -> None:
# depth at which the sampling will be done
DEPTH = -2
diff --git a/tests/make_realistic/test_adcp_make_realistic.py b/tests/make_realistic/test_adcp_make_realistic.py
index 4b23b660..d5635f15 100644
--- a/tests/make_realistic/test_adcp_make_realistic.py
+++ b/tests/make_realistic/test_adcp_make_realistic.py
@@ -1,16 +1,14 @@
import csv
-import py
+from virtualship.make_realistic import adcp_make_realistic
-from virtual_ship.make_realistic import adcp_make_realistic
-
-def test_adcp_make_realistic(tmpdir: py.path.LocalPath) -> None:
+def test_adcp_make_realistic(tmpdir) -> None:
# add noise and convert to CSV
file = adcp_make_realistic("adcp.zarr", out_dir=tmpdir, prefix="ADCP")
# check if CSV is ok and can be loaded
- with open(file, mode="r", newline="") as csvfile:
+ with open(file, newline="") as csvfile:
# ignore lines starting with #, we assume that's metadata or comments
reader = csv.reader(line for line in csvfile if not line.startswith("#"))
for _ in reader:
diff --git a/tests/make_realistic/test_ctd_make_realistic.py b/tests/make_realistic/test_ctd_make_realistic.py
index dc266d95..dc96393a 100644
--- a/tests/make_realistic/test_ctd_make_realistic.py
+++ b/tests/make_realistic/test_ctd_make_realistic.py
@@ -1,10 +1,9 @@
-import py
import seabird
-from virtual_ship.make_realistic import ctd_make_realistic
+from virtualship.make_realistic import ctd_make_realistic
-def test_ctd_make_realistic(tmpdir: py.path.LocalPath) -> None:
+def test_ctd_make_realistic(tmpdir) -> None:
# add noise and convert to cnv
files = ctd_make_realistic("ctd.zarr", out_dir=tmpdir, prefix="CTD_")
diff --git a/virtual_ship/cli/do_expedition.py b/virtual_ship/cli/do_expedition.py
deleted file mode 100644
index 868a1aa3..00000000
--- a/virtual_ship/cli/do_expedition.py
+++ /dev/null
@@ -1,30 +0,0 @@
-"""
-Command line interface tool for virtualship.expedition.do_expedition:do_expedition function.
-
-See --help for usage.
-"""
-
-import argparse
-from pathlib import Path
-
-from virtual_ship.expedition.do_expedition import do_expedition
-
-
-def main() -> None:
- """Entrypoint for the tool."""
- parser = argparse.ArgumentParser(
- prog="do_expedition",
- description="Perform an expedition based on a provided schedule.",
- )
- parser.add_argument(
- "dir",
- type=str,
- help="Directory for the expedition. This should contain all required configuration files, and the result will be saved here as well.",
- )
- args = parser.parse_args()
-
- do_expedition(Path(args.dir))
-
-
-if __name__ == "__main__":
- main()