# coding: utf-8 # /*########################################################################## # Copyright (C) 2016 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. # # ############################################################################*/ """ Tests for peaks module """ import unittest import numpy import math from silx.math.fit import functions from silx.math.fit import peaks class Test_peak_search(unittest.TestCase): """ Unit tests of peak_search on various types of multi-peak functions. """ def setUp(self): self.x = numpy.arange(5000) # (height1, center1, fwhm1, ...) self.h_c_fwhm = (50, 500, 100, 50, 600, 80, 20, 2000, 100, 50, 2250, 110, 40, 3000, 99, 23, 4980, 80) # (height1, center1, fwhm1, eta1 ...) self.h_c_fwhm_eta = (50, 500, 100, 0.4, 50, 600, 80, 0.5, 20, 2000, 100, 0.6, 50, 2250, 110, 0.7, 40, 3000, 99, 0.8, 23, 4980, 80, 0.3,) # (height1, center1, fwhm11, fwhm21, ...) self.h_c_fwhm_fwhm = (50, 500, 100, 85, 50, 600, 80, 110, 20, 2000, 100, 100, 50, 2250, 110, 99, 40, 3000, 99, 110, 23, 4980, 80, 80,) # (height1, center1, fwhm11, fwhm21, eta1 ...) self.h_c_fwhm_fwhm_eta = (50, 500, 100, 85, 0.4, 50, 600, 80, 110, 0.5, 20, 2000, 100, 100, 0.6, 50, 2250, 110, 99, 0.7, 40, 3000, 99, 110, 0.8, 23, 4980, 80, 80, 0.3,) # (area1, center1, fwhm1, ...) self.a_c_fwhm = (2550, 500, 100, 2000, 600, 80, 500, 2000, 100, 4000, 2250, 110, 2300, 3000, 99, 3333, 4980, 80) # (area1, center1, fwhm1, eta1 ...) self.a_c_fwhm_eta = (500, 500, 100, 0.4, 500, 600, 80, 0.5, 200, 2000, 100, 0.6, 500, 2250, 110, 0.7, 400, 3000, 99, 0.8, 230, 4980, 80, 0.3,) # (area, position, fwhm, st_area_r, st_slope_r, lt_area_r, lt_slope_r, step_height_r) self.hypermet_params = (1000, 500, 200, 0.2, 100, 0.3, 100, 0.05, 1000, 1000, 200, 0.2, 100, 0.3, 100, 0.05, 1000, 2000, 200, 0.2, 100, 0.3, 100, 0.05, 1000, 2350, 200, 0.2, 100, 0.3, 100, 0.05, 1000, 3000, 200, 0.2, 100, 0.3, 100, 0.05, 1000, 4900, 200, 0.2, 100, 0.3, 100, 0.05,) def tearDown(self): pass def get_peaks(self, function, params): """ :param function: Multi-peak function :param params: Parameter for this function :return: list of (peak, relevance) tuples """ y = function(self.x, *params) return peaks.peak_search(y=y, fwhm=100, relevance_info=True) def testPeakSearch_various_functions(self): """Run peak search on a variety of synthetic functions, and check that result falls within +-25 samples of the actual peak (reasonable delta considering a fwhm of ~100 samples) and effects of overlapping peaks).""" f_p = ((functions.sum_gauss, self.h_c_fwhm ), (functions.sum_lorentz, self.h_c_fwhm), (functions.sum_pvoigt, self.h_c_fwhm_eta), (functions.sum_splitgauss, self.h_c_fwhm_fwhm), (functions.sum_splitlorentz, self.h_c_fwhm_fwhm), (functions.sum_splitpvoigt, self.h_c_fwhm_fwhm_eta), (functions.sum_agauss, self.a_c_fwhm), (functions.sum_fastagauss, self.a_c_fwhm), (functions.sum_alorentz, self.a_c_fwhm), (functions.sum_apvoigt, self.a_c_fwhm_eta), (functions.sum_ahypermet, self.hypermet_params), (functions.sum_fastahypermet, self.hypermet_params),) for function, params in f_p: peaks = self.get_peaks(function, params) self.assertEqual(len(peaks), 6, "Wrong number of peaks detected") for i in range(6): theoretical_peak_index = params[i*(len(params)//6) + 1] found_peak_index = peaks[i][0] self.assertLess(abs(found_peak_index - theoretical_peak_index), 25) test_cases = (Test_peak_search,) def suite(): loader = unittest.defaultTestLoader test_suite = unittest.TestSuite() for test_class in test_cases: tests = loader.loadTestsFromTestCase(test_class) test_suite.addTests(tests) return test_suite if __name__ == '__main__': unittest.main(defaultTest="suite")