Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
f27d4c2
ngmix update runs, with issues
Jan 9, 2023
b36b92b
still debugging ngmix
Jan 12, 2023
4ea9b42
Merge remote-tracking branch 'origin/develop' into ngmix_update
Jan 12, 2023
56e60ba
change T to r50
Jan 17, 2023
d86c88a
added r50 as galaxy guess option
Jan 17, 2023
52e411e
new version of ngmix produces output. not yet tested the quality
Jan 17, 2023
9b7c8d7
unfinished overhaul of ngmix module
lbaumo Oct 15, 2023
441797e
ngmix module overhaul
lbaumo Oct 15, 2023
2b34488
Merge branch 'CosmoStat:develop' into ngmix_update
lbaumo Oct 15, 2023
396035c
ngmix update psf stuff
lbaumo Oct 16, 2023
139ffae
ngmix module random numbers
lbaumo Oct 16, 2023
ccf6e1a
ngmix module new classes
lbaumo Oct 17, 2023
e09dc48
Merge branch 'ngmix_update' of https://github.com/lbaumo/shapepipe in…
lbaumo Oct 17, 2023
75ddcc8
more ngmix updates
lbaumo Oct 18, 2023
a98063a
ngmix update
lbaumo Oct 18, 2023
886e0db
Added ngmix test fitting script
Feb 2, 2026
8fd590c
docker install: leave extensions
Apr 25, 2026
621bab1
remove obsolete scripts
Apr 26, 2026
06934c9
keeping extension for shapepipe_run.py, updated workflow
Apr 26, 2026
883c4d6
Fixed Dockerfile
Apr 26, 2026
a662554
fix: add bin/ wrappers to git and fix pyproject.toml license format
Apr 26, 2026
ce6804d
fix: use ENV key=value format in Dockerfile
Apr 26, 2026
88f3fe3
fixed extensions of scripts
Apr 26, 2026
25d9238
added missing Git_cat cfg file
martinkilbinger Apr 27, 2026
8bcfe1f
modified Mh runner acfg
Apr 27, 2026
a9e70c6
going to job 512
Apr 28, 2026
a3eec86
added ID to Mh output
May 4, 2026
a813280
added ID to Mh output
May 4, 2026
5856b9f
v2.0 running up to job 256
May 4, 2026
adc2684
fixing log headers; weightwatcher exe
martinkilbinger May 5, 2026
f922f05
Merge remote-tracking branch 'upstream/develop' into ngmix_v2.0
martinkilbinger May 6, 2026
b0c6f31
improved job checks
May 6, 2026
7fccb0e
multi-epoch vignet handling for v2.0
May 6, 2026
546e628
Merge branch 'ngmix_v2.0' of github.com:martinkilbinger/shapepipe-1 i…
martinkilbinger May 6, 2026
8bd99d6
dell changes
martinkilbinger May 7, 2026
e500139
Merge remote-tracking branch 'origin/ngmix_v2.0' into ngmix_v2.0
martinkilbinger May 7, 2026
0686c55
Merge remote-tracking branch 'upstream/develop' into ngmix_v2.0
martinkilbinger May 7, 2026
12254cd
cleaned up cfg files; job 512 seems to be working using ; fixed some …
martinkilbinger May 7, 2026
bed3a50
running until ngmix call
martinkilbinger May 9, 2026
6839230
Merge remote-tracking branch 'remotes/origin/ngmix_update' into ngmix…
martinkilbinger May 9, 2026
d01503d
Update to ngmix v2.4;
martinkilbinger May 10, 2026
fd88094
Added Axel's centroid shift test scripy (py)
May 12, 2026
ceb4f91
Merge branch 'ngmix_v2.0' of github.com:martinkilbinger/shapepipe-1 i…
May 12, 2026
7e00cfd
debugging ngmix and small nb of processed objects
martinkilbinger May 12, 2026
eba7ece
Merge branch 'ngmix_v2.0' of github.com:martinkilbinger/shapepipe-1 i…
martinkilbinger May 12, 2026
b729eb8
adapting centroid shift script to v2.0
May 13, 2026
9f4170d
Add centroid bias validation infrastructure from test_centroid_bug
May 13, 2026
7f3d172
Merge remote-tracking branch 'origin/ngmix_v2.0' into ngmix_v2.0
martinkilbinger May 14, 2026
bd12880
testing centroid bug and fix with three different setting (bug, fix, …
May 15, 2026
440f822
centroid bug fixed for v2.0
May 16, 2026
0f52921
fixed pyproject for Docker deployment
May 16, 2026
3a70fdf
fixing versions in docker
May 16, 2026
77054bb
Merge remote-tracking branch 'origin/ngmix_v2.0' into ngmix_v2.0
martinkilbinger May 18, 2026
60962ff
fixing bugs in ngmix
martinkilbinger May 20, 2026
30181ff
Merge remote-tracking branch 'origin/ngmix_v2.0' into ngmix_v2.0
martinkilbinger May 20, 2026
d146cae
fixed merge errors
martinkilbinger May 21, 2026
67079de
debugged ngmix
martinkilbinger May 22, 2026
00525c4
Merge develop into ngmix_v2.0
cailmdaley Jun 1, 2026
22f1f0a
fix(ngmix): thread seeded rng through noise-image generation
cailmdaley Jun 2, 2026
5cdb1bb
test: smoke-import the shipped ngmix-v2.0 validation scripts
cailmdaley Jun 2, 2026
dd4f656
remove stranded v1 centroid_bias.py from ngmix_v2.0
cailmdaley Jun 2, 2026
bd60dc8
cleanup(ngmix): drop dead code flagged in v2.0 review
cailmdaley Jun 5, 2026
e455127
Merge branch 'develop' into ngmix_v2.0
cailmdaley Jun 8, 2026
d6531b1
fix(ngmix): emit true half-light radii in r50 columns; dedupe PSF siz…
cailmdaley Jun 10, 2026
6ddea5b
fix(ngmix): restore weight mask binarization
cailmdaley Jun 6, 2026
f466c98
feat(ngmix): support background-rms weights
cailmdaley Jun 6, 2026
7a44abd
config(ngmix): wire background-rms vignets
cailmdaley Jun 6, 2026
f79de46
test(ngmix): guard optional rms vignet input
cailmdaley Jun 6, 2026
4aa3b2a
fix(ngmix): zero fallback weights for degenerate constant stamps
cailmdaley Jun 10, 2026
158986a
test(ngmix): pin spatially-varying RMS through the observation chain
cailmdaley Jun 10, 2026
0df6bf6
test: prune deleted fitting.py from validation-script smoke list
cailmdaley Jun 10, 2026
0bc6016
docs(example): state BKG_RMS_VIGNET_PATH all-or-nothing semantics
cailmdaley Jun 10, 2026
b1b4970
Merge remote-tracking branch 'origin/ngmix_v2.0' into fix/ngmix-size-…
cailmdaley Jun 11, 2026
42cdb35
Merge pull request #743 from CosmoStat/fix/ngmix-size-columns
cailmdaley Jun 11, 2026
16789eb
config(example): drop removed CHECK_EXISTING_DIR from ngmix template
cailmdaley Jun 11, 2026
d4ada3d
fix(sextractor): declare positional WCS input in runner decorator
cailmdaley Jun 11, 2026
b2dcd79
docs(ngmix): drop stale LOG_WCS option; headers input is positional
cailmdaley Jun 11, 2026
fcd117f
fix(sextractor): skip TILE_ID metadata key when sizing the CCD scan
cailmdaley Jun 11, 2026
450f3c1
fix(ngmix): NaN-fill failed fit types in compile_results
cailmdaley Jun 11, 2026
00e9f89
fix(ngmix): skip failed-PSF epochs in multiepoch PSF average
cailmdaley Jun 11, 2026
7a1b3b1
fix(ngmix): restore mcal_flags as OR of per-type fit flags
cailmdaley Jun 11, 2026
3eb6a66
fix(example): migrate configs to positional WCS-headers input
cailmdaley Jun 11, 2026
436bcc8
fix(ngmix): rename ntry_fit column to nfev_fit
cailmdaley Jun 11, 2026
05f1584
chore(ngmix): drop dead copyfile import and unused Tile_cat columns
cailmdaley Jun 11, 2026
ceeb62d
removed obsolete cfis_simu directory; superceded by cfis_image_sims (…
martinkilbinger Jun 11, 2026
ff612b7
removed obsolete config file
martinkilbinger Jun 11, 2026
061ca3c
Merge develop into ngmix_v2.0: #737 + #742; uv.lock regenerated
cailmdaley Jun 11, 2026
6f4901b
fix(example): explicit FILE_EXT in config_exp_psfex.ini
cailmdaley Jun 11, 2026
0433a36
fix(example): Ng templates point BKG_RMS_VIGNET_PATH at surviving pro…
cailmdaley Jun 11, 2026
bb93c28
fix(ngmix): per-pixel fixnoise noise image in the background-RMS branch
cailmdaley Jun 11, 2026
c5a9cc4
test(ngmix): galsim noise-injection validation of background-RMS weights
cailmdaley Jun 11, 2026
6bae2a4
test(ngmix): tighten validation docstrings per review (ratio-test sco…
cailmdaley Jun 11, 2026
519a786
fix(run): only import mpi4py when an MPI launcher is present
cailmdaley Jun 11, 2026
dab2d5c
fix(run): review nits — module_dep self-append, surface test stderr
cailmdaley Jun 11, 2026
6b30fd4
Merge fix/lazy-mpi-init into ngmix_v2.0 (#744)
cailmdaley Jun 11, 2026
c23ea84
refactor(run): replace -e/--exclusive flag with NUMBER_LIST (#746)
cailmdaley Jun 11, 2026
e9473a0
fix(scripts): fail fast if NUMBER_LIST cannot be set; dead -e guard
cailmdaley Jun 11, 2026
5a51dd6
Merge pull request #748 from CosmoStat/refactor/number-list-replaces-…
cailmdaley Jun 11, 2026
6eb99aa
test: candide-aware pytest architecture + two scientific guardrails
cailmdaley Jun 12, 2026
71f217b
test: consolidate the suite under one discovery root
cailmdaley Jun 12, 2026
0ee0e94
feat(ngmix): make the Jacobian centroid source configurable (hsm | wcs)
cailmdaley Jun 12, 2026
f912d08
ci: fast-test workflow on push and PR
cailmdaley Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/fast-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Fast tests

# The fast inner-loop signal: the `tests/` suite minus the heavy and
# cluster-only tiers (`-m "not slow and not candide"`), run on every push and
# pull request. This is the quick gate that complements — does not replace —
# `deploy-image.yml`, which builds the dev image and runs the *full* suite
# inside it (the environment that ships). This job skips the Docker build, so
# it returns in a couple of minutes instead of waiting on the image.
#
# Environment is reproduced from `uv.lock` (the repo's single source of pinned
# versions) with `uv sync --frozen`, so CI installs exactly what a developer's
# `.venv` does — no parallel pin set. Tests that need the astromatic binaries
# (Source Extractor, PSFEx) self-skip via `shutil.which`, so they simply don't
# run here; the dev-image CI exercises them.
on:
push:
branches:
- '**'
pull_request:
workflow_dispatch:

# A newer push to the same ref cancels an in-flight run — the fast loop only
# cares about the latest commit.
concurrency:
group: fast-tests-${{ github.ref }}
cancel-in-progress: true

jobs:
fast-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

# uv is the project's package manager; pin the Python it provisions to the
# `requires-python` floor (3.12) so CI matches the container.
- name: Set up uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
python-version: "3.12"
enable-cache: true

# `--frozen` installs the exact versions in uv.lock (incl. the pinned
# ngmix git source) — no resolution, no drift from what ships.
- name: Install (test extra, from lockfile)
run: uv sync --frozen --extra test

# The fast tier: everything under the single `tests/` root except `slow`
# and `candide`. Coverage gates are dropped here (this job is about speed,
# not the coverage report) and the deterministic Hypothesis profile is
# pinned, matching the dev-image CI step.
- name: Run fast suite
env:
HYPOTHESIS_PROFILE: ci
SHAPEPIPE_ON_CANDIDE: "0"
run: >-
uv run --frozen
pytest -m "not slow and not candide"
-o addopts="--strict-markers"
-rs
5 changes: 4 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ Full detail: `docs/source/installation.md` and `docs/source/container.md`.
I/O; `utilities/`; `canfar/` is CANFAR/cluster job orchestration. Console entry
points (`shapepipe_run`, `summary_run`, `canfar_*`) are defined under
`[project.scripts]`.
- `src/shapepipe/tests/` — unit tests; `tests/unit/` holds newer test scaffolding.
- `tests/` — the whole test suite, one discovery root: `module/` (per-module
unit/property/integration tests), `unit/` (structural), `science/` (fast
guardrails), `cluster/` (candide-only), `helpers/` (shared library code).
See `tests/README.md`.
- `example/` — a runnable example pipeline (`example/config.ini`) on a single
CFIS tile; doubles as the CI smoke test.
- `scripts/` — shell / Python / notebook helpers (`sh/`, `python/`, `jupyter/`),
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.jupyter
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Dockerfile for ShapePipe Jupyter Lab
# Uses the shared base image

FROM ghcr.io/cosmostat/shapepipe:v2.0
FROM ghcr.io/cosmostat/shapepipe:develop

# Default command starts Jupyter Lab
ENTRYPOINT ["jupyter","lab","--ip=0.0.0.0","--port=8888","--no-browser","--allow-root"]
3 changes: 3 additions & 0 deletions bin/canfar_monitor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env python
from shapepipe.canfar_run import run_log
run_log()
3 changes: 3 additions & 0 deletions bin/canfar_monitor_log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env python
from shapepipe.canfar_run import run_monitor_log
run_monitor_log()
3 changes: 3 additions & 0 deletions bin/canfar_submit_job.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env python
from shapepipe.canfar_run import run_job
run_job()
3 changes: 3 additions & 0 deletions bin/shapepipe_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env python
from shapepipe.shapepipe_run import main
main()
3 changes: 3 additions & 0 deletions bin/summary_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env python
from shapepipe.summary_run import main
main()
98 changes: 97 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,106 @@
"""Shared pytest configuration for the ShapePipe test suite."""
"""Shared pytest configuration for the ShapePipe test suite.

Markers, environment detection, and the candide skip policy live here so
every test module — wherever it sits in the tree — sees the same rules.

Markers (also declared in ``pyproject.toml`` so ``--strict-markers`` is on):

* ``slow`` — heavy compute (minutes), not part of the fast inner loop.
* ``candide`` — needs the candide cluster and/or its real on-disk data;
meaningless (and auto-skipped) anywhere else.

A ``candide``-marked test only runs on a candide node. Everywhere else it
is skipped with a clear reason, so the same suite is green on a laptop, in
CI, and on the cluster — the cluster-only tests simply do not fire off it.
"""

import os
import re
import socket

import pytest

from hypothesis import settings


settings.register_profile("ci", derandomize=True, max_examples=50)
settings.register_profile("dev", max_examples=200)
settings.load_profile(os.environ.get("HYPOTHESIS_PROFILE", "ci"))


# --------------------------------------------------------------------------- #
# Candide detection
# --------------------------------------------------------------------------- #

# Candide compute / login nodes are named c01, c03, n22..n36, etc. The login
# host this suite is most often driven from is ``c03``. We match the candide
# node-name families rather than a fixed list so new nodes are covered, and
# allow an explicit override for CI or odd hostnames.
_CANDIDE_HOST_RE = re.compile(r"^(c\d|n\d{2})", re.IGNORECASE)


def on_candide():
"""Return True when running on a candide node.

The check is, in order: an explicit ``SHAPEPIPE_ON_CANDIDE`` override
(``1``/``0``), then the hostname against the candide node-name families
(``c0x`` login, ``nXX`` compute). Cheap, import-safe, no cluster calls.
"""
override = os.environ.get("SHAPEPIPE_ON_CANDIDE")
if override is not None:
return override == "1"
return bool(_CANDIDE_HOST_RE.match(socket.gethostname()))


# --------------------------------------------------------------------------- #
# Marker registration + skip policy
# --------------------------------------------------------------------------- #


def pytest_configure(config):
config.addinivalue_line(
"markers",
"slow: heavy compute (minutes); excluded from the fast inner loop.",
)
config.addinivalue_line(
"markers",
"candide: needs the candide cluster and/or its real data; "
"auto-skipped elsewhere.",
)


def pytest_collection_modifyitems(config, items):
"""Skip ``candide`` tests off-cluster.

Collection still happens everywhere — so ``pytest --collect-only`` shows
the cluster tests exist — they are just marked skipped at run time when
not on candide.
"""
if on_candide():
return
skip_candide = pytest.mark.skip(
reason="needs candide (set SHAPEPIPE_ON_CANDIDE=1 to force)"
)
for item in items:
if "candide" in item.keywords:
item.add_marker(skip_candide)


# --------------------------------------------------------------------------- #
# Shared fixtures
# --------------------------------------------------------------------------- #


@pytest.fixture(scope="session")
def artifacts_dir():
"""Directory where guardrail tests drop plots + status summaries.

The artifacts SEAM: a later GitHub Pages / status step publishes from
here. Created on demand so a clean checkout has nothing to commit until
a test actually emits.
"""
from pathlib import Path

path = Path(__file__).parent / "tests" / "_artifacts"
path.mkdir(parents=True, exist_ok=True)
return path
5 changes: 4 additions & 1 deletion docs/source/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ The following options can be added to the `[FILE]` section of the config file
(*e.g.* `.`, `-`, `:`, *etc.*). *optional*ly a regular expression can also be
passed if it is preceded by `RE:` (*e.g.* `RE:-\d{9}`).
- `NUMBER_LIST` : (`str` or `list`, *optional*) A list of number strings
matching the numbering scheme or a file name.
matching the numbering scheme or a file name. Restricts the run to these
numbers; every entry must match an input file found on disk, otherwise the
run fails at start-up. This is also how a single image is processed per
job (formerly the `-e`/`--exclusive` command-line flag).
- `CORRECT_FILE_PATTERN` : (`bool`, *optional*) Option to allow substring file
patterns. Default value is `True`.

Expand Down
22 changes: 13 additions & 9 deletions docs/source/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,26 @@ the bundled example pipeline.

## The automated test suite

The test suite runs with [pytest](https://docs.pytest.org/) and lives in two
trees:
The test suite runs with [pytest](https://docs.pytest.org/) under a single
discovery root, `tests/`, with one tier per subdirectory:

- `tests/unit/` — **structural** tests, one parametrized case per file: every
shell script parses (`bash -n`), every example config parses, every
`shapepipe.*` submodule imports, every `[project.scripts]` entry handles
`-h`, and every `*_runner.py` carries its `@module_runner` metadata. Cheap,
broad, and good at catching the dumb-but-real regressions (a syntax error, a
broken import, a renamed entry point).
- `src/shapepipe/tests/` — **unit, property-based, and integration** tests for
- `tests/module/` — **unit, property-based, and integration** tests for
the analytic surface: pure helpers and geometry (coordinate round-trips,
postage-stamp shapes, the MegaCam CCD flip), tested both by example and with
[Hypothesis](https://hypothesis.readthedocs.io/) property tests where a
function has a clear invariant. Integration tests that need the astromatic
binaries (Source Extractor, PSFEx) build synthetic FITS on the fly rather
than requiring survey data.
- `tests/unit/` — **structural** tests, one parametrized case per file: every
shell script parses (`bash -n`), every example config parses, every
`shapepipe.*` submodule imports, every `[project.scripts]` entry handles
`-h`, and every `*_runner.py` carries its `@module_runner` metadata. Cheap,
broad, and good at catching the dumb-but-real regressions (a syntax error, a
broken import, a renamed entry point).
- `tests/science/` — **fast scientific guardrails** (controlled simulations
with a known answer) and `tests/cluster/` — **candide guardrails** that read
real on-disk catalogs; the latter are marked `candide` and auto-skip off the
cluster. See `tests/README.md` for the full layout and markers.

**CI is the single gate.** On every pull request and every push to `develop`,
`.github/workflows/deploy-image.yml` builds the dev image and runs the suite
Expand Down
5 changes: 1 addition & 4 deletions example/cfis/config_exp_mccd.ini
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ BKG_FROM_HEADER = False
# Type of image check (optional), default not used, can be a list of
# BACKGROUND, BACKGROUND_RMS, INIBACKGROUND, MINIBACK_RMS, -BACKGROUND,
# FILTERED, OBJECTS, -OBJECTS, SEGMENTATION, APERTURES
CHECKIMAGE = BACKGROUND
CHECKIMAGE = BACKGROUND, BACKGROUND_RMS

# File name suffix for the output sextractor files (optional) SUFFIX = tile
SUFFIX = sexcat
Expand Down Expand Up @@ -235,6 +235,3 @@ PSF_MODEL_PATTERN = fitted_model

# PSF model separator
PSF_MODEL_SEPARATOR = -

# For multi-epoch purposes
ME_LOG_WCS = $SP_RUN/output/run_sp_exp_Mh/merge_headers_runner/output/log_exp_headers.sqlite
6 changes: 5 additions & 1 deletion example/cfis/config_exp_psfex.ini
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ INPUT_DIR = last:split_exp_runner, last:mask_runner
# Read pipeline flag files created by mask module
FILE_PATTERN = image, weight, pipeline_flag

# Explicit extensions: a 3-entry FILE_PATTERN override must not fall back on
# the decorator's 4-entry FILE_EXT default (length check fails at startup)
FILE_EXT = .fits, .fits, .fits

NUMBERING_SCHEME = -0000000-0

# SExtractor executable path
Expand Down Expand Up @@ -112,7 +116,7 @@ BKG_FROM_HEADER = False
# Type of image check (optional), default not used, can be a list of
# BACKGROUND, BACKGROUND_RMS, INIBACKGROUND, MINIBACK_RMS, -BACKGROUND,
# FILTERED, OBJECTS, -OBJECTS, SEGMENTATION, APERTURES
CHECKIMAGE = BACKGROUND
CHECKIMAGE = BACKGROUND, BACKGROUND_RMS

# File name suffix for the output sextractor files (optional) SUFFIX = tile
SUFFIX = sexcat
Expand Down
2 changes: 1 addition & 1 deletion example/cfis/config_onthefly.mask
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Paths to executables
[PROGRAM_PATH]

WW_PATH = ww
WW_PATH = weightwatcher
WW_CONFIG_FILE = $SP_CONFIG/mask_default/default.ww

# Indicate cds client executable if no external star catalogue is available
Expand Down
2 changes: 1 addition & 1 deletion example/cfis/config_save.mask
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Paths to executables
[PROGRAM_PATH]

WW_PATH = ww
WW_PATH = weightwatcher
WW_CONFIG_FILE = $SP_CONFIG/mask_default/default.ww

# Indicate cds client executable if no external star catalogue is available
Expand Down
Loading
Loading