Skip to content

Conversation

RichardWaiteSTFC
Copy link
Contributor

@RichardWaiteSTFC RichardWaiteSTFC commented Sep 8, 2025

Description of work

Add module of classes to implement 2D Pawley refinement for POLDI.
Includes:

  1. PeakProfile base class and inherited classes representing types of peak profiles (and how peak parameters change with d-spacing)
  2. Phase class to represent crystal lattice
  3. PawleyPattern1D class to perform 1D Pawley refinements (pre-requisite for 2D Pawley refinement of POLDI)
  4. PawleyPattern2D class to perform 2D Pawley refinement

Closes #38970

Report to: Florencia (POLDI,PSI)

To test:

(1) Load data

## Load data
############

fpath_idf = FileFinder.getFullPath("POLDI_Definition_448_calibrated.xml")
fpath_data = FileFinder.getFullPath("poldi_448x500_chopper5k_silicon.txt")
ws = load_poldi(fpath_data, fpath_idf, chopper_speed=5000, t0=5.855e-02, t0_const=-9.00) # 0.025701, t0_const=85.0)

ws_corr = PoldiAutoCorrelation(InputWorkspace=ws)
ws_corr_d = ConvertUnits(InputWorkspace=ws_corr, OutputWorkspace=ws_corr.name() + '_d', Target='dSpacing')
ws_corr_d = ConvertToPointData(InputWorkspace=ws_corr_d, OutputWorkspace=ws_corr_d.name())

(2) Do 1D refinement of silicon data

# Make phase
##########

si = Phase.from_alatt(3 * [5.431], "F d -3 m")
si.set_hkls_from_dspac_limits(0.7, 3.5)

# 1D Pawley
##########

pawley = PawleyPattern1D(ws_corr_d, [si], profile=GaussianProfile() , bg_func=FlatBackground())  #  bg_func=Chebyshev(n=16))
pawley.estimate_initial_params()

# fit with profile fixed
# start = time()
# pawley.profile_isfree[:-1] = False
# res = pawley.fit()
# print("Elapsed = ", time() - start)

# fit with profile free
start = time()
pawley.profile_isfree[0][:-1] = True
res = pawley.fit()
print("Elapsed = ", time() - start)

# plot fit and initial guess
yguess = pawley.eval_profile(pguess)
yfit = pawley.eval_profile(res.x)
fig, axes = plt.subplots(subplot_kw={'projection': 'mantid'})
axes.plot(ws_corr_d, color='k', marker='o', markersize=3, label='data', wkspIndex=0)
axes.plot(ws_corr_d.readX(0), yfit, '-r', label='fit')
axes.plot(ws_corr_d.readX(0), yguess, '--b', label='guess')
dpks = pawley.phases[0].calc_dspacings()   
for ipk,dpk in enumerate(dpks):
    axes.axvline(dpk, color=3*[0.7])
axes.set_xlabel('d-Spacing ($\\AA$)')
axes.set_ylabel('Intensity (a.u.) ($\\AA$)$^{-1}$')
legend = axes.legend(fontsize=8.0).set_draggable(True).legend
fig.show()

image

Try playing around fixing parameters (see commented code), changing profile to PVProfile, changing background functions etc.

(3) Perform 2D refinement

pawley2d = PawleyPattern2D(ws, [si], profile=GaussianProfile(), global_scale=True , bg_func=FlatBackground())
pawley2d.set_params_from_pawley1d(pawley)


start = time()
res = pawley2d.fit()
print("Elapsed = ", time() - start)

# evaluate fit
ws_sim = pawley2d.eval_2d(res.x)
ws_sim_corr = PoldiAutoCorrelation(InputWorkspace=ws_sim)
ws_corr_resid = Minus(ws_corr, ws_sim_corr)

