Command line

The program axqua. axqua.cli contains the commands that prepare and inspect a case, and axqua.jobcli the commands of the job system. Terminal syntax lists the commands from the perspective of a user.

Case commands

Command-line entry point: axqua.

Two forms:

  • axqua <config.yml> [--check|--dry-run] - build a full TELEMAC case (default; the configuration path is positional).

  • axqua clip <raster> -b <boundary> -o <out> - clip a single raster to a region-of-interest polygon, without needing a full configuration.

  • axqua rating -o <out.csv> --manning <n>|--strickler <Kst> --slope <S0> --width <b> [--side-slope <m>] [--bed-elevation <z>] --q <Q...> - synthesize a normal-flow outflow stage-discharge curve to use as boundaries.stage_discharge.

  • axqua targets <config.yml> [-o <out.xlsx>] [--force] - generate the user-fillable calibration-target-data.xlsx template (hydraulics / morphodynamics ground truth + calibration-parameter ranges) for a case.

  • axqua openfoam <config.yml> [--check] [--cell-size <m>] [--layers <n>] - build the OpenFOAM (interFoam) free-surface case: a terrain-following all-hexahedral mesh, fields seeded from the converged TELEMAC 2D result, and both staged dictionary sets. --check only reports the cell count.

  • axqua case-status <config.yml> [--check-env] [--full] [--json] - report what the case can do (implemented / configured / built / run, per solver) and refresh its MODEL=<SOLVER>_<ENABLED|DISABLED> marker files. --json is what a QGIS plugin reads to decide which tabs to show.

Job verbs (see axqua.jobcli), which run work that outlives this shell:

  • axqua submit <config.yml> --kind <kind> - create a persistent job and start it detached; prints the job id.

  • axqua execute <job> - run a job synchronously here (the debugging path).

  • axqua status <JOB_ID> / cancel / logs / list / profiles.

status is overloaded, and the argument decides: an existing path means the case (the historic meaning, kept working), while an argument matching the job-id grammar means the job. The two cannot collide - a job id is never a path.

axqua.cli.main(argv=None)[source]
Parameters:

argv (list[str] | None)

Return type:

int

Job commands

The job verbs: submit, execute, status, cancel, logs, list.

Kept out of cli.py so the build commands and the job commands stay legible apart, and because a QGIS plugin’s entire view of axqua is this file’s output. Two properties matter more than the exact spelling of any flag:

Machine-readable output. Every verb takes --json and emits one envelope shape: {"ok", "command", "axqua", "data", "error"}. The document goes to stdout and all narration to stderr, so a caller can parse stdout unconditionally. Plan §11 is explicit that QGIS must never parse human-readable console logs to obtain state, and this is what makes that possible.

Exit codes that mean something. A uniform 1 forces a GUI to parse text to find out what went wrong. The AxquaError categories already carry stable codes, so they map onto distinct exit codes here.

The status collision, resolved by a rule

axqua status <config> has always meant case status. The job verb wants the same word. Rather than break the existing spelling or guess, the argument decides:

  • an existing path -> case status (with a deprecation notice pointing at case-status);

  • something matching JOB_ID_RE -> job status.

A job id is never a path and a path never matches the job-id grammar, so the two cannot be confused - and the rule is tested in both directions.

axqua.jobcli.EXIT_OK = 0

Exit codes by error category, so a caller can branch without parsing a message.

axqua.jobcli.emit(command, data, *, as_json, lines=None)[source]

Print a success result in whichever form was asked for.

Parameters:
Return type:

int

axqua.jobcli.fail(command, exc, *, as_json, verbose=False)[source]

Report a failure and choose the exit code from its category.

Parameters:
Return type:

int

axqua.jobcli.parse_args(parser, argv, command)[source]

parser.parse_args, but a usage error still leaves an envelope behind.

argparse prints its usage to stderr and exits 2 with empty stdout. For a shell that is exactly right, but the plugin’s whole boundary is “run it and read the JSON on stdout”, so a mistyped flag arrives there as “axqua returned something that is not JSON” - a message about the protocol, for what is really a typo. Writing the envelope first costs nothing, and argparse’s own message still goes to stderr where it always did. The exit code is unchanged, because shell callers branch on it.

