May 5, 1997

From: Tom Patterson, UW- Electron Microprobe Lab assistant
email: thomp@geology.wisc.edu

To: SX users:

Here's a short and pretty darn useful program I wrote as a first attempt at programming in C. If you're like most of us, you usually forget to keep track of the step size, beam width, X,Y,Z location, high voltage, etc. of the hundreds of images you collect. Well, worry no more. This program 'extractheader' reads and decodes the 1056 byte binary header of an image created by the Cameca SX50 FCIAP and CIAP routines and writes most of the image collection parameters to an ASCII text file. (Now you know what that 1056 offset number represents when you import the image to NIH Image.)

I have included the C source code so you can mess around with it and compile it on your own machines. The code was written for a Sun SPARCstation (SunOS 4.1.2), but it should compile on any UNIX platform. To compile the program, save the source code as 'extractheader.c', and at the UNIX prompt type:

cc -o extractheader extractheader.c

This will create an executable file called 'extractheader'. You can keep this file in your home directory, but it's probably a better idea to stick it in the /usr/bin directory so everybody can use it if you have separate user directories. (You have to be a root user to copy or move stuff in the /usr/bin directory.

To run the program, at the UNIX prompt type:

extractheader image_filename output_filename

The image_filename can be any pathname, but the output_filename is limited to your home directory (i.e. goes there automatically). For example, I can invoke the program from my home directory, /home/geol/thomp, using an image file from any user's directory as input, e.g., /home/geol/joe/Image/imv/image.img; but my output filename can only be a simple filename with no pathname, e.g., text.out. (I haven't been able to get rid of this bug, so any helpful hints would be greatly appreciated. Thanks.) The simplest way to avoid any of this hassle is to change directories to /Image/imv and invoke the program from the same directory as all of your images. That way you keep all the data in the same folder. (You could even have all your users copy the binary executable file to their own /Image/imv directories, but good system administrators will restrict the binary files to /bin directories.)

To look at the extracted data, just output the output_filename file to the screen or printer.

The source code follows as simple text. (Cut below the dotted line down to and including the closing brace, be sure to remove the HTML "PRE" and "/PRE" tags plus any tailing "/BODY" and "/HTML" tags.)

Cut here (to end of file) --------------------------------------------

/* extractheader.c                                           */
/*                                                           */
/* written by thomp, 04/97                                   */
/*                                                           */
/*                                                           */
/* This short C program reads the 1056 byte binary header    */
/* of a Cameca SX50 .img file and extracts and writes most   */
/* of the image acquisition parameters and spectrometer and  */
/* column settings to an ASCII text file.  It was written    */
/* to run on a Sun SPARCstation, but it should work on most  */
/* UNIX systems.  Integer variables are 4 byte(32 bit).      */
/* The 'Input filename:' command will accept any pathname up */
/* to 80 characters in length, but the 'Output filename:'    */
/* command will only accept a filename with the current      */
/* directory as a path.                                      
*/
#include 
#define	SPM 5	/* maximum number of spectrometers */

main(argc,argv)

int argc;
char *argv[];

