Skip to content

skpkg: add scaffold, moved over .git. docs, test #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
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: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# As of now, flake8 does not natively support configuration via pyproject.toml
# https://github.com/microsoft/vscode-flake8/issues/135
[flake8]
exclude =
.git,
Expand Down
1 change: 1 addition & 0 deletions .isort.cfg
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[settings]
# Keep import statement below line_length character limit
line_length = 115
multi_line_output = 3
include_trailing_comma = True
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,9 @@ repos:
- id: codespell
additional_dependencies:
- tomli
- repo: https://github.com/s-weigand/docformatter
rev: 5757c5190d95e5449f102ace83df92e7d3b06c6c
hooks:
- id: docformatter
additional_dependencies: [tomli]
args: [--in-place, --wrap-summaries, "115", --wrap-descriptions, "115"] #--config, ./pyproject.toml]
File renamed without changes.
11 changes: 5 additions & 6 deletions doc/examples/fit_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
##############################################################################
"""Example of peak fitting C60 PDF (unnormalized) with unreliable uncertainties.

Peak fitting in SrMise means fitting a model of initial peaks, which may be
specified manually or estimated with a clustering-based convenience function,
just as with specifying initial peaks for peak extraction. Unlike peak
extraction, it does not attempt to add or remove peaks, apply termination
ripples, or otherwise do anything beyond chi-square fitting using the specified
grid."""
Peak fitting in SrMise means fitting a model of initial peaks, which may be specified manually or estimated with a
clustering-based convenience function, just as with specifying initial peaks for peak extraction. Unlike peak
extraction, it does not attempt to add or remove peaks, apply termination ripples, or otherwise do anything beyond
chi-square fitting using the specified grid.
"""

import matplotlib.pyplot as plt

Expand Down
4 changes: 2 additions & 2 deletions doc/examples/multimodel_known_dG1.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
# See LICENSE.txt for license information.
#
##############################################################################
"""Extract multiple models from crystalline PDF with known uncertainties for
use in later AIC-driven multimodeling analysis.
"""Extract multiple models from crystalline PDF with known uncertainties for use in later AIC-driven multimodeling
analysis.

The multimodel approach generates many models of varying complexity by assuming
a range of experimental uncertainties are physically plausible. This example
Expand Down
4 changes: 2 additions & 2 deletions doc/examples/multimodel_unknown_dG1.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
# See LICENSE.txt for license information.
#
##############################################################################
"""Extract multiple models from nanoparticle PDF with unknown uncertainties for
use in later AIC-driven multimodeling analysis.
"""Extract multiple models from nanoparticle PDF with unknown uncertainties for use in later AIC-driven
multimodeling analysis.

The multimodel approach generates many models of varying complexity by assuming
a range of experimental uncertainties are physically plausible. This example
Expand Down
3 changes: 1 addition & 2 deletions doc/examples/multimodel_unknown_dG2.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
# See LICENSE.txt for license information.
#
##############################################################################
"""AIC-driven multimodel analysis of nanoparticle PDF with unknown
uncertainties.
"""AIC-driven multimodel analysis of nanoparticle PDF with unknown uncertainties.

The multimodel approach generates many models of varying complexity by assuming
a range of experimental uncertainties are physically plausible. This example
Expand Down
3 changes: 2 additions & 1 deletion doc/examples/parameter_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
nyquist (whether to use Nyquist sampling)
supersample (minimum amount to oversample during initial stages)
cres (clustering resolution)
initial_peaks (peaks already assumed to exist during extraction)"""
initial_peaks (peaks already assumed to exist during extraction)
"""

import matplotlib.pyplot as plt

Expand Down
14 changes: 4 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,20 @@ build-backend = "setuptools.build_meta"
name = "diffpy.srmise"
dynamic=['version', 'dependencies']
authors = [
{ name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" },
{name="Luke Granlund", email="granlund@pa.msu.edu"},
{ name="Simon Billinge", email="sb2896@columbia.edu" },
]
maintainers = [
{ name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" },
{ name="Simon Billinge", email="sb2896@columbia.edu" },
]
description = "Peak extraction and peak fitting tool for atomic pair distribution functions."
keywords = ['peak extraction fitting PDF AIC multimodeling']
keywords = ['peak extraction', 'fitting', 'PDF', 'AIC', 'multimodeling']
readme = "README.rst"
requires-python = ">=3.11, <3.14"
classifiers = [
'Development Status :: 3 - Alpha',
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Developers',
'Intended Audience :: Science/Research',
'Intended Audience :: Education',
'License :: OSI Approved :: BSD License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
Expand All @@ -32,7 +30,6 @@ classifiers = [
'Programming Language :: Python :: 3.13',
'Topic :: Scientific/Engineering :: Physics',
'Topic :: Scientific/Engineering :: Chemistry',
'Topic :: Software Development :: Libraries',
]

[project.urls]
Expand All @@ -45,9 +42,6 @@ template = "{tag}"
dev_template = "{tag}"
dirty_template = "{tag}"

[project.scripts]
srmise = "diffpy.srmise.applications.extract:main"

[tool.setuptools.packages.find]
where = ["src"] # list of folders that contain the packages (["."] by default)
include = ["*"] # package names should match these glob patterns (["*"] by default)
Expand Down
1 change: 0 additions & 1 deletion src/diffpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# See LICENSE.rst for license information.
#
##############################################################################

"""Blank namespace package for module diffpy."""


Expand Down
1 change: 0 additions & 1 deletion src/diffpy/srmise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# See LICENSE.rst for license information.
#
##############################################################################

"""Peak extraction and peak fitting tool for atomic pair distribution functions."""

# package version
Expand Down
4 changes: 2 additions & 2 deletions src/diffpy/srmise/applications/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# See LICENSE.txt for license information.
#
##############################################################################
"""plot extracted peaks and comparison to ideal distances (if given)"""
"""Plot extracted peaks and comparison to ideal distances (if given)"""

import optparse
import sys
Expand Down Expand Up @@ -175,7 +175,7 @@ def labelallsubplots():


def makeplot(ppe_or_stability, ip=None, **kwds):
"""Plot stuff"""
"""Plot stuff."""
if isinstance(ppe_or_stability, PeakStability):
stability = ppe_or_stability
ppe = stability.ppe
Expand Down
37 changes: 28 additions & 9 deletions src/diffpy/srmise/basefunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def __init__(
base=None,
Cache=None,
):
"""Set parameterdict defined by subclass
"""Set parameterdict defined by subclass.

Parameters
----------
Expand Down Expand Up @@ -159,32 +159,50 @@ def __init__(
# "Virtual" class methods ####

def actualize(self, *args, **kwds):
"""Create ModelPart instance of self with given parameters. ("Virtual" method)"""
"""Create ModelPart instance of self with given parameters.

