Commit 19c74ac7 authored by Thomas Vincent's avatar Thomas Vincent

remove fit module

parent 894e45e7
#!/usr/bin/python
# coding: utf8
# /*##########################################################################
#
# Copyright (c) 2015-2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
from __future__ import absolute_import
__authors__ = ["D. Naudet"]
__date__ = "01/01/2017"
__license__ = "MIT"
import numpy as np
from .Plotter import Plotter
from ..process.fit.Fitter import Fitter
from ..process.fit.fitresults import FitStatus
from ..process.fit.sharedresults import FitSharedResults
from ..process.fit.fitresults import FitResult
class CentroidFitter(Fitter):
def fit(self, i_fit, i_cube, qx_profile, qy_profile, qz_profile):
profiles = qx_profile, qy_profile, qz_profile
for iax, axis in enumerate(self._AXIS_NAMES):
y = profiles[iax]
Sum = y.sum()
if Sum != 0:
x = getattr(self, "_%s"%axis)
com = x.dot(y) / Sum
#idx = np.abs(x - com).argmin()
max_idx = y.argmax()
I_max = y[max_idx]
x_max = x[max_idx]
self._shared_results.set_results(axis, i_fit,
[com, Sum, I_max, x_max],
FitStatus.OK)
else:
self._shared_results.set_results(axis, i_fit,
[np.nan, np.nan, np.nan, np.nan],
FitStatus.FAILED)
class CentroidResults(FitSharedResults):
def __init__(self,
n_points=None,
shared_results=None,
shared_status=None,
**kwargs):
super(CentroidResults, self).__init__(n_points=n_points,
n_params=4,
n_peaks=1,
shared_results=shared_results,
shared_status=shared_status)
def fit_results(self, *args, **kwargs):
fit_name = 'Centroid'
fitresults = FitResult(fit_name, *args, **kwargs)
for axis in self._AXIS_NAMES:
results = getattr(self, "_npy_%s_results"%axis)
status = getattr(self, "_npy_%s_status"%axis)
for i_p, param in enumerate(("COM", "I_sum", "I_max", "Pos_max")):
fitresults.add_result(axis, 'centroid', param, results[:, 0+i_p].ravel())
fitresults.set_status(axis, status)
return fitresults
class CentroidPlotter(Plotter):
def plotFit(self, plot, x, peakParams):
plot.setGraphTitle('center of mass')
for peakName, peak in peakParams.items():
center = peak.get('COM')
xmax = peak.get('Pos_max')
if np.isfinite(center):
plot.addXMarker(center, legend='center of mass', text="com")
plot.addXMarker(xmax, legend='maximum position',
text="max",
color="gray")
def getPlotTitle(self):
return 'Center Of Mass'
# process = fitH5.processes(entry)[0]
#
# positions = fitH5.get_result(entry, process, 'COM')
#
# plots[0].addCurve(xAcqQX, yAcqQX, legend='measured')
# plots[0].addXMarker(positions.qx[index], legend='center of mass')
# plots[0].setGraphTitle('QX center of mass')
#
# plots[1].addCurve(xAcqQY, yAcqQY, legend='measured')
# plots[1].addXMarker(positions.qy[index], legend='center of mass')
# plots[1].setGraphTitle('QY center of mass')
#
# plots[2].addCurve(xAcqQZ, yAcqQZ, legend='measured')
# plots[2].addXMarker(positions.qz[index], legend='center of mass')
# plots[2].setGraphTitle('QZ center of mass')
#
#!/usr/bin/python
# coding: utf8
# /*##########################################################################
#
# Copyright (c) 2015-2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
from __future__ import absolute_import
__authors__ = ["D. Naudet"]
__date__ = "01/01/2017"
__license__ = "MIT"
import numpy as np
from scipy.optimize import leastsq
from .Plotter import Plotter
from ..process.fit.Fitter import Fitter
from ..process.fit.fitresults import FitStatus
from ..process.fit.sharedresults import FitSharedResults
from ..process.fit.fitresults import FitResult
# Some constants
_const_inv_2_pi_ = np.sqrt(2 * np.pi)
class GaussianFitter(Fitter):
def __init__(self, *args, **kwargs):
super(GaussianFitter, self).__init__(*args, **kwargs)
self._n_peaks = self._shared_results._n_peaks
def fit(self, i_fit, i_cube, qx_profile, qy_profile, qz_profile):
profiles = dict(zip(self._AXIS_NAMES,
[qx_profile, qy_profile, qz_profile]))
for axis in self._AXIS_NAMES: # qx, qy, qz
x = getattr(self, "_%s"%axis)
y = profiles[axis]
# compute guess:
area = y.sum()/self._n_peaks * (x[-1]-x[0])/len(x)
cen = x[y.argmax()]
sigma = area / (y.max() * _const_inv_2_pi_)
guess = np.tile([area, cen, sigma],self._n_peaks)
if self._n_peaks>1: # we don't actually use many peaks yet
# a stupid way to distribute the starting values...
idx = np.where(y>(y.max()/20.))[0]
i_cen = idx[np.arange(0, len(idx), len(idx)//self._n_peaks)]
cens = x[i_cen]
guess[1::3] = cens
fit, success = gaussian_fit(x, y, guess)
self._shared_results.set_results(axis, i_fit, fit, success)
class GaussianResults(FitSharedResults):
def __init__(self,
n_points=None,
n_peaks=1,
shared_results=None,
shared_status=None):
super(GaussianResults, self).__init__(n_points=n_points,
n_params=3,
n_peaks=n_peaks,
shared_results=shared_results,
shared_status=shared_status)
def fit_results(self, *args, **kwargs):
fit_name = 'Gaussian'
fitresults = FitResult(fit_name, *args, **kwargs)
for axis in self._AXIS_NAMES:
results = getattr(self, "_npy_%s_results"%axis)
status = getattr(self, "_npy_%s_status"%axis)
for i_peak in range(self._n_peaks):
peak_name = 'gauss_{0}'.format(i_peak)
i_start = i_peak * 3 # 3 parameters
for i_p, param in enumerate(("Area", "Center", "Sigma")):
fitresults.add_result(axis, peak_name, param,
results[:, i_start+i_p].ravel())
fitresults.set_status(axis, status)
return fitresults
# 1d Gaussian func
# TODO : optimize
def gaussian(x, a, c, s):
"""
Returns (a / (sqrt(2 * pi) * s)) * exp(- 0.5 * ((x - c) / s)^2)
:param x: values for which the gaussian must be computed
:param a: area under curve ( amplitude * s * sqrt(2 * pi) )
:param c: center
:param s: sigma
:return: (a / (sqrt(2 * pi) * s)) * exp(- 0.5 * ((x - c) / s)^2)
"""
# s /= _two_sqrt_2_log_2
return (a * (1. / (_const_inv_2_pi_ * s)) *
np.exp(-0.5 * ((x - c) / s) ** 2))
# 1d Gaussian fit
# TODO : optimize
def gaussian_fit_err(p, x, y):
"""
:param p:
:param x:
:param y:
:return:
"""
n_p = len(p) // 3
gSum = 0.
for i_p in range(n_p):
gSum += gaussian(x, *p[i_p*3:i_p*3 + 3])
return gSum - y
# return gaussian(x, *p) - y
_two_sqrt_2_log_2 = 2 * np.sqrt(2 * np.log(2))
def gaussian_fit(x, y, p):
"""
Fits (leastsq) a gaussian on the provided data f(x) = y.
p = (a, c, s)
and f(x) = (a / (sqrt(2 * pi) * s)) * exp(- 0.5 * ((x - c) / s)^2)
:param x:
:param y:
:param p:
:return: area, position, fwhm
"""
result = leastsq(gaussian_fit_err,
p,
args=(x, y,),
maxfev=100000,
full_output=True)
if result[4] not in [1, 2, 3, 4]:
return [np.nan] * len(p), FitStatus.FAILED
return result[0], FitStatus.OK
def _gauss_first_guess(x, y):
i_max = y.argmax()
y_max = y[i_max]
p1 = x[i_max]
i_fwhm = np.where(y >= y_max / 2.)[0]
fwhm = (x[1] - x[0]) * len(i_fwhm)
p2 = fwhm / np.sqrt(2 * np.log(2)) # 2.35482
p0 = y_max * np.sqrt(2 * np.pi) * p2
return [p0, p1, p2]
class GaussianPlotter(Plotter):
def plotFit(self, plot, x, peakParams):
for peakName, peak in peakParams.items():
height = peak.get('Area')
position = peak.get('Center')
width = peak.get('Sigma')
params = [height, position, width]
if np.all(np.isfinite(params)):
fitted = gaussian(x, *params)
plot.addCurve(x,
fitted,
legend='{0}'.format(peakName),
color='red')
def getPlotTitle(self):
return 'Gaussian'
#!/usr/bin/python
# coding: utf8
# /*##########################################################################
#
# Copyright (c) 2015-2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
from __future__ import absolute_import
__authors__ = ["D. Naudet"]
__date__ = "01/01/2017"
__license__ = "MIT"
class Plotter(object):
def __init__(self):
super(Plotter, self).__init__()
def plotFit(self, plot, x, params):
raise NotImplementedError('Not implemented')
def getPlotTitle(self):
raise NotImplementedError('Not implemented')
#!/usr/bin/python
# coding: utf8
# /*##########################################################################
#
# Copyright (c) 2015-2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
from __future__ import absolute_import
__authors__ = ["D. Naudet"]
__date__ = "01/01/2017"
__license__ = "MIT"
import numpy as np
from silx.math.fit import fittheories, sum_agauss
from silx.math.fit.fitmanager import FitManager
from .Plotter import Plotter
from ..process.fit.Fitter import Fitter
from ..process.fit.fitresults import FitStatus
from ..process.fit.sharedresults import FitSharedResults
from ..process.fit.fitresults import FitResult
class SilxFitter(Fitter):
p_types = ['A', 'P', 'F']
def __init__(self, *args, **kwargs):
super(SilxFitter, self).__init__(*args, **kwargs)
self._n_peaks = self._shared_results._n_peaks
self._fit = FitManager()
self._fit.loadtheories(fittheories)
self._fit.settheory('Area Gaussians')
self._results = np.zeros(3 * self._n_peaks)
def fit(self, i_fit, i_cube, qx_profile, qy_profile, qz_profile):
profiles = qx_profile, qy_profile, qz_profile
fit = self._fit
results = self._results
for iax, axis in enumerate(self._AXIS_NAMES):
failed = False
x = getattr(self, "_%s"%axis)
y = profiles[iax]
fit.setdata(x=x, y=y)
try:
fit.estimate()
fit.runfit()
except Exception as ex:
failed = True
results[:] = np.nan
if not failed:
for param in fit.fit_results:
p_name = param['name']
p_type = p_name[0]
peak_idx = int(p_name[-1]) - 1
if peak_idx >= self._n_peaks:
continue
# TODO : error management
param_idx = self.p_types.index(p_type)
results[peak_idx * 3 + param_idx] = param['fitresult']
self._shared_results.set_results(axis, i_fit, results,
FitStatus.OK)
else:
self._shared_results.set_results(axis, i_fit, results,
FitStatus.FAILED)
class SilxResults(FitSharedResults):
def __init__(self,
n_points=None,
n_peaks=1,
shared_results=None,
shared_status=None):
super(SilxResults, self).__init__(n_points=n_points,
n_params=3,
n_peaks=n_peaks,
shared_results=shared_results,
shared_status=shared_status)
def fit_results(self, *args, **kwargs):
fit_name = 'SilxFit'
fitresults = FitResult(fit_name, *args, **kwargs)
for axis in self._AXIS_NAMES:
results = getattr(self, "_npy_%s_results"%axis)
status = getattr(self, "_npy_%s_status"%axis)
for i_peak in range(self._n_peaks):
peak_name = 'gauss_{0}'.format(i_peak)
i_start = i_peak * 3
for i_p, param in enumerate(("Area", "Center", "FWHM")):
fitresults.add_result(axis, peak_name, param,
results[:, i_start+i_p].ravel())
fitresults.set_status(axis, status)
return fitresults
class SilxPlotter(Plotter):
def plotFit(self, plot, x, peakParams):
for peakName, peak in peakParams.items():
area = peak.get('Area')
position = peak.get('Center')
width = peak.get('FWHM')
params = [area, position, width]
fitSum = None
if np.all(np.isfinite(params)):
fitted = sum_agauss(x, *params)
plot.addCurve(x,
fitted,
legend='{0}'.format(peakName),
color='red')
if fitSum is None:
fitSum = fitted
else:
fitSum += fitted
if fitSum is not None:
plot.addCurve(x, fitSum, legend='Sum')
def getPlotTitle(self):
return 'Silx Gaussian Fit'
#!/usr/bin/python
# coding: utf8
# /*##########################################################################
#
# Copyright (c) 2015-2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
from __future__ import absolute_import
__authors__ = ["D. Naudet"]
__date__ = "01/01/2017"
__license__ = "MIT"
from .Gaussian import GaussianFitter, GaussianResults, GaussianPlotter
from .Centroid import CentroidFitter, CentroidResults, CentroidPlotter
#from .MaxFitter import MaxFitter, MaxResults, MaxPlotter
from .SilxFitter import SilxFitter, SilxResults, SilxPlotter
...@@ -34,7 +34,6 @@ def configuration(parent_package='', top_path=None): ...@@ -34,7 +34,6 @@ def configuration(parent_package='', top_path=None):
config = Configuration('xsocs', parent_package, top_path) config = Configuration('xsocs', parent_package, top_path)
config.add_subpackage('_app') config.add_subpackage('_app')
config.add_subpackage('examples') config.add_subpackage('examples')
config.add_subpackage('fit')
config.add_subpackage('gui') config.add_subpackage('gui')
config.add_subpackage('io') config.add_subpackage('io')
config.add_subpackage('process') config.add_subpackage('process')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment