<appendix id="creatingplugins"> <title >Lisapluginate loomine</title> <para >&kst; evib lihtsat ja standardset liidest, mis hõlbustab lisapluginate loomist. Järgnevalt kirjeldame nii pluginatele esitatavaid põhinõudeid kui ka selgitame, kuidas kasutada juba olemasolevaid päisefaile teatud tüüpi pluginate loomiseks. </para> <sect1 id="creatingbasicplugin"> <title >Plugina loomise põhitõed</title> <para >&kst; plugin koosneb kahest failist — XML-fail ja jagatud objektifail. </para> <sect2 id="creatingbasicpluginxmlfile"> <title >XML-fail</title> <para >XML-fail annab plugina kohta infot ja kirjeldab selle sisendeid ning väljundeid. Allpool on &kst; plugina XML-faili näidis: </para> <informalexample> <screen ><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE Module SYSTEM "file:/Repository/Level2/Soft/ProC/moduledef.dtd"> <module> <intro> <modulename name="testplugin"/> <!-- Mooduli nimi --> <author name="Rick Chern"/> <!-- Autori nimi --> <description text="A test plugin for me"/> <!-- Mooduli kirjeldus --> <version minor="1" major="0"/> <!-- Mooduli versiooni number --> <state devstate="release"/> <!-- Mooduli arenduse seis (see pole kohustuslik)--> </intro> <interface> <!--sisendid siia--> <input> <table type="float" name="Input Vector 1" descr="The first input vector" /> </input> <input> <float name="Input Scalar 1" descr="The first input scalar" /> </input> <!--väljundid siia--> <output> <table type="float" name="Output Vector 1" descr="The first output vector" /> </output> <output> <float name="Output Scalar 1" descr="The first output scalar" /> </output> </interface> </module> </screen> </informalexample> <para >Üldiselt võib ka toodud näidet mallina kasutada ja muuta sektsioonid enda vajadustele sobivaks. Nagu näha, sisaldab XML-fail sõlme <literal >module</literal >. Sõlmel <literal >module</literal > on omakorda sõlmed <literal >intro</literal > ja <literal >interface</literal >. Sõlme <literal >intro</literal > võib muuta vastavalt vajadustele, pidades silmas eeltoodud XML-failis leiduvaid kommentaare. Oluline on see, et <literal >modulename</literal > atribuut <literal >name</literal > oleks täpselt sama kasutatava jagatud objektifaili nimega. </para> <para >Sõlm <literal >interface</literal > kirjeldab plugina sisendeid ja väljundeid. Iga sisendit kirjeldab sõlm <literal >input</literal > ja iga väljundit sõlm <literal >output</literal >. Igal sisendil peab olema järglasest sõlm <literal >table</literal > või <literal >float</literal >. Sõlme <literal >table</literal > atribuut <literal >type</literal > peab olema väärtusega <literal >"float"</literal >. Pane tähele, et oluline on ka sisendite ja väljundite järjekord — seda kasutatakse objektifaili iga sisend- ja väljundmassiivi indeksiväärtuste määramiseks ning selles järjekorras esitatakse sisend- ja väljundväljad ka &kst; pluginaliideses. </para> <para >Kui oled XML-failiga ühele poole saanud, salvesta see kujul <filename >[moodulinimi].xml</filename >, kus <filename >[moodulinimi]</filename > on sõlme <literal >modulename</literal > atribuudi <literal >name</literal > väärtus. </para> </sect2> <sect2 id="creatingbasicpluginobjectfile"> <title >Jagatud objektifail</title> <para >Jagatud objektifail sisaldab plugina tegelikke funktsioone. See tähendab, et just see määrab, kuidas antud sisendist saada vajalik väljund. Toome siinkohal ära jagatud objektifailile esitatavad nõuded: </para> <itemizedlist> <listitem> <para >Objekt peab eksportima järgmise C linkimissümboli: <literallayout ><function ><returnvalue >int</returnvalue > symbol(const double *const <parameter >inArrays[]</parameter >, const int <parameter >inArrayLens[]</parameter >, const double <parameter >inScalars[]</parameter >, double *<parameter >outArrays[]</parameter >, int <parameter >outArrayLens[]</parameter >, double <parameter >outScalars[]</parameter >)</function ></literallayout> </para> <para >kus <replaceable >symbol</replaceable > peab olema XML-faili sõlme <literal >modulename</literal > atribuudi <literal >name</literal > väärtus. See on ainus funktsioon, mille &kst; välja kutsub (kuigi neid funktsioone võib olla ka rohkem). Järgnevalt kirjeldame funktsiooni kõiki argumente: </para> <variablelist> <varlistentry> <term ><varname >const double *const inArrays[]</varname ></term> <listitem> <para >Sisendmassiivide massiiv. Iga sisendmassiiv vastab sisendvektorile. Massiivid on samas järjekorras, nagu XML-failis loetletud vektorid, nii et <literal >inArrays[0]</literal > tähistab esimesele sisendvektorile vastavat massiivi, <literal >inArrays[1]</literal > teisele sisendvektorile vastavat massiivi ja nii edasi. </para> </listitem> </varlistentry> <varlistentry> <term ><varname >const int inArraysLens[]</varname ></term> <listitem> <para >Iga sisendmassiivi massiivipikkusi sisaldav massiiv. Pikkused on samas järekorras, nagu massiivid argumendis <literal >inArrays[]</literal > (nt. <literal >inArrayLens[0]</literal > on <literal >inArrays[0]</literal > pikkus). </para> </listitem> </varlistentry> <varlistentry> <term ><varname >const double inScalars[]</varname ></term> <listitem> <para >Sisendskalaaride massiiv. Skalaarid on samas järjekorras, nagu nad on ära toodud XML-failis. </para> </listitem> </varlistentry> <varlistentry> <term ><varname >double *outArrays[]</varname ></term> <listitem> <para >Väljundmassiivide massiiv. Iga väljundmassiiv vastab väljundvektorile ja massiivid peavad olema samas järjekorras, nagu esinevad väljundvektorid XML-failis. </para> </listitem> </varlistentry> <varlistentry> <term ><varname >int outArrayLens[]</varname ></term> <listitem> <para >Väljundmassiivide pikkusi sisaldav massiiv. Pikkused peavad olema samas järjekorras, nagu on massiivid argumendis <literal >outArrays[]</literal >. </para> </listitem> </varlistentry> <varlistentry> <term ><varname >double outScalars[]</varname ></term> <listitem> <para >Väljundskalaaride massiiv. Skalaarid peavad olema samas järjekorras, nagu nad on ära toodud XML-failis. </para> </listitem> </varlistentry> </variablelist> </listitem> <listitem> <para >Funktsioon peab tagastama <literal >0</literal >, kui see täideti edukalt, vastasel juhul <literal >-1</literal >. </para> </listitem> <listitem> <para >Objektifaili kood peab suutma käsitleda ootamatut sisendit, näiteks tühja sisendmassiivi (enamasti peaks selliste olukordade puhul olema piisav tagastada väärtus <literal >-1</literal >). </para> </listitem> <listitem> <para >Väljundite arv ja tüüp peab täpselt vastama XML-failis antule. </para> </listitem> <listitem> <para >Tõenäoliselt on vajalik muuta <varname >outArrays[]</varname > massiivide suurust. Selleks kasuta funktsiooni <function >realloc()</function >. Nt. </para> <informalexample> <screen >outArrays[0]=(double*)realloc(outArrays[0], 5*sizeof(double)); </screen> </informalexample> <para >eraldab ruumi viiele <varname >outArrays[0]</varname > double'ile. Ära kasuta mingit muud mälueraldajat kui <function >realloc()</function >. </para> </listitem> <listitem> <para >Sisendargumendid peavad olema konstandid. Need ei tohi olla mittekonstandi tüüpi. </para> </listitem> </itemizedlist> <para >Järgnev kujutab endast lihtsa plugina jagatud objektifaili näidislähtekoodi: </para> <informalexample> <screen >#include <stdlib.h> extern "C" int testplugin(const double *const inArrays[], const int inArrayLens[], const double is[], double *outArrays[], int outArrayLens[], double outScalars[]); int testplugin(const double *const inArrays[], const int inArrayLens[], const double is[], double *outArrays[], int outArrayLens[], double outScalars[]) //Accept 1 vector and 1 scalar. Multiply all elements of the vector by the //scalar, and output the resulting vector. Also output the original scalar. { //Set the outputs outArrayLens[0]=inArrayLens[0]; //resize the output arrays outArrays[0]=(double*)realloc(outArrays[0], inArrayLens[0]*sizeof(double)); //multiply each element of the input vector //by the scalar for (int i=0; i<inArrayLens[0]; i++) { outArrays[0][i]=inArrays[0][i] * is[0]; } //now set the output scalar outScalars[0]=is[0]; return 0; } </screen> </informalexample> </sect2> <sect2 id="compilingplugin"> <title >Plugina kompileerimine</title> <para >Kui kasutad plugina kompileerimiseks &gcc;-d, kompileeri lihtsalt objektifail: <screen ><userinput ><command >cc -Wall -c -o minuplugin.o minuplugin.c -fPIC -DPIC</command ></userinput ></screen> </para> <para >ja loo seejärel jagatud teek: <screen ><userinput ><command >ld -o minuplugin.so -shared minuplugin.o</command ></userinput ></screen> </para> <para >Saadavad failid <filename >*.so</filename > ja <filename >*.xml</filename > peavad asuma samas kataloogis. Kui kasutad XML-faili laadimiseks &kst; pluginahaldurit, otsib see automaatselt jagatud objektifaili samast kataloogist. </para> </sect2> </sect1> <sect1 id="creatinglinearfittingplugins"> <title >Lineaarjaotuse pluginate loomine</title> <para >Lineaarjaotuse plugina loomiseks tuleb teostada oma jaotusalgoritmid ja luua vastavad vektorid. Kuid &kst; pakub juba ka omalt poolt päisefaile, mis muudavad vähimruutude lineaarjaotuse plugina teostamise päris lihtsaks, nõudes sinu käeset vaid mõnd funktsiooni. Selles osas kirjeldamegi, kuidas neid faile ära kasutada. </para> <sect2 id="headerslinearfittingplugins"> <title >Päisefailid</title> <para >Lineaarjaotuse tarbeks on kaks päisefaili: <filename >linear.h</filename > (kaalumata lineaarjaotus) ja <filename >linear_weighted.h</filename > (kaalutud lineaarjaotus). Mõlemad asuvad &kst; lähtepaketi kataloogis <filename >kst/plugins/fits/</filename >. Nende kasutamiseks kaasa üks ja ainult üks neist oma plugina lähtekoodi: <screen> #include <../linear.h> </screen > või <screen> #include <../linear_weighted.h> </screen > (mugavuse mõttes asetame plugina lähtekoodi ühe kataloogi võrra hierarhias päisefailidest allapoole). </para> </sect2> <sect2 id="reqfunctionsfittingplugins"> <title >Nõutavate funktsioonide teostamine</title> <para >Üldise lineaarmudeli korral: </para> <para> <inlinemediaobject> <imageobject> <imagedata fileref="Formula-kst-generallinearmodel.png" format="PNG"/> </imageobject> </inlinemediaobject> </para> <para >kus <literal >y</literal > on <literal >n</literal > vaatluse vektor, <literal >X</literal > on prognoositavate muutujate <literal >n</literal > korda <literal >p</literal > maatriks ja <literal >c</literal > on <literal >p</literal > hinnatavate parima jaotuse parameetrite vektor, võimaldavad päisefailid hinnata <literal >c</literal >-d antud <literal >y</literal > ja <literal >X</literal > korral. <literal >X</literal > pakkumiseks peab plugina lähtekoodis olema teostatud järgmine funktsioon: <literallayout ><function ><returnvalue >double</returnvalue > calculate_matrix_entry( double <parameter >dX</parameter >, int <parameter >iPos</parameter > )</function ></literallayout> </para> <para >See funktsioon peab tagastama kirje väärtuse prognoositavate muutujate maatriksi veerus <literal >iPos</literal >, kasutades <literal >x</literal > väärtust <literal >dX</literal >. Funktsiooni kutsub välja linear.h või linear_weighted.h. Funktsiooni teostus sõltub mudelit, mida soovid jaotuse puhul kasutada, ning on unikaalne iga lineaarjaotuse plugina korral. Näiteks polünomiaalmudeli puhul tuleb <function >calculate_matrix_entry</function > teostada nii: <informalexample > <screen >double calculate_matrix_entry( double dX, int iPos ) { double dY; dY = pow( dX, (double)iPos ); return dY; } </screen> </informalexample> </para> </sect2> <sect2 id="callingfittingfunctionslinearfittingplugins"> <title >Jaotusfunktsioonide väljakutsumine</title> <para >Kui sobilik päisefail on kaasatud ja <function >calculate_matrix_entry</function > teostatud, kutsu päisefailist välja sobiv kaasatud jaotusfunktsioon: <screen> <function >kstfit_linear_unweighted( <parameter >inArrays</parameter >, <parameter >inArrayLens</parameter >, <parameter >outArrays</parameter >, <parameter >outArrayLens</parameter >, <parameter >outScalars</parameter >, <parameter >iNumParams</parameter > )</function >; </screen > või <screen ><function >kstfit_linear_weighted( <parameter >inArrays</parameter >, <parameter >inArrayLens</parameter >, <parameter >outArrays</parameter >, <parameter >outArrayLens</parameter >, <parameter >outScalars</parameter >, <parameter >iNumParams</parameter > )</function >; </screen> </para> <para >Iga funktsioon tagastab õnnestumise korral <literal >0</literal > ja ebaõnnestumise korral <literal >-1</literal >, mistõttu tasuks eksporditud C funktsiooni tagastatav väärtus määrata samaks jaotusfunktsiooni tagastatava väärtusega. Lihtsuse mõttes võib plugina kood lihtsalt edastada eksporditud C funktsioonile antud argumendid jaotusfunktsioonile. Pane aga tähele, et inArrays peab olema alljärgneva struktuuriga: </para> <itemizedlist> <listitem> <para ><varname >inArrays[0]</varname > peab sisaldama andmepunktide X-koordinaatide massiivi </para> </listitem> <listitem> <para ><varname >inArrays[1]</varname > peab sisaldama andmepunktide Y-koordinaatide massiivi </para> </listitem> <listitem> <para ><varname >inArrays[2]</varname > on olemas ainult siis, kui kutsutakse välja <function >kstfit_linear_weighted</function > ning sisaldab sel juhul jaotuses kasutatavate kaalude massiivi. </para> </listitem> </itemizedlist> <para >Kõige lihtsam on inArrays korrektset struktuuri tagada vastavat sisendvektorite järjekorda plugina XML-failis kindlaks määrates. </para> <para ><varname >iNumParams</varname > on jaotusmudelis kasutatavate parameetrite arv, mis peab olema võrdne prognoositavate muutujate maatriksi <literal >X</literal > veergude arvuga. <varname >iNumParams</varname > peab olema korrektselt määratud enne jaotusfunktsiooni väljakutsumist. </para> <para >Kui <function >kstfit_linear_unweighted</function > või <function >kstfit_linear_weighted</function > on välja kutsutud, määratakse <varname >outArrays</varname > ja <varname >outScalars</varname > järgmiselt: </para> <itemizedlist> <listitem> <para ><varname >outArrays[0]</varname > sisaldab jaotuvate Y-väärtuste massiivi. </para> </listitem> <listitem> <para ><varname >outArrays[1]</varname > sisaldab jääkide massiivi. </para> </listitem> <listitem> <para ><varname >outArrays[2]</varname > sisaldab hinnatavate parima jaotuse parameetrite massiivi. </para> </listitem> <listitem> <para ><varname >outArrays[3]</varname > sisaldab kovariantsusmaatriksit, mis tagastatakse rida realt massiivis. </para> </listitem> <listitem> <para ><varname >outScalars[0]</varname > sisaldab hii^2/nüü, kus hii^2 on jääkide ruutude kaalutud summa ja nüü on vabadusaste. </para> </listitem> </itemizedlist> <para ><varname >outArrayLens</varname > määrab korrektselt iga väljundmassiivi pikkuse. </para> <para >Kontrolli, et XML-failis määratud väljundid vastaksid sellele, mida tagastab eksporditud C funktsioon (enamasti on selleks lihtsalt jaotusfunktsiooni tagastatud väljundid). </para> </sect2> <sect2 id="examplelinearfittingplugins"> <title >Näide</title> <para >Toome siin lineaarjaotuse plugina lähtekoodi näite. </para> <informalexample> <screen >/* * Polynomial fitting plugin for KST. * Copyright 2004, The University of British Columbia * Released under the terms of the GPL. */ #include "../linear.h" double calculate_matrix_entry( double dX, int iPos ) { double dY; dY = pow( dX, (double)iPos ); return dY; } extern "C" int kstfit_polynomial_unweighted( const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[]); int kstfit_polynomial_unweighted( const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[]) { int iRetVal = -1; int iNumParams; iNumParams = 1 + (int)floor( inScalars[0] ); if( iNumParams > 0 ) { iRetVal = kstfit_linear_unweighted( inArrays, inArrayLens, outArrays, outArrayLens, outScalars, iNumParams ); } return iRetVal; } </screen> </informalexample> </sect2> </sect1> <sect1 id="creatingnonlinearfitplugin"> <title >Mittelineaarse jaotuse pluginate loomine</title> <para >&kst; pakub päisefaile, mis lihtsustavad mittelineaarse vähimruutude jaotuspluginate loomist. Järgnevalt kirjeldame päisefailide kasutamist. </para> <sect2 id="headersnonlinearfittingplugins"> <title >Päisefailid ja definitsioonid</title> <para >Mittelineaarse jaotuse päisefailid asuvad &kst; lähtekoodi kataloogis <filename >kst/plugins/fits_nonlinear</filename >. Nende nimeks on <filename >non_linear.h</filename > ja <filename >non_linear_weighted.h</filename >, vastavalt siis kaalumata ja kaalutud jaotuse jaoks. Nende kasutamiseks kaasa üks ja ainult üks neist oma plugina lähtekoodi: <screen> #include <../non_linear.h> </screen > või <screen> #include <../non_linear_weighted.h> </screen > (mugavuse mõttes asetame plugina lähtekoodi ühe kataloogi võrra hierarhias päisefailidest allapoole). </para> <para >Mittelineaarne jaotus on kordusi kasutav protsess, mistõttu peab määrama ka korduste maksimaalse arvu. Mittelineaarse jaotuse algoritm peatub, kui vähemalt üks järgnevates tingimustest on täidetud: </para> <itemizedlist> <listitem> <para >Sooritati maksimaalne lubatud arv kordusi. </para> </listitem> <listitem> <para >Saavutati täpsus 10<superscript >-4</superscript >. </para> </listitem> </itemizedlist> <para >Lisaks tuleb defineerida mudeli parameetrite arv, sest seda ei edastata jaotusfunktsioonile vahetult. Nende kahe väärtuse määramiseks, lisa järgnev oma lähtekoodi algusse: </para> <screen >#define NUM_PARAMS [num1] #define MAX_NUM_ITERATIONS [num2] </screen> <para >pannes <literal >[num1]</literal > asemele mudeli parameetrite arvu ja <literal >[num2]</literal > asemele maksimaalse lubatud korduste arvu. </para> </sect2> <sect2 id="reqfunctionsnonlinearfittingplugins"> <title >Nõutavate funktsioonide teostamine</title> <para >Mittelineaarse jaotuse päisefailide kasutamiseks tuleb anda mudelina kasutatav funktsioon, funktsiooni osatuletised iga parameetri suhtes ja parima jaotuse parameetrite alghinnang. Selleks tuleb teostada kolm funktsiooni, mida allpool kirjeldamegi. </para> <variablelist> <varlistentry> <term ><function ><returnvalue >double</returnvalue > function_calculate( double <parameter >dX</parameter >, double* <parameter >pdParameters</parameter > )</function ></term> <listitem> <para >See funktsioon arvutab jaotusmudeli Y-väärtuse antud X-väärtuse <literal >dX</literal > korral, kasutades parameetrite massiivi <varname >pdParameters</varname >. Parameetrite järjekord <varname >pdParameters</varname >-s on suvaline, kuid see peaks olema kooskõlas kahe ülejäänud funktsiooniga. Näiteks eksponentmudeli korral saab <function >function_calculate</function > teostada nii: </para> <informalexample> <screen >double function_calculate( double dX, double* pdParameters ) { double dScale = pdParameters[0]; double dLambda = pdParameters[1]; double dOffset = pdParameters[2]; double dY; dY = ( dScale * exp( -dLambda * dX ) ) + dOffset; return dY; } </screen> </informalexample> </listitem> </varlistentry> <varlistentry> <term ><function ><returnvalue >void</returnvalue > function_derivative( double <parameter >dX</parameter >, double* <parameter >pdParameters</parameter >, double* <parameter >pdDerivatives</parameter > )</function ></term> <listitem> <para >See funktsioon arvutab mudeli funktsiooni osatuletised antud X-väärtuse <literal >dX</literal > korral. Osatuletisi peab tagastama <varname >pdDerivatives</varname >. Osatuletiste järjekord massiivis <varname >pdDerivatives</varname > peab vastama parameetrite järjekorrale <varname >pdParameters</varname >-is (s.t. kui <varname >pdParameters[0]</varname > sisaldab eksponentmudeli lambdaparameetrit, peab <varname >pdDerivatives[0]</varname > sisaldama mudeli tuletist lambda suhtes). </para> </listitem> </varlistentry> <varlistentry> <term ><function ><returnvalue >void</returnvalue > function_initial_estimate( const double* <parameter >pdX</parameter >, const double* <parameter >pdY</parameter >, int <parameter >iLength</parameter >, double* <parameter >pdParameterEstimates</parameter > )</function ></term> <listitem> <para >See funktsioon annab jaotusfunktsioonile parima jaotuse parameetrite esialgse hinnangu. Andmepunktide X- ja Y-väärtuste massiivi annavad vastavalt <varname >pdX</varname > ja <varname >pdY</varname > ning andmepunktide arvu <varname >iLength</varname >. Esialgse hinnangu arvutamiseks võid kasutada omal äranägemisel kõiki parameetreid, ainult mõnda või ka mitte ühtegi. Funktsioon annab arvutatud esialgse hinnangu <varname >pdParameterEstimates</varname >-ile, kusjuures hinnangute järjekord vastab parameetrite järjekorral funktsioonide <function >function_calculate</function > ja <function >function_derivative</function > muutujas <varname >pdParameters</varname >. Pea meeles, et esialgne hinnang on olulise tähtsusega määramisel, kas jaotusfunktsioon suudab üldse mingi tulemuse anda või mitte. </para> </listitem> </varlistentry> </variablelist> </sect2> <sect2 id="callingnonlinearfittingplugins"> <title >Jaotusfunktsioonide väljakutsumine</title> <para >Kui kõik nõutud funktsioonid on teostatud, saab kaasatud päisefailist välja kutsuda jaotusfunktsiooni: <screen> kstfit_nonlinear( <parameter >inArrays</parameter >, <parameter >inArrayLens</parameter >, <parameter >inScalars</parameter >, <parameter >outArrays</parameter >, <parameter >outArrayLens</parameter >, <parameter >outScalars</parameter > ); </screen > või <screen> kstfit_nonlinear_weighted( <parameter >inArrays</parameter >, <parameter >inArrayLens</parameter >, <parameter >inScalars</parameter >, <parameter >outArrays</parameter >, <parameter >outArrayLens</parameter >, <parameter >outScalars</parameter > ); </screen > sõltuvalt sellest, kas teostad kaalumata või kaalutud jaotust. </para> <para >Funktsioon tagastab õnnestumise korral <literal >0</literal >, vea korral <literal >-1</literal >, mistõttu tasuks eksporditud C funktsiooni tagastatav väärtus määrata samaks jaotusfunktsiooni tagastatava väärtusega. Lihtsuse mõttes võib plugina kood lihtsalt edastada eksporditud C funktsioonile antud argumendid jaotusfunktsioonile. Pane aga tähele, et inArrays peab olema alljärgneva struktuuriga: </para> <itemizedlist> <listitem> <para ><varname >inArrays[0]</varname > peab sisaldama andmepunktide X-koordinaatide massiivi </para> </listitem> <listitem> <para ><varname >inArrays[1]</varname > peab sisaldama andmepunktide Y-koordinaatide massiivi </para> </listitem> <listitem> <para ><varname >inArrays[2]</varname > on olemas ainult siis, kui kutsutakse välja <function >kstfit_linear_weighted</function > ning sisaldab sel juhul jaotuses kasutatavate kaalude massiivi. </para> </listitem> </itemizedlist> <para >Kõige lihtsam on inArrays korrektset struktuuri tagada vastavat sisendvektorite järjekorda plugina XML-failis kindlaks määrates. </para> <para >Kui <function >kstfit_linear_unweighted</function > või <function >kstfit_linear_weighted</function > on välja kutsutud, määratakse <varname >outArrays</varname > ja <varname >outScalars</varname > järgmiselt: </para> <itemizedlist> <listitem> <para ><varname >outArrays[0]</varname > sisaldab jaotuvate Y-väärtuste massiivi. </para> </listitem> <listitem> <para ><varname >outArrays[1]</varname > sisaldab jääkide massiivi. </para> </listitem> <listitem> <para ><varname >outArrays[2]</varname > sisaldab hinnatavate parima jaotuse parameetrite massiivi. </para> </listitem> <listitem> <para ><varname >outArrays[3]</varname > sisaldab kovariantsusmaatriksit, mis tagastatakse rida realt massiivis. </para> </listitem> <listitem> <para ><varname >outScalars[0]</varname > sisaldab hii^2/nüü, kus hii^2 on jääkide ruutude kaalutud summa ja nüü on vabadusaste. </para> </listitem> </itemizedlist> <para ><varname >outArrayLens</varname > määrab korrektselt iga väljundmassiivi pikkuse. </para> <para >Kontrolli, et XML-failis määratud väljundid vastaksid sellele, mida tagastab eksporditud C funktsioon (enamasti on selleks lihtsalt jaotusfunktsiooni tagastatud väljundid). </para> </sect2> <sect2 id="nonlinearfittingpluginexample"> <title >Näide</title> <para >Järgnevalt toome näite mittelineaarse jaotuse plugina kohta, mis sooritab jaotuse eksponentmudelil.</para> <informalexample> <screen >/* * Exponential fit plugin for KST. * Copyright 2004, The University of British Columbia * Released under the terms of the GPL. */ #define NUM_PARAMS 3 #define MAX_NUM_ITERATIONS 500 #include "../non_linear.h" void function_initial_estimate( const double* pdX, const double* pdY, int iLength, double* pdParameterEstimates ) { KST_UNUSED( pdX ) KST_UNUSED( pdY ) KST_UNUSED( iLength ) pdParameterEstimates[0] = 1.0; pdParameterEstimates[1] = 0.0; pdParameterEstimates[2] = 0.0; } double function_calculate( double dX, double* pdParameters ) { double dScale = pdParameters[0]; double dLambda = pdParameters[1]; double dOffset = pdParameters[2]; double dY; dY = ( dScale * exp( -dLambda * dX ) ) + dOffset; return dY; } void function_derivative( double dX, double* pdParameters, double* pdDerivatives ) { double dScale = pdParameters[0]; double dLambda = pdParameters[1]; double dExp; double ddScale; double ddLambda; double ddOffset; dExp = exp( -dLambda * dX ); ddScale = dExp; ddLambda = -dX * dScale * dExp; ddOffset = 1.0; pdDerivatives[0] = ddScale; pdDerivatives[1] = ddLambda; pdDerivatives[2] = ddOffset; } extern "C" int kstfit_exponential(const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[]); int kstfit_exponential(const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[]) { return kstfit_nonlinear( inArrays, inArrayLens, inScalars, outArrays, outArrayLens, outScalars ); } </screen> </informalexample> </sect2> </sect1> <sect1 id="creatingpassfilterplugins"> <title >Läbipääsufiltripluginate loomine</title> <para >&kst; pakub päisefaile läbipääsufiltrite pluginate teostamise lihtsustamiseks. Järgnevalt kirjeldatakse päisefailide kasutamist. </para> <sect2 id="creatingpassfilterpluginsheaderfiles"> <title >Päisefailid</title> <para >Läbipääsufiltri päisefail asub &kst; lähtekoodi kataloogis <filename >kst/plugins/pass_filters</filename >. Faili nimi on <filename >filters.h</filename >. Selle kasutamiseks kaasa fail oma plugina lähtekoodi: <screen> #include <../filters.h> </screen > (mugavuse mõttes asetame plugina lähtekoodi ühe kataloogi võrra hierarhias päisefailidest allapoole). </para> </sect2> <sect2 id="creatingpassfilterpluginsrequirements"> <title >Nõutavad funktsioonid</title> <para >Päisefail <filename >filter.h</filename > sisaldab ühtainust funktsiooni, mis arvutab antud funktsiooni Fourier' teisenduse, rakendab Fourier' teisendusele antud filtrit ja seejärel arvutab filtreeritud Fourier' teisenduse Fourier' pöördteisenduse. Filtri andmiseks tuleb plugina lähtekoodis teostada järgmine funktsioon: </para> <para ><function ><returnvalue >double</returnvalue > filter_calculate( double <parameter >dFreqValue</parameter >, const double <parameter >inScalars[]</parameter > )</function ></para> <para >See funktsioon arvutab sageduse <literal >dFreqValue</literal > filtreeritud amplituudi. <literal >inScalars[]</literal > sisaldab XML-failis määratud plugina muutmata sisendskalaare. Tõenäoliselt sisaldab <literal >inScalars[]</literal > lõikesagedusi või muid filtri omadusi. Näiteks Butterworthi kõrgpääsufiltri teostamiseks tuleks <function >filter_calculate</function > teostada nii: </para> <informalexample> <screen >double filter_calculate( double dFreqValue, const double inScalars[] ) { double dValue; if( dFreqValue > 0.0 ) { dValue = 1.0 / ( 1.0 + pow( inScalars[1] / dFreqValue, 2.0 * (double)inScalars[0] ) ); } else { dValue = 0.0; } return dValue; } </screen> </informalexample> </sect2> <sect2 id="creatingpassfilterpluginscallingfunction"> <title >Filtri funktsiooni väljakutsumine</title> <para >Kui nõutab <function >filter_calculate</function > on teostatud, saab filtri funktsiooni välja kutsuda päisefailist: </para> <literallayout ><function >kst_pass_filter( <parameter >inArrays</parameter >, <parameter >inArrayLens</parameter >, <parameter >inScalars</parameter >, <parameter >outArrays</parameter >, <parameter >outArrayLens</parameter >, <parameter >outScalars</parameter > );</function ></literallayout> <para >Eksporditud C funktsioonile antud argumendid edastatakse tavaliselt funktsioonile <function >kst_pass_filter</function > muutmatult. Kuid argumentide juures tuleb arvestada mõne piiranguga: </para> <itemizedlist> <listitem> <para ><varname >inArrays[0]</varname > peab sisaldama filtreeritavate andmete massiivi. </para> </listitem> <listitem> <para ><varname >inScalars</varname > peab sisaldama filtrile spetsiifilisi parameetreid, mida kasutab funktsioon <function >filter_calculate</function >. </para> </listitem> </itemizedlist> <para >Pärast funktsiooni väljakutset sisaldab <varname >outArrays[0]</varname > filtreeritud andmemassiivi, ja vastavalt määratakse ka <varname >outArrayLens</varname >. Funktsioon <function >kst_pass_filter</function > ei kasuta muutujat <varname >outScalars</varname >. </para> </sect2> <sect2 id="creatingpassfilterpluginsexample"> <title >Näide</title> <para >Järgnevalt toome Butterworthi kõrgpääsufiltrit teostava läbipääsufiltri näite. </para> <informalexample> <screen >/* * Butterworth low pass filter plugin for KST. * Copyright 2004, The University of British Columbia * Released under the terms of the GPL. */ #include <stdlib.h> #include <math.h> #include "../filters.h" extern "C" int butterworth_highpass(const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[]); int butterworth_highpass(const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[]) { int iReturn; iReturn = kst_pass_filter( inArrays, inArrayLens, inScalars, outArrays, outArrayLens, outScalars ); return iReturn; } double filter_calculate( double dFreqValue, const double inScalars[] ) { double dValue; if( dFreqValue > 0.0 ) { dValue = 1.0 / ( 1.0 + pow( inScalars[1] / dFreqValue, 2.0 * (double)inScalars[0] ) ); } else { dValue = 0.0; } return dValue; }</screen> </informalexample> </sect2> </sect1> </appendix>