marxf.cpp

Go to the documentation of this file.
00001 /***********************************************************************
00002  *
00003  * scan345: marxf.c
00004  *
00005  * Copyright by:        Dr. Claudio Klein
00006  *                      X-ray Research GmbH, Hamburg
00007  *
00008  * Version:     3.0
00009  * Date:        31/10/2000
00010  *
00011  * History:
00012  *
00013  * Date         Version         Description
00014  * ---------------------------------------------------------------------
00015  * 31/10/00     3.0             CBF/imgCIF format implemented
00016  * 15/06/00     2.2             Added feature COMMAND SCAN ADD x ERASE y
00017  *
00018  *
00019  ***********************************************************************/
00020 
00021 #include        <stdio.h>
00022 #include        <ctype.h>
00023 #include        <string.h>
00024 #include        <stdlib.h>
00025 #include        <time.h>
00026 #include        <math.h>
00027 #include        <unistd.h>
00028 #include        <fcntl.h>
00029 #include        <sys/types.h>
00030 #include        <sys/stat.h>
00031 
00032 #include        "marcmd.h"
00033 #include        "esd.h"
00034 #include        "marglobals.h"
00035 #include        "mararrays.h"
00036 #include        "config.h"
00037 #include        "version.h"
00038 #include        <mar345_header.h>
00039 #include        <mar300_header.h>
00040 #include        <nb_header.h>
00041 #include "marxf.h"
00042 
00043 #define                 NB_SIZE         1024
00044 #define                 BOXSIZE         100
00045 #define                 BOX_OFF         100
00046 
00047 #define ltell(a)        lseek( a, 0, SEEK_CUR )
00048 #define min0(a,b)       if ( b < a ) a = b
00049 #define max0(a,b)       if ( b > a ) a = b
00050 
00051 /*
00052  * Global variables
00053  */
00054 MAR345_HEADER           h345;
00055 char                    large_mem               = 1;
00056 char                    scan_in_progress        = 0;
00057 char                    xf_in_progress          = 0;
00058 char                    op_in_progress          = 0;
00059 char                    last_image[128]         = { ""} ;
00060 char                    is_data                 = 0;
00061 
00062 int                     last_total              = 0;
00063 int                     bytes2xfer;
00064 
00065 static int              n1=0,n2=0,adcavg1,adcavg2,adcavg11,adcavg21;
00066 static int              xf_histo[65600];
00067 static int              hist_begin, hist_end, hist_max;
00068 static int              add_A, add_B;
00069 int                     valmax, valmin;
00070 int                     sp_pixels, xf_pixels;
00071 int                     maximum_pixels;
00072 int                     maximum_block;
00073 int                     maximum_bytes;
00074 int                     data_offset;
00075 int                     current_pixel;
00076 int                     xform_status;
00077 
00078 int                     Imax;
00079 float                   AvgI,SigI; 
00080 /*
00081  * Local variables
00082  */
00083 
00084 static char             adc_channel = 0;
00085 static unsigned short   i2_record[MAX_SIZE];
00086 static STRONG           strong_rec[MAX_SIZE/2];
00087 static FILE             *fpnb             = NULL;
00088 
00089 static int              fdspiral          = -1;
00090 static int              iindex            = 0;
00091 static int              i_x0              = 0;
00092 static int              j_y0              = 0;
00093 static int              max_spiral_int    = 0;
00094 static int              spiral_offset     = 0;
00095 static int              ac_size           = 0;
00096 static int              i_rec             = 1;
00097 static int              xf_rec            = 0;
00098 static int              ns_rec            = 0;
00099 static int              fdxf              = 0;
00100 static int              swap_nb           = 0;
00101 static char             start_with_A      = 1;
00102 static int              spiral_size;
00103 static int              total_pixels;
00104 static int              last_block;
00105 static int              last_pixel;
00106 static int              istrong;
00107 static int              nskip;
00108 static int              poff;
00109 static int              nb_index;
00110 static int              lin_dxy[8];
00111 static int              saturation;
00112 static char             spiral_only;
00113 static float            fract_intens;
00114 
00115 static MAR300_HEADER    h300;
00116 static MARNB_HEADER     nb;
00117 
00118 static signed char      x_rec   [NB_SIZE];
00119 static signed char      y_rec   [NB_SIZE];
00120 static unsigned char    nb_rec  [NB_SIZE];
00121 static unsigned short   px_rec  [9*NB_SIZE];
00122 static unsigned char    bit[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
00123 
00124 /*
00125  * External variables
00126  */
00127 extern int              adc1,adc2;
00128 extern int              stat_blocks_sent;
00129 extern int              com_scanmode;
00130 extern char             input_skip_op;
00131 extern char             skip_op;
00132 extern char             keep_image;
00133 extern char             do_xform;
00134 extern int              fdnb;
00135 extern int              stat_scan_add;
00136 
00137 extern int              edit_output;
00138 extern int              nstrong;
00139 extern int              nsat;
00140 extern CONFIG           cfg;
00141 
00142 extern "C" {
00143   extern int            put_pck(unsigned short int*, int, int, int);
00144   extern void           swaplong(char*, int);
00145   extern void           swapshort(char*, int);
00146 
00147 
00148   extern int              Putmar345Header       (int, MAR345_HEADER);
00149   extern int              Putmar300Header       (int, int, MAR300_HEADER);
00150   extern MAR345_HEADER    Getmar345Header       (FILE *);
00151   extern MARNB_HEADER     GetmarNBHeader        (FILE *);
00152   extern int              PutCIFHeader    (char *, char *);
00153   extern int              PutCIFData      (char *, char *, char, unsigned int *);
00154   extern int              GetCIFData      (char *, char *, FILE *, unsigned int *);
00155   extern void             mar3452CIFHeader(char *, char *, MAR345_HEADER );
00156   extern float    GetResol(float, float, float);
00157   extern void           rotate_i4       (unsigned int *, int);
00158   extern void           rotate_i4_anti  (unsigned int *, int);
00159 }
00160 
00161 MarXF::MarXF(QObject *parent)
00162   : inherited(parent)
00163 {
00164 }
00165 
00166 /******************************************************************
00167  * Function: mar_start_scan_readout = starts data readout
00168                                       Open files and read 1. nb_code record
00169 ******************************************************************/
00170 int
00171 MarXF::mar_start_scan_readout(int next_scan) 
00172 {
00173   int           i, i_pix;
00174   int             swap[2];
00175   int             j_dj[8] = { -1, 0, 1,-1, 1,-1, 0, 1};
00176   int             i_di[8] = { -1,-1,-1, 0, 0, 1, 1, 1};
00177   extern char     martable_dir[128];
00178   extern char     nbcode_file[128];
00179 
00180   /* 
00181    * Initialize readout variables 
00182    */
00183   n1 = n2 = adcavg1 = adcavg2 = adcavg11= adcavg21= 0;
00184   adc_channel           = 0;
00185   start_with_A          = 1;
00186   bytes2xfer            = 0;
00187   xform_status          = 0;
00188   scan_in_progress      = 1;
00189   xf_in_progress                = 1;
00190   do_xform              = 1;
00191   stat_xform_msg                = 0;
00192   stat_blocks_sent      = 0;
00193   current_pixel                 = 0;
00194   sp_pixels               = 0;
00195   xf_pixels               = 0;
00196   valmin                  = 999999;
00197   last_pixel              = -1;
00198   last_block                    = -1;
00199   poff                  = 0;
00200   data_offset           = 0;
00201   add_A                 = cfg.adcadd_A[ (int)stat_scanmode ];
00202   add_B                 = cfg.adcadd_B[ (int)stat_scanmode ];
00203   saturation            = 1000000;
00204   stat_pixelsize                = cfg.pixelsize[ (int)stat_scanmode ];
00205 
00206   if ( strncmp( image_file, spiral_file, strlen(spiral_file) )== 0 ) 
00207     spiral_only = 1;
00208   else
00209     spiral_only = 0;
00210 
00211   fdxf                          = 0;
00212 
00213   if ( fdspiral >= 0 ) {
00214     close( fdspiral );
00215     fdspiral = -1;
00216   }
00217                 
00218   /* 
00219    * Initialize xform variables 
00220    */
00221   spiral_offset = 0;
00222 
00223   /* Use the ADC values from controller */
00224   if ( cfg.use_adc == 1 ) {
00225     spiral_offset = cfg.adcoff[(int)stat_scanmode];
00226   }
00227 
00228   max_spiral_int        = 0;
00229   istrong               = 0;
00230   xf_rec                = 0;
00231   iindex                = 1024;
00232   nb_index              = 0;
00233 
00234 
00235   ac_size        = cfg.size[ (int)stat_scanmode ];
00236   total_pixels   = ac_size * ac_size;
00237 
00238   /*
00239    * Open neighbour code file
00240    */
00241   if ( fpnb != NULL ) {
00242     fclose( fpnb );
00243     fpnb = NULL;
00244   }
00245 
00246   if ( stat_scanmode > 3 ) { 
00247     sprintf( nbcode_file,"%s/mar3450.%s", martable_dir, scanner_no);
00248   }
00249   else {
00250     sprintf( nbcode_file,"%s/mar2300.%s", martable_dir, scanner_no);
00251   }
00252 
00253   if ( NULL == (fpnb  = fopen( nbcode_file, "r" ))) {
00254     marError( 1100, 0 );
00255     do_xform        = 0;
00256     keep_image      = 0;
00257   }
00258 
00259   /*
00260    * Read nb header.
00261    */
00262 
00263   nb = GetmarNBHeader( fpnb );
00264 
00265   /*
00266    * Neighbour code header okay ?
00267    */
00268 
00269   if ( nb.mode < 1 ) {
00270     marError( 1101, 0 );
00271     do_xform        = 0;
00272     keep_image      = 0;
00273   }
00274 
00275   /*
00276    * Is byte swapping required ?
00277    */
00278 
00279   if ( nb.byteorder != 1234 ) {
00280     swap_nb = nb.byteorder;
00281     swap[0] = swap_nb;
00282     swaplong( (char*) swap, 4 );
00283     swap_nb = swap[0];
00284     nb.byteorder = 1234;
00285     if ( swap_nb != 1234 ) {
00286       marError( 1102, 0 );
00287       do_xform        = 0;
00288       keep_image      = 0;
00289     }
00290     swap_nb = 1;
00291   }
00292 
00293   /*
00294    * Is the serial no. of nbcode identical to the one
00295    * defined by $MAR_SCANNER_NO ?
00296    */
00297 
00298   if ( atoi( scanner_no ) != nb.scanner ) {
00299     marError( 1103, 0 );
00300   }
00301 
00302   /*
00303    * Is there the desired scanning mode ?
00304    */
00305   i_rec = -1;
00306   for ( i=0; i<=4; i++ ) {
00307     /* Size is identical, use this mode ... */
00308     if ( nb.size[i] == ac_size ) {
00309       i_rec = nb.fpos[i];
00310       i_x0  = nb.x[i];
00311       j_y0  = nb.y[i];
00312       i_pix = nb.pixels[i];
00313       poff  = nb.skip[i] + (int)cfg.toff[(int)stat_scanmode];
00314       nskip = poff-1;
00315       maximum_pixels = nb.pixels[i] + nb.skip[i];
00316       maximum_block  = (int)(maximum_pixels/8192. + 0.999);
00317       maximum_bytes  = maximum_block * 16386;
00318                 
00319       /* When dealing with odd no. of pixels in preturn
00320        * the ADC offset for channels A and B must be
00321        * exchanged
00322        */
00323       if ( nb.skip[i] % 2 != 0 ) {
00324         adc_channel     = 1;
00325         start_with_A    = 0;
00326       }
00327       break;
00328     }
00329   }
00330 
00331   /* 
00332    * When applying offset, take only a fraction when using multiple
00333    * sampling 
00334    */
00335 
00336   if ( i_rec < 0 ) {
00337     marError( 1105, 0 );
00338     do_xform        = 0;
00339     keep_image      = 0;
00340     i_rec           = 0;
00341   }
00342 
00343   /* 
00344    * Create transformed image file 
00345    */
00346   if ( keep_image && !spiral_only ) {
00347 
00348     sprintf( buf, "%s.tmp", image_file );
00349     if ( com_format == OUT_CIF || com_format == OUT_CBF ) {
00350       fdxf = 0;
00351     }
00352     else {
00353       fdxf = creat(     buf,   0666  );
00354 
00355       if ( fdxf == -1 ) {
00356         marError( 1110, 0 );
00357         do_xform = 0;
00358         fdxf     = 0; 
00359       }
00360       /* Close file after creation */
00361       else {
00362         close( fdxf );
00363         fdxf    = 0;
00364       }
00365 
00366       /*
00367        * Open created image file
00368        */
00369       fdxf = open( buf, O_RDWR );    /* Mode = O_RDWR (=2) */
00370       if(  fdxf == -1 ) {
00371         marError( 1111, 0 );
00372         do_xform = 0;
00373         fdxf     = 0; 
00374       }
00375     }
00376   }
00377   else {
00378     if ( !spiral_only )
00379       do_xform    = 0;
00380     keep_spiral = 1;
00381   }
00382 
00383   /* If we write only spirals, free memory and skip next lines */
00384   if ( keep_image == 0 ) {
00385     goto NEXT_1;
00386   }
00387 
00388   for(i = 0; i < 8; i++)
00389     lin_dxy[i] = j_dj[i] * ac_size + i_di[i];
00390 
00391   /* 
00392    * Initialize memory for image arrays... 
00393    */
00394   if ( stat_scan_add == 0 ) {
00395     memset( (char *)u.i4_img, 0, sizeof(int)*total_pixels);
00396   }
00397   memset( (char *)xf_histo, 0, sizeof(int)*65600 );
00398 
00399   for ( i=0; i<MAX_SIZE; i++ ) {
00400     i2_record[i] = 0;
00401   }
00402 
00403   for ( i=0; i<MAX_SIZE/2; i++ ) {
00404     strong_rec[i].val = 0;
00405     strong_rec[i].add = 0;
00406   }
00407 
00408   /* 
00409    * Go to starting position (i_rec) in neighbor code
00410    */
00411  NEXT_1:
00412   if ( do_xform )
00413     fseek( fpnb, i_rec, SEEK_SET);
00414 
00415   if ( debug & 0x40 ) {
00416     fprintf(stdout,"\nscan345:  transformation parameters:\n");
00417     fprintf(stdout,"\tCurrent scan mode:       %d\n",stat_scanmode);
00418     fprintf(stdout,"\tStarting x:              %d\n",i_x0);
00419     fprintf(stdout,"\tStarting y:              %d\n",j_y0);
00420     fprintf(stdout,"\tSpiral offset:           %d\n",poff);
00421     fprintf(stdout,"\tFirst rec at:            %d\n",i_rec);
00422     fprintf(stdout,"\tNo. of pix/rec:          %d\n",ac_size);
00423     fprintf(stdout,"\tTotal no. of pixels:     %d\n",maximum_pixels);
00424     fprintf(stdout,"\tTotal no. of blocks:     %d\n",maximum_block);
00425   }
00426 #ifdef DEBUG
00427 #endif
00428 
00429   /* 
00430    * We cannot write transformed image, so we try to write
00431    * spiral images...
00432    */
00433 
00434   if ( do_xform == 0 && keep_image == 1 ) {
00435     fprintf(stdout, "scan345: Image cannot be transformed!\n");
00436     fprintf(stdout, "scan345: Trying to write spiral files...!\n");
00437     keep_spiral = 1;
00438   }
00439 
00440   /* 
00441    * Write image header first time
00442    */
00443   if ( do_xform == 1 && fdxf > 0 ) {
00444     if ( output_header( (int)1 ) != 1 ) {
00445       do_xform    = 0;
00446       i           = close( fdxf );
00447       keep_spiral = 1;
00448       fdxf        = 0;
00449     }
00450   }
00451 
00452   /* 
00453    * In keep spiral mode, write spiral header to output
00454    */
00455 
00456   if ( output_header( 0 ) != 1 ) {
00457 
00458     /* 
00459      * Spiral file could not be opened, so we have to abort
00460      * data collection
00461      */
00462 
00463     if ( fdxf ) {
00464       i = close( fdxf );
00465       fdxf = 0;
00466     }
00467 
00468     i = close(fdspiral);
00469     fdspiral = -1;
00470     return( 0 );
00471   }
00472 
00473   /*    
00474    */
00475 
00476   spiral_size   = 4096 + maximum_block*16384;
00477 
00478   return( 1 );
00479 
00480 }
00481 
00482 /******************************************************************
00483  * Function: Transform = transforms spiral data
00484  ******************************************************************/
00485 void MarXF::Transform( int i_sp, int block_no, unsigned short *spiral )
00486 {
00487   register unsigned int adc,adcadd;
00488   register int            sp_index, lin_pointer, nb_pointer;    
00489   register int            pixel_intensity;                      
00490   register int            i;                                    
00491 
00492   static   unsigned short *s_p;                   
00493   static   unsigned char  *n_p, nb_byte;                        
00494   static   unsigned short *v_p;                                 
00495   static   signed   char        dx, dy, *x_p, *y_p;
00496 
00497   int                   sp_offset;
00498   static int            n_nb;
00499   double                        dtmp;
00500 
00501   /*
00502    * Used parameters and their values:
00503    * --------------------------------- 
00504    * stat_blocks_sent   = block counter read by this program 
00505    * current_pixel   = pixel counter read by this program 
00506    */
00507 
00508   if ( scan_in_progress == 0 || op_in_progress == 1 ) return;
00509 
00510   /* 
00511    * Block of data has been read successfully... 
00512    */
00513 
00514   /* Pixel offset in some modes 5, 6, 7 ... */
00515   if ( poff > 0 ) {
00516     sp_offset = poff;
00517     if ( i_sp < poff ) {
00518       poff -= i_sp;
00519       current_pixel += i_sp;
00520       goto OUTPUT;
00521     }
00522     i_sp -= poff;
00523     poff  = 0;
00524     current_pixel = nskip;
00525   }
00526   else
00527     sp_offset = 0;
00528 
00529   last_block     = stat_blocks_sent;
00530   last_pixel     = current_pixel;
00531 
00532   /*
00533    * Use new ADC values for this scan. Use first data block
00534    */
00535   if ( block_no <= 1 ) {
00536     adc1 = esd_stb.adc1;
00537     adc2 = esd_stb.adc2;
00538   }
00539 
00540   /*                                                    
00541    * Swap bytes                                         
00542    */                                                   
00543                                                               
00544 #if ( __sgi111 || HPUX111 )                              
00545   swapshort( spiral+sp_offset, i_sp*sizeof(short) );              
00546 #endif
00547                                                               
00548   /* Write data block into spiral file... */
00549   if (keep_spiral) {
00550     i =  write(fdspiral, spiral+sp_offset, i_sp*sizeof(short) );
00551 
00552     if ( i == -1 ) {
00553       /* Error writing spiral record... */
00554       emit print_message(tr("scan345: Error writing spiral block %1\n").arg(stat_blocks_sent));
00555 
00556       if ( do_xform == 0 ) {
00557         close( fdspiral );
00558         fdspiral = -1;
00559         xform_status = -1;
00560         return;
00561       }
00562     }
00563     if ( !keep_image )
00564       current_pixel += i_sp;
00565   } 
00566 
00567   /* Ignore first 2 pixels (set to value of third) */
00568   if ( sp_pixels == 0 ) {
00569     for ( i=0; i<2; i++ ) { 
00570       spiral[i+sp_offset] = spiral[2+sp_offset];
00571     }
00572   }
00573         
00574 
00575   /*
00576    * Monitor progress of transformation
00577    */
00578 #ifdef __osf__
00579   dtmp = block_no/(double)maximum_block;
00580   stat_xform_msg = (int)( 100*dtmp);
00581 #else
00582   stat_xform_msg = (int)( 100*(block_no/(float)maximum_block));
00583   stat_xform_msg = (int)( 100*(current_pixel/(float)maximum_pixels));
00584 #endif
00585 
00586   /******************************************************
00587    ******************************************************
00588    **                                                **
00589    ** Transform pixels for the current spiral_buffer   **
00590    **                                                **
00591    ******************************************************
00592    ******************************************************/
00593 
00594   /* Reset xform_status to 1 */
00595   xform_status   = 1;
00596 
00597   /* If we don't want to write transformed image, skip while loop... */
00598   if ( do_xform == 0 ) {
00599     xform_status = 2;
00600     if ( last_pixel >= maximum_pixels ) {
00601       xform_status = 3;
00602     }
00603   }
00604 
00605   if ( xform_status != 1 || sp_pixels >= maximum_pixels ) goto OUTPUT;
00606                                                               
00607   /* Set pointer to first element in spiral array  and reset counter */
00608   s_p = spiral + sp_offset;               /* Spiral pixel value */  
00609   sp_index = 0;                                         
00610 
00611   /*                                                    
00612    * Read neighbour code for 1024 pixels                
00613    */                                                   
00614  NEXT_NB:                                                      
00615   if ( nb_index == 0 ) {                                
00616     if ( ( nb_index = ReadNB( fpnb ) ) < 1 ) {
00617       xform_status = 3;                     
00618       goto OUTPUT;                          
00619     }                                             
00620                                                               
00621     /* Set pointer to first element in array */   
00622     x_p = x_rec;                /* Pixel x coordinate */
00623     y_p = y_rec;                /* Pixel y coordinate */
00624     n_p = nb_rec;               /* Neighbour byte */
00625     v_p = px_rec;               /* Neighbour contributions */
00626     n_nb = 0;
00627   }                                                     
00628                                                               
00629   /*                                                    
00630    * Loop 1: Transform pixels for this data block       
00631    */                                                   
00632                                                               
00633   while( sp_index < i_sp ) {                            
00634                                                               
00635     /* Dereference pointers */                    
00636     if ( n_nb < 0 ) n_nb = 0;
00637     pixel_intensity = (int)*s_p;                          
00638     dx                  = *x_p;
00639     dy                  = *y_p;                          
00640     nb_byte             = *n_p;                          
00641                                                               
00642     /*                                            
00643      * Get maximum intensity of raw data          
00644      */                                           
00645                                                               
00646     max0( max_spiral_int, pixel_intensity );      
00647 
00648     /*                                            
00649      * Push out values we cannot trust, scale and add offset 
00650      */                                           
00651                                                               
00652     if ( pixel_intensity > cfg.spiral_max ) 
00653       pixel_intensity *= 100;
00654     else {
00655       /* Apply ADC offsets as obtained from STATUS block */
00656       if ( cfg.use_adc ) {
00657         if ( adc_channel == 1 ) {
00658           adc = adc2;
00659           adcadd = add_B;
00660         }
00661         else {
00662           adc = adc1;
00663           adcadd = add_A;
00664 #ifdef DEBUG1
00665           n1++;
00666           adcavg1 += ( pixel_intensity - adc );
00667           adcavg11+= ( pixel_intensity - adc2);
00668           if ( n1 > 100000 ) {
00669             printf( "xxx n1=%8d \tavg1=%1.3f (%1.3f)\n", n1,adcavg1/(double)n1,adcavg11/(double)n1);
00670             n1 = adcavg1 = adcavg11= 0;
00671           }
00672 #endif
00673         }
00674 
00675         pixel_intensity += (spiral_offset + adcadd - adc);
00676                                 
00677       }
00678       else {
00679         if ( adc_channel == 1 )
00680           adcadd = add_B;
00681         else 
00682           adcadd = add_A;
00683         pixel_intensity += adcadd;
00684       }
00685 
00686       adc_channel = adc_channel ^ 0x01;
00687 
00688       pixel_intensity *= cfg.spiral_scale;
00689       if ( pixel_intensity < 0 ) pixel_intensity = 0;
00690     }
00691                                                               
00692     /*                                            
00693      * In neighbor code, nb.scale is 100% contribution.
00694      */                                           
00695                                                               
00696     fract_intens = pixel_intensity / nb.scale;    
00697                                                               
00698     /*                                            
00699      * Actual x, y coordinates are ...            
00700      */                                           
00701                                                               
00702     i_x0 += dx;                                   
00703     j_y0 += dy;                                   
00704                                                               
00705     /*                                            
00706      * Main contribution: position in linear array
00707      */                                           
00708                                                               
00709     lin_pointer = i_x0 * ac_size + j_y0 - 1;      
00710                                                               
00711     /*                                            
00712      * Put pixel value into image array           
00713      */                                           
00714                                                               
00715     if ( lin_pointer >  0 && lin_pointer <= total_pixels)
00716       ImageArray( lin_pointer, *v_p );      
00717                                                               
00718     /* Next contrib pointer ... */                
00719     v_p++;                                        
00720                                                               
00721     /*                                            
00722      * Cartesian neighbours:                      
00723      *                                            
00724      *         0  1  2                            
00725      * bit j:  3     4                            
00726      *         5  6  7                            
00727      */                                           
00728                                                               
00729     for(i = 0; i < 8; i++) {                      
00730                                                               
00731       /* Neighbour does NOT contribute */   
00732       if ( (nb_byte & bit[i] ) == 0 ) continue;
00733                                                               
00734       /* Neighbour does contribute */       
00735       nb_pointer = lin_dxy[i] + lin_pointer;
00736       if ( nb_pointer>0 && nb_pointer<=total_pixels)
00737         ImageArray(  nb_pointer, *v_p );
00738                                                               
00739       /* Next contrib pointer ... */        
00740       v_p++;                                
00741     }                                             
00742                                                               
00743     /* Increase counters */                       
00744     sp_index++;                                   
00745     sp_pixels++;                                  
00746     current_pixel++;
00747                                                               
00748     /* Increase array pointers */                 
00749     s_p++;                                        
00750     x_p++;                                        
00751     y_p++;                                        
00752     n_p++;                                        
00753 
00754     /* Decrease counters */                       
00755     n_nb++;
00756     nb_index--;                                   
00757 
00758     if ( nb_index == 0 || n_nb >= NB_SIZE ) goto NEXT_NB;            
00759 
00760     if ( current_pixel >= maximum_pixels ) {
00761       xform_status = 3;
00762       goto OUTPUT;
00763     }
00764                                                               
00765   } /* End of loop 1: while ( sp_index < i_sp ) */      
00766         
00767  OUTPUT:                                                      
00768   /* 
00769    * Output image when last record of nb_code reached.
00770    */
00771   if ( xform_status == 3 || ( current_pixel >= maximum_pixels && stat_blocks_sent > 0) ) {
00772 
00773 #ifdef DEBUG
00774     if ( debug & 0x80 )
00775       printf("debug (marxf): start of output image xf=%d current_pixel=%d (%d) block=%d\n",
00776              xform_status,current_pixel,maximum_pixels,stat_blocks_sent);
00777 #endif
00778 
00779     if ( current_pixel < maximum_pixels ) {
00780       current_pixel = maximum_pixels;
00781     }
00782                 
00783     if (keep_spiral) {
00784       i = ltell( fdspiral );
00785       memset( (char *)spiral, 0, 8192);
00786       while ( ltell( fdspiral ) < spiral_size )
00787         i=write(fdspiral, spiral, 1*sizeof(short) );
00788     }
00789     output_image();
00790   }
00791 
00792   return;
00793 }
00794 
00795 /******************************************************************
00796  * Function: ImageArray = 
00797  ******************************************************************/
00798 void MarXF::ImageArray( int addr, unsigned short i2_val)
00799 {
00800   /*
00801    * Get 32 bit intensity of this pixel
00802    */
00803 
00804   u.i4_img[ addr ] = u.i4_img[ addr ] +
00805     (int) ( i2_val * fract_intens + 0.5 ); 
00806 
00807 }
00808 
00809 /******************************************************************
00810  * Function: output_image
00811  ******************************************************************/
00812 void MarXF::output_image(void)
00813 {
00814   register unsigned int   *i4_arr;
00815   register unsigned int i4_val;
00816   register unsigned int xx,yy;
00817   time_t                        now;
00818   float                 avgN,avgW,avgO,avgS;
00819   int                   k;
00820   unsigned int          cenmax,cenmin,no, ns, reclen, len, i,j, nhist, pos;
00821   double                        Isum, diff;
00822 
00823 #ifdef DEBUG
00824   if (debug & 0x40  )
00825     printf("debug (marxf): output image started %d\n",scan_in_progress);
00826 #endif
00827 
00828   if ( scan_in_progress == 0 || op_in_progress ) return;
00829 
00830   xf_in_progress        = 0;
00831   op_in_progress        = 1;
00832 
00833 #ifdef FORMAT_TEST
00834   for ( istrong=0, i=0; i<80; i++ ) {
00835     pos = (i+605)*ac_size+500+i;
00836     for ( j=0; j<100; j++, pos++ ) {
00837       i4_val = 70000+i*10000+j*100;
00838       while ( i4_val > 65535 ) {
00839         if ( ch_image[pos] < 250 ) 
00840           ch_image[ pos ]++;
00841         i4_val -= 65535;
00842       }
00843       i2_image[ pos ] = i4_val; 
00844       istrong++;
00845     }
00846   }
00847 #endif
00848   nstrong = istrong;
00849 
00850   /* 
00851    * Only spiral file has been produced, print result and return
00852    */
00853   if ( do_xform == 0 || keep_image == 0 ) {
00854     if ( keep_spiral )
00855       PrintResults( 0 );
00856     goto ALL_DONE;
00857   }
00858 
00859   /* 
00860    * Everything is fine, so go ahead
00861    * and write image to output ...
00862    */
00863 
00864   /* Rotate image by 90 deg. when working in old image format */
00865   if ( com_format == OUT_IMAGE ) {
00866     rotate_i4( u.i4_img, ac_size );
00867   }
00868 
00869   /* 
00870    * Use pointers instead of arrays. This is a bit faster...
00871    */
00872         
00873   i4_arr = u.i4_img;
00874 
00875   /* 
00876    * Init. some variables
00877    */
00878   cenmin                = ac_size/2 - 5;
00879   cenmax                = ac_size/2 + 5;
00880   Isum          = 0.0;
00881   Imax          = 0;
00882   nhist         = 0;
00883   nsat = ns_rec = no = ns = 0;
00884 
00885   /*
00886    * The overflow record is written in standard image format
00887    * In PCK mode, the overflow records follow the header, i.e.
00888    * the first overflow record is: 2
00889    * In IMAGE mode, the overflow records follow the image array,
00890    * i.e. the first overflow record is: 1+ac_size 
00891    */
00892   if ( com_format == OUT_MAR ) {
00893     reclen = 8;                                   
00894     if ( fdxf )
00895       lseek(fdxf, 4096, SEEK_SET);                  
00896   }                                                     
00897   else {                                                
00898     reclen = ac_size/4;                           
00899     if ( fdxf ) {
00900       if ( com_format == OUT_PCK )
00901         lseek(fdxf, 2*ac_size, SEEK_SET);
00902       else
00903         lseek(fdxf, 2*ac_size + 2*total_pixels, SEEK_SET);
00904     }
00905   }                                                     
00906                                                   
00907   /* 
00908    * Loop 1: Go through image and look for values exceeding 16 bits
00909    */
00910   for ( i=j=0; i< total_pixels ; i++, i4_arr++ ) {
00911 
00912     i4_val = *i4_arr;
00913 
00914     /*
00915      * The maximum intensity in the transformed image is...
00916      */
00917 
00918     if ( i4_val > Imax && i4_val < 250000 ) {
00919       xx = i%ac_size;
00920       yy = i/ac_size;
00921       /* Exclude inner 5 pixels from Imax calculation */
00922       if ( xx<cenmin || xx >cenmax || yy<cenmin || yy > cenmax )
00923         Imax = i4_val;
00924     }
00925 
00926     /*
00927      * Add to intensity histogram
00928      */
00929 
00930     if ( i4_val > 0 && i4_val <= 65535 ) {
00931       Isum += i4_val;
00932       nhist++;
00933       xf_histo[ i4_val ]++;
00934       min0( valmin, (int)i4_val );          
00935     }
00936 
00937     /*
00938      * Is overflow counter for pixel i > 0 ?
00939      */
00940 
00941     if ( i4_val <= 65535 ) continue;
00942                 
00943     /* 
00944      * The next pixel value is > 16 bits
00945      */
00946 
00947     strong_rec[no].add = i;
00948     strong_rec[no].val = i4_val;
00949 
00950     /* In IMAGE output mode, add +1 to address!!! */
00951     if ( com_format == OUT_IMAGE || com_format == OUT_PCK )
00952       strong_rec[no].add++;
00953 
00954     /*
00955      * Saturated pixels and sum up intensities
00956      */
00957     if ( strong_rec[no].val > 250000 ) {
00958       nsat++;
00959       strong_rec[no].val = 999999;
00960       *i4_arr = 999999;
00961     }
00962     else {
00963       nhist++;
00964       xx = i%ac_size;
00965       yy = i/ac_size;
00966       if ( xx<cenmin || xx >cenmax || yy<cenmin || yy > cenmax )
00967         max0( Imax, strong_rec[no].val );
00968       Isum += strong_rec[no].val;
00969     }
00970 
00971     /*
00972      * Increment counters
00973      */
00974 
00975     no++;
00976     ns++;
00977 
00978     /*
00979      * Record is full, so write it to output...
00980      */
00981     if ( no == reclen && do_xform && keep_image ) {
00982       ns_rec++;
00983       len = reclen*sizeof(STRONG);
00984       if ( fdxf ) {
00985         if ( write( fdxf, (char *)strong_rec, len) < len ) {
00986           marError( 1112, ltell( fdxf) );
00987           do_xform = 0;
00988         }
00989       }
00990       no = 0;
00991     }
00992   }
00993 
00994   /*
00995    * Fill last oveflow record with zeroes and write to output
00996    */
00997   if ( no > 0 && do_xform && keep_image && !spiral_only ) {
00998     for ( i=no; i<reclen; i++ ) {
00999       strong_rec[i].add = 0;
01000       strong_rec[i].val = 0;
01001     }
01002     ns_rec++;
01003     len = reclen*sizeof(STRONG);
01004     if ( fdxf ) {
01005       if ( write( fdxf, (char *)strong_rec, len) < len ) {
01006         marError( 1112, ltell( fdxf) );
01007         do_xform = 0;
01008       }
01009     }
01010   }
01011   if ( fdxf )
01012     pos = ltell( fdxf );
01013 
01014   /* Get average I */
01015   if ( nhist > 0 ) 
01016     AvgI = Isum/(double)nhist;
01017   else
01018     AvgI = 0.0;
01019 
01020   /* Get Sigma if Intensity */
01021   i4_arr = u.i4_img;
01022   SigI   = 0.0;
01023 
01024   /*
01025    * Go through high intensity array to get Avg, sigma 
01026    */
01027   for ( i=j=0; i< total_pixels ; i++, i4_arr++ ) {
01028     i4_val = *i4_arr;
01029     if ( i4_val == 0 ) continue;
01030     if ( i4_val > 250000 ) {
01031       if ( stat_scanmode < 4 )
01032         i4_val = 131072;
01033       else
01034         i4_val = 65535;
01035     }
01036     diff        = i4_val - AvgI;
01037     diff   *= diff;
01038     SigI   += diff;
01039     j++;        
01040   }
01041   if ( j>1 )
01042     SigI = sqrt( SigI/(double)(j - 1.0) );
01043 
01044   /*
01045    * Since istrong and ns_rec are known by now, we
01046    * can write the image header, next...
01047    */
01048   if ( fdxf )
01049     if ( output_header( 1 ) != 1 ) {
01050       do_xform = 0;
01051     }
01052 
01053   PrintResults( 1 );
01054 
01055   if ( !do_xform ) goto ALL_DONE;                       
01056   if ( input_skip_op || skip_op || spiral_only ) goto SKIP1;                       
01057   /* Print STATS, if configured */
01058   if ( cfg.use_stats && do_xform ) {
01059     j = (int)(cos( 3.14159 / 4.0 ) * (ac_size/2 - BOX_OFF) ); 
01060 
01061     /* NORDWEST */
01062     xx = yy = ac_size/2. - BOXSIZE/2 - j;
01063 
01064     avgW = PrintStats( 0, xx, yy, BOXSIZE, u.i4_img);
01065 
01066     /* WEST */
01067     xx  = BOX_OFF   - BOXSIZE/2;
01068     yy  = ac_size/2 - BOXSIZE/2;
01069     avgW = PrintStats( 1, xx, yy, BOXSIZE, u.i4_img);
01070 
01071     /* NORD */
01072     xx  = ac_size/2 - BOXSIZE/2;
01073     yy  = BOX_OFF   - BOXSIZE/2;
01074     avgN = PrintStats( 1, xx, yy, BOXSIZE, u.i4_img);
01075 
01076     /* OST  */
01077     xx  = ac_size   - BOXSIZE/2 - BOX_OFF;
01078     yy  = ac_size/2 - BOXSIZE/2;
01079     avgO = PrintStats( 1, xx, yy, BOXSIZE, u.i4_img);
01080 
01081     /* SUED */
01082     xx  = ac_size/2 - BOXSIZE/2;
01083     yy  = ac_size   - BOXSIZE/2 - BOX_OFF;
01084     avgS = PrintStats( 1, xx, yy, BOXSIZE, u.i4_img);
01085 
01086     if ( avgO > 0.0 ) avgW /= avgO;
01087     else                  avgW  = 0.0;
01088     if ( avgS > 0.0 ) avgN /= avgS;
01089     else                  avgN  = 0.0;
01090     /*
01091       sprintf( str, "%8.4f%8.4f  ", avgW, avgN);
01092     */
01093     avgW = 100.0-avgW*100.;
01094     avgN = 100.0-avgN*100.;
01095     if ( avgW < 0.0 )
01096       sprintf( str, "%8.3f" , avgW);
01097     else
01098       sprintf( str, " +%6.3f", avgW);
01099 
01100     if ( avgN < 0.0 )
01101       sprintf( str, "%8.3f  " , avgN);
01102     else
01103       sprintf( str, " +%6.3f  ", avgN);
01104 
01105     avgS = PrintStats(99, xx, yy, BOXSIZE, u.i4_img);
01106   }
01107 
01108   /* From image display we got some new information for the
01109    * header which we may will be written again into header */
01110 
01111   i=HistoMinMax();
01112 
01113   /*
01114    * Write CBF/imgCIF output
01115    */
01116 
01117   if ( com_format == OUT_CIF || com_format == OUT_CBF ) {
01118 
01119     /* Fill CIF header structure */
01120     get_header_values( 1 );
01121     sprintf( str, "scan345 (V %s)",MAR_VERSION);
01122     mar3452CIFHeader( str, image_file, h345);
01123 
01124     /* Write CIF header */
01125     if ( PutCIFHeader("scan345", image_file) < 1 ) {
01126       marError( 1115, 0 );
01127       do_xform = 0;
01128     }
01129     else {
01130       /* Write CIF data array */
01131       i= PutCIFData( "scan345", image_file, (char)(com_format-OUT_CIF), u.i4_img);
01132       if ( i == 0 ) {
01133         marError( 1112, i );
01134         do_xform = 0;
01135       }
01136     }
01137 
01138   }
01139 
01140   /* All other formats: convert 32-bit to 16-bit array */
01141   else {
01142     i4_arr = u.i4_img;
01143     for ( k=0; k<total_pixels ; k++) {
01144       i4_val = *i4_arr++;
01145       if ( i4_val > 65535 )
01146         u.i2_img[k] = 65535;
01147       else 
01148         u.i2_img[k] = (unsigned short)i4_val;
01149     }
01150   }
01151 
01152   /*
01153    * Write out the 16 bit image array.
01154    * ---------------------------------
01155    * IMAGE format...                        
01156    */
01157 
01158   if ( com_format == OUT_IMAGE ) {      
01159 
01160     lseek(fdxf, 2*ac_size, SEEK_SET);     
01161 
01162     j = write( fdxf, u.i2_img, 2*total_pixels );
01163     if ( (j < 2*total_pixels) == -1) {
01164       marError( 1112, j );
01165       do_xform = 0;
01166     }
01167     xf_pixels = j/2;                     
01168   }
01169 
01170   /*
01171    * MAR345 format...
01172    */
01173 
01174   else if ( com_format == OUT_MAR || com_format == OUT_PCK ) {
01175     /*
01176      * Write PCK header following the overflow record...
01177      */ 
01178     lseek(fdxf, pos , SEEK_SET);     
01179 
01180     sprintf(str,"\nCCP4 packed image, X: %04d, Y: %04d\n",ac_size,ac_size);
01181     if ( write(fdxf, str, strlen( str )) == -1 ) {
01182       marError( 1112, 2);
01183     }
01184 
01185     j = put_pck( u.i2_img, ac_size, ac_size, fdxf );
01186 
01187     if ( j == 0 ) {
01188       marError( 1112, 3);
01189       do_xform = 0;
01190     }
01191   }
01192 
01193 
01194  SKIP1:
01195                                                               
01196   if ( fdxf && ( com_format != OUT_IMAGE && com_format != OUT_PCK ) ) 
01197     i = output_header( 1 );                  
01198 
01199   /*
01200    * All done: close file, reset markers
01201    */
01202  ALL_DONE:
01203   /* When adding scans, we have to reverse some action
01204    * if there are overflows. We also have to rotate image
01205    * arrays when working in mar300 formats 
01206    */
01207   if ( com_scan_add > 0 && do_xform && fdxf ) {
01208 
01209     /* Convert 16-bits to 32-bits array */
01210     k=total_pixels-1;
01211     while ( k>=0 ) {
01212       i4_val    = (unsigned int)u.i2_img[k];
01213       u.i4_img[k] = i4_val;
01214       k--;
01215     }
01216 
01217     /* High intensity pixels ? */
01218     if ( com_format == OUT_IMAGE )
01219       lseek(fdxf, 2*ac_size + 2*total_pixels, SEEK_SET);
01220     else if ( com_format == OUT_PCK )
01221       lseek(fdxf, 2*ac_size, SEEK_SET);
01222     else                                                 
01223       lseek(fdxf, 4096, SEEK_SET);                  
01224 
01225     for ( no=0; no<=nstrong; no++ ) { 
01226       i =  read(fdxf, strong_rec, 8 );
01227       if ( i != 8 ) { 
01228         break;
01229       }
01230 
01231       i         = strong_rec[0].add;    
01232       i4_val    = strong_rec[0].val;
01233                                                                   
01234       /* In IMAGE output mode, take off -1 from address!!! */
01235       if ( com_format != OUT_MAR ) i--;
01236 
01237       if ( i < 0 || i >= (total_pixels-1) ) continue;
01238 
01239       if ( i4_val < 65535 )
01240         continue;
01241       u.i4_img[i] = i4_val;
01242     }
01243 
01244     /* Rotate image back when working in old image format */
01245     if ( com_format == OUT_IMAGE || com_format == OUT_PCK )
01246       rotate_i4_anti( u.i4_img, ac_size );
01247   } /* End of : if ( com_scan_add > 0 )  */
01248 
01249   /*
01250    * Close and rename files
01251    */
01252   if ( keep_image && !spiral_only ) {
01253 
01254     if ( fdxf ) {
01255       i = close( fdxf );
01256       fdxf = 0;
01257     }
01258     sprintf( buf, "%s.tmp", image_file );
01259 
01260     /* Remove temporary file */
01261     if ( input_skip_op || skip_op ) 
01262       remove( buf );
01263 
01264     /* Rename temporary file to image_file */
01265     else {
01266       rename( buf, image_file );
01267       strcpy( last_image, image_file );
01268     }
01269   }
01270   else if ( spiral_only ) {
01271     strcpy( last_image, image_file );
01272   }
01273 
01274   scan_in_progress = do_xform = 0;
01275   op_in_progress         = 0;
01276 
01277   /* 
01278    * Close spiral file, if in use at all...
01279    */
01280 
01281   if (keep_spiral) {
01282     i = output_header( 0 );                  
01283     close(fdspiral);
01284 
01285     /* Rename tmp to spiral file */
01286     sprintf( buf, "%s.tmp", spiral_file );
01287     rename(  buf, spiral_file );
01288 
01289     /* Compress spiral file */
01290     if ( cfg.use_image == 3 ) {
01291       sprintf( str, "packspiral %s &\n",spiral_file);
01292       system( str ); 
01293     }
01294     fdspiral = -1;
01295   }
01296 
01297 #ifdef DEBUG
01298   if ( debug & 0x40 )
01299     printf("debug (marwh): output image all done\n");
01300 #endif
01301 
01302   /* Open message file */
01303   time( &now );
01304   
01305   emit print_message(QString().sprintf("scan345: OUTPUT IMAGE ENDED at %s",(char *)ctime( &now )));
01306 }
01307 
01308 /******************************************************************
01309  * Function: output_header = writes header 
01310  ******************************************************************/
01311 int
01312 MarXF::output_header(int mode) 
01313 {
01314   int   i;
01315   int   fd;
01316 
01317   /* Spiral file output */
01318 
01319   if ( mode == 0 && fdspiral < 0 ) {
01320 
01321     /*
01322      * Return, if spiral image should not be written 
01323      */
01324 
01325     if ( keep_spiral == 0 ) return( 1 );
01326 
01327     sprintf( buf, "%s.tmp", spiral_file );
01328 
01329     fdspiral = creat( buf, 0666 ); 
01330 
01331     if ( fdspiral == -1 ) {
01332       marError( 1115, 0 );
01333       return( 0 );
01334     }
01335     else 
01336       close( fdspiral );
01337 
01338     /*
01339      * Open created spiral file
01340      */
01341 
01342     fdspiral = open( buf, 2 );    /* Mode = O_RDWR (=2) */
01343 
01344     if(  fdspiral == -1 ) {
01345       marError( 1120, 0 );
01346       return( 0 );
01347     }
01348 
01349                                                               
01350     /* Set file descriptor to spiral */           
01351     fd = fdspiral;                                
01352                                                               
01353   } /* End spiral section */                            
01354 
01355   else if ( mode == 0 && fdspiral >= 0 ) {
01356     /* Set file descriptor to spiral */           
01357     fd = fdspiral;                                
01358   }
01359                                                               
01360   /* Image file output */                               
01361   else {                                                
01362     if ( do_xform == 0 || keep_image == 0 || spiral_only ) return( 1 );
01363 
01364     fd = fdxf;
01365   }
01366 
01367   /*
01368    * Get values for image header
01369    */
01370 
01371   get_header_values( mode );
01372 
01373   /* 
01374    * Rewind file
01375    */
01376 
01377   i = lseek( fd, 0, SEEK_SET );
01378 
01379   if ( com_format == OUT_IMAGE || com_format == OUT_PCK ) {                             
01380     i = Putmar300Header( fd, nb.scanner, h300 );  
01381     lseek( fd, 2*ac_size, SEEK_SET );             
01382   }                                                     
01383   else {                                                
01384     i = Putmar345Header( fd, h345 );              
01385     lseek( fd, 4096, SEEK_SET );                  
01386   }                                                     
01387 
01388   /* Error occured ? */                                 
01389   if ( i < 1 ) {                                        
01390     if ( mode == 0 )                              
01391       marError( 1121, 0 );                   
01392     else {                                        
01393       marError( 1115, 0 );                   
01394       do_xform = 0;                         
01395     }                                             
01396     return( 0 );                                  
01397   }                                      
01398                                                     
01399   return( (int)1 );
01400 }
01401 
01402 /******************************************************************
01403  * Function: get_header_values
01404  ******************************************************************/
01405 void
01406 MarXF::get_header_values(int mode)
01407 {
01408   time_t                clock;                                        
01409   extern int      hist_begin, hist_end, hist_max;               
01410   extern float  op_dosebeg,op_doseend;
01411 
01412 
01413   memcpy( (char *)&h345.gap[0], (char *)stat_gap, 8*sizeof(int));
01414 
01415   /*                                                    
01416    * Fill header values: mar345 header                  
01417    */                                                   
01418   h345.byteorder          = 1234;                       
01419   h345.high               = nstrong;                    
01420   h345.scanner            = nb.scanner;
01421   h345.size               = (short)ac_size;             
01422   if ( com_format == OUT_IMAGE )
01423     h345.format     = 0;     /* IMAGE */
01424   else 
01425     h345.format     = 1;     /* PCK */
01426   h345.mode               = (char)com_mode;            
01427   h345.high               = nstrong;                    
01428   h345.pixels             = ac_size*ac_size;                  
01429   h345.pixel_length       = stat_pixelsize*1000.;        
01430   h345.pixel_height       = stat_pixelsize*1000.;        
01431   h345.xcen               = ac_size/2;
01432   h345.ycen               = ac_size/2;
01433   h345.roff               = cfg.roff[(int)stat_scanmode];
01434   h345.toff               = cfg.toff[(int)stat_scanmode];
01435   h345.gain               = 1.0;
01436   h345.time               = com_time;                  
01437 
01438   h345.dosebeg            = com_dosebeg;               
01439   h345.doseend            = com_doseend;
01440   h345.dosemin            = com_dosemin;               
01441   h345.dosemax            = com_dosemax;               
01442   h345.doseavg            = com_doseavg;               
01443   h345.dosesig            = com_dosesig;               
01444   h345.dosen              = com_dosen;                 
01445   h345.wave               = com_wavelength;             
01446 
01447   if ( start_with_A ) {
01448     h345.adc_A          = adc1;
01449     h345.adc_B          = adc2;
01450     h345.add_A          = add_A;
01451     h345.add_B          = add_B;
01452   }
01453   else {
01454     h345.adc_A          = adc2;
01455     h345.adc_B          = adc1;
01456     h345.add_A          = add_B;
01457     h345.add_B          = add_A;
01458   }
01459 
01460   h345.dist             = com_dist;
01461   h345.resol              = GetResol( (float)(ac_size*stat_pixelsize/2.0),
01462                                       (float)h345.dist,(float)h345.wave);
01463   h345.phibeg           = com_phibeg;    
01464   h345.phiend           = com_phiend;                
01465   h345.omebeg             = com_omebeg;
01466   h345.omeend             = com_omeend;
01467   h345.theta              = com_theta;
01468   h345.chi                = com_chi;                   
01469   h345.phiosc             = com_phiosc;                
01470   h345.omeosc             = com_omeosc;
01471 
01472   h345.valavg             = AvgI;                       
01473   h345.valmin             = valmin;                     
01474   h345.valmax             = Imax;                       
01475   h345.valsig             = SigI;                       
01476                                                               
01477   h345.histbeg            = hist_begin;                 
01478   h345.histend            = hist_end;                   
01479   h345.histmax            = hist_max;
01480 
01481   h345.multiplier               = cfg.spiral_scale;
01482 
01483   /*
01484     h345.slitx          = slitx;
01485     h345.slity          = slity;
01486   */
01487   h345.polar            = com_polar;
01488   h345.kV                       = com_kV;
01489   h345.mA                       = com_mA;
01490 
01491   strcpy( h345.version,         MAR_VERSION );                      
01492   strcpy( h345.program,         "scan345 (ESD)" );                     
01493 
01494   strcpy( h345.source,  com_source );                     
01495   strcpy( h345.filter,  com_filter );                     
01496   strcpy( h345.remark,  com_remark );                     
01497                                                               
01498   time( &clock );                                       
01499   sprintf( str, "%s",(char *) ctime(&clock) );    
01500   memcpy(  h345.date, str, 24 );
01501   memcpy(  h300.date, str, 24 );                      
01502 
01503   /* Specials for spirals ... */                        
01504   if ( mode == 0 ) {                                    
01505     if ( stat_scanmode > 3 ) 
01506       h345.pixel_length = stat_pixelsize*500.;        
01507     h345.pixels         = maximum_pixels - poff;                  
01508     h345.format     = 2;        /* SPIRAL */
01509   }                                                     
01510   /*                                                    
01511    * Fill header values: mar300 header                  
01512    */                                           
01513 
01514   h300.pixels_x           = ac_size;                    
01515   h300.pixels_y           = ac_size;                    
01516   h300.lrecl              = 2*ac_size;                  
01517   h300.max_rec            = ac_size+1;                  
01518   h300.high_pixels        = h345.high;                    
01519   h300.high_records       = ns_rec;                     
01520   h300.counts_start       = (int)op_dosebeg;                          
01521   h300.counts_end         = (int)op_doseend;                          
01522   h300.exptime_sec        = stat_time;                  
01523   h300.exptime_units      = (int)sum_xray_units;        
01524   h300.prog_time          = com_time;                  
01525   h300.r_max            = cfg.diameter[stat_scanmode]/2.;
01526   h300.r_min              = 0;                          
01527   h300.p_r                = nb.pixel_height;                          
01528   h300.p_l                = nb.pixel_length;
01529   h300.p_x                = nb.pixel_height;                          
01530   h300.p_y                = nb.pixel_height;
01531   h300.centre_x           = h345.xcen;                 
01532   h300.centre_y           = h345.ycen;                 
01533   h300.lambda             = h345.wave;
01534   h300.distance           = h345.dist;
01535   h300.phi_start          = h345.phibeg;
01536   h300.phi_end            = h345.phiend;                
01537   h300.omega              = h345.omebeg;                          
01538   h300.multiplier         = h345.multiplier;                 
01539 }
01540 
01541 /******************************************************************
01542  * Function: PrintResults
01543  ******************************************************************/
01544 void
01545 MarXF::PrintResults( int mode )
01546 {
01547   /*
01548    * Print most important results
01549    */
01550 
01551   if ( mode == 1 && !(input_skip_op || skip_op ) )
01552     sprintf( str, "         -> File:      %s\n", image_file);
01553   else {
01554     if ( spiral_only )
01555       sprintf( str, "         -> File:      %s\n", spiral_file);
01556     else
01557       sprintf( str, "     !!! -> File:      %s\n", spiral_file);
01558   }
01559 
01560   emit print_message(str);
01561 
01562   if ( mar_cmd != MDC_COM_SCAN ) {
01563     sprintf( str, "            Phi range     [degrees]: %8.3f --> %1.3f\n",com_phibeg,com_phiend);
01564     if ( cfg.use_phi ) {
01565       emit print_message(str);
01566     }
01567     sprintf( str, "            Exposure time     [sec]: %8.0f\n",com_time);
01568     emit print_message(str);
01569 
01570 #ifdef MAR345
01571     sprintf( str, "            Average X-ray intensity: %8.2f\n", sum_xray_units);
01572     emit print_message(str);
01573 #endif
01574   }
01575 
01576   if ( mode != 0 || input_skip_op || skip_op || spiral_only ) {
01577 
01578     if ( cfg.use_stats ) {
01579       sprintf( str, "            Average image intensity: %8.1f\n",AvgI);
01580       emit print_message( str );
01581     }
01582     sprintf( str, "            Maximum valid intensity: %8d\n", Imax );
01583     emit print_message( str );
01584     sprintf( str, "            No. of pixels > 65535:   %8d\n",nstrong);
01585     if ( istrong > 0 ) {
01586       emit print_message( str );
01587     }
01588     sprintf( str, "            No. of saturated pixels: %8d\n",nsat);
01589     if ( nsat    > 0 ) {
01590       emit print_message( str );
01591     }
01592   }
01593 }
01594 
01595 /******************************************************************
01596  * Function: ReadNB
01597  ******************************************************************/
01598 int
01599 MarXF::ReadNB(FILE *fp)
01600 {                                                             
01601   int             i,n,n_nb;                                     
01602   unsigned short  r_rec[4];                                     
01603   static int      n_rec=0;                                      
01604                                                               
01605   /* Read record with index counters */                 
01606   i  = fread( (unsigned short *)r_rec, sizeof(short), 2, fp );            
01607   /* Swap bytes if required */                          
01608   if (swap_nb) swapshort((char*) r_rec, 2*sizeof(short) );     
01609                                                               
01610   n    = r_rec[0];                                      
01611   n_nb = r_rec[1];                                      
01612                                                               
01613   /* Read record with x coordinate */                   
01614   i += fread( x_rec, sizeof(char), n, fp );             
01615                                                               
01616   /* Read record with x coordinate */                   
01617   i += fread( y_rec, sizeof(char), n, fp );             
01618                                                               
01619   /* Read record with nb_byte */                        
01620   i += fread(nb_rec, sizeof(char), n, fp );             
01621                                                               
01622   if ( i != (3*n+2) ) {                                 
01623     /*
01624       fprintf( stdout, "scan345: only %d out of %d bytes read from nb after pixel %d\n",i,3*n+2,sp_pixels+1);
01625     */
01626     return( 0 );                                  
01627   }                                                     
01628                                                               
01629   /* Read record with n_nb nb contributions */          
01630   if ( n_nb > 0 ) {                                     
01631     i = fread( px_rec, sizeof(unsigned short), n_nb, fp ); 
01632     /* Swap bytes if required */                  
01633     if (swap_nb) swapshort( (char*) px_rec, n_nb*sizeof(short) );
01634                                                               
01635     if ( i != n_nb ) {                            
01636       fprintf( stdout, "scan345: ERROR reading nb at pixel %d in record %ld\n",sp_pixels+1,ftell(fp) );
01637       return( 0 );                              
01638     }                                             
01639   }                                                     
01640                                                               
01641   n_rec++;                                              
01642                                                               
01643   return( n );                                          
01644 }
01645 
01646 /*********************************************************************
01647  * Function: PrintStats
01648  *********************************************************************/
01649 float
01650 MarXF::PrintStats( int mode, int x, int y, int NP, unsigned int *i4_arr) 
01651 {
01652   register unsigned int i,j,*i4;
01653   register unsigned int i4_val;
01654   static time_t         now,last=0 ;
01655   struct        tm              *time_ptr;
01656   int                   n, k,l;
01657   double                        diff,sum,avg,sig;
01658   char                  clock_time[32];
01659 
01660   /* Last call: print time and image name */
01661   if ( mode == 99 ) {
01662     now         = time( NULL );
01663     time_ptr= localtime( &now);
01664     n           = now - last;
01665     if ( last==0 ) n = 0;
01666 
01667     /* Print the date: */
01668     strftime( clock_time, 16, "%a %H:%M.%S", time_ptr );
01669 
01670     sprintf( str, "%s%5d%6d%6.1f%6.1f  %s\n",
01671              clock_time,n,stat_gap[0],adc1/1000.,adc2/1000.,image_file);
01672 
01673     last        = now;
01674     return(1.0);
01675   }
01676 
01677   sig = sum = avg = 0.0;
01678 
01679   for ( i=k=l=0; i<NP; i++ ) {
01680     n = ac_size*( y+i ) + x;
01681     i4 = i4_arr + n ;
01682     for (  j=0; j<NP; j++, i4++ ) {
01683       i4_val = *i4;
01684       if ( i4_val == 0 || i4_val > 250000 ) {
01685         continue;
01686       }
01687       k++;
01688       sum += i4_val;
01689     }
01690   }
01691   sig = 0.0;
01692 
01693   if ( k > 1 )
01694     avg = sum/(double)k;
01695   else 
01696     return( avg);
01697 
01698   for ( i=0; i<NP; i++ ) {
01699     n = ac_size*( y+i ) + x;
01700     i4 = i4_arr + n ;
01701     for (  j=0; j<NP; j++, i4++ ) {
01702       i4_val = *i4;
01703       if ( i4_val == 0 || i4_val > 250000 ) continue;
01704       diff = i4_val - avg;
01705       diff *= diff;
01706       sig += diff;
01707     }
01708   }
01709 
01710   sig = sqrt( sig/(double)(k - 1.0) );
01711 
01712   if ( mode == 0 ) {
01713     sprintf( str, "%7.1f%6.1f", avg, sig);
01714   }
01715 
01716   return avg;
01717 }
01718 
01719 /******************************************************************
01720  * Function: HistoMinMax = finds limits of histogram
01721  ******************************************************************/
01722 int
01723 MarXF::HistoMinMax(void)
01724 {
01725   register int  *hist=xf_histo;
01726   register int  i;
01727   float                 dh, hsumr, hsuml;
01728 
01729   /* 
01730    * Integrate whole histogram 
01731    */
01732 
01733   hsuml=hist_max=0;
01734   for (i=1; i<=65535; i++ ) {
01735     hsuml = hsuml + hist[i];
01736     max0( hist_max, hist[i] );
01737   }
01738 
01739   /* From high intensity end go down stepwise, until right integral
01740    * is 0.002 % from left  integral */
01741 
01742   hist_begin = 0;
01743   hsumr            = 0;
01744   for (i=65535; i>0; i-- ) {
01745     hsumr = hsumr + hist[i];
01746     hsuml = hsuml - hist[i];
01747     if (hsuml>(float)0.0) dh = hsumr/hsuml;
01748     if (dh>0.002) break;
01749   }
01750 
01751   hist_end = i;
01752 
01753   if (hist_end < 250) hist_end = 250;
01754 
01755   return( hist_end );
01756 
01757 }