fig = plt.figure(figsize=(10,5))
gs = GridSpec(2, 1, height_ratios=[2, 1], hspace=0)
axes = [fig.add_subplot(gs[iax], projection='mantid') for iax in range(gs.nrows)]
axes[1].sharex(axes[0])
axes[0].plot(ws_corr, marker='o', color='k', markersize=2, ls='', label='ws_corr: spec 1', wkspIndex=0, distribution=True)
axes[0].plot(ws_sim_corr, ls='-', color='r', alpha=0.8, linewidth=1, label='fit', wkspIndex=0, distribution=True)
axes[1].plot(ws_corr_resid, marker='o', color='k', markersize=2, ls='', label='fit', wkspIndex=0, distribution=True)
axes[1].plot(ws_corr.readX(0), ws_corr.blocksize()*[0], alpha=0.8, linewidth=1,  ls='-', color='r')
dpks = pawley2d.phases[0].calc_dspacings()   
for ipk,dpk in enumerate(dpks):
    axes[0].axvline(2*np.pi/dpk, ymin=0, ymax=axes[0].get_ymargin()/2, ls='-', color='r', alpha=0.5)
axes[1].set_xlabel('q ($\\AA^{-1}$)')
axes[0].set_ylabel('Intensity (a.u.)')
axes[1].set_ylabel('Residuals (a.u.)')
legend = axes[0].legend(fontsize=8.0).set_draggable(True).legend
axes[0].set_xmargin(0.01) # zoom in on x-axis
fig.show()

image

Not sure why it's not fitting the peak at |Q|~2 Ang, it does in the silicon data with chopperspeed=10k


Reviewer

Your comments will be used as part of the gatekeeper process. Comment clearly on what you have checked and tested during your review. Provide an audit trail for any changes requested.

As per the review guidelines:

  • Is the code of an acceptable quality? (Code standards/GUI standards)
  • Has a thorough functional test been performed? Do the changes handle unexpected input/situations?
  • Are appropriately scoped unit and/or system tests provided?
  • Do the release notes conform to the guidelines and describe the changes appropriately?
  • Has the relevant (user and developer) documentation been added/updated?

Gatekeeper

As per the gatekeeping guidelines:

  • Has a thorough first line review been conducted, including functional testing?
  • At a high-level, is the code quality sufficient?
  • Are the base, milestone and labels correct?

@RichardWaiteSTFC RichardWaiteSTFC marked this pull request as draft September 8, 2025 15:36
@RichardWaiteSTFC RichardWaiteSTFC added Diffraction Issues and pull requests related to diffraction Powder Issues and pull requests related to powder diffraction ISIS: Diffraction Issue and pull requests relating to Diffraction at ISIS Epic Used for issues and PRs that are managed under the ISIS Epic Workstream labels Sep 8, 2025
@RichardWaiteSTFC
Copy link
Contributor Author

Blocked by #39776

@andy-bridger andy-bridger self-assigned this Sep 9, 2025
Copy link
Collaborator

@andy-bridger andy-bridger left a comment

Choose a reason for hiding this comment

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

I haven't done functional testing yet as I need to rebuild mantid on my pr testing branch but in the interest of not holding things up I did have a few comments and questions

@github-actions github-actions bot added the Has Conflicts Used by the bot to label pull requests that have conflicts label Sep 9, 2025
Copy link

github-actions bot commented Sep 9, 2025

👋 Hi, @RichardWaiteSTFC,

Conflicts have been detected against the base branch. Please rebase your branch against the base branch.

@github-actions github-actions bot removed the Has Conflicts Used by the bot to label pull requests that have conflicts label Sep 11, 2025
@RichardWaiteSTFC RichardWaiteSTFC marked this pull request as ready for review September 11, 2025 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Diffraction Issues and pull requests related to diffraction Epic Used for issues and PRs that are managed under the ISIS Epic Workstream ISIS: Diffraction Issue and pull requests relating to Diffraction at ISIS Powder Issues and pull requests related to powder diffraction
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement 2D fitting for POLDI Pawley refinement
2 participants