Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/powderline/_code_hash.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"schema_version": "0.26.0",
"kicker_hash": "ec29f60ae1d7a0ad3433d9ab67418050"
"kicker_hash": "53db8708bbdfa12496f974e89a1befbe"
}
55 changes: 49 additions & 6 deletions src/powderline/kicker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2837,6 +2837,41 @@ def set_refinement_cycles(proj: Any, num_cycles: int, print_info: bool = False)
print(f"Set number of refinement cycles to {num_cycles}")


def _refine_with_message(proj) -> tuple[bool, str]:
"""Run the project refinement, returning (ok, GSAS-II failure message).

``G2Project.refine()`` calls ``G2strMain.Refine`` and DISCARDS its
``(OK, Rvals)`` return, so failure text like "Invalid metric tensor for
phase #0" reaches only the console — callers see a silent no-Rwp failure.
Mirror the non-sequential branch of ``refine()`` (index, constraint
check, Refine, reload) to keep ``Rvals['msg']``. Any surprise from
GSAS-II internals falls back to the plain ``proj.refine()`` so behavior
is never worse than before.
"""
try:
from GSASII import GSASIIstrIO as G2stIO
from GSASII import GSASIIstrMain as G2strMain

seq_setting = proj.data['Controls']['data'].get('Seq Data', [])
if not seq_setting:
proj.index_ids() # saves the project, as refine() does
errmsg, _warnmsg = G2stIO.ReadCheckConstraints(proj.filename)
if errmsg:
return False, f"Constraint error: {errmsg}"
ret = G2strMain.Refine(proj.filename, makeBack=False)
proj.reload()
ok, rvals = (ret if isinstance(ret, tuple) and len(ret) == 2
else (True, {}))
msg = rvals.get('msg', '') if isinstance(rvals, dict) else ''
msg = msg.replace('**** ERROR: Refinement failed ****', '').strip()
return bool(ok), msg
except Exception:
pass # GSAS-II internals changed: fall back to the plain call below

proj.refine()
return True, ''
Comment on lines +2868 to +2872


def execute_rietveld_refinement(
proj: Any,
hist: Any,
Expand Down Expand Up @@ -2865,17 +2900,23 @@ def execute_rietveld_refinement(
print(f" Cycles: {controls.refinement_cycles}")
print(f"{'='*60}\n")

# Execute refinement
proj.refine()
# Execute refinement (keeping GSAS-II's failure message, which
# G2Project.refine() would otherwise discard)
refine_ok, g2_msg = _refine_with_message(proj)

# Extract Rwp
rwp_final = hist.residuals.get("wR")

if rwp_final is None:
if not refine_ok or rwp_final is None:
if g2_msg:
error = f"Rietveld refinement failed: {' '.join(g2_msg.split())}"
else:
error = ("Rietveld refinement produced no Rwp — proj.refine() "
"may have failed silently")
return {
'success': False,
'rwp': None,
'error': "Rietveld refinement produced no Rwp — proj.refine() may have failed silently",
'error': error,
}

if verbose:
Expand Down Expand Up @@ -3468,13 +3509,15 @@ def run(
result['fit_profile'] = (
pd.DataFrame(fit_profile_raw) if fit_profile_raw else pd.DataFrame()
)
# `or {}` (not a .get default): early-failure results serialize these
# tables as an explicit null, which .get(key, {}) passes through as None.
result['unit_cell_data'] = {
phase: pd.DataFrame(records)
for phase, records in result.get('unit_cell_data', {}).items()
for phase, records in (result.get('unit_cell_data') or {}).items()
}
result['peak_list_data'] = {
phase: pd.DataFrame(records)
for phase, records in result.get('peak_list_data', {}).items()
for phase, records in (result.get('peak_list_data') or {}).items()
}
refined_params_raw = result.get('refined_parameters')
result['refined_parameters'] = (
Expand Down