linecat 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. linecat/__init__.py +8 -0
  2. linecat/__main__.py +5 -0
  3. linecat/app_info.py +20 -0
  4. linecat/builtin.py +103 -0
  5. linecat/catalog_window.py +605 -0
  6. linecat/cdms.py +392 -0
  7. linecat/convert_dialog.py +99 -0
  8. linecat/data/docs/CDMS.pdf +0 -0
  9. linecat/data/docs/general [CDMS classic documentation].pdf +0 -0
  10. linecat/data/icons/app_icon.png +0 -0
  11. linecat/data/icons/app_image.png +0 -0
  12. linecat/data/molecules/CH3OH/CH3OH, vt=0-2.pdf +0 -0
  13. linecat/data/molecules/CH3OH/CH3OH.svg +1 -0
  14. linecat/data/molecules/CH3OH/c032504-5Q.cat +38743 -0
  15. linecat/data/molecules/NH3/NH3, v=0.pdf +0 -0
  16. linecat/data/molecules/NH3/NH3.svg +1 -0
  17. linecat/data/molecules/NH3/c017506.cat +346 -0
  18. linecat/data/molecules/OH/OH, v=0.pdf +0 -0
  19. linecat/data/molecules/OH/OH, v=1.pdf +0 -0
  20. linecat/data/molecules/OH/OH, v=2.pdf +0 -0
  21. linecat/data/molecules/OH/OH.svg +1 -0
  22. linecat/data/molecules/OH/c017507.cat +1028 -0
  23. linecat/data/molecules/OH/c017508.cat +831 -0
  24. linecat/data/molecules/OH/c017509.cat +722 -0
  25. linecat/data/molecules/SiO/SiO, v=0-10.pdf +0 -0
  26. linecat/data/molecules/SiO/SiO.svg +1 -0
  27. linecat/data/molecules/SiO/c044505.cat +1190 -0
  28. linecat/data/user_guide.pdf +0 -0
  29. linecat/diagram/__init__.py +5 -0
  30. linecat/diagram/elements.py +255 -0
  31. linecat/diagram/latex_cache.py +92 -0
  32. linecat/diagram/tab.py +191 -0
  33. linecat/diagram/table.py +162 -0
  34. linecat/diagram/window.py +715 -0
  35. linecat/filters.py +337 -0
  36. linecat/headers.py +103 -0
  37. linecat/launcher.py +317 -0
  38. linecat/main.py +179 -0
  39. linecat/molecule_box.py +117 -0
  40. linecat/molecules.py +190 -0
  41. linecat/update.py +162 -0
  42. linecat/update_ui.py +301 -0
  43. linecat/widgets.py +192 -0
  44. linecat-0.9.0.dist-info/METADATA +171 -0
  45. linecat-0.9.0.dist-info/RECORD +49 -0
  46. linecat-0.9.0.dist-info/WHEEL +5 -0
  47. linecat-0.9.0.dist-info/entry_points.txt +2 -0
  48. linecat-0.9.0.dist-info/licenses/LICENSE +21 -0
  49. linecat-0.9.0.dist-info/top_level.txt +1 -0
