Warning, /graphics/kst-plot/docbook/kst/creatingplugins-chapter-new.docbook is written in an unsupported language. File is not indexed.
0001 <appendix id="creatingplugins">
0002 <title>Creating Additional Plugins</title>
0003 <warning>
0004 <para>WARNING: This section was written for Kst version 1 and may be somewhat, or even totally obsolete. WARNING</para>
0005 </warning>
0006
0007 <para>
0008 &kst; has a simple and standardized interface that facilitates easy creation of additional plugins.
0009 In addition to detailing basic requirements for plugins, the following sections describe how to make
0010 use of pre-written header files to create certain types of plugins.
0011 </para>
0012
0013 <sect1 id="creatingbasicplugin">
0014 <title>Creating a Basic Plugin</title>
0015 <para>
0016 A &kst; plugin consists of two files—a KDE desktop service file and a shared object file.
0017 </para>
0018
0019 <sect2 id="creatingbasicplugindesktopfile">
0020 <title>The KDE Desktop Service File</title>
0021 <para>
0022 The KDE desktop service file provides information about the plugin to the &kst; plugin loading infrastructure. The following is an example of a KDE desktop service file for a &kst; plugin:
0023 </para>
0024
0025 <informalexample>
0026 <screen>
0027 [Desktop Entry]
0028 Encoding=UTF-8
0029 Type=Service
0030 ServiceTypes=Kst Data Object
0031 X-KDE-ModuleType=Plugin
0032 X-KDE-Library=kst_FOO_plugin
0033 X-Kst-Plugin-Author=FOO
0034 Name=FOO Plugin
0035 Comment=The FOO algorithm for Kst.
0036 </screen>
0037 </informalexample>
0038
0039 <para>
0040 Generally, you can use the example above as a template and modify the FOO entries to fit your plugin.
0041 As can be seen from the example, the desktop service file consists of a series of key value pairs. The
0042 <literal>ServiceTypes</literal> entry should be left as seen above. This key indicates that the plugin inherits
0043 the KstDataObject class. See the API documentation for the interfaces this class exposes. The
0044 <literal>X-KDE-Library</literal> key points to the shared object file that implements your plugin. Do not
0045 include the shared object's file extension.
0046 </para>
0047
0048 <para>
0049 Once you have completed the desktop file, save it as <filename>[X-KDE-LIBRARY].desktop</filename>, where
0050 <filename>[X-KDE-LIBRARY]</filename> is the value of the key in the desktop file.
0051 </para>
0052
0053 </sect2>
0054
0055 <sect2 id="creatingbasicpluginobjectfile">
0056 <title>The Shared Object File</title>
0057 <para>
0058 The shared object file contains the actual functionality of the plugin. The following are the
0059 requirements for the shared object file:
0060 </para>
0061
0062 <itemizedlist>
0063
0064 <listitem>
0065 <para>
0066 The object must inherit the KstDataObject class:
0067
0068 <informalexample>
0069 <screen>
0070 #ifndef FOOPLUGIN_H
0071 #define FOOPLUGIN_H
0072
0073 #include <kstdataobject.h>
0074
0075 class FooPlugin : public KstDataObject {
0076 Q_OBJECT
0077 public:
0078 FooPlugin(QObject *parent, const char *name, const QStringList &args);
0079 virtual ~FooPlugin();
0080
0081 virtual KstObject::UpdateType update(int);
0082 virtual QString propertyString() const;
0083 virtual KstDataObjectPtr makeDuplicate(KstDataObjectDataObjectMap&);
0084
0085 protected slots:
0086 virtual void _showDialog();
0087 };
0088
0089 #endif
0090
0091 </screen>
0092 </informalexample>
0093 </para>
0094
0095 </listitem>
0096
0097 </itemizedlist>
0098
0099 <para>
0100 The following is an example of the shared object file source code for a simple
0101 plugin:
0102 </para>
0103 <informalexample>
0104 <screen>
0105 </screen>
0106 </informalexample>
0107 </sect2>
0108
0109
0110 <sect2 id="compilingplugin">
0111 <title>Compiling the Plugin</title>
0112 <para>
0113 If you are using &gcc; to compile your plugin, simply compile the object file:
0114 <screen><userinput><command>cc -Wall -c -o myplugin.o myplugin.c -fPIC -DPIC</command></userinput></screen>
0115 </para>
0116 <para>and then create the shared library:
0117 <screen><userinput><command>ld -o myplugin.so -shared myplugin.o</command></userinput></screen>
0118 </para>
0119 <para>
0120 The resulting <filename>*.so</filename> file and <filename>*.xml</filename> file must be put in the same
0121 directory. When you use &kst;'s Plugin Manager to load the XML file, it will automatically look for the
0122 shared object file in the same directory.
0123 </para>
0124
0125 </sect2>
0126 </sect1>
0127
0128 <sect1 id="creatinglinearfittingplugins">
0129 <title>Creating Linear Fit Plugins</title>
0130 <para>
0131 To create a linear fit plugin, you could implement your own fitting algorithms and output the appropriate
0132 vectors. However, &kst; already comes with header files that make it easy for you to implement linear
0133 least-squares fit plugins by just providing a few functions.
0134 This section will describe how to take advantage of these files.
0135 </para>
0136
0137 <sect2 id="headerslinearfittingplugins">
0138 <title>Header Files</title>
0139 <para>
0140 Two header files are provided for performing linear fits, <filename>linear.h</filename>
0141 (for unweighted linear fits) and
0142 <filename>linear_weighted.h</filename> (for weighted linear fits). They are both located under
0143 <filename>kst/plugins/fits/</filename> in the &kst; source tarball. To use these files, include only one
0144 of them in the source code for your plugin:
0145 <screen>
0146 #include <../linear.h>
0147 </screen>
0148 or
0149 <screen>
0150 #include <../linear_weighted.h>
0151 </screen>
0152 (by convention, we will place the source code for the plugin one directory below where the header files
0153 are).
0154 </para>
0155
0156 </sect2>
0157
0158 <sect2 id="reqfunctionsfittingplugins">
0159 <title>Implementing Required Functions</title>
0160 <para>
0161 Given a general linear model:
0162 </para>
0163 <para>
0164 <inlinemediaobject>
0165 <imageobject>
0166 <imagedata fileref="Formula-kst-generallinearmodel.png" format="PNG"/>
0167 </imageobject>
0168 </inlinemediaobject>
0169 </para>
0170 <para>
0171 where <literal>y</literal> is a vector of <literal>n</literal> observations, <literal>X</literal>
0172 is an <literal>n</literal> by <literal>p</literal> matrix of predictor variables, and <literal>c</literal>
0173 is the vector of <literal>p</literal> best-fit parameters that are to be estimated, the header files
0174 provide functions for estimating <literal>c</literal> for a given <literal>y</literal> and
0175 <literal>X</literal>. To provide <literal>X</literal>, the following function needs to be
0176 implemented in the source code for the plugin:
0177 <literallayout><function><returnvalue>double</returnvalue> calculate_matrix_entry( double <parameter>dX</parameter>, int <parameter>iPos</parameter> )</function></literallayout>
0178 </para>
0179 <para>
0180 This function should return the value of the entry in column <literal>iPos</literal>
0181 of the matrix of predictor variables, using <literal>x</literal> value <literal>dX</literal>.
0182 This function will be called by linear.h or linear_weighted.h. The implementation of this function
0183 depends on the model you wish to use for the fit, and is unique to each linear fit plugin.
0184 For example, to fit to a polynomial model, <function>calculate_matrix_entry</function> could
0185 be implemented as follows:
0186 <informalexample>
0187 <screen>
0188 double calculate_matrix_entry( double dX, int iPos ) {
0189 double dY;
0190 dY = pow( dX, (double)iPos );
0191 return dY;
0192 }
0193 </screen>
0194 </informalexample>
0195 </para>
0196
0197 </sect2>
0198
0199 <sect2 id="callingfittingfunctionslinearfittingplugins">
0200 <title>Calling the Fitting Functions</title>
0201 <para>
0202 Once the appropriate header file has been included and <function>calculate_matrix_entry</function>
0203 has been implemented, call the appropriate fitting function included from the header file:
0204 <screen>
0205 <function>kstfit_linear_unweighted( <parameter>inArrays</parameter>, <parameter>inArrayLens</parameter>,
0206 <parameter>outArrays</parameter>, <parameter>outArrayLens</parameter>,
0207 <parameter>outScalars</parameter>, <parameter>iNumParams</parameter> )</function>;
0208 </screen>
0209 or
0210 <screen>
0211 <function>kstfit_linear_weighted( <parameter>inArrays</parameter>, <parameter>inArrayLens</parameter>,
0212 <parameter>outArrays</parameter>, <parameter>outArrayLens</parameter>,
0213 <parameter>outScalars</parameter>, <parameter>iNumParams</parameter> )</function>;
0214 </screen>
0215 </para>
0216 <para>
0217 Each function will return <literal>0</literal> on success, or <literal>-1</literal> on
0218 error, so it is a good idea to set the return value of the exported C function to be equal to the return
0219 value of the fitting function. To maintain simplicity, the code for the plugin can simply pass the
0220 arguments given to the exported C function to the fitting function. Note, however, that inArrays must
0221 be structured as follows:
0222 </para>
0223 <itemizedlist>
0224 <listitem>
0225 <para>
0226 <varname>inArrays[0]</varname> must contain the array of x coordinates of the data points
0227 </para>
0228 </listitem>
0229
0230 <listitem>
0231 <para>
0232 <varname>inArrays[1]</varname> must contain the array of y coordinates of the data points
0233 </para>
0234 </listitem>
0235
0236 <listitem>
0237 <para>
0238 <varname>inArrays[2]</varname> only exists if <function>kstfit_linear_weighted</function>
0239 is being called, and must contain the array of weights to use for the fit.
0240 </para>
0241 </listitem>
0242 </itemizedlist>
0243 <para>
0244 The easiest way to ensure that inArrays is structured correctly is to specify the correct
0245 order of input vectors in the XML file for the plugin.
0246 </para>
0247 <para>
0248 <varname>iNumParams</varname> is the number of parameters in the fitting model used, which
0249 should be equal to the number of columns in the matrix <literal>X</literal> of
0250 predictor variables. <varname>iNumParams</varname> must be set correctly before the fitting
0251 function is called.
0252 </para>
0253 <para>
0254 After <function>kstfit_linear_unweighted</function> or <function>kstfit_linear_weighted</function>
0255 is called, <varname>outArrays</varname> and <varname>outScalars</varname>
0256 will be set as follows:
0257 </para>
0258 <itemizedlist>
0259 <listitem>
0260 <para>
0261 <varname>outArrays[0]</varname> will contain the array of fitted y values.
0262 </para>
0263 </listitem>
0264
0265 <listitem>
0266 <para>
0267 <varname>outArrays[1]</varname> will contain the array of residuals.
0268 </para>
0269 </listitem>
0270
0271 <listitem>
0272 <para>
0273 <varname>outArrays[2]</varname> will contain the array of best-fit parameters that were estimated.
0274 </para>
0275 </listitem>
0276
0277 <listitem>
0278 <para>
0279 <varname>outArrays[3]</varname> will contain the covariance matrix, returned row after row in an array.
0280 </para>
0281 </listitem>
0282
0283 <listitem>
0284 <para>
0285 <varname>outScalars[0]</varname> will contain chi^2/nu, where chi^2 is the weighted sum of squares of the residuals,
0286 and nu is the degrees of freedom.
0287 </para>
0288 </listitem>
0289 </itemizedlist>
0290 <para>
0291 <varname>outArrayLens</varname> will be correctly set to indicate the length of each output array.
0292 </para>
0293
0294 <para>
0295 Ensure that the specified outputs in the XML file match those that the exported C function returns (which
0296 in most cases will simply be the outputs returned by the fitting function).
0297 </para>
0298
0299
0300 </sect2>
0301
0302 <sect2 id="examplelinearfittingplugins">
0303 <title>Example</title>
0304 <para>
0305 The following is an example of the source code for a linear fit plugin.
0306 </para>
0307 <informalexample>
0308 <screen>
0309 /*
0310 * Polynomial fitting plugin for KST.
0311 * Copyright 2004, The University of British Columbia
0312 * Released under the terms of the GPL.
0313 */
0314
0315 #include "../linear.h"
0316
0317 double calculate_matrix_entry( double dX, int iPos ) {
0318 double dY;
0319
0320 dY = pow( dX, (double)iPos );
0321
0322 return dY;
0323 }
0324
0325 extern "C" int kstfit_polynomial_unweighted(
0326 const double *const inArrays[],
0327 const int inArrayLens[],
0328 const double inScalars[],
0329 double *outArrays[], int outArrayLens[],
0330 double outScalars[]);
0331
0332 int kstfit_polynomial_unweighted(
0333 const double *const inArrays[],
0334 const int inArrayLens[],
0335 const double inScalars[],
0336 double *outArrays[], int outArrayLens[],
0337 double outScalars[])
0338 {
0339 int iRetVal = -1;
0340 int iNumParams;
0341
0342 iNumParams = 1 + (int)floor( inScalars[0] );
0343 if( iNumParams > 0 ) {
0344 iRetVal = kstfit_linear_unweighted( inArrays, inArrayLens,
0345 outArrays, outArrayLens,
0346 outScalars, iNumParams );
0347 }
0348
0349 return iRetVal;
0350 }
0351 </screen>
0352 </informalexample>
0353 </sect2>
0354
0355 </sect1>
0356
0357 <sect1 id="creatingnonlinearfitplugin">
0358 <title>Creating Non-linear Fit Plugins</title>
0359 <para>
0360 &kst; provides header files designed to simplify the creation of non-linear least-squares fit plugins.
0361 The following sections detail the use of the header files.
0362 </para>
0363
0364 <sect2 id="headersnonlinearfittingplugins">
0365 <title>Header Files and Definitions</title>
0366 <para>
0367 The non-linear fit header files are located in <filename>kst/plugins/fits_nonlinear</filename> of
0368 the &kst; source tarball. The files are named <filename>non_linear.h</filename> and
0369 <filename>non_linear_weighted.h</filename> for unweighted and weighted fits, respectively.
0370 To use these files, include only one of them in the source code for your plugin:
0371 <screen>
0372 #include <../non_linear.h>
0373 </screen>
0374 or
0375 <screen>
0376 #include <../non_linear_weighted.h>
0377 </screen>
0378 (by convention, we will place the source code for the plugin one directory below where the header files
0379 are).
0380 </para>
0381
0382 <para>
0383 As non-linear fitting is an iterative process, you must also define the maximum number of iterations
0384 that should be performed. The non-linear fitting algorithm will stop when at least one of the following
0385 conditions is true:
0386 </para>
0387 <itemizedlist>
0388 <listitem>
0389 <para>
0390 The maximum number of iterations has been reached.
0391 </para>
0392 </listitem>
0393 <listitem>
0394 <para>
0395 A precision of 10<superscript>-4</superscript> has been reached.
0396 </para>
0397 </listitem>
0398 </itemizedlist>
0399 <para>
0400 In addition, you need to define the number of parameters in the model, as it is not passed to the fitting
0401 function explicitly. To define these two values, include the following at the top of your source code:
0402 </para>
0403 <screen>
0404 #define NUM_PARAMS [num1]
0405 #define MAX_NUM_ITERATIONS [num2]
0406 </screen>
0407 <para>
0408 replacing <literal>[num1]</literal> with the number of parameters in the model, and <literal>[num2]</literal>
0409 with the maximum number of iterations to perform.
0410 </para>
0411 </sect2>
0412
0413 <sect2 id="reqfunctionsnonlinearfittingplugins">
0414 <title>Implementing Required Functions</title>
0415 <para>
0416 To use the header files for non-linear fits, you must provide the function to use as the model,
0417 the partial derivatives of the function with respect to each parameter, and initial estimates
0418 of the best-fit parameters.
0419 To do this, three functions must be implemented. These functions
0420 are described below.
0421 </para>
0422 <variablelist>
0423 <varlistentry>
0424 <term><function><returnvalue>double</returnvalue> function_calculate( double <parameter>dX</parameter>, double* <parameter>pdParameters</parameter> )</function></term>
0425 <listitem>
0426 <para>
0427 This function calculates the y value of the fitting model for a given x value <literal>dX</literal>,
0428 using the supplied array of parameters <varname>pdParameters</varname>. The order of parameters in
0429 <varname>pdParameters</varname> is arbitrary, but should be consistent with the other two
0430 implemented functions.
0431 For example, for an exponential model,
0432 <function>function_calculate</function> could be implemented as follows:
0433 </para>
0434 <informalexample>
0435 <screen>
0436 double function_calculate( double dX, double* pdParameters ) {
0437 double dScale = pdParameters[0];
0438 double dLambda = pdParameters[1];
0439 double dOffset = pdParameters[2];
0440 double dY;
0441
0442 dY = ( dScale * exp( -dLambda * dX ) ) + dOffset;
0443
0444 return dY;
0445 }
0446 </screen>
0447 </informalexample>
0448 </listitem>
0449 </varlistentry>
0450
0451 <varlistentry>
0452 <term><function><returnvalue>void</returnvalue> function_derivative( double <parameter>dX</parameter>, double* <parameter>pdParameters</parameter>, double* <parameter>pdDerivatives</parameter> )</function></term>
0453 <listitem>
0454 <para>
0455 This function calculates the partial derivatives of the model function for
0456 a give value of x <literal>dX</literal>. The partial derivatives should be returned in
0457 <varname>pdDerivatives</varname>. The order of the partial derivatives in the array
0458 <varname>pdDerivatives</varname> should correspond to the order of the parameters
0459 in <varname>pdParameters</varname> (i.e. if <varname>pdParameters[0]</varname> contains
0460 the parameter lambda for an exponential model, <varname>pdDerivatives[0]</varname> should
0461 contain the derivative of the model with respect to lambda).
0462 </para>
0463 </listitem>
0464 </varlistentry>
0465
0466 <varlistentry>
0467 <term><function><returnvalue>void</returnvalue> function_initial_estimate(
0468 const double* <parameter>pdX</parameter>, const double* <parameter>pdY</parameter>,
0469 int <parameter>iLength</parameter>, double* <parameter>pdParameterEstimates</parameter> )</function></term>
0470 <listitem>
0471 <para>
0472 This function provides an initial estimate of the best-fit parameters to the fitting function. The array of
0473 x values and y values of the data points are provided in <varname>pdX</varname> and <varname>pdY</varname>
0474 respectively, and the number of data points is provided by <varname>iLength</varname>. You can use any or
0475 none of these parameters at your discretion to calculate the initial estimate. The function should put the
0476 calculated initial estimates in <varname>pdParameterEstimates</varname>, with the order of the estimates
0477 corresponding to the order of the parameters in <varname>pdParameters</varname> of
0478 <function>function_calculate</function> and <function>function_derivative</function>. Keep in mind that the
0479 initial estimate is important in determining whether or not the fitting function converges to a solution.
0480 </para>
0481 </listitem>
0482 </varlistentry>
0483
0484 </variablelist>
0485
0486 </sect2>
0487
0488 <sect2 id="callingnonlinearfittingplugins">
0489 <title>Calling the Fitting Functions</title>
0490 <para>
0491 Once all the required functions have been implemented, the fitting function from the included header file
0492 can be called:
0493 <screen>
0494 kstfit_nonlinear( <parameter>inArrays</parameter>, <parameter>inArrayLens</parameter>,
0495 <parameter>inScalars</parameter>, <parameter>outArrays</parameter>,
0496 <parameter>outArrayLens</parameter>, <parameter>outScalars</parameter> );
0497 </screen>
0498 or
0499 <screen>
0500 kstfit_nonlinear_weighted( <parameter>inArrays</parameter>, <parameter>inArrayLens</parameter>,
0501 <parameter>inScalars</parameter>, <parameter>outArrays</parameter>,
0502 <parameter>outArrayLens</parameter>, <parameter>outScalars</parameter> );
0503 </screen>
0504 depending on whether you are implementing a non-weighted fit or a weighted fit.
0505 </para>
0506
0507 <para>
0508 The function will return <literal>0</literal> on success, or <literal>-1</literal> on
0509 error, so it is simplest to set the return value of the exported C function to be equal to the return
0510 value of the fitting function. To maintain simplicity, the code for the plugin can simply pass the
0511 arguments given to the exported C function to the fitting function. Note, however, that inArrays must
0512 be structured as follows:
0513 </para>
0514 <itemizedlist>
0515 <listitem>
0516 <para>
0517 <varname>inArrays[0]</varname> must contain the array of x coordinates of the data points
0518 </para>
0519 </listitem>
0520
0521 <listitem>
0522 <para>
0523 <varname>inArrays[1]</varname> must contain the array of y coordinates of the data points
0524 </para>
0525 </listitem>
0526
0527 <listitem>
0528 <para>
0529 <varname>inArrays[2]</varname> only exists if <function>kstfit_linear_weighted</function>
0530 is being called, and must contain the array of weights to use for the fit.
0531 </para>
0532 </listitem>
0533 </itemizedlist>
0534 <para>
0535 The easiest way to ensure that inArrays is structured correctly is to specify the correct
0536 order of input vectors in the XML file for the plugin.
0537 </para>
0538 <para>
0539 After <function>kstfit_linear_unweighted</function> or <function>kstfit_linear_weighted</function>
0540 is called, <varname>outArrays</varname> and <varname>outScalars</varname>
0541 will be set as follows:
0542 </para>
0543 <itemizedlist>
0544 <listitem>
0545 <para>
0546 <varname>outArrays[0]</varname> will contain the array of fitted y values.
0547 </para>
0548 </listitem>
0549
0550 <listitem>
0551 <para>
0552 <varname>outArrays[1]</varname> will contain the array of residuals.
0553 </para>
0554 </listitem>
0555
0556 <listitem>
0557 <para>
0558 <varname>outArrays[2]</varname> will contain the array of best-fit parameters that were estimated.
0559 </para>
0560 </listitem>
0561
0562 <listitem>
0563 <para>
0564 <varname>outArrays[3]</varname> will contain the covariance matrix, returned row after row in an array.
0565 </para>
0566 </listitem>
0567
0568 <listitem>
0569 <para>
0570 <varname>outScalars[0]</varname> will contain chi^2/nu, where chi^2 is the weighted sum of squares of the residuals,
0571 and nu is the degrees of freedom.
0572 </para>
0573 </listitem>
0574 </itemizedlist>
0575 <para>
0576 <varname>outArrayLens</varname> will be correctly set to indicate the length of each output array.
0577 </para>
0578
0579 <para>
0580 Ensure that the specified outputs in the XML file match those that the exported C function returns (which
0581 in most cases will simply be the outputs returned by the fitting function).
0582 </para>
0583
0584 </sect2>
0585
0586 <sect2 id="nonlinearfittingpluginexample">
0587 <title>Example</title>
0588 <para>The following is an example of a non-linear fit plugin that performs a fit to an exponential model.</para>
0589 <informalexample>
0590 <screen>
0591 /*
0592 * Exponential fit plugin for KST.
0593 * Copyright 2004, The University of British Columbia
0594 * Released under the terms of the GPL.
0595 */
0596
0597 #define NUM_PARAMS 3
0598 #define MAX_NUM_ITERATIONS 500
0599
0600 #include "../non_linear.h"
0601
0602 void function_initial_estimate( const double* pdX, const double* pdY,
0603 int iLength, double* pdParameterEstimates ) {
0604 KST_UNUSED( pdX )
0605 KST_UNUSED( pdY )
0606 KST_UNUSED( iLength )
0607
0608 pdParameterEstimates[0] = 1.0;
0609 pdParameterEstimates[1] = 0.0;
0610 pdParameterEstimates[2] = 0.0;
0611 }
0612
0613 double function_calculate( double dX, double* pdParameters ) {
0614 double dScale = pdParameters[0];
0615 double dLambda = pdParameters[1];
0616 double dOffset = pdParameters[2];
0617 double dY;
0618
0619 dY = ( dScale * exp( -dLambda * dX ) ) + dOffset;
0620
0621 return dY;
0622 }
0623
0624 void function_derivative( double dX, double* pdParameters, double* pdDerivatives ) {
0625 double dScale = pdParameters[0];
0626 double dLambda = pdParameters[1];
0627 double dExp;
0628 double ddScale;
0629 double ddLambda;
0630 double ddOffset;
0631
0632 dExp = exp( -dLambda * dX );
0633 ddScale = dExp;
0634 ddLambda = -dX * dScale * dExp;
0635 ddOffset = 1.0;
0636
0637 pdDerivatives[0] = ddScale;
0638 pdDerivatives[1] = ddLambda;
0639 pdDerivatives[2] = ddOffset;
0640 }
0641
0642 extern "C" int kstfit_exponential(const double *const inArrays[], const int inArrayLens[],
0643 const double inScalars[],
0644 double *outArrays[], int outArrayLens[],
0645 double outScalars[]);
0646
0647 int kstfit_exponential(const double *const inArrays[], const int inArrayLens[],
0648 const double inScalars[],
0649 double *outArrays[], int outArrayLens[],
0650 double outScalars[])
0651 {
0652 return kstfit_nonlinear( inArrays, inArrayLens,
0653 inScalars, outArrays,
0654 outArrayLens, outScalars );
0655 }
0656 </screen>
0657 </informalexample>
0658
0659 </sect2>
0660 </sect1>
0661
0662 <sect1 id="creatingpassfilterplugins">
0663 <title>Creating Pass Filter Plugins</title>
0664 <para>
0665 &kst; provides header files to simplify the implementation of pass filter plugins. The use of these
0666 header files is described below.
0667 </para>
0668 <sect2 id="creatingpassfilterpluginsheaderfiles">
0669 <title>Header Files</title>
0670 <para>
0671 The pass filter header file is located in <filename>kst/plugins/pass_filters</filename> of
0672 the &kst; source tarball. The file is named <filename>filters.h</filename>
0673 To use this file, include it in the source code for your plugin:
0674 <screen>
0675 #include <../filters.h>
0676 </screen>
0677 (by convention, we will place the source code for the plugin one directory below where the header files
0678 are).
0679 </para>
0680 </sect2>
0681
0682 <sect2 id="creatingpassfilterpluginsrequirements">
0683 <title>Required Functions</title>
0684 <para>
0685 The <filename>filters.h</filename> header file contains a single function that calculates the Fourier
0686 transform of a supplied function, applies the supplied filter to the Fourier transform, and then calculates
0687 the inverse Fourier transform of the filtered Fourier transform. To supply the filter, the following
0688 function needs to be implemented in the source code for your plugin:
0689 </para>
0690 <para><function><returnvalue>double</returnvalue> filter_calculate( double <parameter>dFreqValue</parameter>, const double <parameter>inScalars[]</parameter> )</function></para>
0691 <para>
0692 This function should calculate the filtered amplitude for the frequency <literal>dFreqValue</literal>.
0693 <literal>inScalars[]</literal> will contain the unaltered input scalars for the plugin, specified in the
0694 XML file. Most likely <literal>inScalars[]</literal> will contain cutoff frequencies or other
0695 properties of the filter. For example, to implement a Butterworth high-pass filter,
0696 <function>filter_calculate</function> could be implemented as follows:
0697 </para>
0698 <informalexample>
0699 <screen>
0700 double filter_calculate( double dFreqValue, const double inScalars[] ) {
0701 double dValue;
0702 if( dFreqValue > 0.0 ) {
0703 dValue = 1.0 / ( 1.0 +
0704 pow( inScalars[1] / dFreqValue, 2.0 * (double)inScalars[0] ) );
0705 } else {
0706 dValue = 0.0;
0707 }
0708 return dValue;
0709 }
0710 </screen>
0711 </informalexample>
0712 </sect2>
0713
0714 <sect2 id="creatingpassfilterpluginscallingfunction">
0715 <title>Calling the Filter Function</title>
0716 <para>
0717 Once the required <function>filter_calculate</function> has been implemented, the filter function
0718 from the header file can be called:
0719 </para>
0720 <literallayout><function>kst_pass_filter( <parameter>inArrays</parameter>,
0721 <parameter>inArrayLens</parameter>,
0722 <parameter>inScalars</parameter>,
0723 <parameter>outArrays</parameter>,
0724 <parameter>outArrayLens</parameter>,
0725 <parameter>outScalars</parameter> );</function></literallayout>
0726 <para>
0727 The arguments supplied to the exported C function can usually be passed to
0728 <function>kst_pass_filter</function> without modification. However, there are a few restrictions
0729 on the arguments:
0730 </para>
0731 <itemizedlist>
0732 <listitem>
0733 <para>
0734 <varname>inArrays[0]</varname> must contain the array of data to filter.
0735 </para>
0736 </listitem>
0737
0738 <listitem>
0739 <para>
0740 <varname>inScalars</varname> should contain the filter-specific parameters to be used by
0741 the <function>filter_calculate</function> function.
0742 </para>
0743 </listitem>
0744 </itemizedlist>
0745 <para>
0746 After the function call, <varname>outArrays[0]</varname> will contain the filtered array of data, and
0747 <varname>outArrayLens</varname> will be set appropriately. The <function>kst_pass_filter</function>
0748 function does not use <varname>outScalars</varname>.
0749 </para>
0750 </sect2>
0751
0752 <sect2 id="creatingpassfilterpluginsexample">
0753 <title>Example</title>
0754 <para>
0755 The following is an example of a pass filter plugin that implements the Butterworth high-pass filter.
0756 </para>
0757 <informalexample>
0758 <screen>/*
0759 * Butterworth low pass filter plugin for KST.
0760 * Copyright 2004, The University of British Columbia
0761 * Released under the terms of the GPL.
0762 */
0763
0764 #include <stdlib.h>
0765 #include <math.h>
0766 #include "../filters.h"
0767
0768 extern "C" int butterworth_highpass(const double *const inArrays[], const int inArrayLens[],
0769 const double inScalars[],
0770 double *outArrays[], int outArrayLens[],
0771 double outScalars[]);
0772
0773 int butterworth_highpass(const double *const inArrays[], const int inArrayLens[],
0774 const double inScalars[],
0775 double *outArrays[], int outArrayLens[],
0776 double outScalars[])
0777 {
0778 int iReturn;
0779
0780 iReturn = kst_pass_filter( inArrays,
0781 inArrayLens,
0782 inScalars,
0783 outArrays,
0784 outArrayLens,
0785 outScalars );
0786
0787 return iReturn;
0788 }
0789
0790 double filter_calculate( double dFreqValue, const double inScalars[] ) {
0791 double dValue;
0792
0793 if( dFreqValue > 0.0 ) {
0794 dValue = 1.0 / ( 1.0 + pow( inScalars[1] / dFreqValue, 2.0 * (double)inScalars[0] ) );
0795 } else {
0796 dValue = 0.0;
0797 }
0798
0799 return dValue;
0800 }</screen>
0801 </informalexample>
0802 </sect2>
0803
0804 </sect1>
0805 </appendix>
0806
0807
0808 <!-- Keep this comment at the end of the file
0809 Local variables:
0810 mode: xml
0811 sgml-omittag:nil
0812 sgml-shorttag:nil
0813 sgml-namecase-general:nil
0814 sgml-general-insert-case:lower
0815 sgml-minimize-attributes:nil
0816 sgml-always-quote-attributes:t
0817 sgml-indent-step:0
0818 sgml-indent-data:true
0819 sgml-parent-document:("index.docbook" "book" "appendix")
0820 sgml-exposed-tags:nil
0821 sgml-local-catalogs:nil
0822 sgml-local-ecat-files:nil
0823 End:
0824 -->