("Virtual" method)
"""
emsg = "actualize() must be implemented in a BaseFunction subclass."
raise NotImplementedError(emsg)

def estimate_parameters(self, *args, **kwds):
"""Estimate BaseFunction parameters from supplied data. ("Virtual" method)"""
"""Estimate BaseFunction parameters from supplied data.

("Virtual" method)
"""
emsg = "estimate_parameters() must be implemented in a BaseFunction subclass."
raise NotImplementedError(emsg)

def _jacobianraw(self, *args, **kwds):
"""Calculate the jacobian. ("Virtual" method)"""
"""Calculate the jacobian.

("Virtual" method)
"""
emsg = "_jacobianraw() must be implemented in a BaseFunction subclass."
raise NotImplementedError(emsg)

def _transform_derivativesraw(self, *args, **kwds):
"""Convert BaseFunction parameters to another form. ("Virtual" method)"""
"""Convert BaseFunction parameters to another form.

("Virtual" method)
"""
emsg = "transform_parameters() must be implemented in a BaseFunction subclass."
raise NotImplementedError(emsg)

def _transform_parametersraw(self, *args, **kwds):
"""Convert BaseFunction parameters to another form. ("Virtual" method)"""
"""Convert BaseFunction parameters to another form.

("Virtual" method)
"""
emsg = "transform_parameters() must be implemented in a BaseFunction subclass."
raise NotImplementedError(emsg)

def _valueraw(self, *args, **kwds):
"""Calculate value of function. ("Virtual" method)"""
"""Calculate value of function.

("Virtual" method)
"""
emsg = "_valueraw must() be implemented in a BaseFunction subclass."
raise NotImplementedError(emsg)

Expand Down Expand Up @@ -373,7 +391,7 @@ def pgradient(self, p, format):
return

def getmodule(self):
"""Return 'diffpy.srmise.basefunction'"""
"""Return 'diffpy.srmise.basefunction'."""
return "diffpy.srmise.basefunction"

def writestr(self, baselist):
Expand Down Expand Up @@ -480,7 +498,8 @@ def safefunctionlist(fs):
is guaranteed to be safe for saving/reinstantiating peak functions.

Parameters
fs: List of BaseFunction instances."""
fs: List of BaseFunction instances.
"""
fsafe = []
for f in fs:
BaseFunction.safefunction(f, fsafe)
Expand Down
20 changes: 8 additions & 12 deletions src/diffpy/srmise/baselines/arbitrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,12 @@
class Arbitrary(BaselineFunction):
"""Methods for evaluating a baseline from an arbitrary function.

