Convert all TString::Tokenize() call sites to PStringUtils::Split. The
persisted RunSummary TObjArray (read from the MusrRoot file via
FindObjectAny and iterated with TObjArrayIter) and the run-title TObjString
returned by TLemRunHeader::GetRunTitle() remain ROOT types, since they come
from external interfaces / on-disk format, not from tokenization.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace ROOT's TString::Tokenize() + TObjArray/TObjString token
handling with the dependency-free PStringUtils::Split() across all
command/theory parsing in PFitter (GetPhaseParams, GetParFromFun,
CheckCommands and the Execute* helpers). Split() mirrors Tokenize()
semantics (delimiter-set, skips empty tokens), so token counts and
indices are unchanged. Each token is still copied into a TString,
so the downstream Atoi/Atof/IsFloat/IsDigit/Contains/CompareTo logic
stays as-is.
Using a std::vector<std::string> removes the manual TObjArray
cleanup and incidentally fixes three pre-existing leaks: the
tokens array in ExecuteFitRange was never freed, and the early
return paths in ExecutePrintLevel and the SECTOR check in
CheckCommands skipped the cleanup.
Build of libPMusr and musrfit is clean; full ctest suite passes
(85/85).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace ROOT's TString::Tokenize() + TObjArray/TObjString token
handling with the dependency-free PStringUtils::Split() across
msr2msr_run, msr2msr_param and msr2msr_theory. Split() mirrors
Tokenize() semantics (skips empty tokens), so token counts and
indices are unchanged.
Using a std::vector<std::string> removes the manual TObjArray
cleanup and incidentally fixes a pre-existing leak in
msr2msr_theory, which tokenized in every branch but never deleted
the TObjArray.
Since msr2msr links only against ROOT (not PMusr, where
PStringUtils lives) and PStringUtils is pure C++17, compile
classes/PStringUtils.cpp directly into the msr2msr executable
rather than pulling in the whole PMusr library.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GCC's -Wstringop-overflow flagged the memcpy in SobolIni() with a bound
of (size_t)(-4): on the (in practice unreachable) path where the Sobol
generator polynomial 'powers' is 0, the bit-count loop leaves inibits at
its initial -1, so inibits*sizeof underflows. The generator-polynomial
table always has a non-zero first column, so this never happens at run
time, but the compiler cannot prove it.
Guard the copy with 'if (inibits > 0)', which silences the false-positive
warning and hardens the edge case without changing behaviour for valid
input.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
OpenMP 5.2 deprecates the '-' reduction operator (-Wdeprecated-openmp)
because it is functionally identical to '+': the private reduction copy
is initialised to 0 and partial results are combined by addition in both
cases. All affected loops accumulate with 'mllh += ...', so switching to
reduction(+:mllh) is results-identical and silences the warning.
Fixes the pragma in PRunMuMinus.cpp and the two in PRunSingleHisto.cpp,
and corrects the now-inaccurate "for subtraction" doc comment.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The QProcess::finished lambdas used [=], which implicitly captures 'this'
to call member functions (exitStatusMusrWiz, fileReload,
exitStatusMusrSetSteps). Implicit 'this' capture via [=] is deprecated in
C++20; name it explicitly with [=, this]. Applied to both the qt6 and qt5
copies.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The fallback date placeholder string contained the sequence '??-', which
the compiler interprets as a trigraph for '~' (-Wtrigraphs warning).
Escape the question marks (\?) so the literal string is unchanged while
the warning is silenced.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the ROOT TString::Tokenize()/TObjArray/TObjString machinery used
for parsing the RGB color code in OnCharacters() with the C++17
PStringUtils helpers (Split/IsInt/ToInt). Drops the manual heap cleanup
and the <TObjArray.h>/<TObjString.h> includes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
IsInt now recognises (possibly signed) integers such as "-5" or "+42",
making it slightly more permissive than TString::IsDigit(). A lone sign,
a double sign, or a sign following a digit are still rejected. strToNum
test expectations updated accordingly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stand-alone test under src/tests/strToNum exercising every PStringUtils
method (Split / IsInt / IsFloat / ToInt / ToDouble / IsEqualNoCase /
ContainsNoCase / BeginsWithNoCase). Three modes: built-in pass/fail
suite, ad-hoc inspection of command-line strings, and an interactive
prompt. Adds -h/--help and -i/--interactive options. Pure C++17, no
ROOT dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ToDouble() had the same shortcoming as ToInt(): wrapping strtod() with a
nullptr endptr made a failed conversion indistinguishable from a
legitimate 0.0. Add an optional `bool *ok` out-parameter that reports
success. strtod() (with endptr + errno) is kept instead of
std::from_chars so the accepted input set stays identical to
TString::Atof() (leading whitespace skipped, leading '+' honoured,
trailing characters ignored); ok is set false on a non-numeric string or
an ERANGE overflow. The parameter defaults to nullptr, so existing call
sites keep compiling unchanged.
Convert the IsFloat-guarded ToDouble call sites in PMsrHandler to the
single-parse ToDouble(token, &ok) form (replacing the IsFloat() guard +
separate ToDouble() that parsed every token twice). All downstream
>=0 / <=0 / range checks are preserved, and push_back sites only append
on success so no spurious 0.0 is stored on error. Number-vs-keyword
discriminators (pos.error/boundary "none", rrf_phase/fourier-phase parX)
are restructured so the keyword branch is taken when ok is false.
As a side effect this fixes a latent gap in the GLOBAL rrf_freq handler,
where a non-numeric frequency previously slipped through with a stale
value instead of raising an error.
The IsFloat-guarded ToInt fit-range offsets (fgb/lgb) are intentionally
left untouched, as there the guard type differs from the conversion.
All 85 integration tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ToInt() previously wrapped strtol() with a nullptr endptr, so a failed
conversion was indistinguishable from a legitimate 0 (matching the old
TString::Atoi() behaviour). Switch the implementation to std::from_chars
and add an optional `bool *ok` out-parameter that reports success: it is
set to false on a non-numeric string or an out-of-range value, true
otherwise. Leading whitespace is skipped and trailing characters are
ignored, preserving the Atoi-like prefix semantics. The parameter
defaults to nullptr, so existing call sites keep compiling unchanged.
Convert the parse-validation call sites in PMsrHandler to the single
-parse ToInt(token, &ok) form, replacing the IsInt() guard + separate
ToInt() (which parsed every token twice). All downstream >0 / >=0 /
range / enum checks are preserved.
Left untouched the call sites where IsInt() acts as a structural
discriminator rather than a numeric validator (write path, xy-data
index-vs-label, fParamInUse usage scans) and the IsFloat-guarded ToInt
offsets, where switching to ToInt(&ok) would change parsing semantics.
All 85 integration tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reduce the ROOT footprint of the MSR parser by removing the pervasive
TString::Tokenize / TObjArray / TObjString / dynamic_cast pattern (28
tokenize sites, 14 TObjArray, 106 TObjString) used to split lines into
tokens, together with the manual `delete tokens` cleanup.
Add a new dependency-free C++17 utility class PStringUtils (Split, IsInt,
IsFloat, ToInt, ToDouble, IsEqualNoCase, ContainsNoCase, BeginsWithNoCase)
that replicates the relevant TString semantics exactly, so it can be reused
elsewhere in the suite. IsInt/IsFloat tolerate surrounding whitespace to
match TString::IsDigit/IsFloat (needed for tokens split on ',' / ';' only).
The public API and the PMusr.h data structures keep TString unchanged; only
the internal tokenizing logic is rewritten. Net -451 lines in
PMsrHandler.cpp. All 85 integration tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
getValues()/getErrors() return a std::vector by value, but the QVector was
built from begin() of one call and end() of a second call -> iterators into
two distinct temporaries -> UB and a segfault in getValues(). Bind the result
to a single local before taking begin()/end(). Same in getPosErr/getNegErr.
This surfaced reliably when plotting a <python>-generated variable added via
the GUI (the script path was unaffected as it reads getValues() only once).
Also fix check() to validate the actually selected collections
(GetCollection(idx[i]) instead of GetCollection(i)).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use the new coll[]/collErr[] interface so sigmaSC-vs-temp-py.txt computes both
SigmaSC_10 and SigmaSC_150 in one block instead of one block per collection.
Collection 0 is addressed by index (coll[0]) and collection 1 by name
(coll['...Tscan.db']) to show both addressing modes. Output is unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A <python> variable block previously saw only the parameters of the single
collection the variable is linked to via 'col', injected as bare names plus
par[]/parErr[]. To compute variables for several collections one therefore
needed a separate block per collection.
Now every loaded collection is additionally injected as coll[]/collErr[]
dictionaries, addressable both by integer index (matching 'col <idx>' /
'select <idx>') and by collection name; index and name keys reference the same
per-parameter dict. A single block placed after all 'var = python' declarations
can thus compute - and combine - variables for any collection, e.g.
coll[0]['Sigma'] or coll['NAME.db']['Sigma'].
The bound-collection bare names / par[] / parErr[] are unchanged, so existing
scripts and GUI variables keep working. The collection list is threaded through
PmuppScript::var_cmd and the GUI add()/check() paths into PVarHandler.
Verified: a one-block script using both an index key and a name key reproduces
the numeric output of the equivalent two-block script bit-for-bit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
getPythonBlock() always returned the first <python> ... </python>
entry of the script, so when several 'var X = python' declarations
each had their own block, every declaration after the first one
re-ran the first block and the read-back of the requested variable
failed. Thread the script index through var_cmd into getPythonBlock,
which now scans from that position onwards. Each declaration is
paired with the next block in script order.
Previously only y-errors were rendered. The IPC data file format now
includes x-errors per point (x, xPosErr, xNegErr, y, yPosErr, yNegErr,
...). Both the live canvas (PMuppCanvas) and the ROOT macro exports
(GUI and script path) propagate x-errors to TGraphAsymmErrors;
x-errors default to 0.0 when the parameter carries none.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Variables can now be computed by an embedded Python3 interpreter in addition
to the Boost.Spirit X3 expression engine. A <python> ... </python> block
receives all collection parameters as per-run lists (bare names, plus
par[]/parErr[] dictionaries as a fallback for names that are not valid Python
identifiers such as 'lambda') and must assign <name> and <name>Err; errors are
user supplied. Works both in the GUI variable dialog and in scripts.
The feature is optional and only enabled when ROOT is built with TPython
(CMake target ROOT::ROOTTPython); otherwise it compiles out. See MUPP_PY.README
for ROOT configure requirements and usage.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add ${HDF5_LIBRARIES} to PMusr link dependencies so HDF5 C++ symbols
(H5::DataType, H5::PredType, etc.) used in PRunDataHandler.cpp resolve.
- Add ${FFTW3_INCLUDE} to musrRootValidation and write_musrRoot_runHeader
include paths; both pull in PMusr.h which transitively includes fftw3.h.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>