Parameters:
axqua.jobcli.run_submit(argv)[source]
Parameters:

argv (list[str])

Return type:

int

axqua.jobcli.run_execute(argv)[source]
Parameters:

argv (list[str])

Return type:

int

axqua.jobcli.run_job_status(argv)[source]
Parameters:

argv (list[str])

Return type:

int

axqua.jobcli.run_cancel(argv)[source]
Parameters:

argv (list[str])

Return type:

int

axqua.jobcli.run_logs(argv)[source]
Parameters:

argv (list[str])

Return type:

int

axqua.jobcli.run_list(argv)[source]
Parameters:

argv (list[str])

Return type:

int

axqua.jobcli.run_profiles(argv)[source]
Parameters:

argv (list[str])

Return type:

int

Profile commands

axqua profile: inspect, create and check the profile of this computer.

The profile (axqua.core.profile) is what the Configuration tab of the QGIS plugin edits. These commands are the same operations for a terminal, and they are how the plugin performs them: it never imports aXqua, so reading, writing and checking a profile all go through here and come back as one JSON document.

path where the active profile is, or would be show print it detect what a profile for this computer would contain; writes nothing init detect, written to the default location (refuses to overwrite) check everything that is wrong with it, as findings; never fails on a finding write replace it with a JSON document read from standard input locate locate <program> <folder>: what aXqua runs of a program in that folder

axqua.profilecli.run_profile(argv)[source]
Parameters:

argv (list[str])

Return type:

int

Installation commands

axqua install: install TELEMAC, OpenFOAM and the postprocessors.

overview what this computer is, and what is installed, running or was tried plan what an installation would do and what is missing; changes nothing packages the system packages an installation needs; --elevate installs them start run an installation, detached unless --foreground status how far an installation is, with the end of its log (--tail) cancel stop an installation; what is already built stays list every installation on record telemac-examples download the files that TELEMAC’s own example cases read

The installation wizards of the QGIS plugin are these commands with a window around them. run is what a detached installation executes and is not meant to be typed.

axqua.installcli.run_install(argv)[source]
Parameters:

argv (list[str])

Return type:

int

Export commands

axqua export: TELEMAC results for ParaView and VisIt.

axqua export <case-file> convert every result of the case axqua export <case-file> --list what the case has, and what is exported already axqua export <result.slf> convert one file, without a case

QGIS reads the result format of TELEMAC directly; ParaView and VisIt do not. The conversion (axqua.postproc.selafin_vtk) writes one folder per result with a .pvd file for ParaView and a .visit file for VisIt, into the folder vtk of the postprocessing folder of the case. An OpenFOAM result needs no conversion: both programs open the case folder.

axqua.exportcli.run_export(argv)[source]
Parameters:

argv (list[str])

Return type:

int

Case file commands

axqua schema, axqua case and axqua check: what an editor of a case needs.

The case editor of the QGIS plugin never imports aXqua, so everything it does to a case file goes through here and comes back as one JSON document:

schema every setting of a case file: label, kind, unit, explanation case read the case file as it is written case write replace it with a JSON document read from standard input case new a new case file with the entries every case has check everything that is wrong with a case, as findings

case write writes what it is given and then checks it. A case is incomplete while it is being filled in, and an editor that refused to save an incomplete case would lose the work. The original file is kept as <name>.bak the first time it is replaced, because writing goes through the data and the comments of a hand-written file are not kept.

axqua.casecli.run_schema(argv)[source]
Parameters:

argv (list[str])

Return type:

int

axqua.casecli.run_check(argv)[source]
Parameters:

argv (list[str])

Return type:

int

axqua.casecli.run_case(argv)[source]
Parameters:

argv (list[str])

Return type:

int

Example case commands

axqua example: get an example case onto this computer.

list the example cases there are, with their size get put one into a folder, ready to be opened in the plugin or run in a terminal

An example is a folder that works on its own: the case file, a guide and the input data. See axqua.core.examples for where the examples are read from.

axqua.examplecli.run_example(argv)[source]
Parameters:

argv (list[str])

Return type:

int