Supports baseline calculations with arbitrary functions. These functions,
if implemented, must have the following signatures and return values:
valuef(pars, x) ==> numpy.array of length x if x is a sequence
==> number if x is a number
jacobianf(pars, x, free) ==> list, each element a numpy.array of length x if
x is a sequence or None if value of free for
that parameter is False.
==> list, each element a number if x is a number
or None if value of free for that parameter is
False
estimatef(x, y) ==> numpy.array of length npars
Supports baseline calculations with arbitrary functions. These functions, if implemented, must have the
following signatures and return values: valuef(pars, x) ==> numpy.array of length x if x is a sequence
==> number if x is a number jacobianf(pars, x, free) ==> list, each element a numpy.array of length x if
x is a sequence or None if value of free for that parameter is False.
==> list, each element a number if x is a number or None if value of free for that
parameter is False estimatef(x, y) ==> numpy.array of length npars
"""

def __init__(self, npars, valuef, jacobianf=None, estimatef=None, Cache=None):
Expand Down Expand Up @@ -117,7 +112,8 @@ def estimate_parameters(self, r, y):
The numpy array of parameters in the default internal format.

we raise NotImplementedError if no estimation routine is defined, and
SrMiseEstimationError if parameters cannot be estimated for any other."""
SrMiseEstimationError if parameters cannot be estimated for any other.
"""
if self.estimatef is None:
emsg = "No estimation routine provided to Arbitrary."
raise NotImplementedError(emsg)
Expand Down
5 changes: 3 additions & 2 deletions src/diffpy/srmise/baselines/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def __init__(
base=None,
Cache=None,
):
"""Set parameterdict defined by subclass
"""Set parameterdict defined by subclass.

parameterdict : dict
The dictionary mapping string keys to their index in a
Expand All @@ -91,7 +91,8 @@ def __init__(
additional functionality.
Cache : class
The class (not instance) which implements caching of BaseFunction
evaluations."""
evaluations.
"""
BaseFunction.__init__(self, parameterdict, parformats, default_formats, metadict, base, Cache)

# "Virtual" class methods ####
Expand Down
8 changes: 4 additions & 4 deletions src/diffpy/srmise/baselines/fromsequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
class FromSequence(BaselineFunction):
"""Methods for evaluation of a baseline from discrete data via interpolation.

FromSequence uses cubic spline interpolation (no smoothing) on discrete
points to approximate the baseline at arbitrary points within the
interpolation domain. This baseline function permits no free parameters."""
FromSequence uses cubic spline interpolation (no smoothing) on discrete points to approximate the baseline at
arbitrary points within the interpolation domain. This baseline function permits no free parameters.
"""

def __init__(self, *args, **kwds):
"""Initialize a baseline object based on input sequences `x` and `y`.
Expand Down Expand Up @@ -233,7 +233,7 @@ def xyrepr(self, var):
return "[%s]" % ", ".join([repr(v) for v in var])

def readxy(self, filename):
""" """
""""""
from diffpy.srmise.srmiseerrors import SrMiseDataFormatError

# TODO: Make this safer
Expand Down
2 changes: 1 addition & 1 deletion src/diffpy/srmise/baselines/nanospherical.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ def _valueraw2(self, pars, r):
return -s * r * (1 - (3.0 / 4.0) * rdivR + (1.0 / 16.0) * rdivR**3)

def _getdomain(self, pars, r):
"""Return slice object for which r > 0 and r < twice the radius
"""Return slice object for which r > 0 and r < twice the radius.

Parameters
----------
Expand Down
14 changes: 8 additions & 6 deletions src/diffpy/srmise/dataclusters.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class DataClusters:
"""

def __init__(self, x, y, res):
"""Constructor
"""Constructor.

Parameters
----------
Expand Down Expand Up @@ -102,8 +102,7 @@ def __eq__(self, other):
)

def _clear(self):
"""
Clear all data and reset the cluster object to a transient initial state.
"""Clear all data and reset the cluster object to a transient initial state.

The purpose of this method is to provide a clean state before creating new clustering operations.
The object is updated in-place and no new instance is returned.
Expand Down Expand Up @@ -175,8 +174,8 @@ def _setdata(self, x, y, res):
def __next__(self):
"""Cluster point with largest y-coordinate left, returning self.

next() always adds at least one additional point to the existing
cluster, or raises an exception if all points have been clustered.
next() always adds at least one additional point to the existing cluster, or raises an exception if all
points have been clustered.
"""
if self.status == self.INIT:
raise Exception("Cannot cluster next point while status is INIT.")
Expand Down Expand Up @@ -465,7 +464,10 @@ def plot(self, *args, **kwds):
return

def animate(self):
"""Animate clustering. Restores state when complete."""
"""Animate clustering.

Restores state when complete.
"""
clusters = self.clusters
current_idx = self.current_idx
lastcluster_idx = self.lastcluster_idx
Expand Down
Loading