Git commit ce3146c34bd53923c850fcaf62412adfeb5d802a by Stefan Gerlach. Committed on 14/07/2016 at 22:48. Pushed by sgerlach into branch 'master'.
added Legendre filter form M +1 -1 ChangeLog M +2 -1 doc/index.docbook M +35 -3 src/backend/nsl/nsl_filter.c M +2 -2 src/backend/nsl/nsl_filter.h M +21 -5 src/backend/nsl/nsl_filter_test.c M +1 -0 src/kdefrontend/dockwidgets/XYFourierFilterCurveDock.cpp http://commits.kde.org/labplot/ce3146c34bd53923c850fcaf62412adfeb5d802a diff --git a/ChangeLog b/ChangeLog index fb7db99..a59a3a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,7 +5,7 @@ New features: * Export of spreadsheets and matrices to LaTeX tables * Interpolation of data including different splines, cosine, exponential, cubic Hermite (Catmull-Rom, cardinal, Kochanek-Bartels) and rational functions * Data smoothing using moving average (centered or lagged), percentile filter or Savitzky-Golay algorithm - * Fourier filter (low pass, high pass, band pass, band reject) with ideal, Butterworth or Chebychev I+II kernel + * Fourier filter (low pass, high pass, band pass, band reject) with ideal, Butterworth, Chebychev I+II or Legendre filter * Fourier transform with many window functions (Welch, Hann, Hamming, etc.) calculating magnitude, amplitude, power, phase, dB, etc. and supporting one/two sided spectrum with or without shift and x scaling to frequency, index or period * Filter and search capabilities in the drop down box for the selection of data sources diff --git a/doc/index.docbook b/doc/index.docbook index 5585285..bef5754 100644 --- a/doc/index.docbook +++ b/doc/index.docbook @@ -860,7 +860,7 @@ The menu is only available when a datapicker object is selected on the <guilabel <listitem><para>Low pass</para></listitem> <listitem><para>High pass</para></listitem> <listitem><para>Band pass</para></listitem> - <listitem><para>Band reject (Band block)</para></listitem> + <listitem><para>Band reject (band block)</para></listitem> </itemizedlist> <para> where any of them can have the form @@ -869,6 +869,7 @@ The menu is only available when a datapicker object is selected on the <guilabel <listitem><para>Ideal</para></listitem> <listitem><para>Butterworth (order 1 to 10)</para></listitem> <listitem><para>Chebyshev type I or II (order 1 to 10)</para></listitem> + <listitem><para>Optimal Legendre (order 1 to 10)</para></listitem> </itemizedlist> <para> The cutoff value(s) can be specified in the units frequency (Hertz), fraction (0.0 to 1.0) or index diff --git a/src/backend/nsl/nsl_filter.c b/src/backend/nsl/nsl_filter.c index c669614..58d6c2d 100644 --- a/src/backend/nsl/nsl_filter.c +++ b/src/backend/nsl/nsl_filter.c @@ -62,21 +62,28 @@ int nsl_filter_apply(double data[], size_t n, nsl_filter_type type, nsl_filter_f break; case nsl_filter_form_butterworth: for (i = 0; i < n/2+1; i++) { - factor = 1./sqrt(1.+gsl_sf_pow_int(i/cutindex, 2*order)); + factor = 1./sqrt(1. + gsl_sf_pow_int(i/cutindex, 2*order)); data[2*i] *= factor; data[2*i+1] *= factor; } break; case nsl_filter_form_chebyshev_i: for (i = 0; i < n/2+1; i++) { - factor = 1./sqrt(1.+gsl_sf_pow_int(nsl_sf_poly_chebyshev_T(order, i/cutindex), 2)); + factor = 1./sqrt(1. + gsl_sf_pow_int(nsl_sf_poly_chebyshev_T(order, i/cutindex), 2)); data[2*i] *= factor; data[2*i+1] *= factor; } break; case nsl_filter_form_chebyshev_ii: for (i = 1; i < n/2+1; i++) { /* i==0: factor=1 */ - factor = 1./sqrt(1.+1./gsl_sf_pow_int(nsl_sf_poly_chebyshev_T(order, cutindex/i), 2)); + factor = 1./sqrt(1. + 1./gsl_sf_pow_int(nsl_sf_poly_chebyshev_T(order, cutindex/i), 2)); + data[2*i] *= factor; + data[2*i+1] *= factor; + } + break; + case nsl_filter_form_legendre: + for (i = 0; i < n/2+1; i++) { + factor = 1./sqrt(1. + nsl_sf_poly_optimal_legendre(order, i*i/(cutindex*cutindex) )); data[2*i] *= factor; data[2*i+1] *= factor; } @@ -112,6 +119,14 @@ int nsl_filter_apply(double data[], size_t n, nsl_filter_type type, nsl_filter_f data[2*i+1] *= factor; } break; + case nsl_filter_form_legendre: + data[0]=data[1]=0; + for (i = 1; i < n/2+1; i++) { + factor = 1./sqrt(1. + nsl_sf_poly_optimal_legendre(order, cutindex*cutindex/(i*i) )); + data[2*i] *= factor; + data[2*i+1] *= factor; + } + break; } break; case nsl_filter_type_band_pass: @@ -145,6 +160,15 @@ int nsl_filter_apply(double data[], size_t n, nsl_filter_type type, nsl_filter_f data[2*i+1] *= factor; } break; + case nsl_filter_form_legendre: + data[0]=data[1]=0; + for (i = 1; i < n/2+1; i++) { + factor = 1./sqrt(1. + nsl_sf_poly_optimal_legendre(order, + (i*i-2.*centerindex*centerindex+gsl_pow_4(centerindex)/(i*i))/gsl_pow_2(bandwidth) )); + data[2*i] *= factor; + data[2*i+1] *= factor; + } + break; } break; case nsl_filter_type_band_reject: @@ -174,6 +198,14 @@ int nsl_filter_apply(double data[], size_t n, nsl_filter_type type, nsl_filter_f data[2*i+1] *= factor; } break; + case nsl_filter_form_legendre: + for (i = 0; i < n/2+1; i++) { + factor = 1./sqrt(1. + nsl_sf_poly_optimal_legendre(order, + gsl_pow_2(i*bandwidth)/gsl_pow_2(i*i-centerindex*centerindex) )); + data[2*i] *= factor; + data[2*i+1] *= factor; + } + break; } break; } diff --git a/src/backend/nsl/nsl_filter.h b/src/backend/nsl/nsl_filter.h index be97f88..2732093 100644 --- a/src/backend/nsl/nsl_filter.h +++ b/src/backend/nsl/nsl_filter.h @@ -35,9 +35,9 @@ typedef enum {nsl_filter_type_low_pass, nsl_filter_type_high_pass, nsl_filter_type_band_pass, nsl_filter_type_band_reject} nsl_filter_type; /*TODO: Threshold */ extern const char* nsl_filter_type_name[]; -#define NSL_FILTER_FORM_COUNT 4 +#define NSL_FILTER_FORM_COUNT 5 typedef enum {nsl_filter_form_ideal, nsl_filter_form_butterworth, nsl_filter_form_chebyshev_i, - nsl_filter_form_chebyshev_ii} nsl_filter_form; /*TODO: Gaussian, Bessel, ... */ + nsl_filter_form_chebyshev_ii, nsl_filter_form_legendre} nsl_filter_form; /*TODO: Gaussian, Bessel, ... */ extern const char* nsl_filter_form_name[]; /* unit for cutoff Frequency=0..f_max, Fraction=0..1, Index=0..N-1 diff --git a/src/backend/nsl/nsl_filter_test.c b/src/backend/nsl/nsl_filter_test.c index 492a54d..f891488 100644 --- a/src/backend/nsl/nsl_filter_test.c +++ b/src/backend/nsl/nsl_filter_test.c @@ -37,14 +37,30 @@ print_data(double data[], int n) { } int main() { - double data[]={1, 2, 3, 3, 1, -1, 0, 1, 1, 0}; + /* double data[]={1, 2, 3, 3, 1, -1, 0, 1, 1, 0}; */ /*double data[]={1, 1, 3, 3, 1, -1, 0, 1, 1};*/ /*double data[]={1, 2, 3, 3, 1};*/ - const int N=10; + const int N=1002; /*const int N=9;*/ + double data[N]; - print_data(data, N); - nsl_filter_fourier(data, N, nsl_filter_type_high_pass, nsl_filter_form_ideal, 0, 0, 2); + int i; + for(i=0;i<N;i++) + data[i]=1.0; + + /* filter form */ + /*nsl_filter_apply(data, N, nsl_filter_type_low_pass, nsl_filter_form_legendre, 2, 50, 2);*/ + /*nsl_filter_apply(data, N, nsl_filter_type_high_pass, nsl_filter_form_legendre, 2, 50, 2);*/ + /*nsl_filter_apply(data, N, nsl_filter_type_band_pass, nsl_filter_form_legendre, 2, 100, 50);*/ + nsl_filter_apply(data, N, nsl_filter_type_band_reject, nsl_filter_form_legendre, 2, 100, 100); + for(i=0; i < N/2; i++) + printf("%d %g\n", i, data[2*i]); + + /*print_data(data, N);*/ + /* all pass order,cut,bw */ + /*nsl_filter_fourier(data, N, nsl_filter_type_high_pass, nsl_filter_form_ideal, 0, 0, 2); */ + + /* filter tests */ /*nsl_filter_fourier(data, N, nsl_filter_type_low_pass, nsl_filter_form_ideal, 0, 3, 2);*/ /*nsl_filter_fourier(data, N, nsl_filter_type_high_pass, nsl_filter_form_ideal, 0, 3, 2);*/ /*nsl_filter_fourier(data, N, nsl_filter_type_band_pass, nsl_filter_form_ideal, 0, 2, 2);*/ @@ -52,7 +68,7 @@ int main() { /*nsl_filter_fourier(data, N, nsl_filter_type_low_pass, nsl_filter_form_butterworth, 1, 2, 2);*/ /*nsl_filter_fourier(data, N, nsl_filter_type_high_pass, nsl_filter_form_butterworth, 1, 2, 2);*/ /*nsl_filter_fourier(data, N, nsl_filter_type_band_pass, nsl_filter_form_butterworth, 2, 2, 2);*/ - print_data(data, N); + /*print_data(data, N);*/ return 0; } diff --git a/src/kdefrontend/dockwidgets/XYFourierFilterCurveDock.cpp b/src/kdefrontend/dockwidgets/XYFourierFilterCurveDock.cpp index d17e322..b6f8ef9 100644 --- a/src/kdefrontend/dockwidgets/XYFourierFilterCurveDock.cpp +++ b/src/kdefrontend/dockwidgets/XYFourierFilterCurveDock.cpp @@ -299,6 +299,7 @@ void XYFourierFilterCurveDock::formChanged() { case nsl_filter_form_butterworth: case nsl_filter_form_chebyshev_i: case nsl_filter_form_chebyshev_ii: + case nsl_filter_form_legendre: uiGeneralTab.sbOrder->setVisible(true); uiGeneralTab.lOrder->setVisible(true); break; _______________________________________________ kde-doc-english mailing list [email protected] https://mail.kde.org/mailman/listinfo/kde-doc-english