linecat/__init__.py ADDED
@@ -0,0 +1,8 @@
1
+ """linecat: viewer for spectral line catalogs."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ try:
6
+ __version__ = version("linecat")
7
+ except PackageNotFoundError:
8
+ __version__ = "0.0.0"
linecat/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ """``python -m linecat``: the same as the ``linecat`` command (used by the app launcher)."""
2
+
3
+ from linecat.main import main
4
+
5
+ raise SystemExit(main())
linecat/app_info.py ADDED
@@ -0,0 +1,20 @@
1
+ """Names and addresses of the app, used by the window, the launcher and the update check."""
2
+
3
+ from linecat import __version__
4
+
5
+ APP_NAME = "Line Catalog Explorer"
6
+ """Name shown to the user (window, splash, launcher)."""
7
+
8
+ APP_VERSION = __version__
9
+ """Installed version (``0.0.0`` when linecat is not installed as a package)."""
10
+
11
+ DIST_NAME = "linecat"
12
+ """Name of the package on PyPI."""
13
+
14
+ GITHUB_REPO = "vahid-anari/linecat"
15
+ """GitHub repository (``owner/name``); its Releases hold the release notes."""
16
+
17
+ PYPI_URL = f"https://pypi.org/project/{DIST_NAME}/"
18
+ PYPI_JSON_URL = f"https://pypi.org/pypi/{DIST_NAME}/json"
19
+ RELEASES_URL = f"https://github.com/{GITHUB_REPO}/releases"
20
+ RELEASES_API_URL = f"https://api.github.com/repos/{GITHUB_REPO}/releases?per_page=30"
linecat/builtin.py ADDED
@@ -0,0 +1,103 @@
1
+ """Built-in catalogs: the CDMS sources shipped with linecat, converted once into a per-user folder.
2
+
3
+ The `.cat` files live in the package (`linecat/data/molecules/<SPECIES>/`, next to the species'
4
+ CDMS documentation PDFs and its picture). Their CSVs are written
5
+ read-only to the user's application-data folder (on macOS
6
+ `~/Library/Application Support/linecat/catalogs/`), next to a stamp file holding the linecat
7
+ version that built them. `ensure_builtin_catalogs` rebuilds them when a CSV is missing or the
8
+ stamp differs, so a new converter version regenerates them by itself.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import os
14
+ import stat
15
+ from pathlib import Path
16
+ from typing import Callable
17
+
18
+ from linecat import __version__
19
+ from linecat.cdms import ConversionResult, convert_molecule_catalog
20
+ from linecat.molecules import REGISTRY
21
+
22
+ DATA_DIR = Path(__file__).resolve().parent / "data"
23
+ SOURCES_DIR = DATA_DIR / "molecules" # one folder per species: .cat files, documentation PDFs, <SPECIES>.svg
24
+ DOCS_DIR = DATA_DIR / "docs" # general CDMS documentation
25
+ ICONS_DIR = DATA_DIR / "icons"
26
+ APP_ICON = ICONS_DIR / "app_icon.png" # made by tools/make_icon.py
27
+ APP_IMAGE = ICONS_DIR / "app_image.png" # splash picture, made by tools/make_splash.py
28
+ STAMP_NAME = ".linecat-version"
29
+
30
+
31
+ def molecule_image(species: str) -> Path | None:
32
+ """The species' picture (`<SPECIES>.svg` in its folder), if there is one."""
33
+ path = SOURCES_DIR / species / f"{species}.svg"
34
+ return path if path.is_file() else None
35
+
36
+
37
+ def molecule_docs(species: str) -> list[Path]:
38
+ """The CDMS documentation PDFs of the species' entries, sorted by name."""
39
+ folder = SOURCES_DIR / species
40
+ return sorted(folder.glob("*.pdf")) if folder.is_dir() else []
41
+
42
+
43
+ def general_docs() -> list[Path]:
44
+ """The general CDMS documentation PDFs, sorted by name."""
45
+ return sorted(DOCS_DIR.glob("*.pdf")) if DOCS_DIR.is_dir() else []
46
+
47
+
48
+ def user_guide() -> Path:
49
+ """The User Guide PDF (built by tools/build_docs.sh)."""
50
+ return DATA_DIR / "user_guide.pdf"
51
+
52
+
53
+ def builtin_dir() -> Path:
54
+ """Folder that holds the built-in CSV catalogs (created on demand)."""
55
+ from PySide6.QtCore import QStandardPaths
56
+
57
+ base = QStandardPaths.writableLocation(QStandardPaths.GenericDataLocation)
58
+ return Path(base) / "linecat" / "catalogs"
59
+
60
+
61
+ def builtin_csv(species: str, folder: Path | None = None) -> Path:
62
+ """Path of the built-in CSV of ``species``."""
63
+ return (folder or builtin_dir()) / f"CDMS_{REGISTRY[species].species}.csv"
64
+
65
+
66
+ def builtin_is_current(folder: Path | None = None) -> bool:
67
+ """True when every species' CSV exists and was built by this linecat version."""
68
+ folder = folder or builtin_dir()
69
+ stamp = folder / STAMP_NAME
70
+ if not stamp.is_file() or stamp.read_text().strip() != __version__:
71
+ return False
72
+ return all(builtin_csv(code, folder).is_file() for code in REGISTRY)
73
+
74
+
75
+ def _remove(path: Path) -> None:
76
+ if path.exists():
77
+ os.chmod(path, stat.S_IWUSR | stat.S_IRUSR)
78
+ path.unlink()
79
+
80
+
81
+ def ensure_builtin_catalogs(
82
+ folder: Path | None = None,
83
+ progress: Callable[[str, int, int], None] | None = None,
84
+ ) -> list[ConversionResult]:
85
+ """Build the built-in CSVs if any is missing or out of date; return what was built (empty if nothing).
86
+
87
+ `progress` is called with (species, rows done, rows total), as for `cdms.convert_all`.
88
+ """
89
+ folder = folder or builtin_dir()
90
+ if builtin_is_current(folder):
91
+ return []
92
+ folder.mkdir(parents=True, exist_ok=True)
93
+ _remove(folder / STAMP_NAME)
94
+ results = []
95
+ for code in REGISTRY:
96
+ target = builtin_csv(code, folder)
97
+ _remove(target)
98
+ callback = (lambda done, total, code=code: progress(code, done, total)) if progress is not None else None
99
+ result = convert_molecule_catalog(code, outdir=folder, catalogs_dir=SOURCES_DIR, progress=callback)
100
+ os.chmod(result.path, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) # read-only
101
+ results.append(result)
102
+ (folder / STAMP_NAME).write_text(__version__ + "\n")
103
+ return results