polarhist.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  * Quick nine points Gxsm Plugin GUIDE by PZ:
00006  * ------------------------------------------------------------
00007  * 1.) Make a copy of this "PolarHist.C" to "your_plugins_name.C"!
00008  * 2.) Replace all "PolarHist" by "your_plugins_name" 
00009  *     --> please do a search and replace starting here NOW!! (Emacs doese preserve caps!)
00010  * 3.) Decide: One or Two Source Math: see line 54
00011  * 4.) Fill in GxsmPlugin Structure, see below
00012  * 5.) Replace the "about_text" below a desired
00013  * 6.) * Optional: Start your Code/Vars definition below (if needed more than the run-fkt itself!), 
00014  *       Goto Line 155 ff. please, and see comment there!!
00015  * 7.) Fill in math code in PolarHist_run(), 
00016  *     have a look at the Data-Access methods infos at end
00017  * 8.) Add PolarHist.C to the Makefile.am in analogy to others
00018  * 9.) Make a "make; make install"
00019  * A.) Call Gxsm->Tools->reload Plugins, be happy!
00020  * ... That's it!
00021  * 
00022  * Gxsm Plugin Name: PolarHist.C
00023  * ========================================
00024  * 
00025  * Copyright (C) 1999 The Free Software Foundation
00026  *
00027  * Authors: Percy Zahl <zahl@fkp.uni-hannover.de>
00028  * additional features: Andreas Klust <klust@fkp.uni-hannover.de>
00029  *
00030  * This program is free software; you can redistribute it and/or modify
00031  * it under the terms of the GNU General Public License as published by
00032  * the Free Software Foundation; either version 2 of the License, or
00033  * (at your option) any later version.
00034  *
00035  * This program is distributed in the hope that it will be useful,
00036  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00037  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00038  * GNU General Public License for more details.
00039  *
00040  * You should have received a copy of the GNU General Public License
00041  * along with this program; if not, write to the Free Software
00042  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00043  */
00044 
00045 
00046 /* Please do not change the Begin/End lines of this comment section!
00047  * this is a LaTeX style section used for auto generation of the PlugIn Manual 
00048  * Chapter. Add a complete PlugIn documentation inbetween the Begin/End marks!
00049  * All "% PlugInXXX" commentary tags are mandatory
00050  * All "% OptPlugInXXX" tags are optional
00051  * --------------------------------------------------------------------------------
00052 % BeginPlugInDocuSection
00053 % PlugInDocuCaption: Generate a polar histogramm
00054 % PlugInName: polarhist
00055 % PlugInAuthor: Percy Zahl
00056 % PlugInAuthorEmail: zahl@users.sf.net
00057 % PlugInMenuPath: Math/Statistics/Polar Histogram
00058 
00059 % PlugInDescription
00060 This PlugIn generates from two data sets one (polar) histogram...
00061 
00062 % PlugInUsage
00063 Example:
00064 \begin{enumerate}
00065 \item open the demo Ge pyramid image
00066 \item optional for slow machines, scale by x and y 0.2
00067   (\GxsmMenu{Math/Transformation/Scan Scan}), then activate this
00068   channel
00069 \item call \GxsmMenu{Math/Statistics/Slope Abs}, use Facet Radius = 5
00070     (with scale down image)
00071 \item do \GxsmEmph{Autodisp} on resulting \GxsmEmph{Math} channel
00072 \item activate the original (e.g. scaled down image)
00073 \item set a free channel to \GxsmEmph{Math}
00074 \item call \GxsmMenu{Math/Statistics/Slope Dir}
00075 \item the ``Slope Abs'' resulting channel to \GxsmEmph{Mode-Active}
00076 \item the ``Slope Dir'' resulting channel to \GxsmEmph{Mode-X}
00077 \item call \GxsmMenu{Math/Statistics/Polar Hist}\\
00078 angular slices 180\\
00079 data channels  200\\
00080 data start 0\\
00081 data end   45\\
00082 Vmode 1\\
00083 \end{enumerate}
00084 
00085 data start = data end = 0 : auto ranging (min/max) is used
00086 
00087 % OptPlugInSources
00088 The active channel is used as histogramm data source, the X-channel is used as bin
00089 
00090 % OptPlugInObjects
00091 A optional rectangle is used for data extraction...
00092 
00093 % OptPlugInDest
00094 The computation result is placed into an existing math channel, else
00095 into a new created math channel.
00096 
00097 %% OptPlugInConfig
00098 %
00099 
00100 %% OptPlugInFiles
00101 %Does it uses, needs, creates any files? Put info here!
00102 
00103 % OptPlugInKnownBugs
00104 Produces sometimes strange output... pending to fix!
00105 
00106 % OptPlugInNotes
00107 Docu not finished jet, PlugIn makes Gxsm unstable after usage -- work in progress.
00108 
00109 %% OptPlugInHints
00110 %
00111 
00112 % EndPlugInDocuSection
00113  * -------------------------------------------------------------------------------- 
00114  */
00115 
00116 
00117 #include <gtk/gtk.h>
00118 #include "config.h"
00119 #include "gxsm/plugin.h"
00120 
00121 // Plugin Prototypes
00122 static void PolarHist_init( void );
00123 static void PolarHist_about( void );
00124 static void PolarHist_configure( void );
00125 static void PolarHist_cleanup( void );
00126 
00127 // Define Type of math plugin here, only one line should be commented in!!
00128 // #define GXSM_ONE_SRC_PLUGIN__DEF
00129 #define GXSM_TWO_SRC_PLUGIN__DEF
00130 
00131 // Math-Run-Function, use only one of (automatically done :=)
00132 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00133 // "OneSrc" Prototype
00134  static gboolean PolarHist_run( Scan *Src, Scan *Dest );
00135 #else
00136 // "TwoSrc" Prototype
00137  static gboolean PolarHist_run( Scan *Src1, Scan *Src2, Scan *Dest );
00138 #endif
00139 
00140 // Fill in the GxsmPlugin Description here
00141 GxsmPlugin PolarHist_pi = {
00142   NULL,                   // filled in and used by Gxsm, don't touch !
00143   NULL,                   // filled in and used by Gxsm, don't touch !
00144   0,                      // filled in and used by Gxsm, don't touch !
00145   NULL,                   // The Gxsm-App Class Ref.pointer (called "gapp" in Gxsm) is 
00146                           // filled in here by Gxsm on Plugin load, 
00147                           // just after init() is called !!!
00148   // ----------------------------------------------------------------------
00149   // Plugins Name, CodeStly is like: Name-M1S|M2S-BG|F1D|F2D|ST|TR|Misc
00150   "PolarHist-"
00151 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00152   "M1S"
00153 #else
00154   "M2S"
00155 #endif
00156   "-ST",
00157   // Plugin's Category - used to autodecide on Pluginloading or ignoring
00158   // NULL: load, else
00159   // example: "+noHARD +STM +AFM"
00160   // load only, if "+noHARD: no hardware" and Instrument is STM or AFM
00161   // +/-xxxHARD und (+/-INST or ...)
00162   NULL,
00163   // Description, is shown by PluginViewer (Plugin: listplugin, Tools->Plugin Details)
00164   "Calculates a Polar Histogramm from two Srcs: data, angle",
00165   // Author(s)
00166   "Percy Zahl",
00167   // Menupath to position where it is appendet to
00168   N_("_Math/_Statistics/"),
00169   // Menuentry
00170   N_("Polar Histogramm"),
00171   // help text shown on menu
00172   N_("from two Channels: 1.: data 2.:polar angle!"),
00173   // more info...
00174   "no more info",
00175   NULL,          // error msg, plugin may put error status msg here later
00176   NULL,          // Plugin Status, managed by Gxsm, plugin may manipulate it too
00177   // init-function pointer, can be "NULL", 
00178   // called if present at plugin load
00179   PolarHist_init,  
00180   // query-function pointer, can be "NULL", 
00181   // called if present after plugin init to let plugin manage it install itself
00182   NULL, // query should be "NULL" for Gxsm-Math-Plugin !!!
00183   // about-function, can be "NULL"
00184   // can be called by "Plugin Details"
00185   PolarHist_about,
00186   // configure-function, can be "NULL"
00187   // can be called by "Plugin Details"
00188   PolarHist_configure,
00189   // run-function, can be "NULL", if non-Zero and no query defined, 
00190   // it is called on menupath->"plugin"
00191   NULL, // run should be "NULL" for Gxsm-Math-Plugin !!!
00192   // cleanup-function, can be "NULL"
00193   // called if present at plugin removeal
00194   PolarHist_cleanup
00195 };
00196 
00197 // special math Plugin-Strucure, use
00198 // GxsmMathOneSrcPlugin PolarHist_m1s_pi -> "OneSrcMath"
00199 // GxsmMathTwoSrcPlugin PolarHist_m2s_pi -> "TwoSrcMath"
00200 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00201  GxsmMathOneSrcPlugin PolarHist_m1s_pi
00202 #else
00203  GxsmMathTwoSrcPlugin PolarHist_m2s_pi
00204 #endif
00205  = {
00206    // math-function to run, see prototype(s) above!!
00207    PolarHist_run
00208  };
00209 
00210 // Text used in Aboutbox, please update!!
00211 static const char *about_text = N_("Gxsm PolarHist Plugin\n\n"
00212                                    "This Plugin calculates a polar\n"
00213                                    "Histogramm of data in Src1,\n"
00214                                    "polar angle in Src2.");
00215 
00216 // Symbol "get_gxsm_plugin_info" is resolved by dlsym from Gxsm, used to get Plugin's info!! 
00217 // Essential Plugin Function!!
00218 GxsmPlugin *get_gxsm_plugin_info ( void ){ 
00219   PolarHist_pi.description = g_strdup_printf(N_("Gxsm MathOneArg PolarHist plugin %s"), VERSION);
00220   return &PolarHist_pi; 
00221 }
00222 
00223 // Symbol "get_gxsm_math_one|two_src_plugin_info" is resolved by dlsym from Gxsm, 
00224 // used to find out which Math Type the Plugin is!! 
00225 // Essential Plugin Function!!
00226 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00227 GxsmMathOneSrcPlugin *get_gxsm_math_one_src_plugin_info( void ) {
00228   return &PolarHist_m1s_pi; 
00229 }
00230 #else
00231 GxsmMathTwoSrcPlugin *get_gxsm_math_two_src_plugin_info( void ) { 
00232   return &PolarHist_m2s_pi; 
00233 }
00234 #endif
00235 
00236 // 5.) Start here with the plugins code, vars def., etc.... here.
00237 // ----------------------------------------------------------------------
00238 //
00239 
00240 int PolSlices    = 180;
00241 int DataChannels = 200;
00242 double DataStart = 0.;
00243 double DataEnd   = 90.;
00244 int Vmode        = 2;
00245 
00246 // init-Function
00247 static void PolarHist_init(void)
00248 {
00249   PI_DEBUG (DBG_L2, "PolarHist Plugin Init");
00250 }
00251 
00252 // about-Function
00253 static void PolarHist_about(void)
00254 {
00255   const gchar *authors[] = { PolarHist_pi.authors, NULL};
00256   gtk_widget_show(gnome_about_new ( PolarHist_pi.name,
00257                                     VERSION,
00258                                     N_("(C) 2000 the Free Software Foundation"),
00259                                     about_text,
00260                                     authors,
00261                                     NULL, NULL, NULL
00262                                     ));
00263 }
00264 
00265 // configure-Function
00266 static void PolarHist_configure(void)
00267 {
00268   GtkWidget *dialog;
00269   GtkWidget *vbox;
00270   GtkWidget *hbox;
00271   GtkWidget *info;
00272   GtkWidget *input;
00273   Gtk_EntryControl *ec;
00274 
00275   dialog = gnome_dialog_new(_("Polar Histogramm Setup"),
00276                             GNOME_STOCK_BUTTON_OK,
00277                             NULL); 
00278         
00279   gnome_dialog_set_close(GNOME_DIALOG(dialog), FALSE);
00280   gnome_dialog_close_hides(GNOME_DIALOG(dialog), FALSE);
00281   gnome_dialog_set_default(GNOME_DIALOG(dialog), 0);
00282 
00283   vbox = gtk_vbox_new (FALSE, 0);
00284   gtk_widget_show (vbox);
00285 
00286   gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox),
00287                      vbox, TRUE, TRUE, GNOME_PAD);
00288 
00289   info = gtk_label_new ("Polar Histogramm Setup");
00290   gtk_widget_show (info);
00291   gtk_box_pack_start(GTK_BOX(vbox), info, TRUE, TRUE, GNOME_PAD);
00292 
00293   input = PolarHist_pi.app->mygtk_create_input("# angular slices", vbox, hbox);
00294   ec = new Gtk_EntryControl(PolarHist_pi.app->xsm->Unity, 
00295                            "Value out of range !", 
00296                            &PolSlices, 
00297                            2., 3600., ".0f", input);
00298 
00299   input = PolarHist_pi.app->mygtk_create_input("# data channels", vbox, hbox);
00300   ec = new Gtk_EntryControl(PolarHist_pi.app->xsm->Unity, 
00301                            "Value out of range !",
00302                            &DataChannels,
00303                            2., 100000., ".0f", input);
00304 
00305   info = gtk_label_new ("Data Range (0...0 -> auto)");
00306   gtk_widget_show (info);
00307   gtk_box_pack_start(GTK_BOX(vbox), info, TRUE, TRUE, GNOME_PAD);
00308 
00309   input = PolarHist_pi.app->mygtk_create_input("Data Start", vbox, hbox);
00310   ec = new Gtk_EntryControl(PolarHist_pi.app->xsm->Unity, 
00311                            "Value out of range !",
00312                            &DataStart,
00313                            -1e10, 1e10, ".3f", input);
00314 
00315   input = PolarHist_pi.app->mygtk_create_input("Data End", vbox, hbox);
00316   ec = new Gtk_EntryControl(PolarHist_pi.app->xsm->Unity, 
00317                            "Value out of range !",
00318                            &DataEnd,
00319                            -1e10, 1e10, ".3f", input);
00320 
00321   input = PolarHist_pi.app->mygtk_create_input("Vmode 1=cir,2=rect", vbox, hbox);
00322   ec = new Gtk_EntryControl(PolarHist_pi.app->xsm->Unity, 
00323                            "Value out of range !",
00324                            &Vmode,
00325                            0., 10., ".0f", input);
00326 
00327   gtk_widget_show(dialog);
00328 
00329   gnome_dialog_run_and_close(GNOME_DIALOG(dialog));
00330 } 
00331 
00332 // cleanup-Function
00333 static void PolarHist_cleanup(void)
00334 {
00335   PI_DEBUG (DBG_L2, "PolarHist Plugin Cleanup");
00336 }
00337 
00338 double Phi(double dx, double dy){
00339     double q23=0.;
00340     if(dx<0.){
00341         q23=180.;
00342         if(dy<0. )
00343           q23=-180.;
00344     }
00345 
00346     if(fabs(dx)>1e-6)
00347       return q23+180.*atan(dy/dx)/M_PI;
00348     else return dy>0.?90.:-90.;
00349 }
00350 
00351 // run-Function
00352 #ifdef GXSM_ONE_SRC_PLUGIN__DEF
00353  static gboolean PolarHist_run(Scan *Src, Scan *Dest)
00354 #else
00355  static gboolean PolarHist_run(Scan *Src1, Scan *Src2, Scan *Dest)
00356 #endif
00357 {
00358   // put plugins math code here...
00359   if(Src1->data.s.nx != Src2->data.s.nx || Src1->data.s.ny != Src2->data.s.ny)
00360     return MATH_SELECTIONERR;
00361 
00362   PolarHist_configure();
00363 
00364   // easy and fast acess macro
00365 #define GetNumValPhi(V,P)  Num[PolSlices*(V) + (P)]
00366 #define IncNumValPhi(V,P)  ++Num[PolSlices*(V) + (P)]
00367   long *Num = new long[PolSlices * DataChannels];
00368   memset(Num, 0, sizeof(Num));
00369 
00370   // Autorange?
00371   if((DataStart == 0. && DataEnd == 0.) | DataStart > DataEnd)
00372     Src1->mem2d->HiLo(&DataEnd, &DataStart, FALSE, NULL, NULL, 1);
00373 
00374   double DataRange = DataEnd - DataStart;
00375   double SliceAng  = 360./(double)PolSlices;
00376 
00377   // Now do Counting
00378   for(int line=0; line<Src1->data.s.ny; line++)
00379     for(int col=0; col<Src1->data.s.nx; col++){
00380       int v = (int)rint((Src1->mem2d->GetDataPkt(col, line)-DataStart)*(double)DataChannels/DataRange);
00381       int p = (int)rint(Src2->mem2d->GetDataPkt(col, line)/SliceAng);
00382       p += PolSlices; p = p % PolSlices;
00383       if( v < 0 || v >= DataChannels || p < 0 || p >= PolSlices)
00384         continue;
00385       IncNumValPhi(v, p);
00386     }
00387 
00388   // Setup Destination
00389   // and Fillup Polar Plot
00390   UnitObj *u;
00391   Dest->data.SetXUnit(u=new UnitObj("rPhi","rPhi"));
00392   Dest->data.SetYUnit(u); delete u;
00393   Dest->data.SetZUnit(u=new UnitObj("#","#")); delete u;
00394   Dest->data.s.dz = 1.;
00395 
00396   switch(Vmode){
00397   case 1:
00398     Dest->data.s.nx = Dest->data.s.ny = DataChannels*2-1;
00399     Dest->mem2d->Resize(Dest->data.s.nx, Dest->data.s.ny, ZD_FLOAT);
00400     Dest->data.s.rx = Dest->data.s.ry = DataRange;
00401     Dest->data.s.x0 = Dest->data.s.y0 = DataStart;
00402     Dest->mem2d->data->MkXLookup(-DataRange, DataRange);
00403     Dest->mem2d->data->MkYLookup(-DataRange, DataRange);
00404     for(int line=0; line<Dest->data.s.ny; line++)
00405       for(int col=0; col<Dest->data.s.nx; col++){
00406         int dx= col-Dest->data.s.nx/2;
00407         int dy=line-Dest->data.s.ny/2;
00408         int v = (int)rint(sqrt(dx*dx+dy*dy));
00409         int p = (int)rint(Phi(dx, dy)/SliceAng);
00410         p += PolSlices; p = p % PolSlices;
00411         if( v < 0 || v >= DataChannels || p < 0 || p >= PolSlices)
00412           continue;
00413         if(v > (int)((double)DataChannels/2/M_PI))
00414           Dest->mem2d->PutDataPkt((double)GetNumValPhi(v, p), col, line);
00415         else{
00416           double sumup=0.;
00417           if(v>0){
00418             for(int i=p-(int)((double)DataChannels/2/M_PI/v); 
00419                 i<=p+(int)((double)DataChannels/2/M_PI/v); ++i)
00420               sumup += GetNumValPhi(v, (i+PolSlices)%PolSlices);
00421             sumup /= (1+2*(int)((double)DataChannels/2/M_PI/v));
00422             sumup *= (double)DataChannels/2/M_PI/v;
00423           }
00424           else
00425             for(int i=0; i<PolSlices; ++i)
00426               sumup += GetNumValPhi(v, i);
00427           Dest->mem2d->PutDataPkt(sumup, col, line);
00428         }
00429       }
00430     break;
00431   default:
00432     Dest->data.s.nx = DataChannels;
00433     Dest->data.s.ny = PolSlices;
00434     Dest->mem2d->Resize(Dest->data.s.nx, Dest->data.s.ny, ZD_LONG);
00435     Dest->data.s.rx = Dest->data.s.ry = DataRange;
00436     Dest->data.s.x0 = Dest->data.s.y0 = DataStart;
00437     Dest->mem2d->data->MkXLookup(0., DataRange);
00438     Dest->mem2d->data->MkYLookup(0., 360.);
00439     for(int line=0; line<Dest->data.s.ny; line++)
00440       for(int col=0; col<Dest->data.s.nx; col++)
00441         Dest->mem2d->PutDataPkt((double)GetNumValPhi(col, line), col, line);
00442     break;
00443   }
00444 
00445   delete[] Num;
00446 
00447   return MATH_OK;
00448 }
00449 
00450 // END

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