plane_max_prop.C

Go to the documentation of this file.
00001 /* Gnome gxsm - Gnome X Scanning Microscopy
00002  * universal STM/AFM/SARLS/SPALEED/... controlling and
00003  * data analysis software
00004  *
00005  * plugin_helper reports your answers as
00006 author          =Percy Zahl
00007 email                   =zahl@users.sf.net
00008 pluginname              =plane_max_prop
00009 pluginmenuentry         =Plane max prop
00010 menupath                =Math/Background/
00011 entryplace              =Background
00012 shortentryplace =BG
00013 abouttext               =Calculates a max propability plane and subtracts it.
00014 smallhelp               =Plane max propability
00015 longhelp                =Calculates a max propability plane and subtracts it.
00016  * 
00017  * Gxsm Plugin Name: plane_max_prop.C
00018  * ========================================
00019  * 
00020  * Copyright (C) 1999 The Free Software Foundation
00021  *
00022  * Authors: Percy Zahl <zahl@fkp.uni-hannover.de>
00023  * additional features: Andreas Klust <klust@fkp.uni-hannover.de>
00024  *
00025  * This program is free software; you can redistribute it and/or modify
00026  * it under the terms of the GNU General Public License as published by
00027  * the Free Software Foundation; either version 2 of the License, or
00028  * (at your option) any later version.
00029  *
00030  * This program is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00033  * GNU General Public License for more details.
00034  *
00035  * You should have received a copy of the GNU General Public License
00036  * along with this program; if not, write to the Free Software
00037  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00038  */
00039 
00040 
00041 /* Please do not change the Begin/End lines of this comment section!
00042  * this is a LaTeX style section used for auto generation of the PlugIn Manual 
00043  * Chapter. Add a complete PlugIn documentation inbetween the Begin/End marks!
00044  * All "% PlugInXXX" commentary tags are mandatory
00045  * All "% OptPlugInXXX" tags are optional and can be removed or commented in
00046  * --------------------------------------------------------------------------------
00047 % BeginPlugInDocuSection
00048 % PlugInDocuCaption: Plane max. propability
00049 % PlugInName: plane_max_prop
00050 % PlugInAuthor: Percy Zahl, L.Anderson, Greg P. Kochanski
00051 % PlugInAuthorEmail: zahl@users.sf.net
00052 % PlugInMenuPath: Math/Background/Plane max prop
00053 
00054 % PlugInDescription
00055 Calculates a max propability plane and subtracts it. It's purpose is
00056 to find automatically the best fitting plane to orient a
00057 stepped/vicinal surface in a way, that the terraces are horizontal.
00058 
00059 % PlugInUsage
00060 Call \GxsmMenu{Math/Background/Plane max prop}.
00061 
00062 % OptPlugInSources
00063 The active channel is used as data source.
00064 
00065 %% OptPlugInObjects
00066 %A optional rectangle is used for data extraction...
00067 
00068 % OptPlugInDest
00069 The computation result is placed into an existing math channel, else
00070 into a new created math channel.
00071 
00072 %% OptPlugInConfig
00073 %describe the configuration options of your plug in here!
00074 
00075 %% OptPlugInFiles
00076 %Does it uses, needs, creates any files? Put info here!
00077 
00078 %% OptPlugInRefs
00079 %Any references?
00080 
00081 %% OptPlugInKnownBugs
00082 %Are there known bugs? List! How to work around if not fixed?
00083 
00084 % OptPlugInNotes
00085 This code in work in progress, it is originated from PMSTM
00086 \GxsmFile{mpplane.c} and was rewritten as a Gxsm math PlugIn. It looks
00087 like something does not work like expected, the corrected plane is not
00088 right for some still not found reason.
00089 
00090 %% OptPlugInHints
00091 %Any tips and tricks?
00092 
00093 % EndPlugInDocuSection
00094  * -------------------------------------------------------------------------------- 
00095  */
00096 
00097 #include <gtk/gtk.h>
00098 #include "config.h"
00099 #include "gxsm/plugin.h"
00100 
00101 // Plugin Prototypes
00102 static void plane_max_prop_init( void );
00103 static void plane_max_prop_about( void );
00104 static void plane_max_prop_configure( void );
00105 static void plane_max_prop_cleanup( void );
00106 
00107 // Define Type of math plugin here, only one line should be commented in!!
00108 #define GXSM_ONE_SRC_PLUGIN__DEF
00109 // #define GXSM_TWO_SRC_PLUGIN__DEF
00110 
00111 // Math-Run-Function, use only one of (automatically done :=)
00112 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00113 // "OneSrc" Prototype
00114  static gboolean plane_max_prop_run( Scan *Src, Scan *Dest );
00115 #else
00116 // "TwoSrc" Prototype
00117  static gboolean plane_max_prop_run( Scan *Src1, Scan *Src2, Scan *Dest );
00118 #endif
00119 
00120 // Fill in the GxsmPlugin Description here
00121 GxsmPlugin plane_max_prop_pi = {
00122   NULL,                   // filled in and used by Gxsm, don't touch !
00123   NULL,                   // filled in and used by Gxsm, don't touch !
00124   0,                      // filled in and used by Gxsm, don't touch !
00125   NULL,                   // The Gxsm-App Class Ref.pointer (called "gapp" in Gxsm) is 
00126                           // filled in here by Gxsm on Plugin load, 
00127                           // just after init() is called !!!
00128   // ----------------------------------------------------------------------
00129   // Plugins Name, CodeStly is like: Name-M1S|M2S-BG|F1D|F2D|ST|TR|Misc
00130   "plane_max_prop-"
00131 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00132   "M1S"
00133 #else
00134   "M2S"
00135 #endif
00136   "-BG",
00137   // Plugin's Category - used to autodecide on Pluginloading or ignoring
00138   // NULL: load, else
00139   // example: "+noHARD +STM +AFM"
00140   // load only, if "+noHARD: no hardware" and Instrument is STM or AFM
00141   // +/-xxxHARD und (+/-INST or ...)
00142   NULL,
00143   // Description, is shown by PluginViewer (Plugin: listplugin, Tools->Plugin Details)
00144   "Calculates a max propability plane and subtracts it.",                   
00145   // Author(s)
00146   "Percy Zahl",
00147   // Menupath to position where it is appendet to
00148   N_("_Math/_Background/"),
00149   // Menuentry
00150   N_("Plane max prop"),
00151   // help text shown on menu
00152   N_("Calculates a max propability plane and subtracts it."),
00153   // more info...
00154   "Plane max propability",
00155   NULL,          // error msg, plugin may put error status msg here later
00156   NULL,          // Plugin Status, managed by Gxsm, plugin may manipulate it too
00157   // init-function pointer, can be "NULL", 
00158   // called if present at plugin load
00159   plane_max_prop_init,  
00160   // query-function pointer, can be "NULL", 
00161   // called if present after plugin init to let plugin manage it install itself
00162   NULL, // query should be "NULL" for Gxsm-Math-Plugin !!!
00163   // about-function, can be "NULL"
00164   // can be called by "Plugin Details"
00165   plane_max_prop_about,
00166   // configure-function, can be "NULL"
00167   // can be called by "Plugin Details"
00168   plane_max_prop_configure,
00169   // run-function, can be "NULL", if non-Zero and no query defined, 
00170   // it is called on menupath->"plugin"
00171   NULL, // run should be "NULL" for Gxsm-Math-Plugin !!!
00172   // cleanup-function, can be "NULL"
00173   // called if present at plugin removeal
00174   plane_max_prop_cleanup
00175 };
00176 
00177 // special math Plugin-Strucure, use
00178 // GxsmMathOneSrcPlugin plane_max_prop_m1s_pi -> "OneSrcMath"
00179 // GxsmMathTwoSrcPlugin plane_max_prop_m2s_pi -> "TwoSrcMath"
00180 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00181  GxsmMathOneSrcPlugin plane_max_prop_m1s_pi
00182 #else
00183  GxsmMathTwoSrcPlugin plane_max_prop_m2s_pi
00184 #endif
00185  = {
00186    // math-function to run, see prototype(s) above!!
00187    plane_max_prop_run
00188  };
00189 
00190 // Text used in Aboutbox, please update!!
00191 static const char *about_text = N_("Gxsm plane_max_prop Plugin\n\n"
00192                                    "Calculates a max propability plane and subtracts it.");
00193 
00194 // Symbol "get_gxsm_plugin_info" is resolved by dlsym from Gxsm, used to get Plugin's info!! 
00195 // Essential Plugin Function!!
00196 GxsmPlugin *get_gxsm_plugin_info ( void ){ 
00197   plane_max_prop_pi.description = g_strdup_printf(N_("Gxsm MathOneArg plane_max_prop plugin %s"), VERSION);
00198   return &plane_max_prop_pi; 
00199 }
00200 
00201 // Symbol "get_gxsm_math_one|two_src_plugin_info" is resolved by dlsym from Gxsm, 
00202 // used to find out which Math Type the Plugin is!! 
00203 // Essential Plugin Function!!
00204 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00205 GxsmMathOneSrcPlugin *get_gxsm_math_one_src_plugin_info( void ) {
00206   return &plane_max_prop_m1s_pi; 
00207 }
00208 #else
00209 GxsmMathTwoSrcPlugin *get_gxsm_math_two_src_plugin_info( void ) { 
00210   return &plane_max_prop_m2s_pi; 
00211 }
00212 #endif
00213 
00214 /* Here we go... */
00215 // init-Function
00216 static void plane_max_prop_init(void)
00217 {
00218         PI_DEBUG (DBG_L2, "plane_max_prop Plugin Init");
00219 }
00220 
00221 // about-Function
00222 static void plane_max_prop_about(void)
00223 {
00224         const gchar *authors[] = { plane_max_prop_pi.authors, NULL};
00225         gtk_widget_show(gnome_about_new ( plane_max_prop_pi.name,
00226                                           VERSION,
00227                                     N_("(C) 2000 the Free Software Foundation"),
00228                                     about_text,
00229                                     authors,
00230                                     NULL, NULL, NULL
00231                                     ));
00232 }
00233 
00234 // configure-Function
00235 static void plane_max_prop_configure(void)
00236 {
00237         if(plane_max_prop_pi.app)
00238                 plane_max_prop_pi.app->message("plane_max_prop Plugin Configuration");
00239 }
00240 
00241 // cleanup-Function
00242 static void plane_max_prop_cleanup(void)
00243 {
00244         PI_DEBUG (DBG_L2, "plane_max_prop Plugin Cleanup");
00245 }
00246 
00247 /*
00248  * higher Math-Routines
00249  * from: Greg P. Kochanski
00250  */
00251 
00252 #define F1      6
00253 #define F2      12
00254 #define F3      5
00255 #define DFAC 2
00256 #define WEIGHTFAC       3
00257 #define EPS 1
00258 
00259 /* Confine a to the range
00260  * defined by b and c.
00261  */
00262 #define fbound(a,b,c)                                       \
00263     {                                                       \
00264         double uttemp;                              \
00265                                                             \
00266         if ((a) < (uttemp = (b)) || (a) > (uttemp = (c)))   \
00267             (a) = uttemp;                                   \
00268     }
00269 
00270 #define DATA double
00271 #define LONGDATA double
00272 #define INT int
00273 
00274 struct mode_out {double low, high, best; };
00275 
00276 int random_number(int);
00277 
00278 #define NRAND   97
00279 
00280 #ifndef RAND_MAX
00281 # define RAND_MAX       32767
00282 #endif
00283 
00284 int random_number(int x)
00285 {
00286         static gboolean initted = FALSE;
00287         static int v[NRAND];
00288         static unsigned vv;
00289 
00290         if (x<0) x=0;
00291 
00292         if(!initted)    {
00293                 int i;
00294                 initted = TRUE;
00295                 for(i=0;i<NRAND;i++)
00296                         (void)rand();
00297                 for(i=0;i<NRAND;i++)
00298                         v[i] = rand();
00299                 vv = rand();
00300         }
00301         {
00302                 const unsigned y = vv%NRAND;
00303                 vv = v[ y ];
00304                 v[y] = rand();
00305         }
00306 
00307         {
00308                 const int out = ((long)vv*x)/((long)RAND_MAX+1);
00309 
00310                 return ((out>0)?out:0);
00311         }
00312 }
00313 
00314 
00315 gboolean mode(DATA *d, int n, int stop, struct mode_out *rv)
00316 {
00317         DATA qmin, qmax;
00318         DATA split1, split2, lastqmax, lastqmin;
00319         INT low, med, high, nmax, i, delta;
00320         double tmp;
00321 
00322 
00323         for(i=0,qmin=qmax=d[0];i<n;i++)
00324                 if(d[i] > qmax) qmax = d[i];
00325                 else if(d[i] < qmin)    qmin = d[i];
00326         qmax ++;        /* defined as qmin<=d[i]<qmax */
00327         if((LONGDATA)qmax-qmin < 3*stop)
00328                 qmax = qmin + 3*stop;
00329  
00330         while(1)        {
00331                 lastqmax = qmax;        
00332                 lastqmin = qmin;
00333                 split1 = qmin + (qmax-qmin+EPS)/3;
00334                 split2 = qmax - (qmax-qmin+EPS)/3;
00335    
00336                 for(low=med=high=0,i=0;i<n;i++) {
00337                         if(d[i]>=qmin && d[i]<split1)
00338                                 low++;
00339                         else if(d[i]>=split1 && d[i]<split2)
00340                                 med++;
00341                         else if(d[i]>=split2 && d[i]<qmax)
00342                                 high++;
00343                 }
00344    
00345    
00346                 /* adjust for cases where bins are of different lengths. */
00347                 low = (INT)(((DATA)low * (qmax-qmin))/(3*(split1-qmin)));
00348                 med = (INT)(((DATA)med * (qmax-qmin))/(3*(split2-split1)));
00349                 high = (INT)(((DATA)high * (qmax-qmin))/(3*(qmax-split2)));
00350    
00351    
00352                 nmax = low>med ? (low>high ? low : high) : (med>high ? med : high);
00353                 delta = (INT)(DFAC * sqrt((double)nmax) + 0.5);
00354    
00355                 if(low+delta<nmax && med+delta<nmax)    {
00356                         qmin = split2 - ((LONGDATA)qmax-qmin+EPS)/F1;
00357                         qmax = qmax + ((LONGDATA)qmax-qmin+EPS)/F3;
00358                 }
00359                 else if(med+delta<nmax && high+delta<nmax)      {
00360                         qmin = qmin - ((LONGDATA)qmax-qmin+EPS)/F3;
00361                         qmax = split1 + ((LONGDATA)qmax-qmin+EPS)/F1;
00362                 }
00363                 else if(low+delta<nmax && high+delta<nmax)      {
00364                         qmin = split1 - ((LONGDATA)qmax-qmin+EPS)/F1;
00365                         qmax = split2 + ((LONGDATA)qmax-qmin+EPS)/F1;
00366                 }
00367                 else if(low+delta<nmax) {
00368                         qmin = split1 - ((LONGDATA)qmax-qmin+EPS)/F2;
00369                         qmax = qmax + ((LONGDATA)qmax-qmin+EPS)/F2;
00370                 }
00371                 else if(high+delta<nmax)        {
00372                         qmin = qmin - ((LONGDATA)qmax-qmin+EPS)/F2;
00373                         qmax = split2 + ((LONGDATA)qmax-qmin+EPS)/F2;
00374                 }
00375                 else break;
00376    
00377                 if((LONGDATA)qmax-qmin<3*stop && (LONGDATA)lastqmax-lastqmin>=4*stop) {
00378                         if(lastqmax-qmax>qmin-lastqmin)
00379                                 qmax = qmin+3*stop;
00380                         else if(qmin-lastqmin>lastqmax-qmax)
00381                                 qmin = qmax-3*stop;
00382                         else if((LONGDATA)lastqmax-lastqmin>=qmax-qmin+3*stop)
00383                         {qmax += stop; qmin -= stop;}
00384                         else if(qmax-qmin >= 2*stop)
00385                                 qmax += stop;
00386                         else    {
00387                                 qmax = lastqmax;        qmin = lastqmin;
00388                                 break;
00389                         }
00390                 }
00391                 else if((LONGDATA)qmax-qmin < 3*stop)   {
00392                         qmax = lastqmax;        qmin = lastqmin;
00393                         break;
00394                 }
00395         }
00396  
00397         tmp = WEIGHTFAC * delta/(double)DFAC;
00398         split1 = qmin + (qmax-qmin+EPS)/3;
00399         split2 = qmax - (qmax-qmin+EPS)/3;
00400  
00401         rv->best = (((LONGDATA)qmin+split1-EPS)*exp((low-nmax)/tmp) +
00402                     ((LONGDATA)split1+split2-EPS)* exp((med-nmax)/tmp) +
00403                     ((LONGDATA)split2+qmax-EPS)*exp((high-nmax)/tmp)) /
00404                 (2.0*(exp((low-nmax)/tmp) +
00405                       exp((med-nmax)/tmp) +
00406                       exp((high-nmax)/tmp)));
00407         rv->low = ((LONGDATA)qmin+split1-EPS)/2.0;
00408         rv->high = ((LONGDATA)split2+qmax-EPS)/2.0;
00409  
00410         return (TRUE);
00411 }
00412 
00413 
00414 #define SAMPLE  10000
00415 
00416 gboolean deltamode(Scan *Src, int m, int n, int dm, int dn, 
00417                struct mode_out *answer)
00418 {
00419         int l, sample;
00420         DATA *ds;
00421  
00422         sample = (long)m*n<SAMPLE ? m*n : SAMPLE;
00423         ds = (DATA *)malloc(sizeof(*ds) * sample);
00424 
00425         for(l=0;l<sample;l++)   {
00426                 int i, j;
00427                 i = random_number(m-abs(dm))+(dm>0 ? 0 : -dm);
00428                 j = random_number(n-abs(dn))+(dn>0 ? 0 : -dn);
00429                 ds[l] = Src->mem2d->GetDataPkt (j+dn, i+dm) - Src->mem2d->GetDataPkt (j, i);
00430         }
00431         if ( (l > sample) || (l<1))     { 
00432                 return (FALSE);
00433         }
00434         mode(ds, l, 1, answer);
00435         free((void *)ds);
00436         return (TRUE);
00437 }
00438 
00439 
00440 
00441 #define START   8
00442 /* maximum probability plane */
00443 
00444 
00445 // run-Function
00446 static gboolean plane_max_prop_run(Scan *Src, Scan *Dest)
00447 {
00448         struct mode_out x1, xy1, y1, yx1;
00449         int i, j, delta, n, m;
00450         double xs, ys, xt, yt, xmi, xma, ymi, yma, xtu, ytu, xu, yu;
00451         double tosub;
00452 
00453         m = Dest->mem2d->GetNy (); // # lines
00454         n = Dest->mem2d->GetNx (); // # rows
00455         xmi = xma = ymi = yma = xs = ys = 0.0;
00456         for(delta=START; delta<m/2 && delta<n/2; delta*=2)      {
00457                 if (!deltamode(Src, m, n, delta, 0, &x1))
00458                         return(MATH_UNDEFINED);
00459                 if (!deltamode(Src, m, n, 0, delta, &y1))
00460                         return(MATH_UNDEFINED);
00461                 if (!deltamode(Src, m, n, delta, delta, &xy1))
00462                         return(MATH_UNDEFINED);
00463                 if (!deltamode(Src, m, n, delta, -delta, &yx1))
00464                         return(MATH_UNDEFINED);
00465   
00466                 xt = (xy1.best + yx1.best)/(2.0*delta);
00467                 yt = (xy1.best - yx1.best)/(2.0*delta);
00468                 xtu = (xy1.high+yx1.high-xy1.low-yx1.low)/2.0;
00469                 ytu = (xy1.high-xy1.low-yx1.high+yx1.low)/2.0;
00470                 xu = (x1.high-x1.low+xtu)/(2.0*delta);
00471                 yu = (y1.high-y1.low+ytu)/(2.0*delta);
00472                 x1.best /= (double)delta;
00473                 y1.best /= (double)delta;
00474 
00475                 if(delta > START) {
00476                         if(((xt>xma || xt<xmi) && (x1.best>xma || x1.best<xmi)) ||
00477                            ((yt>yma || yt<ymi) && (y1.best>yma || y1.best<ymi)))
00478                                 break;
00479                         fbound(xt, xmi, xma);
00480                         fbound(yt, ymi, yma);
00481                         fbound(x1.best, xmi, xma);
00482                         fbound(y1.best, ymi, yma);
00483                         xs = (x1.best + xt)/2.0;
00484                         ys = (y1.best + yt)/2.0;
00485           
00486                         xmi = MAX(xmi, xs-0.60*xu);
00487                         xma = MIN(xma, xs+0.60*xu);
00488                         ymi = MAX(ymi, ys-0.60*yu);
00489                         yma = MIN(yma, ys+0.60*yu);
00490                 }
00491                 else    {
00492                         xs = (x1.best + xt)/2.0;
00493                         ys = (y1.best + yt)/2.0;
00494                         xmi = xs - 0.60*xu;
00495                         xma = xs + 0.60*xu;
00496                         ymi = ys - 0.60*yu;
00497                         yma = ys + 0.60*yu;
00498                 }
00499         }
00500 
00501         for(i=0; i<m; i++) 
00502                 for(j=0; j<n; j++)
00503                         Dest->mem2d->PutDataPkt (Src->mem2d->GetDataPkt (j, i) - i*ys - j*xs, j, i);
00504 
00505 //              for(j=0, tosub=i*xs; j<n; j++, tosub+=ys)
00506         
00507 
00508         double max, min, off;
00509         Dest->mem2d->HiLo(&max, &min);
00510 
00511         off=(max+min)/2.;
00512         for(i=0;i<m;i++)
00513                 for(j=0;j<n;j++) 
00514                         Dest->mem2d->data->Zadd(-off, j, i);
00515 
00516         return MATH_OK;
00517 }
00518 

Generated on Sat Apr 1 09:04:20 2006 for GXSM by  doxygen 1.4.6