diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 07c9cee..0000000 --- a/.coveragerc +++ /dev/null @@ -1,20 +0,0 @@ -[run] -cover_pylib = false -omit = - /home/travis/virtualenv/* - */site-packages/* - */bin/* - -[report] -exclude_lines = - pragma: no cover - def __repr__ - except RuntimeError - except NotImplementedError - except ImportError - except FileNotFoundError - except CalledProcessError - logging.warning - logging.error - logging.critical - if __name__ == .__main__.: \ No newline at end of file diff --git a/.flake8 b/.flake8 index 1fca636..dcef1b7 100644 --- a/.flake8 +++ b/.flake8 @@ -2,5 +2,3 @@ max-line-length = 132 ignore = E501,W504, W503 exclude = .git,__pycache__,.eggs/,doc/,docs/,build/,dist/,archive/ -per-file-ignores = - __init__.py:F401 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 44a9715..0000000 --- a/.gitattributes +++ /dev/null @@ -1,20 +0,0 @@ -.gitattributes text eol=lf -.gitignore text eol=lf -Makefile text eol=lf -*.yml text eol=lf -LICENSE text eol=lf -*.ipynb text eol=lf -*.txt text eol=lf -*.py text eol=lf -*.sh text eol=lf -*.c text eol=lf -*.cpp text eol=lf -*.f text eol=lf -*.f90 text eol=lf -*.for text eol=lf -*.md text eol=lf -*.rst text eol=lf -*.csv text eol=lf -*.m text eol=lf -*.grc text eol=lf -*.pas text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94f9c2e..ba3e3ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,35 +4,29 @@ on: push: paths: - "*.py" - pull_request: - paths: - - "*.py" + - ".github/workflows/ci.yml" jobs: - linux: - runs-on: ubuntu-latest + core: + + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + runs-on: ${{ matrix.os }} + steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v5 with: python-version: '3.x' + + - uses: actions/checkout@v4 + - run: pip install .[tests,lint] + - run: flake8 + - run: mypy - - run: pytest - working-directory: tests - integration: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [windows-latest, macos-latest] - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - run: pip install .[tests] - run: pytest - working-directory: tests diff --git a/.lgtm.yml b/.lgtm.yml deleted file mode 100644 index b06edf3..0000000 --- a/.lgtm.yml +++ /dev/null @@ -1,4 +0,0 @@ -extraction: - python: - python_setup: - version: 3 diff --git a/LoadMSPdata.py b/LoadMSPdata.py index f1c667f..019510a 100755 --- a/LoadMSPdata.py +++ b/LoadMSPdata.py @@ -4,14 +4,6 @@ import dmsp import dmsp.plots as dmp -try: - import seaborn as sns - - sns.set_context("talk", font_scale=1.25) - sns.set_style("ticks") -except ImportError: - pass - """ Note: elevation from North Horizon, so to get near magnetic zenith at Poker Flat we use elevation angles FROM NORTH of 95-110 degrees corresponding to symmetric about 77.5 elevation angle @@ -36,44 +28,36 @@ -r 0.5 1 3 is a starting point for 6300/4278 ratio """ - -def main(): - p = ArgumentParser( - description="reading Poker Flat Research Range Meridian Scanning Photometer" - ) - p.add_argument("ncfn", help="netCDF data file name to read") - p.add_argument("-t", "--tlim", help="time window to zoom plot in on", nargs=2) - p.add_argument( - "-e", "--elim", help="elevation limits to plot FROM NORTH HORIZON", nargs=2, type=float - ) - p.add_argument( - "-r", - "--ratlim", - help="min,mid,max of ratio plot colormap", - nargs=3, - type=float, - default=[0.5, 1, 3], - ) - p.add_argument("--wl", help="wavelengths to ratio [A]", nargs=2) - p.add_argument( - "--elfid", - help="elevation angles at which to place fiducials (for other camera)", - type=float, - nargs=2, - default=[], - ) - p.add_argument("-v", "--verbose", action="store_true") - p = p.parse_args() - - Intensity = dmsp.load(p.ncfn, p.tlim, p.elim) - dmp.plotmspspectra(Intensity, p.elfid) - # %% ratios - if p.wl: - ratio = Intensity[p.wl[0]] / Intensity[p.wl[1]] - dmp.plotratio(ratio, p.wl, Intensity, p.elfid, p.ratlim, p.verbose) - - show() - - -if __name__ == "__main__": - main() +p = ArgumentParser(description="reading Poker Flat Research Range Meridian Scanning Photometer") +p.add_argument("ncfn", help="netCDF data file name to read") +p.add_argument("-t", "--tlim", help="time window to zoom plot in on", nargs=2) +p.add_argument( + "-e", "--elim", help="elevation limits to plot FROM NORTH HORIZON", nargs=2, type=float +) +p.add_argument( + "-r", + "--ratlim", + help="min,mid,max of ratio plot colormap", + nargs=3, + type=float, + default=[0.5, 1, 3], +) +p.add_argument("--wl", help="wavelengths to ratio [A]", nargs=2) +p.add_argument( + "--elfid", + help="elevation angles at which to place fiducials (for other camera)", + type=float, + nargs=2, + default=[], +) +p.add_argument("-v", "--verbose", action="store_true") +a = p.parse_args() + +Intensity = dmsp.load(a.ncfn, a.tlim, a.elim) +dmp.plotmspspectra(Intensity, a.elfid) +# %% ratios +if a.wl: + ratio = Intensity[a.wl[0]] / Intensity[a.wl[1]] + dmp.plotratio(ratio, a.wl, Intensity, a.elfid, a.ratlim, a.verbose) + +show() diff --git a/README.md b/README.md index d46ae77..ccb204e 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,12 @@ # Digital Meridian Spectrometer [![image](https://zenodo.org/badge/DOI/10.5281/zenodo.167565.svg)](https://doi.org/10.5281/zenodo.167565) -[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/space-physics/digital-meridian-spectrometer.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/space-physics/digital-meridian-spectrometer/context:python) -![ci](https://github.com/space-physics/digital-meridian-spectrometer/workflows/ci/badge.svg) -[![PyPi version](https://img.shields.io/pypi/pyversions/dmsp.svg)](https://pypi.python.org/pypi/dmsp) -[![PyPi Download stats](http://pepy.tech/badge/dmsp)](http://pepy.tech/project/dmsp) +[![ci](https://github.com/space-physics/digital-meridian-spectrometer/actions/workflows/ci.yml/badge.svg)](https://github.com/space-physics/digital-meridian-spectrometer/actions/workflows/ci.yml) +[![PyPI Download stats](http://pepy.tech/badge/dmsp)](http://pepy.tech/project/dmsp) For Geophysical Institute's Poker Flat Digital Meridian Spectrometer, which uses NetCDF -![example of PF-DMSP data](tests/demo.png) +![example of PF-DMSP data](src/dmsp/tests/demo.png) This library is also usable from Matlab, as seen in `dmsp.m`. @@ -19,24 +17,15 @@ This library is also usable from Matlab, as seen in `dmsp.m`. * [other dates](http://optics.gi.alaska.edu/realtime/data/archive/PKR_MSP_X/) * FTP: ftp://optics.gi.alaska.edu/PKR/DMSP -## Install +Install: ```sh python -m pip install -e . ``` -### Matlab +[LoadMSPdata.py](./LoadMSPdata.py) creates many plots. -Matlab users need: - -* Matlab ≥ R2018b -* `dmsp` package installed into the [Python environment associated with Matlab](https://www.scivision.dev/matlab-python-user-module-import/#switching-python-version) - -## Usage - -`LoadMSPdata.py` creates many plots. - -Use as a Python module is like: +Use as a Python module: ```python import dmsp @@ -44,31 +33,4 @@ import dmsp dat = dmsp.load('~/data/myfile.PF') ``` -which returns [xarray.Dataset](http://xarray.pydata.org/en/stable/generated/xarray.Dataset.html) - -## Notes - -Graphically browse the files with the `ncview` program: - -```sh -apt install ncview -``` - -### Error: libnetcdf.so.7 - -if you get - -> ImportError: libnetcdf.so.7: cannot open shared object file: No such file or directory - -try: - -```sh -apt install libnetcdf-dev -python -m pip install netcdf4 -``` - -or - -```sh -conda install netcdf4 -``` +which returns [xarray.Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html) diff --git a/archive/.appveyor.yml b/archive/.appveyor.yml deleted file mode 100644 index d4d994d..0000000 --- a/archive/.appveyor.yml +++ /dev/null @@ -1,19 +0,0 @@ -image: -- Visual Studio 2017 -- Ubuntu1804 - -stack: python 3 - -environment: - PY_DIR: C:\Python37-x64 - -clone_depth: 25 - -build: off - -init: -- cmd: set PATH=%PY_DIR%;%PY_DIR%\Scripts;%PATH% - -install: pip install -e .[tests] - -test_script: pytest -rsv diff --git a/archive/.travis.yml b/archive/.travis.yml deleted file mode 100644 index eb0fcad..0000000 --- a/archive/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: python -group: travis_latest -dist: xenial - -git: - depth: 25 - quiet: true - -matrix: - include: - - os: linux - python: 3.6 - - os: linux - python: 3.7 - install: pip install -e .[tests,cov] - script: - - flake8 - - mypy . - after_success: - - pytest --cov - - coveralls -# - os: osx -# language: minimal -# install: pip3 install -e .[tests] -# - os: windows -# language: minimal -# before_install: -# - choco install python3 -# - export PATH="/c/Python37:/c/Python37/Scripts:$PATH" - -install: pip install -e .[tests] - -script: pytest -rsv diff --git a/dmsp/__init__.py b/dmsp/__init__.py deleted file mode 100644 index af5e1b7..0000000 --- a/dmsp/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -''' -Copyright 2020 Michael Hirsch, Ph.D. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -''' - -from .io import load diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index 9399dd5..0000000 --- a/mypy.ini +++ /dev/null @@ -1,12 +0,0 @@ -[mypy] -files = dmsp/ - -ignore_missing_imports = True -strict_optional = False -allow_redefinition = True -show_error_context = False -show_column_numbers = True -warn_unreachable = False - -[mypy-xarray] -follow_imports = skip diff --git a/pyproject.toml b/pyproject.toml index 7418137..82a3b5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,34 @@ [build-system] -requires = ["setuptools", "wheel"] +requires = ["setuptools>=61.0.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "dmsp" +description = "Load and plot UAF Geophysical Institute Digital Meridian Spectrometer data" +keywords = [ "aurora", "spectrograph" ] +classifiers = [ + "Development Status :: 4 - Beta", + "Environment :: Console", + "Intended Audience :: Science/Research", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering :: Atmospheric Science" +] +dependencies = ["netCDF4", "xarray", "numpy", "python-dateutil"] +requires-python = ">=3.8" +dynamic = ["version", "readme"] + +[tool.setuptools.dynamic] +readme = {file = ["README.md"], content-type = "text/markdown"} +version = {attr = "dmsp.__version__"} + +[project.optional-dependencies] +tests = ["pytest"] +lint = ["flake8", "flake8-bugbear", "flake8-builtins", "flake8-blind-except", "mypy", + "types-python-dateutil", "types-requests"] + +[tool.mypy] +files = ["src"] +ignore_missing_imports = true [tool.black] line-length = 99 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 3b2bd13..0000000 --- a/setup.cfg +++ /dev/null @@ -1,43 +0,0 @@ -[metadata] -name = dmsp -version = 0.6.0 -author = Michael Hirsch, Ph.D. -author_email = scivision@users.noreply.github.com -description = Load and plot UAF Geophysical Institute Digital Meridian Spectrometer data -url = https://github.com/space-physics/meridian-spectrometer-reader -keywords = - aurora - spectrograph -classifiers = - Development Status :: 4 - Beta - Environment :: Console - Intended Audience :: Science/Research - License :: OSI Approved :: MIT License - Programming Language :: Python :: 3 - Topic :: Scientific/Engineering :: Atmospheric Science -license_files = - LICENSE.txt -long_description = file: README.md -long_description_content_type = text/markdown - -[options] -python_requires = >= 3.6 -include_package_data = True -packages = find: -install_requires = - netCDF4 - xarray - numpy - python-dateutil - -[options.extras_require] -tests = - pytest -lint = - flake8 - flake8-bugbear - flake8-builtins - flake8-blind-except - mypy -plot = - matplotlib diff --git a/setup.py b/setup.py deleted file mode 100644 index c823345..0000000 --- a/setup.py +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env python -from setuptools import setup - -setup() diff --git a/src/dmsp/__init__.py b/src/dmsp/__init__.py new file mode 100644 index 0000000..0e32a5b --- /dev/null +++ b/src/dmsp/__init__.py @@ -0,0 +1,5 @@ +from .io import load + +__version__ = "1.0.0" + +__all__ = ["load"] diff --git a/dmsp/io.py b/src/dmsp/io.py similarity index 92% rename from dmsp/io.py rename to src/dmsp/io.py index 8edf5aa..0619e79 100644 --- a/dmsp/io.py +++ b/src/dmsp/io.py @@ -1,5 +1,7 @@ +from __future__ import annotations from pathlib import Path -from typing import Tuple +import typing + from netCDF4 import Dataset import xarray import numpy as np @@ -8,7 +10,9 @@ def load( - fn: Path, tlim: Tuple[datetime, datetime] = None, elevlim: Tuple[float, float] = None + fn: Path, + tlim: tuple[datetime, datetime] | None = None, + elevlim: tuple[float, float] | None = None, ) -> xarray.Dataset: """ This function works with 1983-2010 netCDF3 as well as 2011-present netCDF4 files. @@ -28,6 +32,8 @@ def load( secdayutc = f["Time"][:] # convert to datetimes -- need as ndarray for next line t = np.array([d0 + timedelta(seconds=int(s)) for s in secdayutc]) + + tind: typing.Any if tlim is not None and len(tlim) == 2: if isinstance(tlim[0], str): tlim = [parse(t) for t in tlim] @@ -39,6 +45,7 @@ def load( elevation is not stored anywhere in the data files... """ elv = np.arange(181.0) + elind: typing.Any if elevlim is not None and len(elevlim) == 2: elind = (elevlim[0] <= elv) & (elv <= elevlim[1]) else: diff --git a/dmsp/plots.py b/src/dmsp/plots.py similarity index 97% rename from dmsp/plots.py rename to src/dmsp/plots.py index 63509e9..e378d46 100644 --- a/dmsp/plots.py +++ b/src/dmsp/plots.py @@ -1,4 +1,6 @@ from datetime import datetime +import typing + import numpy as np import xarray from matplotlib.pyplot import figure @@ -109,7 +111,7 @@ def plotratio( ratio = ratio.T fg = figure(figsize=(20, 12)) - ax = fg.subplots(3, 1, sharex=True) + ax: typing.Any = fg.subplots(3, 1, sharex=True) spectrasubplot(dat, fg, ax[:2], elfid, True, [1e3, 1e4]) # FIXME make ratlim based @@ -149,7 +151,8 @@ def plotratio( nrow = nsub // ncol fg = figure() - axs = fg.subplots(nrow, ncol, sharey=True, sharex=True) + axs: typing.Any = fg.subplots(nrow, ncol, sharey=True, sharex=True) + for i, ax in enumerate(axs.ravel()): if i == nsub: break diff --git a/tests/PKR_SMSP_STD_20141011.NC b/src/dmsp/tests/PKR_SMSP_STD_20141011.NC similarity index 100% rename from tests/PKR_SMSP_STD_20141011.NC rename to src/dmsp/tests/PKR_SMSP_STD_20141011.NC diff --git a/tests/demo.png b/src/dmsp/tests/demo.png similarity index 100% rename from tests/demo.png rename to src/dmsp/tests/demo.png diff --git a/tests/test_mod.py b/src/dmsp/tests/test_mod.py similarity index 100% rename from tests/test_mod.py rename to src/dmsp/tests/test_mod.py diff --git a/dmsp/ticks.py b/src/dmsp/ticks.py similarity index 97% rename from dmsp/ticks.py rename to src/dmsp/ticks.py index 0065ea2..c30daf6 100644 --- a/dmsp/ticks.py +++ b/src/dmsp/ticks.py @@ -1,12 +1,15 @@ """These functions separated due to time-consuming imports""" + from datetime import timedelta + import numpy as np import xarray + from matplotlib.dates import DateFormatter from matplotlib.dates import MinuteLocator, SecondLocator -def tickfix(t, fg, ax, tfmt: str = "%H:%M:%S"): +def tickfix(t, fg, ax, tfmt: str = "%H:%M:%S") -> None: majtick, mintick = timeticks(t[-1] - t[0]) if majtick: ax.xaxis.set_major_locator(majtick)