{

/* the image header consists of two parts: */

/* the first part contains 19 integers, most of them unknown */

struct first_hdr {
  int magic_number;
  int size_x;
  int size_y;
  int unknown_1;
  int unknown_2;
  int unknown_3;
  int unknown_4;
  int unknown_5;
  int unknown_6;
  int pix_depth;
  int unknown_7;
  int unknown_8;
  int unknown_9;
  int unknown_10;
  int unknown_11;
  int unknown_12;
  int unknown_13;
  int unknown_14;
  int hdr_offset;
} one_hdr,*pone_hdr;

/* the second part is described by the SX file 'desinc.h' */

struct second_hdr {
  char label[20];	/* cond. file without extension */
  char comnt[80];	/* comment line */
  char date[28];	/* creation date */
  float bmcur;		/* beam-current 0->10000 nA */
  float hgtv;		/* hight-voltage 0->50 Kv */
  char cond[8];		/* column condition on file */
  int spect;		/* number of spectrometer */
  int stgpos[3];	/* stage position X,Y,Z -100000 -> 100000 */
  int modx;		/* mode 0:64 , 1:128 , 2:256 or 3:512  */
  int mody;		/* = nptx , npty */
  float step;		/* um */
  float time;		/* ms */
  int modscan;		/* scanning mode 0:beam or 1:stage */
  int bmrot;		/* beam rotation 0->359 deg */
  int modacc;	/* acquisition mode 0:auto or 1:man = adjust */
  int modz;		/* z correction 0:no or 1:yes  = iupdz */
  int semc;		/* SEM channels 0:no 1:M1 or 2:M2 */
  int vidc;		/* video channels 0:VS1 or 1:VS2 = numvs */
  int elecs;		/* Electron signal 0:SE , 1:BSE or 2:ABS */
  int ray[SPM];		/* 0->6 for : no ray,Ka,Kb,La,Lb,Ma or Mb */
  int pos[SPM];		/* Spectro position 22000->83000 */
  char symb[SPM][8];	/* element symbol for each spectro */
  int crys[SPM];	/* Crystal number in list of 4 */
  char namest[SPM][20];	/* standard name */
  int papc;		/* pap correction no/yes */
  int nxt[SPM][6];	/* Xtal configuration */
  int offset[3];	/* stage offset x,y,z */
  int stglim[3][2];	/* stage position limite min/max for x,y,z */
  int stgfoc[4][3];	/* each stage corner position x,y,z */
  int nwds;		/* number of specto use (  ");
    exit(8);
  }

  input = fopen(argv[1],"r");
  if (input == NULL)
  {
    puts("open input_file error");
    exit(8);
  }

  output = fopen(argv[2],"w");
  if (output == NULL)
  {
    puts("open output_file error");
    exit(8);
  }

  fread(pone_hdr,sizeof(*pone_hdr),1,input);
  fread(ptwo_hdr,sizeof(*ptwo_hdr),1,input);

  fclose(input);

  fprintf(output,"filename: %s\n",ptwo_hdr->label);
  fprintf(output,"creation date: %s\n",ptwo_hdr->date);
  fprintf(output,"image size (pixels): %d X %ld\n",
          pone_hdr->size_x,
          pone_hdr->size_y);
  fprintf(output,"pixel depth: %d bit\n",pone_hdr->pix_depth);
  fprintf(output,"header offset: %d bytes\n",pone_hdr->hdr_offset);
  fprintf(output,"beam current (nA): %f\n",ptwo_hdr->bmcur);
  fprintf(output,"high voltage (kV): %f\n",ptwo_hdr->hgtv);
  fprintf(output,"step size (microns): %f\n",ptwo_hdr->step);
  fprintf(output,"count time (milliseconds): %f\n",ptwo_hdr->time);
  fprintf(output,"beam size (microns): %d\n",ptwo_hdr->bmsiz);
  fprintf(output,"magnification: %f\n",ptwo_hdr->mag);
  fprintf(output,"image center (X,Y,Z): (%d,%d,%d)\n",
          ptwo_hdr->stgpos[0],
          ptwo_hdr->stgpos[1],
          ptwo_hdr->stgpos[2]);

  switch (ptwo_hdr->elecs)
  {
    case 0:
      fprintf(output,"electron signal: SE\n");
      break;
    case 1:
      fprintf(output,"electron signal: BSE\n");
      break;
    case 2:
      fprintf(output,"electron signal: ABS\n");
  }

  if (ptwo_hdr->flag_acq)
  {
    fprintf(output,"acquisition mode: FCIAP\n");
    fprintf(output,"accumulated frames: %d\n",ptwo_hdr->frames);
  }
  else
  {
    fprintf(output,"acquisition mode: CIAP\n");
  }

  if (ptwo_hdr->modscan)
  {
    fprintf(output,"scan mode: stage\n");
  }
  else
  {
    fprintf(output,"scan mode: beam\n");
  }
  if (ptwo_hdr->nwds)
  {
    fprintf(output,"Spectrometer parameters:\n");
    for (i=0; icrys[i] + (i*4);
      fprintf(output,"\t%s",ptwo_hdr->xnam[xnam_index]);
      fprintf(output,"\t%d",ptwo_hdr->pos[i]);
      fprintf(output,"\t%s",ptwo_hdr->symb[i]);
      switch (ptwo_hdr->ray[i])
      {
        case 0:
          fprintf(output,"\tno ray\n");
          break;
        case 1:
          fprintf(output,"\tKa\n");
          break;
        case 2:
          fprintf(output,"\tKb\n");
          break;
        case 3:
          fprintf(output,"\tLa\n");
          break;
        case 4:
          fprintf(output,"\tLb\n");
          break;
        case 5:
          fprintf(output,"\tMa\n");
          break;
        case 6:
          fprintf(output,"\tMb\n");
          break;
      }
    }
  }    
  
  fclose(output);
}


Pure ascii version of extractheader.c 
program
Return to our sx50 software mod 
page