scan.C

Go to the documentation of this file.
00001 /* Gxsm - Gnome X Scanning Microscopy
00002  * universal STM/AFM/SARLS/SPALEED/... controlling and
00003  * data analysis software
00004  * 
00005  * Copyright (C) 1999,2000,2001,2002,2003 Percy Zahl
00006  *
00007  * Authors: Percy Zahl <zahl@users.sf.net>
00008  * additional features: Andreas Klust <klust@users.sf.net>
00009  * WWW Home: http://gxsm.sf.net
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00024  */
00025 
00026 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 8 c-style: "K&R" -*- */
00027 
00028 #include <locale.h>
00029 #include <libintl.h>
00030 
00031 
00032 #include <time.h>
00033 #include "surface.h"
00034 #include "xsmmasks.h"
00035 #include "glbvars.h"
00036 #include "action_id.h"
00037 #include "xsm.h"
00038 
00039 int scandatacount=0;
00040 
00041 Scan::Scan(Scan *scanmaster){
00042         refcount=0;
00043         Running = 0;
00044         Pkt2d = NULL;
00045         numpkt2d = 0;
00046         objects_id = 0;
00047         objects_list = NULL;
00048         realloc_pkt2d(16);
00049         vdata = scanmaster->vdata;;
00050         mem2d = new Mem2d(1,1,scanmaster->mem2d->GetTyp()); // MemObj. anlegen
00051         if (vdata)
00052                 data.CpUnits(*vdata);
00053         data.s.tStart=data.s.tEnd=(time_t)0;
00054         view=NULL; // noch klein View
00055         VFlg  = scanmaster->VFlg;
00056         ChanNo= scanmaster->ChanNo;
00057         State = IS_FRESH;
00058 }
00059 
00060 
00061 Scan::Scan(int vtype, int vflg, int ChNo, SCAN_DATA *vd, ZD_TYPE mtyp){
00062         refcount=0;
00063         Running = 0;
00064         Pkt2d = NULL;
00065         numpkt2d = 0;
00066         objects_id = 0;
00067         objects_list = NULL;
00068         realloc_pkt2d(16);
00069         vdata = vd;
00070         mem2d = new Mem2d(1,1,mtyp); // MemObj. anlegen
00071         if(vd)
00072                 data.CpUnits(*vdata);
00073         data.s.tStart=data.s.tEnd=(time_t)0;
00074         view=NULL; // noch klein View
00075         VFlg  = SCAN_V_QUICK;
00076         ChanNo= ChNo;
00077         State = IS_FRESH;
00078         if(vflg)
00079                 VFlg = vflg;
00080         if(vtype)
00081                 SetView(vtype);
00082         SetVM(vflg, vdata);
00083 }
00084 
00085 Scan::~Scan(){
00086         if(State==NOT_SAVED)
00087                 ;
00088         if(view) delete view; // ggf. alten View löschen
00089         view=NULL;
00090         delete mem2d; // MemObj. löschen
00091         delete[] Pkt2d; 
00092         destroy_all_objects ();
00093 }
00094 
00095 int Scan::add_object (const gchar *name, const gchar *text,
00096                      int np, void (*f_xyi)(int, double&, double&)){
00097         scan_object_data *sod = new scan_object_data (++objects_id, name, text, np, f_xyi); 
00098         objects_list = g_slist_prepend (objects_list, sod);
00099         return sod->get_id ();
00100 }
00101 
00102 void Scan::update_object (int id, 
00103                           const gchar *name, const gchar *text,
00104                           void (*f_xyi)(int, double&, double&)){
00105         ((scan_object_data*) g_slist_nth_data(objects_list, find_object (id))) -> update (name, text, f_xyi); 
00106 }
00107 
00108 int Scan::find_object (int id){
00109         for(unsigned int i=0; i< g_slist_length(objects_list); i++)
00110                 if (((scan_object_data*) g_slist_nth_data(objects_list, i)) -> get_id () == id)
00111                         return (int)i;
00112         return -1;
00113 }
00114 
00115 int Scan::del_object (int id){
00116         for(unsigned int i=0; i< g_slist_length(objects_list); i++){
00117                 scan_object_data* sod = (scan_object_data*) g_slist_nth_data(objects_list, i);
00118                 if (sod->get_id() == id){
00119                         objects_list = g_slist_remove((GSList*) objects_list, sod);
00120                         delete sod;
00121                         return 0;
00122                 }
00123         }
00124         return -1;
00125 }
00126 
00127 
00128 
00129 void Scan::realloc_pkt2d(int n){
00130         if (numpkt2d < n){
00131                 if (Pkt2d)
00132                         delete[] Pkt2d;
00133                 Pkt2d = new Point2D[numpkt2d = n];
00134                 XSM_DEBUG(DBG_L2, "Scan::realloc_pkt2d: n=" << n );
00135                 for (int i=0; i<n; ++i)
00136                         Pkt2d[i].x = Pkt2d[i].y = 0;
00137                 XSM_DEBUG(DBG_L2, "Scan::realloc_pkt2d done." );
00138         }
00139 }
00140 
00141 void Scan::AutoDisplay(double hi, double lo, int Delta){
00142 
00143         if (hi == 0. && lo == 0.){
00144                 SetVM (-1, NULL, Delta);
00145 
00146                 // step 2: calculate contrast and bright from Zmin, Zrange
00147                 mem2d->AutoDataSkl (&vdata->display.contrast, &vdata->display.bright);
00148                 // store high and low in vdata
00149                 mem2d->GetZHiLo (&vdata->display.cpshigh, &vdata->display.cpslow);
00150                 // calculate Vrange in Units
00151                 vdata->display.vrange_z = fabs (vdata->s.dz * mem2d->GetZRange ())
00152                         * (vdata->display.vrange_z > 0. ? 1.:-1.);
00153                 vdata->display.voffset_z = 0.;
00154                 // only neede by SPALEED
00155                 vdata->display.cpshigh /= vdata->display.cnttime; // correct to CPS now!
00156                 vdata->display.cpslow  /= vdata->display.cnttime;
00157 
00158         } else {
00159 
00160                 mem2d->SetHiLo (hi, lo);
00161                 mem2d->AutoDataSkl (&vdata->display.contrast, &vdata->display.bright);
00162                 mem2d->GetZHiLo (&vdata->display.cpshigh, &vdata->display.cpslow);
00163                 vdata->display.vrange_z = vdata->s.dz * fabs (mem2d->GetZRange ())
00164                         * (vdata->display.vrange_z > 0. ? 1.:-1.);
00165                 vdata->display.voffset_z = 0.;
00166                 vdata->display.cpshigh /= vdata->display.cnttime; // correct to CPS now!
00167                 vdata->display.cpslow  /= vdata->display.cnttime;
00168         }
00169 
00170         data.GetDisplay_Param(*vdata);
00171 }
00172 
00173 int Scan::SetVM(int vflg, SCAN_DATA *src, int Delta){
00174         if (vflg > 0)
00175                 data.display.ViewFlg=vflg;
00176 
00177         if (view)
00178                 view->setup_data_transformation();
00179 
00180         if (src)
00181                 data.GetDisplay_Param (*src);
00182 
00183         if (IS_SPALEED_CTRL){
00184                 mem2d->SetHiLo(data.display.GetCntHigh(), data.display.GetCntLow());
00185                 mem2d->AutoDataSkl(&data.display.contrast, &data.display.bright);
00186         }else{
00187                 // step 1: Recalculate Zmin, Zmax -> Zrange (mem2d internal)
00188                 if (PktVal == 2)
00189                         if(gapp->xsm->ZoomFlg & VIEW_TOLERANT)
00190                                 mem2d->AutoHistogrammEvalMode (&Pkt2d[0], &Pkt2d[1], Delta);
00191                         else
00192                                 mem2d->HiLoMod (&Pkt2d[0], &Pkt2d[1], Delta);
00193                 else{ // look for any rectangle, uses the first found from "end"
00194                         int success = FALSE;
00195                         int n_obj = number_of_object ();
00196                         Point2D p[2];
00197                         while (n_obj--){
00198                                 scan_object_data *obj_data = get_object_data (n_obj);
00199                 
00200                                 if (strncmp (obj_data->get_name (), "Rectangle", 9) )
00201                                         continue; // only points are used!
00202 
00203                                 if (obj_data->get_num_points () != 2) 
00204                                         continue; // sth. is weired!
00205 
00206                                 double x,y; x=y=0.;
00207                                 obj_data->get_xy_pixel (0, x, y);
00208                                 p[0].x = (int)x; p[0].y = (int)y;
00209                                 obj_data->get_xy_pixel (1, x, y);
00210                                 p[1].x = (int)x; p[1].y = (int)y;
00211 
00212                                 success = TRUE;
00213                                 break;
00214                         }
00215                         if (success){
00216                                 if(gapp->xsm->ZoomFlg & VIEW_TOLERANT)
00217                                         mem2d->AutoHistogrammEvalMode (&Pkt2d[0], &Pkt2d[1], Delta);
00218                                 else
00219                                         mem2d->HiLoMod (&p[0], &p[1], Delta);
00220                         } else {
00221                                 if(gapp->xsm->ZoomFlg & VIEW_TOLERANT)
00222                                         mem2d->AutoHistogrammEvalMode (NULL, NULL, Delta);
00223                                 else
00224                                         mem2d->HiLoMod (NULL, NULL, Delta);
00225                         }
00226                 }
00227 
00228                 if (vflg >= 0) {
00229                         // step 2: adjust to user settings, 
00230                         //         offset is relative to data average
00231                         mem2d->SetDataVRangeZ (data.display.vrange_z, 
00232                                                data.display.voffset_z,
00233                                                data.s.dz);
00234                         // calculate contrast and bright
00235                         mem2d->AutoDataSkl(&data.display.contrast, &data.display.bright);
00236                 }
00237         }
00238 
00239         if (vflg >= 0)
00240                 draw ();
00241 
00242         return 0;
00243 }
00244 
00245 void Scan::hide(){;}
00246 
00247 void Scan::Activate(){
00248         XSM_DEBUG (DBG_L2, "Scan::Activate VFlg=" << VFlg);
00249         
00250         GetDataSet(*vdata);
00251         VFlg = data.display.ViewFlg;
00252         gapp->spm_update_all(VFlg);
00253 }
00254 
00255 int Scan::SetView(int vtype){ 
00256         if(view) delete view; // ggf. alten View löschen
00257         view = NULL;
00258         switch(vtype){
00259         case ID_CH_V_NO:
00260                 return ID_CH_V_NO;
00261                 break;
00262         case ID_CH_V_GREY: 
00263                 view = new Grey2D(this, ChanNo);
00264                 SetVM();
00265                 draw();
00266                 return ID_CH_V_GREY;
00267                 break;
00268         case ID_CH_V_PROFILE:
00269                 view = new Profiles(this, ChanNo);
00270                 draw();
00271                 return ID_CH_V_PROFILE;
00272                 break;
00273         case ID_CH_V_SURFACE:
00274                 //    return ID_CH_V_NO; // just disable
00275                 view = new Surf3d(this, ChanNo);
00276                 SetVM();
00277                 draw();
00278                 return ID_CH_V_SURFACE;
00279                 break;
00280         default:    
00281                 return ID_CH_V_NO;
00282         }
00283 
00284 }
00285 
00286 int Scan::draw(int y1, int y2){
00287         if (view){
00288                 mem2d->SetDataSkl (data.display.contrast, data.display.bright);
00289                 //    XSMDEBUGLVL(8,"Scan::draw");
00290                 if(y1>0)
00291                         view->update(y1,y2);
00292                 else
00293                         view->draw();
00294         }
00295         //  else XSM_DEBUG (DBG_L2, "no view !");
00296         return 0;
00297 }
00298 
00299 int Scan::create(gboolean RoundFlg, gboolean subgrid){
00300         if(vdata){
00301                 Display_Param disp_tmp;
00302                 // jetzt alle Werte übernehmen
00303                 data.GetScan_Param(*vdata);
00304                 data.GetUser_Info(*vdata);
00305 // **           data.GetDSP_Param(*vdata);
00306                 data.UpdateUnits();
00307 //    XSM_DEBUG (DBG_L2, "Scan:Create, viewdata:" << " c:" << data.display.contrast << " vdata:" << vdata->s.nx << "x" << vdata->s.ny);
00308                 
00309                 if(State == IS_FRESH){ // nur falls neu, sonst beibehalten
00310                         data.GetDisplay_Param(*vdata);
00311 // **                   data.GetLayer_Param(*vdata);
00312                 }
00313         }
00314         
00315         data.ui.SetName("noname");
00316         
00317         mem2d->Resize(data.s.nx, data.s.ny);
00318 
00319 //--OffRotFix--
00320         mem2d->data->MkXLookup (-data.s.rx/2, data.s.rx/2);
00321 
00322         switch(data.orgmode){
00323         case SCAN_ORG_MIDDLETOP:
00324                 mem2d->data->MkYLookup (0., -data.s.ry); break;
00325         case SCAN_ORG_CENTER:
00326                 mem2d->data->MkYLookup (data.s.ry/2, -data.s.ry/2); break;
00327         }
00328         
00329         // "Anzeige-Daten" aktualisieren
00330         if (vdata){
00331                 vdata->GetScan_Param(data);
00332                 vdata->GetUser_Info(data);
00333         } else {
00334                 data.s.nvalues = 1;
00335                 data.s.ntimes = 1;
00336         }
00337 
00338         XSM_DEBUG (DBG_L2, "Scan::create done");
00339         State= IS_NEW;
00340         Running = 0;
00341         
00342         return 0;
00343 }
00344 
00345 void Scan::start(){  
00346         data.UpdateUnits ();
00347         data.s.tStart = time (0);
00348         inc_refcount ();
00349         data.ui.SetOriginalName ("unknown (not saved)");
00350         if (vdata){
00351                 vdata->ui.SetOriginalName ("unknown (not saved)");
00352                 gapp->ui_update();
00353         }
00354         Running = 1;
00355 }
00356 void Scan::stop(int StopFlg, int line){
00357         data.s.tEnd = time (0);
00358         if (StopFlg && gapp->xsm->hardware->FreeOldData ()){
00359                 mem2d->Resize (data.s.nx, data.s.ny=line);
00360                 data.s.ry = data.s.ny*data.s.dy;
00361                 draw ();
00362         }
00363         Running = 0;
00364         dec_refcount ();
00365         if (vdata){
00366                 vdata->ui.SetOriginalName ("unknown (not saved)");
00367                 gapp->ui_update(); // hack as long signal "changed" did not work
00368                 data.ui.SetComment (vdata->ui.comment);
00369         }
00370 }
00371 
00372 // get updated copy of user fields comment, ...
00373 void Scan::CpyUserEntries(SCAN_DATA &src){
00374         data.GetUser_Info (src);
00375 }
00376 
00377 // get complete data set
00378 void Scan::CpyDataSet(SCAN_DATA &src){
00379         data.GetScan_Param (src);
00380 // **   data.GetLayer_Param (src);
00381         data.GetUser_Info (src);
00382 // **   data.GetDSP_Param (src);
00383         data.GetDisplay_Param (src);
00384         data.UpdateUnits ();
00385 }
00386 
00387 // put back dataset without dsp-params
00388 void Scan::GetDataSet(SCAN_DATA &dst){
00389         dst.GetScan_Param (data);
00390 
00391         if (!Running) // new - 20041022, do not put back if scan is running!!
00392                 dst.GetUser_Info (data);
00393 
00394         dst.GetDisplay_Param (data);
00395 // **   if (IS_SPALEED_CTRL) // need to get Energy and gatettime !
00396 // **           dst.GetDSP_Param (data);
00397         dst.UpdateUnits ();
00398 // **   dst.GetLayer_Param (data);
00399         dst.SetZUnit (data.Zunit);
00400 }
00401 
00402 int Scan::Pixel2World (int ix, int iy, double &wx, double &wy, SCAN_COORD_MODE scm){
00403         switch (scm){
00404         case SCAN_COORD_ABSOLUTE:
00405         {
00406                 double s = sin (data.s.alpha*M_PI/180.);
00407                 double c = cos (data.s.alpha*M_PI/180.);
00408                 double rx = mem2d->data->GetXLookup (ix);
00409                 double ry = mem2d->data->GetYLookup (iy);
00410                 // offset + rotation
00411                 wx = data.s.x0 + c*rx + s*ry;
00412                 wy = data.s.y0 - s*rx + c*ry;
00413         }
00414         break;
00415         case SCAN_COORD_RELATIVE:
00416                 wx = mem2d->data->GetXLookup (ix);
00417                 wy = mem2d->data->GetYLookup (iy);
00418                 break;
00419         }
00420         return 0;
00421 }
00422 
00423 int Scan::World2Pixel (double wx, double wy, int &ix, int &iy, SCAN_COORD_MODE scm){
00424         double rx=0.,ry=0.;
00425         int ix0,iy0;
00426 
00427         switch (scm){
00428         case SCAN_COORD_ABSOLUTE:
00429         {
00430                 double s = sin (data.s.alpha*M_PI/180.);
00431                 double c = cos (data.s.alpha*M_PI/180.);
00432                 wx -= data.s.x0; // remove offset
00433                 wy -= data.s.y0;
00434                 rx = c*wx - s*wy; // inverse rotation
00435                 ry = s*wx + c*wy;
00436         }
00437         break;
00438         case SCAN_COORD_RELATIVE:
00439                 rx = wx;
00440                 ry = wy;
00441                 break;
00442         }
00443 
00444         // linear guess -- not using lookup here!
00445 //      ix0 = round((rx - data.s.x0) / data.s.dx + (double)data.s.nx/2.);
00446 //      iy0 = round(-(ry - data.s.y0) / data.s.dy + ((data.orgmode == SCAN_ORG_CENTER)? (double)data.s.ny/2. : 0.));
00447         ix0 = (int)round(rx / data.s.dx + (double)data.s.nx/2.);
00448         iy0 = (int)round(-ry / data.s.dy + ((data.orgmode == SCAN_ORG_CENTER)? (double)data.s.ny/2. : 0.));
00449 
00450         // lookup search/check
00451 /*
00452         do {
00453                 x = mem2d->data->GetXLookup (ix0);
00454                 y = mem2d->data->GetYLookup (iy0);
00455         } while (0);
00456 */
00457 
00458         ix = ix0;
00459         iy = iy0;
00460 
00461         return 0;
00462 }

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