Repository navigation
mctest: %Scan: prototype - #2772
Merged
Merged
Conversation
…mcrun
%Scan: header lines describe a parameter scan test, using the mcrun scan
syntax unchanged (so every mcrun scan form works), followed by one target
detector value per scan point in a {}-enclosed list that may span lines:
* %Scan: mcrun SE_example.instr dBz=-0.0001,0.0001 -N41 -n1e5 Detector: detector_I={
* 86.04,101.892,...
* 85.406 }
mctest:
- %Scan: lines become tests like %Example: (own testnb, dir, JSON with
"scan": true and list-valued targetval/testval)
- "mcrun" and "*.instr" tokens on %Example:/%Scan: lines are ignored; a
scan's own -n is used, else at most 1e5 per point
- scans run with --scan_split=auto unless MPI is used, timeout scales with
the number of points, mcdisplay runs at the first scan point
- values are read from the scan's mccode.dat (McCode and NeXus formats);
a scan passes when all points are within 20% of target
- new --noscans option to skip scans
mcviewtest: one cell per scan ("scan, 41/41 pts (41/41 pts OK)"), with a
per-point test/target/percent hover tooltip.
mcdoc: %Scan: lines are shown like %Example: lines, as "Scan: ...", with
the target value list shortened to "{N values}".
mcrun:
- --scan_split=auto (alias for the existing 0): number of cores minus one
- --scan_split is only overridden by an explicit multi-process --mpi
(--mpi defaults to 1), with a warning when that happens
- each scan point i now uses seed base+i*1024 in both the serial and the
--scan_split scanner (previously only the latter), so serial and split
scans give identical, reproducible results for a given --seed; without
--seed the base is taken from the current time and logged; --seeds
scans use the scanned seeds unchanged
SE_example gets a 41-point %Scan: test (targets from -s 1000).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… dirs
Scan curves loaded from mccode.dat had an empty filepath and all shared
filename 'mccode.dat', while the html frontends derive output file names
from those fields:
- mcplot-html wrote every curve to '.html'/'_log.html' in the cwd, and
its parallel jobs raced on exists()/remove() of that shared file
(FileNotFoundError).
- mccoplot-html wrote every pane to 'coplot_mccode.html', so all panes
showed the last detector.
- mcplotdiff-html crashed: scan curves have no 'values' triplet, no
(I, ERR) yvar pair and no N column.
Fixes:
- mcplotloader: give each scan curve a unique filepath <scandir>/<yvar>
(e.g. scan/detector_I), so mcplot-html writes scan/detector_I.html.
- mcplot-html: drop the racy exists()/remove() before writing; open('w')
already truncates.
- mcplotdiffloader: add monitor_basename() (basename of filepath, else
filename) and use it to key and match monitors and to name the diff
.dat files and the mccode.sim entries. Ordinary monitors keep their old
names (e.g. PSD.dat). Make the diff and the .dat writer handle scan
curves: % diff from summed curves when 'values' is empty, a derived
<name>_ERR yvar, and N=0 rows when there is no N column.
- mccoplot-html/mcplotdiff-html: use monitor_basename() for page names
and for locating existing mcplot-html pages to link to.
Verified with an SE_example scan (-N41): mcplot-html, mccoplot-html and
mcplotdiff-html produce one page per scan curve; the diff output dir
reopens with mcplot-html; single step-dir diff/coplot output names are
unchanged; matplotlib mcplot/mccoplot still work.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Now adding %Scan: lines to instruments with non-executed Example: (without %) scans lines. |
Scan examples that were written as plain "Example:"/"mcrun ..."/"mxrun ..." header lines are turned into %Scan: tests, with reference values generated the way mctest runs them (--no-mpi -s 1000 --scan_split=auto). Ranges, point counts and ncount are adjusted so every point has at most ~8% statistical error, keeping the 20% per-point tolerance meaningful: McStas: - SE_example2: dBz scan, 41 pts (as SE_example) - Tomography: omega=0,340 -N18; drops the stale offfile=bunny.off (the instrument has no such parameter, so every point failed) - SESANS_Delft: By=0,0.0468 -N31 -n1e6 - Test_PowderN_Res: radius=0.001,0.021 -N21 - Test_Magnon_bcc_TAS: hw=0,1 -N21 -n1e6 on e_monitor (e_monitor1 was up to 100% noisy and zero for most hw) - Test_Dispersion_relation_TAS: -M -N 5,5 (was 21,21 = 441 pts) - Samples_Incoherent: SAMPLE=1,5 -N5 STOP=1 (prose examples kept) - LLB_6T2: C60 200 rocking curve over the peak, phi=9.27,10.37 -N12 -n1e7 (was -N31 -n1e8 with --mpi); moved out of %Parameters McXtrace: - SSRL_bl_11_2_white_src / _not_white_src: Etohit=6900,7500 -N31 -n1e6 (was -N601) - SOLEIL_DISCO: x_screw=20,103 -N21 scan=1 on the Wavelength monitor - SOLEIL_ROCK: Cu edge E0=8.5,9.5 -N21 -n1e6 on fluo_monitor - Czerny_Turner: x_screw=20,103 -N21 -n1e6 scan=1 on Wavelength %Scan: lines are placed before any following descriptive text, so mcdoc keeps that text in the description. mctest: also ignore an "mxrun" token on %Example:/%Scan: lines. Verified: mctest and mxtest --local on all 13 pass with every point at 100% (macOS arm64); together they add ~2.5 min on 12 cores. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s_Incoherent Reference values generated as mctest runs them (--no-mpi -s 1000 --scan_split=auto), ranges trimmed to the curve after trial scans so every point has at most ~6% statistical error: - TAS1_C1: monochromator rocking curve PHM=-38.077,-36.077 -N11 - TAS1_C1_Tilt: collimator tilt OMC1=-44.5,55.5 -N21 - TAS1_Diff_Slit: direct beam C1=30 TT=-0.6,0.6 -N13 - TAS1_Diff_Powder: powder line TT=32.92,34.32 -N15 - TAS1_Diff_Vana: flat incoherent background TT=31.52,35.52 -N21 - TAS1_Powder, TAS1_Vana: analyzer scan OMA=-19.45,-15.45 -N21; a note explains the transmission dip (with TTA=0 the detector looks straight through the analyzer) (all -n1e6) - SOLEIL_ROCK: Mn/Cr edge scan E0=5.7,6.8 sample_file=MnCr -N21 -n1e6 replaces its prose example line - Samples_Incoherent: the two beamstop-removed scans SAMPLE=2,5 -N4 STOP=0 (PSD_Sphere_4pi) and with DB=1 (Dirbeam) Doc fix: OMC1 is in arcmin (the code divides it by 60), not deg, in the six TAS1 instruments that have it. Verified: mctest/mxtest --local pass with every point at 100% (macOS arm64); together ~3.5 min, of which 74 s is the SOLEIL_ROCK Mn/Cr scan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
%Scan: header lines are mctest test definitions like %Example: lines, so
edits to them must still list the .comp/.instr file. A %Scan: line runs
on to the } closing its target values, which may span several header
lines; the header's * prefixes inside the {} are ignored, so re-wrapping
the values is not a change. The stderr reason is now %Example/%Scan.
Checked on a0f97e1 and aa47fec: all 13 resp. 9 instruments with new
%Scan: lines are listed (previously skipped as header-only edits).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both scans failed outside the reference setup (other seeds / MPI rank layouts): the true seed-to-seed scatter is far larger than the reported error bars, because few independent histories get past the monochromator and the downstream SPLIT (sample / fluorescence) reuses them, so the errors are underestimated. E.g. LLB_6T2 at -n1e7: points moved up to 50% with +/-3% error bars; SOLEIL_ROCK Mn/Cr at -n1e6: 3 of 21 points >20% off, worst 50%, with +/-4% error bars. The header example lines are restored to their pre-%Scan text. LLB_6T2 keeps SPLIT 10 on Monoc, which halves the real scatter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ation - tomo_recon.py: Python port (numpy + matplotlib) of the old Matlab tomo_recon.m. Filtered back-projection (ramp*Hann filter, as Matlab iradon's 'hann') of an mcrun omega scan, one sinogram per detector row from the I block of each step's x_y monitor file, using -log(I/I_max) as projection. Shows the 3 central slices; --save writes vol.npy. Usage: python tomo_recon.py <scan dir> [--save] - Tomography.instr / README.md: point to tomo_recon.py instead of the Matlab function (which needed the imaging toolbox, PGPLOT output and is no longer in tools/matlab). - %Scan: now a full rotation omega=0,350 -N36 -n1e6, with targets from that scan (error bars ~0.1%, no SPLIT in the instrument). Verified: mctest passes the scan (36/36 points at 100%, ~48 s); tomo_recon.py reconstructs an 80x80x40 volume from it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Description says what the instrument does (OFF sample rotated by omega around y, transmitted beam on a 2D detector) and gives a working tomography command (omega=0,355 -N72 -n1e7 -d TomoScan), replacing the stale example with the non-existent offfile= parameter and the unshipped bunny.off. - %Scan: moved after %Example so mcdoc keeps the description intact; now a full rotation in 5 deg steps, omega=0,355 -N72 -n1e6, targets generated as mctest runs it (-s 1000 --scan_split=auto). - Defaults det_w=0.25, det_h=0.15, opts="x bins=128 y bins=64"; %Example: target updated for the smaller detector (9.37708e-10). - README.md regenerated with mcdoc's Markdown writer. Verified: mctest passes the %Example (100%) and the scan (72/72 points at 100%, ~82 s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scan failed on Windows CI (mxtest --mpi=auto, 29/31 points, worst 125%): the two SPLIT 10 Bragg crystals reuse each history up to 100x, so at 1e6 the real seed-to-seed scatter was 8-12% per point against 3-5% error bars. At 1e7 the typical scatter is ~2%. Targets are the mean of seeds 1000/2000/3000 (all within 8% of it). Verified: mxtest --seed 5000 (31/31, worst 92%, 50 s) and --mpi=auto (31/31, worst 106%, 92 s) on macOS arm64. Expect ~15 min on Windows CI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
@mads-bertelsen, @g5t, @farhi, @Lomholy won't request a full review from either of you (I know you are all busy with other stuff), but wanted you to know this is incoming. A quick thumbs up / down is sufficient for now - and we can of course re-model details later. |
Contributor
Author
|
@Lomholy likes it. ;-) This makes me think "let's roll with it for a while". Merging. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Free-form text area
Please describe what your PR is adding in terms of features or bugfixes:
mctest:
%Scan:tests, per-point scan seeds in mcrun, and HTML plotting of scan directoriesSummary
Adds a scan test mode to mctest. An instrument header can now hold a
%Scan:line, which gives an mcrun parameter scan and one expected detector value per scan point:The scan arguments go to mcrun unchanged, so every mcrun scan syntax works (
a,b -N,a:delta:b,-L,-M,-N=a,b,c, …) and mctest has no scan parsing of its own.The HTML plotting frontends could not plot mcrun scan directories, which mctest scan results need. This PR fixes that too.
Changes
mctest
%Scan:line becomes a test like%Example:: its own test number, output directory and JSON entry ("scan": true, with list-valuedtargetval/testval).{}-enclosed, comma-separated list and may span several header lines.mcrunand*.instrtokens on%Example:/%Scan:lines are ignored.-nif given, otherwise at most1e5per point.--scan_split=autounless MPI is used. The timeout scales with the number of points. mcdisplay runs at the first scan point.mccode.dat, which works for both the McCode and NeXus formats. A scan passes when every point is within 20 % of its target.--noscansoption.mcviewtest: one cell per scan (e.g.
scan, 41/41 pts (41/41 pts OK)). Hovering shows each point's test value, target and percentage. The diff/coplot links now work for scan rows (see plotting below).mcdoc:
%Scan:lines appear like%Example:lines, labelledScan: …, with the value list shortened to{N values}.mcrun
--scan_split=autois an alias for the existing (undocumented)0: the number of cores minus one.--scan_splitis now overridden only by an explicit--mpigreater than 1, with a warning. Before, the default--mpi=1silently disabled it.iusesbase + i*1024in both the serial and the--scan_splitscanner. Before, only the split scanner did this.--seedif given, otherwise the current time, which is logged so the run can be reproduced.--seedsscans use the scanned seeds unchanged.HTML plotting of mcrun scan directories (mcplot-html, mccoplot-html, mcplotdiff-html)
Scan curves loaded from
mccode.dathad an emptyfilepath, and all of them had the file namemccode.dat. The HTML frontends build output file names from those two fields, so:.html/_log.htmlin the current directory, and its parallel jobs raced on deleting that shared file (FileNotFoundError).coplot_mccode.html, so all panes showed the last detector.valuestriplet, no(I, ERR)pair and noNcolumn.Fixes:
mcplotloader: each scan curve gets its ownfilepath,<scandir>/<yvar>(e.g.scan/detector_I), so mcplot-html writesscan/detector_I.html.mcplotdiffloader:monitor_basename(): the base name offilepath, falling back tofilename. It is used to key and match monitors and to name the diff.datfiles and theirmccode.simentries. Ordinary monitors keep their old names (e.g.PSD.dat)..datwriter now handle scan curves: the % difference comes from the summed curves when there is novaluestriplet, an<name>_ERRcolumn is derived, andNis written as 0 when there is no N column.monitor_basename().Instruments:
SE_examplegets a 41-point%Scan:test, with targets generated using-s 1000.Serial mcrun scans run with
--seednow give different numbers than before. Each point gets its own seed instead of every point reusing the same one, which also removes the point-to-point correlation in the noise. Split scans are unchanged, and serial and split scans now give identical results for a given seed. Without--seed, scans were already non-reproducible, so nothing is lost there.Testing (macOS arm64, clang,
mccode-devconda env, McStas only)mctest --instr SE_example: 41/41 points pass (about 4 s with--scan_split). Also passes with--nexus.--noscansskips the scan.-s 1000give identical results. A--seeds=7,9 -N3scan matches single runs at those seeds.Scan: … {41 values}.-N41):Not tested / known gaps
%Scan:line yet and mxtest/mxrun/mxplot weren't run.--mpi(scans then run serially through MPI).Declaration of use of AI-tools
^ 🤖 Generated with Claude Code
Development OS / boundary conditions
Please describe what OS you developed and tested your additions on, and if any special dependencies are required:
PR Checklist for contributing to McStas/McXtrace
For a coherent and useful contribution to McStas/McXtrace, please fill in relevant parts of the checklist:
My contribution contains something else