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&mdash;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 &lt;kstdataobject.h&gt;
0074 
0075 class FooPlugin : public KstDataObject {
0076   Q_OBJECT
0077 public:
0078     FooPlugin(QObject *parent, const char *name, const QStringList &#038;args);
0079     virtual ~FooPlugin();
0080 
0081     virtual KstObject::UpdateType update(int);
0082     virtual QString propertyString() const;
0083     virtual KstDataObjectPtr makeDuplicate(KstDataObjectDataObjectMap&#038;);
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 &lt;../linear.h&gt;
0147 </screen>
0148 or
0149 <screen>
0150 #include &lt;../linear_weighted.h&gt;
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 &gt; 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 &lt;../non_linear.h&gt;
0373 </screen>
0374 or
0375 <screen>
0376 #include &lt;../non_linear_weighted.h&gt;
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 &lt;../filters.h&gt;
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 &lt;stdlib.h&gt;
0765 #include &lt;math.h&gt;
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 &gt; 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 -->