WSxM_io.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  * Gxsm Plugin Name: WSxM_io.C
00006  * ========================================
00007  * 
00008  * Copyright (C) 2001 The Free Software Foundation
00009  *
00010  * Authors: Thorsten Wagner <thorsten.wagner@uni-essen.de> 
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00025  */
00026 
00027 /* Please do not change the Begin/End lines of this comment section!
00028  * this is a LaTeX style section used for auto generation of the PlugIn Manual 
00029  * Chapter. Add a complete PlugIn documentation inbetween the Begin/End marks!
00030  * All "% PlugInXXX" commentary tags are mandatory
00031  * All "% OptPlugInXXX" tags are optional
00032  * --------------------------------------------------------------------------------
00033 % BeginPlugInDocuSection
00034 % PlugInDocuCaption: Import/export for WSxM Nanotec Electronica SPM data
00035 % PlugInName: WSxM_io
00036 % PlugInAuthor: Thorsten Wagner
00037 % PlugInAuthorEmail: stm@users.sf.net
00038 % PlugInMenuPath: File/Im,Export/WXsM
00039 
00040 % PlugInDescription
00041 Data import/export of the WSxM data format (version 2) used by Nanotec
00042 Electronica.
00043 
00044 % PlugInUsage
00045 Call it from \GxsmMenu{File/Im,Export/WXsM}. Also a normal open or
00046 drag- and drop action from gmc, nautilus or Netscape (URL) will
00047 automatic import WSxM files.
00048 
00049 % OptPlugInRefs
00050 \GxsmWebLink{www.nanotec.es}
00051 
00052 %% OptPlugInKnownBugs
00053 %Are there known bugs? List! How to work around if not fixed?
00054 The import algorithm is not complete yet. You will get the image, but the scan data are only fake.
00055 
00056 % OptPlugInNotes
00057 DnD and URL drops are not tested.
00058 
00059 %% OptPlugInHints
00060 %Any tips and tricks?
00061 
00062 % EndPlugInDocuSection
00063  * -------------------------------------------------------------------------------- 
00064  */
00065 
00066 #include <gtk/gtk.h>
00067 // #include <linux/coff.h>
00068 #include "config.h"
00069 #include "gxsm/plugin.h"
00070 #include "gxsm/dataio.h"
00071 #include "gxsm/action_id.h"
00072 #include "gxsm/glbvars.h"
00073 #include "plug-ins/hard/sranger_hwi.h"
00074 #include "WSxM_header.h"                // File distributet with WSxM to make header of data file
00075 #include <netcdf.hh>                    // used to read additional data from original file
00076 
00077 #define WSXM_MAXCHARS 1000
00078 #define IS_PICO_AMP 100      // Check whether saving as pico is more suitable
00079 
00080 extern DSPControl *DSPControlClass;
00081 using namespace std;
00082 
00083 // Plugin Prototypes
00084 static void WSxM_im_export_init (void);
00085 static void WSxM_im_export_query (void);
00086 static void WSxM_im_export_about (void);
00087 static void WSxM_im_export_configure (void);
00088 static void WSxM_im_export_cleanup (void);
00089 
00090 static void WSxM_im_export_filecheck_load_callback (gpointer data );
00091 static void WSxM_im_export_filecheck_save_callback (gpointer data );
00092 
00093 static void WSxM_im_export_import_callback (GtkWidget *w, void *data);
00094 static void WSxM_im_export_export_callback (GtkWidget *w, void *data);
00095 
00096 // Fill in the GxsmPlugin Description here
00097 GxsmPlugin WSxM_im_export_pi = {
00098   NULL,                   // filled in and used by Gxsm, don't touch !
00099   NULL,                   // filled in and used by Gxsm, don't touch !
00100   0,                      // filled in and used by Gxsm, don't touch !
00101   NULL,                   // The Gxsm-App Class Ref.pointer (called "gapp" in Gxsm) is 
00102                           // filled in here by Gxsm on Plugin load, 
00103                           // just after init() is called !!!
00104   "WSxM-ImExport",        // Plugins Name, CodeStly is like: Name-M1S|M2S-BG|F1D|F2D|ST|TR|Misc
00105   NULL,                   // Plugin's Category - used to autodecide on Pluginloading or ignoring -- NULL: always
00106   "Im/Export of the WSxM data format (version 2).",     // Description, is shown by PluginViewer (Plugin: listplugin, Tools->Plugin Details)
00107   "Thorsten Wagner",      // Author(s)/* Gnome gxsm - Gnome X Scanning Microscopy
00108   N_("_File/_Import/,_File/_Export/"), // sep. im/export menuentry path by comma!
00109   N_("WSxM,WSxM"), // menu entry (same for both)
00110   N_("WSxM import,WSxM export"), // short help for menu entry
00111   N_("WSxM data file import and export filter.\n WSxM is a powerful data manipulation program for spm data. \n Visit for more details www.nanotec.es!"),
00112   NULL,          // error msg, plugin may put error status msg here later
00113   NULL,          // Plugin Status, managed by Gxsm, plugin may manipulate it too
00114   WSxM_im_export_init,  
00115   WSxM_im_export_query,  
00116   // about-function, can be "NULL"
00117   // can be called by "Plugin Details"
00118   WSxM_im_export_about,
00119   // configure-function, can be "NULL"
00120   // can be called by "Plugin Details"
00121   WSxM_im_export_configure,
00122   // run-function, can be "NULL", if non-Zero and no query defined, 
00123   // it is called on menupath->"plugin"
00124   NULL,
00125   // cleanup-function, can be "NULL"
00126   // called if present at plugin removeal
00127   WSxM_im_export_cleanup
00128 };
00129 
00130 // Text used in Aboutbox, please update!!
00131 static const char *about_text = N_("Gxsm file import/export plugin for WSxM files\n\n"
00132                                    "This plugin writes in WSxM datafiles."
00133         );
00134 
00135 static const char *file_mask = "*.top";
00136 
00137 // Symbol "get_gxsm_plugin_info" is resolved by dlsym from Gxsm, used to get Plugin's info!! 
00138 // Essential Plugin Function!!
00139 GxsmPlugin *get_gxsm_plugin_info ( void ){ 
00140   WSxM_im_export_pi.description = g_strdup_printf(N_("Gxsm WSxM import/export plugin %s"), VERSION);
00141   return &WSxM_im_export_pi; 
00142 }
00143 
00144 // Query Function, installs Plugin's in File/Import and Export Menupaths!
00145 // ----------------------------------------------------------------------
00146 // Import Menupath is "File/Import/WSxM import"
00147 // Export Menupath is "File/Export/WSxM import"
00148 // ----------------------------------------------------------------------
00149 // !!!! make sure the "WSxM_im_export_cleanup()" function (see below) !!!!
00150 // !!!! removes the correct menuentries !!!!
00151 
00152 static void WSxM_im_export_query(void)
00153 {
00154         gchar **path  = g_strsplit (WSxM_im_export_pi.menupath, ",", 2);
00155         gchar **entry = g_strsplit (WSxM_im_export_pi.menuentry, ",", 2);
00156         gchar **help  = g_strsplit (WSxM_im_export_pi.help, ",", 2);
00157 
00158         static GnomeUIInfo menuinfo_i[] = { 
00159                 { GNOME_APP_UI_ITEM, NULL, NULL,
00160                   NULL, NULL,
00161                   NULL, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_OPEN,
00162                   0, GDK_CONTROL_MASK, NULL },
00163                 GNOMEUIINFO_END
00164         };
00165         menuinfo_i[0].label  = entry[0];
00166         menuinfo_i[0].hint   = help[0];
00167         menuinfo_i[0].moreinfo  = (gpointer) WSxM_im_export_import_callback; 
00168         menuinfo_i[0].user_data = WSxM_im_export_pi.name;
00169 
00170         gnome_app_insert_menus (
00171                 GNOME_APP(WSxM_im_export_pi.app->getApp()), 
00172                 path[0], 
00173                 menuinfo_i
00174                 );
00175         
00176 
00177         static GnomeUIInfo menuinfo_e[] = { 
00178                 { GNOME_APP_UI_ITEM, NULL, NULL,
00179                   NULL, NULL,
00180                   NULL, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SAVE,
00181                   0, GDK_CONTROL_MASK, NULL },
00182                 GNOMEUIINFO_END
00183         };
00184         menuinfo_e[0].label  = entry[1];
00185         menuinfo_e[0].hint   = help[1];
00186         menuinfo_e[0].moreinfo  = (gpointer) WSxM_im_export_export_callback; 
00187         menuinfo_e[0].user_data = WSxM_im_export_pi.name;
00188 
00189         gnome_app_insert_menus (
00190                 GNOME_APP(WSxM_im_export_pi.app->getApp()), 
00191                 path[1],
00192                 menuinfo_e
00193                 );
00194 
00195         if(WSxM_im_export_pi.status) g_free(WSxM_im_export_pi.status); 
00196         WSxM_im_export_pi.status = g_strconcat (
00197                 N_("Plugin query has attached "),
00198                 WSxM_im_export_pi.name, 
00199                 N_(": File IO Filters are ready to use."),
00200                 NULL);
00201         
00202         // clean up
00203         g_strfreev (path);
00204         g_strfreev (entry);
00205         g_strfreev (help);
00206 
00207 
00208         if(WSxM_im_export_pi.status) g_free(WSxM_im_export_pi.status); 
00209         WSxM_im_export_pi.status = g_strconcat (
00210                 N_("Plugin query has attached "),
00211                 WSxM_im_export_pi.name, 
00212                 N_(": File IO Filters are ready to use"),
00213                 NULL);
00214         
00215 // register this plugins filecheck functions with Gxsm now!
00216 // This allows Gxsm to check files from DnD, open, 
00217 // and cmdline sources against all known formats automatically - no explicit im/export is necessary.
00218         WSxM_im_export_pi.app->ConnectPluginToLoadFileEvent (WSxM_im_export_filecheck_load_callback);
00219         WSxM_im_export_pi.app->ConnectPluginToSaveFileEvent (WSxM_im_export_filecheck_save_callback);
00220 }
00221 
00222 
00223 // 5.) Start here with the plugins code, vars def., etc.... here.
00224 // ----------------------------------------------------------------------
00225 //
00226 
00227 
00228 // init-Function
00229 static void WSxM_im_export_init(void)
00230 {
00231   PI_DEBUG (DBG_L2, "WSxM Import/Export Plugin Init" );
00232 }
00233 
00234 // about-Function
00235 static void WSxM_im_export_about(void)
00236 {
00237   const gchar *authors[] = { WSxM_im_export_pi.authors, NULL};
00238   gtk_widget_show(gnome_about_new ( WSxM_im_export_pi.name,
00239                                     VERSION,
00240                                     N_("(C) 2001 the Free Software Foundation"),
00241                                     about_text,
00242                                     authors,
00243                                     NULL, NULL, NULL
00244                                     ));
00245 }
00246 
00247 // configure-Function
00248 static void WSxM_im_export_configure(void)
00249 {
00250   if(WSxM_im_export_pi.app)
00251     WSxM_im_export_pi.app->message("WSxM Import/Export Plugin Configuration");
00252 }
00253 
00254 // cleanup-Function, make sure the Menustrings are matching those above!!!
00255 static void WSxM_im_export_cleanup(void)
00256 {
00257         gchar **path  = g_strsplit (WSxM_im_export_pi.menupath, ",", 2);
00258         gchar **entry = g_strsplit (WSxM_im_export_pi.menuentry, ",", 2);
00259 
00260         gchar *tmp = g_strconcat (path[0], entry[0], NULL);
00261         gnome_app_remove_menus (GNOME_APP (WSxM_im_export_pi.app->getApp()), tmp, 1);
00262         g_free (tmp);
00263 
00264         tmp = g_strconcat (path[1], entry[1], NULL);
00265         gnome_app_remove_menus (GNOME_APP (WSxM_im_export_pi.app->getApp()), tmp, 1);
00266         g_free (tmp);
00267 
00268         g_strfreev (path);
00269         g_strfreev (entry);
00270 
00271         PI_DEBUG (DBG_L2, "Plugin Cleanup done.");
00272 }
00273 
00274 
00275         /* --------------------------------------------------------------------------------
00276                         make a new derivate of the base class "Dataio"
00277                         definition of all used function for im- and export
00278         --------------------------------------------------------------------------------*/
00279 
00280 class WSxM_ImExportFile : public Dataio{
00281  public:
00282   WSxM_ImExportFile(Scan *s, const char *n) : Dataio(s,n){ };
00283   virtual FIO_STATUS Read();
00284   virtual FIO_STATUS Write();
00285  private:
00286   FIO_STATUS WSxMRead(const char *fname);
00287   void WriteInLowEndian (const void *buffer, FILE *stream);
00288   void SetUnit(gchar* sValue, gchar* sUnit, double dValae, double dFactor=1.0);
00289   void ReplaceChar(char *string, char oldpiece=',', char newpiece='.');
00290   void SeparateLine(char *sInput, char *sOutput, char cSeparator=10);
00291 };
00292 
00293 // d2d import :=)
00294 FIO_STATUS WSxM_ImExportFile::Read(){
00295         FIO_STATUS ret;
00296         gchar *fname=NULL;
00297 
00298         fname = (gchar*)name;
00299 
00300         // name should have at least 4 chars: ".ext"
00301         if (fname == NULL || strlen(fname) < 4)
00302                 return  FIO_NOT_RESPONSIBLE_FOR_THAT_FILE;
00303  
00304         // check for file exists and is OK !
00305         // else open File Dlg
00306         ifstream f;
00307         f.open(fname, ios::in);
00308         if(!f.good()){
00309                 PI_DEBUG (DBG_L2, "Error: Can't open file!" );
00310                 return status=FIO_OPEN_ERR;
00311         }
00312         f.close();
00313 
00314         // Check all known File Types:
00315         
00316         // WSxM ".top" type?
00317         if ((ret=WSxMRead (fname)) !=  FIO_NOT_RESPONSIBLE_FOR_THAT_FILE)
00318                 return ret;
00319 
00320         return  FIO_NOT_RESPONSIBLE_FOR_THAT_FILE;
00321 }
00322 
00323 
00324   /*----------------------------------------------------------------------
00325        import WSxM file format
00326   ----------------------------------------------------------------------*/
00327 
00328 FIO_STATUS WSxM_ImExportFile::WSxMRead(const char *fname){
00329         // Am I resposible for that file, is it a "top" format ?
00330         if (strncmp(fname+strlen(fname)-4,".top",4))
00331                 return FIO_NOT_RESPONSIBLE_FOR_THAT_FILE;
00332         
00333         // feel free to do a more sophisticated file type check...
00334         PI_DEBUG (DBG_L2, "It's a WSxM File!" );
00335         // initialize variables first
00336         // file name
00337         char *szSourceFileName = (gchar *)fname;
00338         // file pointer
00339         FILE *pSourceFile = NULL;
00340         // header
00341         WSxM_HEADER header;
00342         
00343         // parameter for opening binary data
00344         // set 1 for UNIX and 0 otherwise  
00345         int bUnixEnv = 1;  
00346         // the header is ASCII. So opening the header in text mode
00347         pSourceFile = fopen (szSourceFileName, "rt");
00348         if (pSourceFile==NULL){
00349                 return FIO_OPEN_ERR;
00350                 }
00351         // initializing Header for read
00352         HeaderInit (&header);
00353         HeaderRead (&header,pSourceFile);
00354 
00355         // close file and open it again in binary mode
00356         pSourceFile = fopen (szSourceFileName,"rb");
00357         if (pSourceFile == NULL){
00358                 return FIO_OPEN_ERR;
00359                 }
00360                 
00361         /* Set the position of file pointer after the image header */
00362         fseek (pSourceFile, HeaderGetSize(&header), SEEK_SET);
00363         
00364         int iCol, iRow, iNumCols, iNumRows;
00365         short buffer;
00366         char szComments[100] = "";
00367 
00368         iNumCols = (int) HeaderGetAsNumber (&header, IMAGE_HEADER_GENERAL_INFO, IMAGE_HEADER_GENERAL_INFO_NUM_COLUMNS);
00369         iNumRows = (int) HeaderGetAsNumber (&header, IMAGE_HEADER_GENERAL_INFO, IMAGE_HEADER_GENERAL_INFO_NUM_ROWS);
00370  
00371         // Lets allocate some memory for the scan data.The data of the type short
00372         scan->mem2d->Resize (
00373                 scan->data.s.nx = iNumCols,
00374                 scan->data.s.ny = iNumRows,
00375                 ZD_SHORT
00376                 );
00377   
00378         // this is mandatory.
00379         scan->data.s.ntimes  = 1;
00380         scan->data.s.nvalues = 1;
00381   
00382         /* Reads a point from the source file and writes it to the memory */
00383         for (iCol=0; iCol<iNumCols; iCol++)
00384         {
00385                 for (iRow=0; iRow<iNumRows; iRow++)
00386                 {
00387                         fread (&buffer, sizeof (short), 1, pSourceFile);
00388                         scan->mem2d->PutDataPkt (
00389                                 (double)buffer,
00390                                 iRow, iCol);
00391                                 }
00392         }
00393         printf("Data has been read succesfully!");
00394         // put some usefull values in the ui structure
00395         if(getlogin()){
00396                 scan->data.ui.SetUser (getlogin());
00397         }
00398         else{
00399                 scan->data.ui.SetUser ("unkonwn user");
00400         }
00401         time_t t; // Scan - set timestamp 
00402         time(&t);
00403         gchar *tmp;
00404         tmp = g_strconcat ((ctime(&t)), "(Imported)", NULL);
00405         scan->data.ui.SetDateOfScan (tmp);
00406         g_free (tmp);
00407         scan->data.ui.SetName (fname);
00408         scan->data.ui.SetOriginalName (fname);
00409         scan->data.ui.SetType ("WSxM Type: SHORT ");
00410         tmp = g_strconcat (scan->data.ui.comment,
00411                            "Imported by gxsm WSxM import plugin from:\n",
00412                            fname,
00413                            NULL);
00414         scan->data.ui.SetComment (tmp);
00415         g_free (tmp);
00416 
00417         // initialize scan structure -- this is a minimum example
00418         scan->data.s.dx = 1;
00419         scan->data.s.dy = 1;
00420         scan->data.s.dz = 1;
00421         scan->data.s.rx = scan->data.s.nx;
00422         scan->data.s.ry = scan->data.s.ny;
00423         scan->data.s.x0 = 0;
00424         scan->data.s.y0 = 0;
00425         scan->data.s.alpha = 0;
00426         scan->mem2d->data->MkYLookup(scan->data.s.y0, scan->data.s.y0+scan->data.s.ry);
00427         scan->mem2d->data->MkXLookup(scan->data.s.x0-scan->data.s.rx/2., scan->data.s.x0+scan->data.s.rx/2.);
00428 
00429         // be nice and reset this to some defined state
00430         scan->data.display.cpshigh       = 1e3;
00431         scan->data.display.cpslow        = 1.;
00432         scan->data.display.cnttime       = 1.;
00433 
00434         // set the default view parameters
00435         scan->data.display.bright = 32.;
00436         scan->data.display.contrast = 1.0;
00437         
00438         /* Header destruction */
00439         HeaderDestroy (&header);
00440         /* Close the files */
00441         fclose (pSourceFile);
00442         // WSxM read done.
00443         return FIO_OK; 
00444 }
00445 
00446 
00447   /*----------------------------------------------------------------------
00448        export WSxM file format
00449   ----------------------------------------------------------------------*/
00450 
00451 FIO_STATUS WSxM_ImExportFile::Write(){
00452         const gchar *fname;
00453 
00454         if(strlen(name)>0)
00455                 fname = (const char*)name;
00456         else
00457                 fname = gapp->file_dialog("File Export: WSxM type"," ","*.top","","WSxM write");
00458         if (fname == NULL) return FIO_NO_NAME;
00459 
00460         // check if we like to handle this
00461         if (strncmp(fname+strlen(fname)-4,".top",4))
00462                 return FIO_NOT_RESPONSIBLE_FOR_THAT_FILE;
00463 
00464         // need to write scan size?
00465         // nx = scan->mem2d->GetNx(), ny = scan->mem2d->GetNy()
00466 
00467         // need some data like X scan range?
00468         // scan->data.s.rx, .ry
00469         // scan->data.s.dx, .dy, .dz
00470         // scan->data.s.x0, .y0
00471         // scan->data.s.alpha, ... see Gxsm/src/xsmtypes.h for a complete structure listing!
00472 
00473                 
00474   // File pointer
00475   FILE *pDestinationFile = NULL;
00476   // set destination for write 
00477   gchar *sDestinationFileName = (gchar *)fname;
00478   
00479   // Header 
00480   WSxM_HEADER header;
00481   // parameter for writing binary data
00482   // set 1 for UNIX and 0 otherwise  
00483   int bUnixEnv = 1;  
00484   // the header is ASCII. So opening the header in text mode
00485   pDestinationFile = fopen (sDestinationFileName, "wt");
00486   if (pDestinationFile==NULL){
00487     return FIO_OPEN_ERR;
00488   }
00489 
00490   // header must be initialised
00491   HeaderInit (&header);
00492 
00493 
00494   /*----------------------------------------------------------------------
00495        functions to build up the header
00496   ----------------------------------------------------------------------*/
00497 
00498   // for correct data export we need a reflection at the center
00499   // double val=0.;
00500   double **arrImageData; // bufferarray for image data
00501   arrImageData = (double**) calloc(scan->mem2d->GetNy(), sizeof(double*));
00502         for (int j=0; j < scan->mem2d->GetNy(); ++j){
00503         arrImageData[j]=(double *) calloc (scan->mem2d->GetNx(), sizeof(double));
00504                 for (int i=0; i < scan->mem2d->GetNx(); ++i){
00505                         // like to check the current view mode? 
00506                         // Here is how to do this:
00507                         // val = (double)scan->mem2d->GetDataVMode(i,j);
00508                         // but feel free to just ignore and take the original value:
00509                         // val = scan->mem2d->GetDataPkt(i,j);
00510                         arrImageData[j][i]=scan->mem2d->GetDataPkt(scan->data.s.nx-1-i,scan->data.s.ny-1-j);    
00511                 }
00512         }
00513         
00514   // find max and min of the data
00515   double iMax=arrImageData[0][0], iMin=arrImageData[0][0];
00516   for (int iCol=0; iCol<scan->data.s.ny; iCol++){
00517     for (int iRow=0; iRow<scan->data.s.nx; iRow++){
00518       if (arrImageData[iCol][iRow]>iMax){
00519                 iMax=arrImageData[iCol][iRow];
00520       }
00521       if (arrImageData[iCol][iRow]<iMin){
00522                 iMin=arrImageData[iCol][iRow];
00523       }
00524     }
00525   }
00526 
00527   // buffer variable
00528   char szValue[WSXM_MAXCHARS];          // Needed to handle/convert different values
00529   double buffer_double;
00530   unsigned int buffer_uint;
00531   
00532   /*----------------------------------------------------------------------
00533        Header Sektion: General_Info
00534   ----------------------------------------------------------------------*/
00535   // define number of pixel
00536   sprintf (szValue, "%i", scan->data.s.nx);
00537   HeaderAddValue(&header, IMAGE_HEADER_GENERAL_INFO, IMAGE_HEADER_GENERAL_INFO_NUM_COLUMNS, szValue);
00538   sprintf (szValue, "%i", scan->data.s.ny);
00539   HeaderAddValue(&header, IMAGE_HEADER_GENERAL_INFO, IMAGE_HEADER_GENERAL_INFO_NUM_ROWS, szValue);
00540   HeaderAddValue(&header, IMAGE_HEADER_GENERAL_INFO, IMAGE_HEADER_GENERAL_INFO_ACQ_CHANNEL, "TOPO"); 
00541   HeaderAddValue(&header, IMAGE_HEADER_GENERAL_INFO, IMAGE_HEADER_GENERAL_INFO_HEAD_TYPE, xsmres.InstrumentType);
00542   // Z_Amplitude = ZMax - ZMin
00543   buffer_double=double(iMax-iMin);
00544   SetUnit(&szValue[0], scan->data.Zunit->Alias(), buffer_double*scan->data.s.dz);
00545   ReplaceChar (&szValue[0]);
00546   HeaderAddValue(&header, IMAGE_HEADER_GENERAL_INFO, IMAGE_HEADER_GENERAL_INFO_Z_AMPLITUDE, szValue);
00547   PI_DEBUG (DBG_L2, "WSxM header section General Info written");
00548  
00549   /*----------------------------------------------------------------------
00550        Header Sektion: Control
00551   ----------------------------------------------------------------------*/
00552         // define size (x/y amplitude)of the image  
00553         SetUnit (&szValue[0], scan->data.Xunit->Alias(), double(scan->data.s.rx));
00554         ReplaceChar (&szValue[0]);
00555         HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_X_AMPLITUDE, szValue);
00556         SetUnit (&szValue[0], scan->data.Yunit->Alias(), double(scan->data.s.ry));
00557         ReplaceChar (&szValue[0]);
00558         HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_Y_AMPLITUDE, szValue);
00559         // tunneling parameter
00560         /*----------------------------------------------------------------------
00561           Open actual nc-file again to get additional data
00562           ----------------------------------------------------------------------*/
00563         NcError ncerr(NcError::verbose_nonfatal);
00564         NcFile nc(scan->data.ui.name);
00565         if (! nc.is_valid()){// Data have not been saved as nc-file. Get data from user interface.
00566           std::cout<<"WSxM::Export: Not possible to open parent nc-file."<<std::endl;
00567           if (! strstr(xsmres.HardwareType, "Innovative_DSP:SPM")) {
00568                 PI_DEBUG(DBG_L1, "Exporting from old style DSP Control window.");
00569                 // using old style for pci32
00570                 // Sorry for that, but an IUnit was not implemented yet, so using default unit nA
00571                 SetUnit (&szValue[0], "nA", double(scan->data.s.Current));
00572                 ReplaceChar (&szValue[0]);
00573                 HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_SET_POINT, szValue);
00574                 PI_DEBUG (DBG_L1, "Warning: Set current unit to default (nA).");
00575                 PI_DEBUG (DBG_L1, "Is " << ((double)(scan->data.s.Current)) << " nA correct?");
00576                 SetUnit (&szValue[0], scan->data.Vunit->Alias(), double(scan->data.s.Bias));
00577                 ReplaceChar (&szValue[0]);
00578                 HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_BIAS, szValue);
00579           }
00580           if (! strstr(xsmres.HardwareType, "Sranger")) { 
00581                 // new style hardware interface used by the signal ranger board
00582                 PI_DEBUG(DBG_L1, "Exporting from new HWI window.");
00583                 SetUnit (&szValue[0], "V", double(DSPControlClass->bias));
00584                 ReplaceChar (&szValue[0]);
00585                 HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_BIAS, szValue);
00586                 if (IS_AFM_CTRL) { 
00587                         // AFM uses voltage set point
00588                         SetUnit (&szValue[0], "V", double(DSPControlClass->voltage_set_point));
00589                         ReplaceChar (&szValue[0]);
00590                         HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_SET_POINT, szValue);
00591                 }
00592                 else { 
00593                         // SPM uses current set point
00594                         SetUnit (&szValue[0], "nA", double(DSPControlClass->current_set_point));
00595                         ReplaceChar (&szValue[0]);
00596                         HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_SET_POINT, szValue);
00597                 }
00598           }
00599         }
00600         else {// Data have been saved as nc-file. Look up data in nc-file.
00601           PI_DEBUG (DBG_L1, "Parent nc-file "<<scan->data.ui.name<<" opened");
00602           buffer_double=0;
00603           //Read out old parameter, if new one is available overwrite
00604           //Find correct value for set point
00605           if(nc.get_var("dsp_itunnel")) {
00606             buffer_double = nc.get_var("dsp_itunnel")->values()->as_double(0);
00607             SetUnit (&szValue[0], "nA", double(buffer_double));
00608             PI_DEBUG (DBG_L1, "Use old dsp_itunnel: "<<buffer_double <<"nA");
00609             PI_DEBUG (DBG_L1, "Warning: Set current unit to default (nA). Is " << buffer_double << " nA correct?");
00610           }
00611           if(nc.get_var("sranger_hwi_current_set_point")) {
00612             buffer_double = nc.get_var("sranger_hwi_current_set_point")->values()->as_double(0);
00613             SetUnit (&szValue[0], "nA", double(buffer_double));
00614             PI_DEBUG (DBG_L1, "Overwrite with sranger_hwi_current_set_point: "<<buffer_double<<"nA");
00615           }
00616           if(nc.get_var("sranger_hwi_voltage_set_point")) {
00617             buffer_double = nc.get_var("sranger_hwi_voltage_set_point")->values()->as_double(0);
00618             SetUnit (&szValue[0], "V", double(buffer_double));
00619             PI_DEBUG (DBG_L1, "Overwrite with sranger_hwi_voltage_set_point: "<<buffer_double<<"V");
00620             }
00621           ReplaceChar (&szValue[0]);
00622           HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_SET_POINT, szValue);
00623           
00624           //Find correct value for tunneling bias
00625           if(nc.get_var("dsp_utunnel")) {
00626             buffer_double = nc.get_var("dsp_utunnel")->values()->as_double(0);
00627             SetUnit (&szValue[0], "nA", double(buffer_double));
00628             PI_DEBUG (DBG_L1, "Use old dsp_utunnel: "<<buffer_double<< "V");
00629           }
00630           if(nc.get_var("sranger_hwi_bias")) {
00631             buffer_double = nc.get_var("sranger_hwi_bias")->values()->as_double(0);
00632             SetUnit (&szValue[0], "V", double(buffer_double));
00633             PI_DEBUG (DBG_L1, "Overwrite with sranger_hwi_bias: "<<buffer_double<< "V");
00634           }
00635           ReplaceChar (&szValue[0]);
00636           HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_BIAS, szValue);
00637 
00638           //Write scan direction
00639           if(nc.get_var("spm_scancontrol")) {
00640             strncpy(&szValue[0], nc.get_var("spm_scancontrol")->values()->as_string(0),8);
00641             PI_DEBUG (DBG_L1, "Found attribute scan direction: "<< szValue);
00642             ReplaceChar (&szValue[0]);
00643             HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_SCAN_DIRECTION, szValue);
00644           }
00645 
00646         }
00647         
00648         // X,Y Offset
00649         SetUnit (&szValue[0], scan->data.Xunit->Alias(), double(scan->data.s.x0));
00650         ReplaceChar (&szValue[0]);
00651         HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_X_OFFSET, szValue);
00652         SetUnit (&szValue[0], scan->data.Yunit->Alias(), double(scan->data.s.y0));
00653         ReplaceChar (&szValue[0]);
00654         HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_Y_OFFSET, szValue);
00655         // Z Gain
00656         sprintf (szValue, "1.0");
00657         HeaderAddValue(&header, IMAGE_HEADER_CONTROL, IMAGE_HEADER_CONTROL_Z_GAIN,szValue);
00658         //Rotation
00659         SetUnit (szValue,"Deg",double(scan->data.s.alpha));
00660         ReplaceChar(szValue); 
00661         HeaderAddValue(&header,IMAGE_HEADER_CONTROL,IMAGE_HEADER_CONTROL_ROTATION,szValue);
00662         PI_DEBUG (DBG_L2, "WSxM header section Control written"); 
00663   
00664   /*----------------------------------------------------------------------
00665        Header Sektion: Misc_Info
00666   ----------------------------------------------------------------------*/
00667   // set file format version
00668   HeaderAddValue(&header, IMAGE_HEADER_MISC_INFO, IMAGE_HEADER_MISC_INFO_VERSION, IMAGE_HEADER_VERSION);
00669   // write comments to header
00670   buffer_uint=0;
00671   strcpy(szValue,"");                          // clear variables
00672   unsigned int max_uint=WSXM_MAXCHARS;         // buffer variable to take trace of the max number chars in string
00673   char buffer_string[WSXM_MAXCHARS];           // buffer for string operation
00674   while (buffer_uint+1<strlen(scan->data.ui.comment)&&buffer_uint+1<max_uint)
00675   {
00676         strcpy(buffer_string,"");
00677         if (scan->data.ui.comment[buffer_uint]==10)              // check if there is an empty line
00678           {// empty line
00679             buffer_uint++;
00680             PI_DEBUG(DBG_L2,"WSXM::write(): Blank line in comment detected and deleted!");
00681           }
00682         else
00683           {// no empty line
00684             SeparateLine(&scan->data.ui.comment[buffer_uint],&buffer_string[0],10);
00685             max_uint-=2;
00686             if (strlen(szValue)+strlen(buffer_string)+2>max_uint)                  // make sure that there is segmentation fault
00687               {// comment is longer than WSXM_MAXCHARS
00688                 PI_DEBUG (DBG_L2, "WSXM::write(): Warnig: Comments are too long! They will be cut.");
00689                 if (((signed int)(max_uint-strlen(szValue)-2))>0)
00690                   {
00691                     strncat(&szValue[0], &buffer_string[0], max_uint-strlen(szValue)-2);
00692                     strcat(&szValue[0],"\r\n");
00693                   }
00694                 ++buffer_uint+=strlen(&buffer_string[0]);               // add one because of the '\n'
00695                 PI_DEBUG (DBG_L2, buffer_string);
00696               }
00697             else 
00698               {// length of comment is okey
00699                 strcat(&szValue[0],&buffer_string[0]);
00700                 strcat(&szValue[0],"\r\n");
00701                 ++buffer_uint+=strlen(&buffer_string[0]);               // add one because of the '\n'
00702               }
00703           }
00704   }
00705   ReplaceChar (szValue,':',' ');
00706   HeaderAddValue(&header, IMAGE_HEADER_MISC_INFO, IMAGE_HEADER_MISC_INFO_COMMENTS, szValue);
00707   // set ZMin, ZMax
00708   SetUnit(&szValue[0], scan->data.Zunit->Alias(), double(iMax)*scan->data.s.dz);
00709   ReplaceChar (&szValue[0]);
00710   HeaderAddValue(&header, IMAGE_HEADER_MISC_INFO, IMAGE_HEADER_MISC_INFO_MAXIMUM, szValue);
00711   SetUnit(&szValue[0], scan->data.Zunit->Alias(), double(iMin)*scan->data.s.dz);
00712   ReplaceChar (&szValue[0]);
00713   HeaderAddValue(&header, IMAGE_HEADER_MISC_INFO, IMAGE_HEADER_MISC_INFO_MINIMUM, szValue);
00714   PI_DEBUG (DBG_L2, "WSxM header section Misc Info written");
00715 
00716   /*----------------------------------------------------------------------
00717        Header Sektion: Heads
00718   ----------------------------------------------------------------------*/
00719   // informationen for callibration
00720   sprintf(szValue,"%g %c/V",xsmres.XPiezoAV,197);
00721   ReplaceChar (&szValue[0]);
00722   HeaderAddValue(&header, IMAGE_HEADER_HEADS, IMAGE_HEADER_HEADS_X_CALIBRATION, szValue);
00723   sprintf(szValue,"%g %c/V",xsmres.YPiezoAV,197);
00724   ReplaceChar (&szValue[0]);
00725   HeaderAddValue(&header, IMAGE_HEADER_HEADS, IMAGE_HEADER_HEADS_Y_CALIBRATION, szValue);
00726   sprintf(szValue,"%g %c/V",xsmres.ZPiezoAV,197); 
00727   ReplaceChar (&szValue[0]);
00728   HeaderAddValue(&header, IMAGE_HEADER_HEADS, IMAGE_HEADER_HEADS_Z_CALIBRATION, szValue); 
00729   PI_DEBUG (DBG_L2, "WSxM header section Heads written");
00730   
00731   /*----------------------------------------------------------------------
00732        save file to disk
00733   ----------------------------------------------------------------------*/
00734   // writing the header in ASCII mode
00735   HeaderWrite(&header, pDestinationFile);
00736   HeaderDestroy (&header);
00737   PI_DEBUG (DBG_L2, "WSxM header written succesfully");
00738   // close file and open it again in binary mode
00739   fclose(pDestinationFile);
00740   pDestinationFile=fopen(sDestinationFileName, "ab");
00741   if (pDestinationFile==NULL){
00742     return FIO_OPEN_ERR;
00743   }
00744   short buffer;
00745   for (int j=0; j < scan->mem2d->GetNy(); ++j){
00746         for (int i=0; i < scan->mem2d->GetNx(); ++i){
00747                 buffer = (short) arrImageData[j][i]; 
00748                 if (bUnixEnv){
00749                 // Write in low endian
00750                 // Convert data in low endian format. Plugin should run on unix systems.
00751                 WriteInLowEndian (&buffer,pDestinationFile);
00752         }
00753                 else {
00754                         // No data conversion. Plugin should run on a PC.
00755                                 fwrite(&buffer,sizeof(short),1,pDestinationFile);       
00756                 }
00757     }
00758   }
00759   PI_DEBUG (DBG_L2, "WSxM body written succesful");
00760   // closing file finaly
00761   fclose(pDestinationFile);
00762   return FIO_OK; 
00763 }
00764 
00765 
00766   /*----------------------------------------------------------------------
00767        WriteInLowEndian: Write binary data in PC style (Windows compatible)
00768   ----------------------------------------------------------------------*/
00769 
00770 void WSxM_ImExportFile::WriteInLowEndian(const void *buffer, FILE *stream)
00771 {
00772   fwrite (&((char*)buffer)[0],sizeof (char),1,stream);
00773   fwrite (&((char*)buffer)[1],sizeof (char),1,stream);
00774   // PI_DEBUG (DBG_L2, "Write in low endian style");
00775         
00776 }
00777 
00778   /*----------------------------------------------------------------------
00779        SetUnit: Adds Unit to String
00780   ----------------------------------------------------------------------*/
00781 void WSxM_ImExportFile::SetUnit(gchar* sValue, gchar* sUnit, double dValue, double dFactor)
00782 {// Global unit table declared in xsm.C
00783   UnitsTable *UnitPtr = XsmUnitsTable;                                               
00784   gchar prec_str[WSXM_MAXCHARS];
00785   gchar *finalUnit;
00786   dValue=dValue*dFactor; // Use dFactor for scalling
00787   // Checking for the correct unit of the tunneling current, because WSxM only acceptes 2 decimals
00788   if(!strcmp(sUnit,"nA"))
00789     {
00790       if(((int)(dValue * IS_PICO_AMP)) == 0)
00791         {// better use pA
00792           finalUnit = g_strdup("pA");
00793         }
00794       else
00795         {// use standard unit
00796           finalUnit = g_strdup(sUnit);
00797         }       
00798     }
00799   else
00800          finalUnit = g_strdup(sUnit);           
00801    
00802         
00803   // handling the Arc Unit
00804   if(!strcmp(finalUnit,"Deg"))
00805     {
00806         snprintf(sValue,WSXM_MAXCHARS,"%g %s",dValue / UnitPtr->fac,"°");   
00807         g_free(finalUnit);
00808         return;
00809     }
00810   
00811   //check if a global unit alias exists
00812   for(;UnitPtr->alias;UnitPtr++)                                                                                
00813         if(!strcmp(finalUnit,UnitPtr->alias))
00814           break;
00815  
00816   g_free(finalUnit);
00817   if(!UnitPtr->alias)
00818     {// Default: digital units
00819       snprintf(sValue,WSXM_MAXCHARS,"%g", dValue);
00820       PI_DEBUG(DBG_L2,"Data will be saved in digital units");
00821     }
00822   else
00823     {// substituting A with 197
00824       if(!strcmp(UnitPtr->alias,"AA"))
00825         {// angstrom need an extra handling
00826           snprintf(prec_str,WSXM_MAXCHARS,"%%%s %%c",UnitPtr->prec2);
00827           snprintf(sValue,WSXM_MAXCHARS,prec_str,dValue / UnitPtr->fac,197);  
00828           return;
00829         }
00830       else {
00831         snprintf(prec_str,WSXM_MAXCHARS,"%%%s %%s",UnitPtr->prec2);
00832         snprintf(sValue,WSXM_MAXCHARS,prec_str,dValue / UnitPtr->fac, UnitPtr->s);      
00833       }
00834     }
00835 }
00836 
00837   /*----------------------------------------------------------------------
00838        ReplaceChar: Replaces A Char Within A String
00839        Default: Replacing ',' by '.'
00840   ----------------------------------------------------------------------*/
00841 void WSxM_ImExportFile::ReplaceChar(char *string, char oldpiece, char newpiece)
00842 {
00843    for (;*string;string++)
00844     {
00845       if (*string==oldpiece) *string=newpiece;
00846     }
00847 }
00848 
00849  /*----------------------------------------------------------------------
00850        SeparateLine: Separates Lines vom sInput to sOutput
00851        Default Separator is '\n'
00852   ----------------------------------------------------------------------*/
00853 
00854 void WSxM_ImExportFile::SeparateLine(char *sInput, char *sOutput, char cSeparator)
00855 {
00856         for (;*sInput;sInput++)
00857     {
00858       if (*sInput==cSeparator) {
00859         break;
00860         }
00861       else {
00862         strncat(sOutput,sInput,1);
00863         }
00864     }
00865 }
00866 
00867 // Plugin's Notify Cb's, registered to be called on file load/save to check file
00868 // return via filepointer, it is set to Zero or passed as Zero if file has been processed!
00869 // That's all fine, you should just change the Text Stings below...
00870 
00871 
00872 static void WSxM_im_export_filecheck_load_callback (gpointer data ){
00873         gchar **fn = (gchar**)data;
00874         if (*fn){
00875                 PI_DEBUG (DBG_L2, "Check File: WSxM_im_export_filecheck_load_callback called with >"
00876                      << *fn << "<" );
00877 
00878                 Scan *dst = gapp->xsm->GetActiveScan();
00879                 if(!dst){ 
00880                         gapp->xsm->ActivateFreeChannel();
00881                         dst = gapp->xsm->GetActiveScan();
00882                 }
00883                 WSxM_ImExportFile fileobj (dst, *fn);
00884 
00885                 FIO_STATUS ret = fileobj.Read(); 
00886                 if (ret != FIO_OK){ 
00887                         // I'am responsible! (But failed)
00888                         if (ret != FIO_NOT_RESPONSIBLE_FOR_THAT_FILE)
00889                                 *fn=NULL;
00890                         // no more data: remove allocated and unused scan now, force!
00891                         gapp->xsm->SetMode(-1, ID_CH_M_OFF, TRUE); 
00892                         PI_DEBUG (DBG_L2, "Read Error " << ((int)ret) << "!!!!!!!!" );
00893                 }else{
00894                         // got it!
00895                         *fn=NULL;
00896 
00897                         // Now update gxsm main window data fields
00898                         gapp->xsm->ActiveScan->GetDataSet(gapp->xsm->data);
00899                         gapp->spm_update_all();
00900                         dst->draw();
00901                 }
00902         }else{
00903                 PI_DEBUG (DBG_L2, "WSxM_im_export_filecheck_load: Skipping" );
00904         }
00905 }
00906 
00907 static void WSxM_im_export_filecheck_save_callback (gpointer data ){
00908         gchar **fn = (gchar**)data;
00909         if (*fn){
00910                 Scan *src;
00911                 PI_DEBUG (DBG_L2, "Check File: WSxM_im_export_filecheck_save_callback called with >"
00912                      << *fn << "<" );
00913 
00914                 WSxM_ImExportFile fileobj (src = gapp->xsm->GetActiveScan(), *fn);
00915 
00916                 FIO_STATUS ret;
00917                 ret = fileobj.Write(); 
00918 
00919                 if(ret != FIO_OK){
00920                         // I'am responsible! (But failed)
00921                         if (ret != FIO_NOT_RESPONSIBLE_FOR_THAT_FILE)
00922                                 *fn=NULL;
00923                         PI_DEBUG (DBG_L2, "Write Error " << ((int)ret) << "!!!!!!!!" );
00924                 }else{
00925                         // write done!
00926                         *fn=NULL;
00927                 }
00928         }else{
00929                 PI_DEBUG (DBG_L2, "WSxM_im_export_filecheck_save: Skipping >" << *fn << "<" );
00930         }
00931 }
00932 
00933 // Menu Call Back Function
00934 
00935 static void WSxM_im_export_import_callback(GtkWidget *w, void *data){
00936         gchar **help = g_strsplit (WSxM_im_export_pi.help, ",", 2);
00937         gchar *dlgid = g_strconcat (WSxM_im_export_pi.name, "-import", NULL);
00938         gchar *fn = gapp->file_dialog (help[0], NULL, file_mask, NULL, dlgid);
00939         g_strfreev (help); 
00940         g_free (dlgid);
00941         WSxM_im_export_filecheck_load_callback (&fn );
00942 }
00943 
00944 static void WSxM_im_export_export_callback(GtkWidget *w, void *data){
00945         gchar **help = g_strsplit (WSxM_im_export_pi.help, ",", 2);
00946         gchar *dlgid = g_strconcat (WSxM_im_export_pi.name, "-export", NULL);
00947         gchar *fn = gapp->file_dialog(help[1], NULL, file_mask, NULL, dlgid);
00948         g_strfreev (help); 
00949         g_free (dlgid);
00950         WSxM_im_export_filecheck_save_callback (&fn );
00951 }

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