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 -->