Hi Jonas,
I'm guessing you found your way to the example here?
https://github.com/diffpy/cmi_exchange/blob/master/cmi_scripts/pdfrectprofile/rectangleprofile.py
(2) Possibly you don't actually need convolution for the way the PDF is synthesized. If your peak width model is length dependent, returning an x-dependent peak width in from the `__call__` method of your custom class might be sufficient? This might be a fundamental roadblock to implementation in DiffPy, on the other hand-- you would essentially be writing functionals, which may be incompatible with the PDFCalculator design.
That said, I abandoned this project in DiffPy (sorry devs!) and deserted to Topas.
Here are two examples attempting a range dependent peak width using DiffPy, either modifying (subclassing) or replacing the standard model:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"""
Example use:
from diffpy_helpers import CustomPeakWidth, CustomConstantPeakWidth
calc = rec.zif8.G._calc
calc.peakwidthmodel = CustomConstantPeakWidth()
calc.peakwidthmodel._deregisterType('jeong')
calc.peakwidthmodel.width = 0.5
calc.rcut = 6.5
calc.c1 = 0.03
print(calc.peakwidthmodel)
evaluate(rec)
ax.plot(rec.zif8.G.profile.x, rec.zif8.G.profile.ycalc, 'k--')
Created on Sun Mar 1 10:45:26 2020
@author: peter
"""
from copy import copy
from diffpy.srreal.peakprofile import PeakProfile
from diffpy.srreal.peakwidthmodel import PeakWidthModel, JeongPeakWidth, DebyeWallerPeakWidth, ConstantPeakWidth
class CustomConstantPeakWidth(ConstantPeakWidth):
""" """
def model(self, pt):
"""
model(pt) multiplicatively scales the Jeong peak width model
must be overriden in custom class instance.
Args:
- pt (float)
Returns:
model(pt) (float) | 1.
"""
if not hasattr(self, 'rcut'):
self.rcut = 0.
if not hasattr(self, 'c1'):
self.c1 = 0.
if pt <= self.rcut:
return 1.
elif pt > self.rcut:
return 1 + (pt - self.rcut) * self.c1
def calculate(self, bnds) -> float:
"""" """
return self.width * self.model(bnds.distance())
# End CustomPeakWidth
class CustomPeakWidth(JeongPeakWidth):
""" """
def model(self, pt):
"""
model(pt) multiplicatively scales the Jeong peak width model
must be overriden in custom class instance.
Args:
- pt (float)
Returns:
model(pt) (float) | 1.
"""
if not hasattr(self, 'rcut'):
self.rcut = 0.
if not hasattr(self, 'c1'):
self.c1 = 0.
if pt <= self.rcut:
return 1.
elif pt > self.rcut:
return 1 + (pt - self.rcut) * self.c1
def type(self):
""" """
return 'custompeakwidth'
def calculate(self, bnds) -> float:
"""" """
return super().calculate(bnds) * self.model(bnds.distance())
# End CustomPeakWidth
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
And here's a similar strategy implemented in Topas
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
Developing a range-dependent / correlated motion model for molecular crystals
Author: Peter Metz
Date: August 18 2020 11:18 EST
*/
' --- func defs ---
fn jeong(sigma, del1, del2, Qb)
{
' Jeong peak width model a.k.a. beqpdfgui
def default = 0;
' handle div by zero
def arg = If(X <= 0, default, (1 - (del1)/X - (del2)/X^2 + (Qb)^2 X^2)) ;
' handle imaginary
def eva = If(arg <= 0, default, sigma Sqrt(arg)) ;
' return
return eva ;
}
fn shifted_exp(rcut, sigma, exp)
{
' sigma(r) = sigma ( 1 + (X-rcut) ^ exp )
return sigma If( X <= rcut, 1, 1 + (X-rcut)^exp ) ;
}
fn mod1(sigma, del1, del2, Qb, rcut, exp)
{
' functional sigma(r) = shifted( jeong(r) )
return shifted_exp(rcut, jeong(sigma, del1, del2, Qb), exp) ;
}
fn mod2(sigma, del1, del2, Qb, rcut, exp)
{
' product sigma(r) = jeong(r) shifted_exp(r)
return jeong(sigma, del1, del2, Qb) shifted_exp(rcut, 1, exp) ;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you're unacquainted with Topas' syntax multiplication is implicit, so `mod1` is a functional, whereas `mod2` is a product.
I hope some of this is helpful, and attracts more discussion around this very interesting problem! I see it as a fundamental pathway forward for materials presenting multiple dissimilar bonding modes.
-Peter