Skip to content

Add a rotor_scan_resolution input key - #1019

Open
alongd wants to merge 1 commit into
mainfrom
i002-scanres-input-key
Open

Add a rotor_scan_resolution input key#1019
alongd wants to merge 1 commit into
mainfrom
i002-scanres-input-key

Conversation

@alongd

@alongd alongd commented Aug 23, 2026

Copy link
Copy Markdown
Member

Motivation

ARC had no user-facing way to state the resolution of its 1D rotor scans. The value came from
rotor_scan_resolution in the settings of whatever process happened to be running. This bit us
for real: a machine-wide settings override silently put every rotor scan on a workstation below
the resolution where the downstream Fourier fit is valid, for a week, with no crash and no
warning
— a silent wrong answer. This PR makes a run able to state what it needs, so resolution is
a property of the run and not of the host that launched it.

What changed

Adds a user-facing input key rotor_scan_resolution (degrees; points per rotor = 360 / value):

project: my_project
level_of_theory: wb97xd/def2tzvp
rotor_scan_resolution: 4.0
species:
  - label: ethane
    smiles: CC

Route (input → job), through the existing per-job override channel rather than a new one:

ARC.__init__(rotor_scan_resolution=...)  ->  validated, stored, round-tripped via as_dict()
ARC.execute()  ->  Scheduler(rotor_scan_resolution=...)
run_job()      ->  set_scan_resolution(args, job_type)  ->  args['trsh']['scan_res'] = value
job_factory -> JobAdapter -> set_job_attributes  ->  scan_res used by the ESS scan
  • Only job_type == 'scan' (the continuous 1D ESS scans) is affected. Brute-force ND directed
    scans (job_type='directed_scan', which use dihedral_increment) and the pipe path are untouched.
  • An explicit troubleshooting scan_res is never overridden — troubleshooting still wins.

Guard: refuse a too-coarse value

A resolution coarser than 20° (fewer than 18 points per rotor) is refused with InputError at
input-parse time, not merely warned. Below 18 points RMG-Py's Fourier fitter never runs and
get_potential() reads an uninitialised C double — a coarse value is not a preference but a silent
wrong answer, which is exactly the incident above. 20.0° (18 points) is the coarsest still accepted.

Backwards compatibility

Absent the key, behaviour is byte-identical to before: rotor_scan_resolution defaults to
None, as_dict() omits it (so restart.yml is unchanged), and set_scan_resolution leaves the
job args untouched so the settings default (8.0) still reaches the job.

Tests

Four new tests (parse/store/round-trip; absent-key no-op; the guard; and a real scan JobAdapter
built via job_factory receiving the value and falling back to the settings default when unset).

  • arc/main_test.py arc/scheduler_test.py: 63 passed.
  • arc/job/adapters/common_test.py arc/job/adapters/gaussian_test.py: 31 passed.

Run under arc_env (Python 3.14) with HOME pointed at an empty dir (ARC's suite reads
~/.arc/settings.py) and -n0 -o addopts="".

@codecov

codecov Bot commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.59%. Comparing base (a08d314) to head (f6ceb91).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1019      +/-   ##
==========================================
+ Coverage   64.55%   64.59%   +0.04%     
==========================================
  Files         119      119              
  Lines       39788    39805      +17     
  Branches    10307    10312       +5     
==========================================
+ Hits        25684    25711      +27     
+ Misses      11123    11117       -6     
+ Partials     2981     2977       -4     
Flag Coverage Δ
functionaltests 64.59% <ø> (+0.04%) ⬆️
unittests 64.59% <ø> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a run-level rotor_scan_resolution input key so 1D rotor scan resolution is owned by the run (not host settings), validated at input parse time, and routed through the existing per-job troubleshooting override channel to downstream scan jobs.

Changes:

  • Introduce rotor_scan_resolution on ARC with validation + restart round-tripping via as_dict().
  • Thread the value into Scheduler and inject it into scan jobs via args['trsh']['scan_res'] when appropriate.
  • Add unit tests covering parsing/round-tripping, guard behavior, and propagation into real scan jobs.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
arc/main.py Adds rotor_scan_resolution to ARC, validates it, and persists it in restart dicts when set.
arc/scheduler.py Accepts run-level rotor_scan_resolution and injects it into scan job args without overriding explicit troubleshooting.
arc/main_test.py Adds tests for parsing/round-tripping and validation guard behavior.
arc/scheduler_test.py Adds tests ensuring injection happens only for scan jobs and reaches JobAdapter.scan_res.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread arc/main.py
Let an ARC run state its 1D rotor scan resolution (the degree increment)
instead of inheriting rotor_scan_resolution from whatever host settings the
launching process happens to read. The value is threaded from the input file
through the Scheduler into each scan job via the existing
args['trsh']['scan_res'] channel. Absent the key, behaviour is byte-identical:
the settings default still applies and restart.yml is unchanged.

A value coarser than 20 degrees (fewer than 18 points per rotor) is refused at
input time, because below that threshold RMG-Py's Fourier fitter never runs and
get_potential() returns a silent wrong answer -- the failure that motivated this.
@alongd
alongd force-pushed the i002-scanres-input-key branch from 2bd60a8 to f6ceb91 Compare August 23, 2026 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants