This archive web page is obsolete!

Please refer to the new mailman archive! Argh ! Monitor_nD again


[Date Prev][Date Next] [Chronological] [Thread] [Top]

Argh ! Monitor_nD again



Hy all of you,

The usage of McStas macros is a bit tricky, but it works usually fine. In the case of the Moniotr_nD component v0.14, I called the DETECTOR_OUT... macros, that use the 'compcurname' DEFINE (name of current component). These macros just call the mcdetector_out... functions.
As with v0.14, the component functions are only compiled once, the functions where initialised with the first instance of compcurname (first monitor) and all following monitors had the same name. This does not prevent the monitors to output data in the right files, but the monitor titles where all identical in mcplot.
I here provide v0.14.1 that corrects this bug (and I hope McStas will always have the detector_out_xx functions !)

Cheers. EF.

-- 
What's up Doc ?
--------------------------------------------
Emmanuel FARHI, http://www.ill.fr/tas/people/Farhi.html   \|/ ____ \|/
CS-Group ILL4/156, Institut Laue-Langevin (ILL) Grenoble  ~@-/ oO \-@~
6 rue J. Horowitz, BP 156, 38042 Grenoble Cedex 9,France  /_( \__/ )_\
Work :Tel (33/0) 4 76 20 71 35. Fax (33/0) 4 76 48 39 06     \__U_/
 
/*******************************************************************************
*
* Component: Monitor_nD
*
* %Identification
* Written by: <a href="mailto:farhi@ill.fr">Emmanuel Farhi</a>
* Date: 14th Feb 2000.
* Origin: <a href="http://www.ill.fr">ILL (France)</a>
* Version: 0.14.1
* Modified by: EF, 29th Feb 2000 : added more options, monitor shape, theta, phi
* Modified by: EF, 10th Mar 2000 : use struct. 
* Modified by: EF, 25th May 2000 : correct Vars.Mon2D_Buffer alloc bug.
* Modified by: EF, 17th Oct 2000 : spin detector ok. (0.13.4)
* Modified by: EF, 19th Jan 2001 : 'auto limits' bug corrected (0.13.5)
* Modified by: EF, 01st Feb 2001 : PreMonitor for correlation studies (0.13.6)
* Modified by: EF, 02nd Feb 2001 : user variable (0.13.7)
* Modified by: EF, 2th  Feb 2001 : 3He gas absorption handling (0.13.8)
* Modified by: EF, 5th  Mar 2001 : intermediate savings (0.13.9)
* Modified by: EF, 5th  Apr 2001 : use global functions (0.14) compile faster
* Modified by: EF, 18th Apr 2001 : passes DETECTOR_OUT to mcdetector_out

*
* This component is a general Monitor that can output 0/1/2D signals 
* (Intensity vs. [something] and vs. [something] ...)
*
* %Description
* This component is a general Monitor that can output 0/1/2D signals 
* It can produce many 1D signals (one for any variable specified in 
* option list), or a single 2D output (two variables related).
* Also, an additional 'list' of neutrons can be produced.
* By default, monitor is square (in x/y plane). disk is also possible
* The 'cylinder' option will change that for banana shaped detector
* The 'sphere' option simulates spherical detector.
* In normal configuration, the Monitor_nD measures the current parameters 
* of the neutron that is beeing detected. But a PreMonitor_nD component can 
* be used in order to study correlations between a neutron being detected in
* a Monitor_nD place, and given parameters that are monitored elsewhere 
* (at <b>PreMonitor_nD</b>).
* It is also possible, using the 'intermediate' keyword, to save monitor results
* every X percent of the simulation. The monitor can also act as a 3He gas
* detector, taking into account the detection efficiency.
* 
* <b>Possible options are</b>
* Variables to record:
*     kx ky kz k wavevector (Angs-1) [    usually axis are
*     vx vy vz v            (m/s)         x=horz., y=vert., z=on axis]
*     x y z radius          (m)      Distance, Position
*     t time                (s)      Time of Flight
*     energy omega          (meV)
*     lambda wavelength     (Angs)
*     p intensity flux      (n/s) or (n/cm^2/s)
*     ncounts               (1)
*     sx sy sz              (1)      Spin
*     vdiv ydiv dy          (deg)    vertical divergence (y)
*     hdiv divergence xdiv  (deg)    horizontal divergence (x)
*     angle                 (deg)    divergence from <z> direction
*     theta longitude       (deg)    longitude (x/z) [for sphere and cylinder]
*     phi   lattitude       (deg)    lattitude (y/z) [for sphere and cylinder]
*
*     user user1            will monitor the [Mon_Name]_Vars.UserVariable{1|2}
*     user2                 to be assigned in an other component (see below)
*
* <b>Other options are:</b>
*     auto {limits}             Automatically set detector limits
*     all  {limits or bins}     To set all limits or bins values
*     bins=[bins=20]            Number of bins in the detector along dimension
*     borders                   To also count off-limits neutrons
*                               (X < min or X > max)
*     cylinder                  To get a cylindrical monitor (e.g. banana)
*                               (radius along x, height along y).
*     disk                      Disk flat xy monitor
*                               radius is max abs value of xmin xmax ymin ymax
*     file=string               Detector image file name. default is component
*                               name, plus date and variable extension.
*     square                    Square flat xy monitor
*     limits=[min max]          Lower/Upper limits for axes
*                               (see below for the variable unit)
*     list=[counts=1000] or all For a long file of neutron characteristics
*                               with [counts] or all events
*     multiple                  For 1D monitors into multiple independant files
*     no or not                 Revert next option
*     outgoing                  Monitor outgoing beam in non flat (sph/cyl) det
*                               (default is incoming beam)
*     per cm2                   Intensity will be per cm^2
*     slit or absorb            Absorb neutrons that are out detector
*     sphrere                   To get a spherical monitor (e.g. a 4PI)
*                               radius is max abs value of xmin xmax ymin ymax
*     unactivate                To unactivate detector (0D detector)
*     premonitor                Will monitor neutron parameters stored
*                               previously with <b>PreMonitor_nD</b>.
*     verbose                   To display additional informations
*     3He_pressure=[3 in bars]  The 3He gas pressure in detector.
*                               3He_pressure=0 means perfect detector (default)
*     intermediate=[5 in %]     Save results every n% steps in simulation
*
* <b>EXAMPLES:</b>
* MyMon = Monitor_nD(
*   xmin = -0.1, xmax = 0.1,
*   ymin = -0.1, ymax = 0.1,
*   options = "intensity per cm2 angle,limits=[-5 5] bins=10,with
*              borders, file = mon1");
*                           will monitor neutron angle from [z] axis, between -5
*                        and 5 degrees, in 10 bins, into "mon1.A" output 1D file
*   options = "sphere theta phi outgoing"   for a sphere PSD detector (out beam)
*                                    and saves into file "MyMon_[Date_ID].th_ph"
*   options = "angle radius auto limits"   is a 2D monitor with automatic limits
*   options = "list kx ky kz energy" records each neutron contribution in 1 file
*   options = "multiple kx ky kz energy and list all neutrons" 
*          makes 4 output 1D files and produces a complete list for all neutrons
*
*
* How to monitor anything in my simulation: with the 'user' option
*  In a component, you will put for instance in INITIALIZE and/or
*  TRACE sections (same is valid with user2)
*
*  struct MonitornD_Variables *Vars = &(MC_GETPAR(Guide_Mon, Vars));
*               with name of monitor that you will use in instr 
*  strcpy(Vars->UserName1,"My variable label");
*  Vars->UserVariable1++;
*
*  and in the instrument description:
*
*  COMPONENT Guide_Mon = Monitor_nD(
*   xmin = -0.05, xmax = 0.05,
*   ymin = -0.1, ymax = 0.1,
*   options="user1, limits=[0 15], bins=15")
*  AT (0,0,0) RELATIVE GuideEnd
*
* See also the example in <a href="PreMonitor_nD.html">PreMonitor_nD</a>.
*
* %Parameters
* INPUT PARAMETERS:
*
* xmin:   (m)    Lower x bound of opening
* xmax:   (m)    Upper x bound of opening
* ymin:   (m)    Lower y bound of opening
* ymax:   (m)    Upper y bound of opening
* options:(str)  String that specifies the configuration of the monitor</br>
*                 The general syntax is "[x] options..." (see <b>Descr.</b>)
*
* OUTPUT PARAMETERS:
*
* DEFS: structure containing Monitor_nD Defines (struct)
* Vars: structure containing Monitor_nD variables (struct)
*
* %Link 
* <a href="http://www.ill.fr/tas/mcstas/">McStas at ILL</a>
* <a href="PreMonitor_nD.html">PreMonitor_nD</a>
*
* %End
*******************************************************************************/

DEFINE COMPONENT Monitor_nD
DEFINITION PARAMETERS (options)
SETTING PARAMETERS (xmin, xmax, ymin, ymax)
/* these are protected C variables */
OUTPUT PARAMETERS (DEFS, Vars)
STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p)
POLARISATION PARAMETERS (sx,sy,sz)

DECLARE
%{

#ifndef FLT_MAX
#define FLT_MAX 1E37
#endif
#ifndef Monitor_nD_Version

#define Monitor_nD_Version "0.14"
#define MONnD_COORD_NMAX  30  /* max number of variables to record */
  
  /* here we define some DEFINE constants */
  typedef struct MonitornD_Defines
  {
    char COORD_NONE  ;
    char COORD_X     ;
    char COORD_Y     ;
    char COORD_Z     ;
    char COORD_VX    ;
    char COORD_VY    ;
    char COORD_VZ    ;
    char COORD_T     ;
    char COORD_P     ;
    char COORD_SX    ;
    char COORD_SY    ;
    char COORD_SZ    ;
    char COORD_KX    ;
    char COORD_KY    ;
    char COORD_KZ    ;
    char COORD_K     ;
    char COORD_V     ; 
    char COORD_ENERGY; 
    char COORD_LAMBDA; 
    char COORD_RADIUS; 
    char COORD_HDIV  ; 
    char COORD_VDIV  ; 
    char COORD_ANGLE ; 
    char COORD_NCOUNT; 
    char COORD_THETA ; 
    char COORD_PHI   ; 
    char COORD_USER1 ; 
    char COORD_USER2 ;

    /* token modifiers */
    char COORD_VAR   ; /* next token should be a variable or normal option */
    char COORD_MIN   ; /* next token is a min value */
    char COORD_MAX   ; /* next token is a max value */
    char COORD_DIM   ; /* next token is a bin value */
    char COORD_FIL   ; /* next token is a filename */
    char COORD_EVNT  ; /* next token is a buffer size value */
    char COORD_3HE   ; /* next token is a 3He pressure value */
    char COORD_INTERM; /* next token is an intermediate save value (percent) */

    char TOKEN_DEL[32]; /* token separators */

    char SHAPE_SQUARE; /* shape of the monitor */
    char SHAPE_DISK  ; 
    char SHAPE_SPHERE; 
    char SHAPE_CYLIND; 
    
  } MonitornD_Defines_type;
  
  typedef struct MonitornD_Variables
  {
    double area;
    double Sphere_Radius     ;
    double Cylinder_Height   ;
    char   Flag_With_Borders ;   /* 2 means xy borders too */
    char   Flag_List         ;   /* 1 store 1 buffer, 2 is list all */
    char   Flag_Multiple     ;   /* 1 when n1D, 0 for 2D */
    char   Flag_Verbose      ;
    int    Flag_Shape        ;
    char   Flag_Auto_Limits  ;   /* get limits from first Buffer */
    char   Flag_Absorb       ;   /* monitor is also a slit */
    char   Flag_per_cm2      ;   /* flux is per cm2 */
    
    int    Coord_Number      ;   /* total number of variables to monitor, plus intensity (0) */
    long   Buffer_Block      ;   /* Buffer size for list or auto limits */
    long   Neutron_Counter   ;   /* event counter, simulation total counts is mcget_ncount() */
    long   Buffer_Counter    ;   /* index in Buffer size (for realloc) */
    long   Buffer_Size       ;
    char   Coord_Type[MONnD_COORD_NMAX];    /* type of variable */
    char   Coord_Label[MONnD_COORD_NMAX][30];       /* label of variable */
    char   Coord_Var[MONnD_COORD_NMAX][30]; /* short id of variable */
    int    Coord_Bin[MONnD_COORD_NMAX];             /* bins of variable array */
    double Coord_Min[MONnD_COORD_NMAX];             
    double Coord_Max[MONnD_COORD_NMAX];
    char   Monitor_Label[MONnD_COORD_NMAX*30];      /* Label for monitor */
    char   Mon_File[128];    /* output file name */

    double cx,cy,cz;
    double cvx, cvy, cvz;
    double csx, csy, csz;
    double cs1, cs2, ct, cp;
    double He3_pressure;
    char   Flag_UsePreMonitor    ;   /* use a previously stored neutron parameter set */
    char   UserName1[128];
    char   UserName2[128];
    double UserVariable1;
    double UserVariable2;
    double Intermediate;
    double IntermediateCnts;
    char   option[1024];
    
    int    Nsum;
    double psum, p2sum;
    int    **Mon2D_N;
    double **Mon2D_p;
    double **Mon2D_p2;
    double *Mon2D_Buffer;
    
    char   compcurname[128];

  } MonitornD_Variables_type;
  
/* global functions to be defined once for faster compile */
/* code can anyway get big. may be included in an external .c file 
   to be included once */
  
/* this routine is used to save results at end of simulation, but also 
 * during simulation (SIGUSR... intermediate steps) */ 
void Monitor_nD_OutPut(aDEFS, aVars, dofree)
  MonitornD_Defines_type *aDEFS;
  MonitornD_Variables_type *aVars;
  char dofree;
  /* dofree = 0 : no free, =1 : free variables (last call) */
  {
    char   *fname;
    long    i,j;
    int    *p0m = NULL;
    double *p1m = NULL;
    double *p2m = NULL;
    char    Coord_X_Label[1024];
    double  min1d, max1d; 
    double  min2d, max2d;
    int     bin1d, bin2d;
    char    While_End = 0;
    long    While_Buffer = 0;
    double  XY, pp;
    double  Coord[MONnD_COORD_NMAX];
    long    Coord_Index[MONnD_COORD_NMAX];
    char    label[1024];
    
    if (dofree == 0)
    {
      if (aVars->Flag_Verbose) printf("Monitor_nD: %s save intermediate results (%.2f %%).\n", aVars->compcurname, 100*mcget_run_num()/mcget_ncount());
    }

    /* check Buffer flush when end of simulation reached */
    if ((aVars->Buffer_Counter < aVars->Buffer_Block) && aVars->Flag_Auto_Limits)
    {
      /* Get Auto Limits */
      if (aVars->Flag_Verbose) printf("Monitor_nD: %s getting %i Auto Limits from List (%li).\n", aVars->compcurname, aVars->Coord_Number, aVars->Buffer_Counter);
      for (i = 1; i <= aVars->Coord_Number; i++)
      {
        aVars->Coord_Min[i] = FLT_MAX;
        aVars->Coord_Max[i] = -FLT_MAX;

        for (j = 0; j < aVars->Buffer_Counter; j++)
        { 
                XY = aVars->Mon2D_Buffer[j*(aVars->Coord_Number+2) + (i-1)];  /* scanning variables in Buffer */
          if (XY < aVars->Coord_Min[i]) aVars->Coord_Min[i] = XY;
          if (XY > aVars->Coord_Max[i]) aVars->Coord_Max[i] = XY;

        }
      }
      aVars->Flag_Auto_Limits = 2;  /* pass to 2nd auto limits step */
      aVars->Buffer_Block = aVars->Buffer_Counter;
    
      while (!While_End)
      { /* we generate Coord[] and Coord_index[] from Buffer (auto limits) or passing neutron */
        if (While_Buffer < aVars->Buffer_Block)
        {
          /* first while loops (While_Buffer) */
          /* auto limits case : scan Buffer within limits and store in Mon2D */ 
          for (i = 1; i <= aVars->Coord_Number; i++)
          {
            /* scanning variables in Buffer */
            XY = (aVars->Coord_Max[i]-aVars->Coord_Min[i]);
            Coord[i] = aVars->Mon2D_Buffer[While_Buffer*(aVars->Coord_Number+2) + (i-1)];
            Coord[0] = aVars->Mon2D_Buffer[While_Buffer*(aVars->Coord_Number+2) + (aVars->Coord_Number)];
            pp = Coord[0];
            if (XY > 0) Coord_Index[i] = floor((aVars->Mon2D_Buffer[(i-1) + While_Buffer*(aVars->Coord_Number+2)]-aVars->Coord_Min[i])*aVars->Coord_Bin[i]/XY);
            else Coord_Index[i] = 0;
            if (aVars->Flag_With_Borders)
            {
              if (Coord_Index[i] < 0) Coord_Index[i] = 0;
              if (Coord_Index[i] >= aVars->Coord_Bin[i]) Coord_Index[i] = aVars->Coord_Bin[i] - 1;
            }
          } /* end for */
          While_Buffer++;
        } /* end if in Buffer */
        else /* (While_Buffer >= aVars->Buffer_Block) && (aVars->Flag_Auto_Limits == 2) */ 
        {
          aVars->Flag_Auto_Limits = 0;
          While_End = 1;
          if (!aVars->Flag_List && dofree) /* free Buffer not needed (no list to output) */
          { /* Dim : (aVars->Coord_Number+2)*aVars->Buffer_Block matrix (for p, dp) */ 
            free(aVars->Mon2D_Buffer);
          }
        }

        /* store n1d/2d section from Buffer */

        /* 1D and n1D case : aVars->Flag_Multiple */
        if (aVars->Flag_Multiple)
        { /* Dim : aVars->Coord_Number*aVars->Coord_Bin[i] vectors (intensity is not included) */ 
          for (i= 0; i < aVars->Coord_Number; i++)
          {
            j = Coord_Index[i+1];
            if (j >= 0 && j < aVars->Coord_Bin[i+1])
            {
              aVars->Mon2D_N[i][j]++;
              aVars->Mon2D_p[i][j] += pp;
              aVars->Mon2D_p2[i][j] += pp*pp;
            }
          }
        }
        else /* 2D case : aVars->Coord_Number==2 and !aVars->Flag_Multiple and !aVars->Flag_List */
        if ((aVars->Coord_Number == 2) && !aVars->Flag_Multiple)
        { /* Dim : aVars->Coord_Bin[1]*aVars->Coord_Bin[2] matrix */
          i = Coord_Index[1];
          j = Coord_Index[2];
          if (i >= 0 && i < aVars->Coord_Bin[1] && j >= 0 && j < aVars->Coord_Bin[2])
          {
            aVars->Mon2D_N[i][j]++;
            aVars->Mon2D_p[i][j] += pp;
            aVars->Mon2D_p2[i][j] += pp*pp;
          }
        } /* end store 2D/1D */
      } /* end while */
    } /* end Force Get Limits */

    if (aVars->Flag_Verbose) 
    {
      printf("Monitor_nD: %s is a %s.\n", aVars->compcurname, aVars->Monitor_Label);
      printf("Monitor_nD: version %s with options=%s\n", Monitor_nD_Version, aVars->option);
    }

    /* write oputput files (sent to file as p[i*n + j] vectors) */
    if (aVars->Coord_Number == 0) 
    {
      /* DETECTOR_OUT_0D(aVars->Monitor_Label, aVars->Nsum, aVars->psum, aVars->p2sum); */
      mcdetector_out_0D(aVars->Monitor_Label, aVars->Nsum, aVars->psum, aVars->p2sum, aVars->compcurname);
    }
    else
    if (strlen(aVars->Mon_File) > 0) 
    { 
      fname = (char*)malloc(strlen(aVars->Mon_File)+10*aVars->Coord_Number);
      if (aVars->Flag_List) /* List */
      {
        if (aVars->Flag_List == 2) aVars->Buffer_Size = aVars->Neutron_Counter;
        strcpy(fname,aVars->Mon_File);
        if (strchr(aVars->Mon_File,'.') == NULL) strcat(fname, "_list");

        min1d = 1; max1d = aVars->Coord_Number+2;
        min2d = 0; max2d = aVars->Buffer_Size; 
        bin1d = aVars->Coord_Number+2; bin2d = aVars->Buffer_Size;
        strcpy(Coord_X_Label,"");
        for (i= 1; i <= aVars->Coord_Number; i++)
        {
          if (min2d < aVars->Coord_Min[i]) min2d = aVars->Coord_Min[i];
          if (max2d < aVars->Coord_Max[i]) max2d = aVars->Coord_Max[i];
          strcat(Coord_X_Label, aVars->Coord_Var[i]);
          strcat(Coord_X_Label, " ");
          if (strchr(aVars->Mon_File,'.') == NULL)
                  { strcat(fname, "."); strcat(fname, aVars->Coord_Var[i]); }
        }
        strcat(Coord_X_Label, "I I_err");
        if (aVars->Flag_Verbose) printf("Monitor_nD: %s write monitor file %s List (%ix%li).\n", aVars->compcurname, fname,(aVars->Coord_Number+2),aVars->Buffer_Size);
        p0m = (int *)malloc((aVars->Coord_Number+2)*aVars->Buffer_Size*sizeof(int));
        p1m = (double *)malloc((aVars->Coord_Number+2)*aVars->Buffer_Size*sizeof(double));
        if (min2d == max2d) max2d = min2d+1e-6;
        if (min1d == max1d) max1d = min1d+1e-6;
        if (dofree == 0)
        {
          sprintf(label, "%s (%.2f %%)", aVars->Monitor_Label, 100*mcget_run_num()/mcget_ncount());
        }
        else
          strcpy(label, aVars->Monitor_Label);
        if (p1m == NULL) /* use Raw Buffer line output */
        {
          if (aVars->Flag_Verbose) printf("Monitor_nD: %s cannot allocate memory for transpose. Skipping.\n", aVars->compcurname);
          if (p0m != NULL) free(p0m);
          /*
          DETECTOR_OUT_2D(
            label,
            aVars->Coord_Label[0],
            Coord_X_Label,
            min2d, max2d, 
            min1d, max1d, 
            bin2d,
            bin1d,
            (int *)aVars->Mon2D_Buffer,aVars->Mon2D_Buffer,aVars->Mon2D_Buffer,
            fname); 
           */
           mcdetector_out_2D(
            label,
            aVars->Coord_Label[0],
            Coord_X_Label,
            min2d, max2d, 
            min1d, max1d, 
            bin2d,
            bin1d,
            (int *)aVars->Mon2D_Buffer,aVars->Mon2D_Buffer,aVars->Mon2D_Buffer,
            fname, aVars->compcurname); 
        
        }
        else /* transpose for column output */
        {
          for (i=0; i < aVars->Coord_Number+2; i++) 
            for (j=0; j < aVars->Buffer_Size; j++)
            {
              p1m[i*aVars->Buffer_Size+j] = aVars->Mon2D_Buffer[j*(aVars->Coord_Number+2) + i];
              p0m[i*aVars->Buffer_Size+j] = 1;
            }
            /* DETECTOR_OUT_2D(
              label,
              Coord_X_Label,
              aVars->Coord_Label[0],
              min1d, max1d, 
              min2d, max2d, 
              bin1d,
              bin2d,
              p0m,p1m,aVars->Mon2D_Buffer,
              fname); */
          mcdetector_out_2D(
              label,
              Coord_X_Label,
              aVars->Coord_Label[0],
              min1d, max1d, 
              min2d, max2d, 
              bin1d,
              bin2d,
              p0m,p1m,aVars->Mon2D_Buffer,
              fname, aVars->compcurname); 
          free(p0m);
          free(p1m);
        }
      }
      if (aVars->Flag_Multiple) /* n1D */
      {
        for (i= 0; i < aVars->Coord_Number; i++)
        {
          strcpy(fname,aVars->Mon_File);
          if (strchr(aVars->Mon_File,'.') == NULL)
                  { strcat(fname, "."); strcat(fname, aVars->Coord_Var[i+1]); }
          sprintf(Coord_X_Label, "%s monitor", aVars->Coord_Label[i+1]);
          if (dofree == 0)
          {
            sprintf(label, "%s (%.2f %%)", Coord_X_Label, 100*mcget_run_num()/mcget_ncount());
          }
          else
            strcpy(label, Coord_X_Label);
          if (aVars->Flag_Verbose) printf("Monitor_nD: %s write monitor file %s 1D (%i).\n", aVars->compcurname, fname, aVars->Coord_Bin[i+1]);
          min1d = aVars->Coord_Min[i+1];
          max1d = aVars->Coord_Max[i+1];
          if (min1d == max1d) max1d = min1d+1e-6;
          /*
          DETECTOR_OUT_1D(
            label,
            aVars->Coord_Label[i+1],
            aVars->Coord_Label[0],
            aVars->Coord_Var[i+1],
            min1d, max1d, 
            aVars->Coord_Bin[i+1],
            aVars->Mon2D_N[i],aVars->Mon2D_p[i],aVars->Mon2D_p2[i],
            fname); 
            */
            mcdetector_out_1D(
            label,
            aVars->Coord_Label[i+1],
            aVars->Coord_Label[0],
            aVars->Coord_Var[i+1],
            min1d, max1d, 
            aVars->Coord_Bin[i+1],
            aVars->Mon2D_N[i],aVars->Mon2D_p[i],aVars->Mon2D_p2[i],
            fname, aVars->compcurname); 
        }
      }
      else
      if (aVars->Coord_Number == 2)  /* 2D */
      {
        strcpy(fname,aVars->Mon_File);

        p0m = (int *)malloc(aVars->Coord_Bin[1]*aVars->Coord_Bin[2]*sizeof(int));
        p1m = (double *)malloc(aVars->Coord_Bin[1]*aVars->Coord_Bin[2]*sizeof(double));
        p2m = (double *)malloc(aVars->Coord_Bin[1]*aVars->Coord_Bin[2]*sizeof(double));

        if (p2m == NULL) 
        {
          if (aVars->Flag_Verbose) printf("Monitor_nD: %s cannot allocate memory for 2D array (%i). Skipping.\n", aVars->compcurname, 3*aVars->Coord_Bin[1]*aVars->Coord_Bin[2]*sizeof(double));
          if (p0m != NULL) free(p0m);
          if (p1m != NULL) free(p1m);
        }
        else
        {
          for (i= 0; i < aVars->Coord_Bin[1]; i++)
          {
            for (j= 0; j < aVars->Coord_Bin[2]; j++)
            {
              p0m[j + i*aVars->Coord_Bin[2]] = aVars->Mon2D_N[i][j];
              p1m[j + i*aVars->Coord_Bin[2]] = aVars->Mon2D_p[i][j];
              p2m[j + i*aVars->Coord_Bin[2]] = aVars->Mon2D_p2[i][j];
            }
          }
          if (strchr(aVars->Mon_File,'.') == NULL)
                  { strcat(fname, "."); strcat(fname, aVars->Coord_Var[1]);
              strcat(fname, "_"); strcat(fname, aVars->Coord_Var[2]); }
          if (aVars->Flag_Verbose) printf("Monitor_nD: %s write monitor file %s 2D (%ix%i).\n", aVars->compcurname, fname, aVars->Coord_Bin[1], aVars->Coord_Bin[2]);

          min1d = aVars->Coord_Min[1];
                max1d = aVars->Coord_Max[1];
                if (min1d == max1d) max1d = min1d+1e-6;
                min2d = aVars->Coord_Min[2];
                max2d = aVars->Coord_Max[2];
                if (min2d == max2d) max2d = min2d+1e-6;
                if (dofree == 0)
                {
                  sprintf(label, "%s (%.2f %%)", aVars->Monitor_Label, 100*mcget_run_num()/mcget_ncount());
                }
                else
                  strcpy(label, aVars->Monitor_Label);
                  /*
                DETECTOR_OUT_2D(
                  label,
                  aVars->Coord_Label[1],
                  aVars->Coord_Label[2],
                  min1d, max1d,  
                  min2d, max2d,  
                  aVars->Coord_Bin[1],
                  aVars->Coord_Bin[2],
                  p0m,p1m,p2m,
                  fname); */
                  
                mcdetector_out_2D(
                  label,
                  aVars->Coord_Label[1],
                  aVars->Coord_Label[2],
                  min1d, max1d,  
                  min2d, max2d,  
                  aVars->Coord_Bin[1],
                  aVars->Coord_Bin[2],
                  p0m,p1m,p2m,
                  fname, aVars->compcurname);

                if (p0m != NULL) free(p0m);
          if (p1m != NULL) free(p1m);
          if (p2m != NULL) free(p2m); 
        }
      }
      free(fname);
    }

    /* Now Free memory Mon2D.. */
    if ((aVars->Flag_Auto_Limits || aVars->Flag_List) && aVars->Coord_Number)
    { /* Dim : (aVars->Coord_Number+2)*aVars->Buffer_Block matrix (for p, dp) */ 
      if (aVars->Mon2D_Buffer != NULL && dofree) free(aVars->Mon2D_Buffer);
    }
       
    /* 1D and n1D case : aVars->Flag_Multiple */
    if (aVars->Flag_Multiple && aVars->Coord_Number && dofree)
    { /* Dim : aVars->Coord_Number*aVars->Coord_Bin[i] vectors */ 
      for (i= 0; i < aVars->Coord_Number; i++)
      { 
        free(aVars->Mon2D_N[i]);
        free(aVars->Mon2D_p[i]);
        free(aVars->Mon2D_p2[i]);
      }
      free(aVars->Mon2D_N);
      free(aVars->Mon2D_p);
      free(aVars->Mon2D_p2);
    }
    

    /* 2D case : aVars->Coord_Number==2 and !aVars->Flag_Multiple and !aVars->Flag_List */
    if ((aVars->Coord_Number == 2) && !aVars->Flag_Multiple && dofree)
    { /* Dim : aVars->Coord_Bin[1]*aVars->Coord_Bin[2] matrix */
      for (i= 0; i < aVars->Coord_Bin[1]; i++)
      { 
        free(aVars->Mon2D_N[i]);
        free(aVars->Mon2D_p[i]);
        free(aVars->Mon2D_p2[i]);
      }
      free(aVars->Mon2D_N); 
      free(aVars->Mon2D_p);
      free(aVars->Mon2D_p2);
    }
  }
  
void Monitor_nD_Init(aDEFS, aVars, m_xmin, m_xmax, m_ymin, m_ymax)
  MonitornD_Defines_type *aDEFS;
  MonitornD_Variables_type *aVars;
  double m_xmin, m_xmax, m_ymin, m_ymax;
  {
    long carg = 1;
    char *option_copy, *token;
    char Flag_New_Token = 1;
    char Flag_End       = 1;
    char Flag_All       = 0;
    char Flag_No        = 0;
    char Set_aVars_Coord_Type;
    char Set_Coord_Flag = 0;
    char Set_aVars_Coord_Label[30];
    char Set_aVars_Coord_Var[30];
    char Short_Label[MONnD_COORD_NMAX][30];
    char Set_Coord_Mode;
    long i=0;
    double lmin, lmax;
    long    t;
    
    t = (long)time(NULL);

    aDEFS->COORD_NONE   =0;
    aDEFS->COORD_X      =1;
    aDEFS->COORD_Y      =2;
    aDEFS->COORD_Z      =3;
    aDEFS->COORD_VX     =4;
    aDEFS->COORD_VY     =5;
    aDEFS->COORD_VZ     =6;
    aDEFS->COORD_T      =7;
    aDEFS->COORD_P      =8;
    aDEFS->COORD_SX     =9;
    aDEFS->COORD_SY     =10;
    aDEFS->COORD_SZ     =11;
    aDEFS->COORD_KX     =12;
    aDEFS->COORD_KY     =13;
    aDEFS->COORD_KZ     =14;
    aDEFS->COORD_K      =15;
    aDEFS->COORD_V      =16;
    aDEFS->COORD_ENERGY =17;
    aDEFS->COORD_LAMBDA =18;
    aDEFS->COORD_RADIUS =19;
    aDEFS->COORD_HDIV   =20;
    aDEFS->COORD_VDIV   =21;
    aDEFS->COORD_ANGLE  =22;
    aDEFS->COORD_NCOUNT =23;
    aDEFS->COORD_THETA  =24;
    aDEFS->COORD_PHI    =25;
    aDEFS->COORD_USER1  =26;
    aDEFS->COORD_USER2  =26;

/* token modifiers */
    aDEFS->COORD_VAR    =0;    /* next token should be a variable or normal option */
    aDEFS->COORD_MIN    =1;    /* next token is a min value */
    aDEFS->COORD_MAX    =2;    /* next token is a max value */
    aDEFS->COORD_DIM    =3;    /* next token is a bin value */
    aDEFS->COORD_FIL    =4;    /* next token is a filename */
    aDEFS->COORD_EVNT   =5;    /* next token is a buffer size value */
    aDEFS->COORD_3HE    =6;    /* next token is a 3He pressure value */
    aDEFS->COORD_INTERM =7;    /* next token is an intermediate save value (%) */

    strcpy(aDEFS->TOKEN_DEL, " =,;[](){}:");  /* token separators */

    aDEFS->SHAPE_SQUARE =0;    /* shape of the monitor */
    aDEFS->SHAPE_DISK   =1;
    aDEFS->SHAPE_SPHERE =2;
    aDEFS->SHAPE_CYLIND =3;

    aVars->Sphere_Radius     = 0;
    aVars->Cylinder_Height   = 0;
    aVars->Flag_With_Borders = 0;   /* 2 means xy borders too */
    aVars->Flag_List         = 0;   /* 1 store 1 buffer, 2 is list all */
    aVars->Flag_Multiple     = 0;   /* 1 when n1D, 0 for 2D */
    aVars->Flag_Verbose      = 0;
    aVars->Flag_Shape        = aDEFS->SHAPE_SQUARE;
    aVars->Flag_Auto_Limits  = 0;   /* get limits from first Buffer */
    aVars->Flag_Absorb       = 0;   /* monitor is also a slit */
    aVars->Flag_per_cm2      = 0;   /* flux is per cm2 */
    aVars->Coord_Number      = 0;   /* total number of variables to monitor, plus intensity (0) */
    aVars->Buffer_Block      = 1000;     /* Buffer size for list or auto limits */
    aVars->Neutron_Counter   = 0;   /* event counter, simulation total counts is mcget_ncount() */
    aVars->Buffer_Counter    = 0;   /* index in Buffer size (for realloc) */
    aVars->Buffer_Size       = 0;
    aVars->UserVariable1     = 0;
    aVars->UserVariable2     = 0;
    aVars->He3_pressure      = 0;
    aVars->IntermediateCnts = 0;
    
    Set_aVars_Coord_Type = aDEFS->COORD_NONE;
    Set_Coord_Mode = aDEFS->COORD_VAR;

    /* parse option string */ 
    
    option_copy = (char*)malloc(strlen(aVars->option));
    if (option_copy == NULL)
    {
      printf("Monitor_nD: %s cannot allocate option_copy (%i). Fatal.\n", aVars->compcurname, strlen(aVars->option));
      exit(-1);
    }
    
    
    if (strlen(aVars->option))
    {
      Flag_End = 0;
      strcpy(option_copy, aVars->option);
    }
    
    if (strstr(aVars->option, "cm2") || strstr(aVars->option, "cm^2")) aVars->Flag_per_cm2 = 1;
  
    if (aVars->Flag_per_cm2) strcpy(aVars->Coord_Label[0],"Intensity [n/cm^2/s]");
    else strcpy(aVars->Coord_Label[0],"Intensity [n/s]");
    strcpy(aVars->Coord_Var[0],"p");
    aVars->Coord_Type[0] = aDEFS->COORD_P;
    aVars->Coord_Bin[0] = 1;
    aVars->Coord_Min[0] = 0;
    aVars->Coord_Max[0] = FLT_MAX;
    
    /* default file name is comp name+dateID */
    sprintf(aVars->Mon_File, "%s_%i", aVars->compcurname, t); 
  
    carg = 1;
    while((Flag_End == 0) && (carg < 128))
    {
      if (Flag_New_Token) /* to get the previous token sometimes */
      {
        if (carg == 1) token=(char *)strtok(option_copy,aDEFS->TOKEN_DEL);
        else token=(char *)strtok(NULL,aDEFS->TOKEN_DEL);
        if (token == NULL) Flag_End=1;
      }
      Flag_New_Token = 1;
      if ((token != NULL) && (strlen(token) != 0))
      {
      /* first handle option values from preceeding keyword token detected */
        if (Set_Coord_Mode == aDEFS->COORD_MAX)
        { 
          if (!Flag_All) 
            aVars->Coord_Max[aVars->Coord_Number] = atof(token); 
          else
            for (i = 0; i <= aVars->Coord_Number; aVars->Coord_Max[i++] = atof(token));
          Set_Coord_Mode = aDEFS->COORD_VAR; Flag_All = 0;
        }
        if (Set_Coord_Mode == aDEFS->COORD_MIN)
        { 
          if (!Flag_All) 
            aVars->Coord_Min[aVars->Coord_Number] = atof(token); 
          else
            for (i = 0; i <= aVars->Coord_Number; aVars->Coord_Min[i++] = atof(token));
          Set_Coord_Mode = aDEFS->COORD_MAX; 
        }
        if (Set_Coord_Mode == aDEFS->COORD_DIM)
        { 
          if (!Flag_All) 
            aVars->Coord_Bin[aVars->Coord_Number] = atoi(token); 
          else
            for (i = 0; i <= aVars->Coord_Number; aVars->Coord_Bin[i++] = atoi(token));
          Set_Coord_Mode = aDEFS->COORD_VAR; Flag_All = 0;
        }
        if (Set_Coord_Mode == aDEFS->COORD_FIL)
        { 
          if (!Flag_No) strcpy(aVars->Mon_File,token); 
          else { strcpy(aVars->Mon_File,""); aVars->Coord_Number = 0; Flag_End = 1;}
          Set_Coord_Mode = aDEFS->COORD_VAR;
        }
        if (Set_Coord_Mode == aDEFS->COORD_EVNT)
        { 
          if (!strcmp(token, "all") || Flag_All) aVars->Flag_List = 2;
          else { i = atoi(token); if (i) aVars->Buffer_Counter = i; }
          Set_Coord_Mode = aDEFS->COORD_VAR; Flag_All = 0;
        }
        if (Set_Coord_Mode == aDEFS->COORD_3HE)
        { 
            aVars->He3_pressure = atof(token); 
            Set_Coord_Mode = aDEFS->COORD_VAR; Flag_All = 0; 
        }
        if (Set_Coord_Mode == aDEFS->COORD_INTERM)
        { 
            aVars->Intermediate = atof(token); 
            Set_Coord_Mode = aDEFS->COORD_VAR; Flag_All = 0; 
        }

        /* now look for general option keywords */
        if (!strcmp(token, "borders")) 
        { if (Flag_No) { aVars->Flag_With_Borders = 0; Flag_No = 0; }
          else aVars->Flag_With_Borders = 1; }
        if (!strcmp(token, "verbose")) 
        { if (Flag_No) { aVars->Flag_Verbose = 0; Flag_No = 0; }
          else aVars->Flag_Verbose      = 1; }
        if (!strcmp(token, "multiple")) 
        { if (Flag_No) { aVars->Flag_Multiple = 0; Flag_No = 0; }
          else aVars->Flag_Multiple = 1; }
        if (!strcmp(token, "list")) 
        { if (Flag_No) { aVars->Flag_List = 0; Flag_No = 0; }
          else aVars->Flag_List = 1; 
          Set_Coord_Mode = aDEFS->COORD_EVNT; }

        if (!strcmp(token, "limits") || !strcmp(token, "min")) Set_Coord_Mode = aDEFS->COORD_MIN;
        if (!strcmp(token, "slit") || !strcmp(token, "absorb")) 
        { if (Flag_No) { aVars->Flag_Absorb = 0; Flag_No = 0; }
          else aVars->Flag_Absorb = 1; }
        if (!strcmp(token, "max")) Set_Coord_Mode = aDEFS->COORD_MAX;
        if (!strcmp(token, "bins")) Set_Coord_Mode = aDEFS->COORD_DIM;
        if (!strcmp(token, "file")) 
        { Set_Coord_Mode = aDEFS->COORD_FIL;
          if (Flag_No) { strcpy(aVars->Mon_File,""); aVars->Coord_Number = 0; Flag_End = 1;}}
        if (!strcmp(token, "unactivate")) { Flag_End = 1; aVars->Coord_Number = 0; }
        if (!strcmp(token, "all")) 
        { if (Flag_No) { Flag_All = 0; Flag_No = 0; }
          else Flag_All = 1; }
        if (!strcmp(token, "sphere")) 
        { if (Flag_No) { aVars->Flag_Shape = aDEFS->SHAPE_SQUARE; Flag_No = 0; }
          else aVars->Flag_Shape = aDEFS->SHAPE_SPHERE; }
        if (!strcmp(token, "cylinder")) 
        { if (Flag_No) { aVars->Flag_Shape = aDEFS->SHAPE_SQUARE; Flag_No = 0; }
          else aVars->Flag_Shape = aDEFS->SHAPE_CYLIND; }
        if (!strcmp(token, "square")) aVars->Flag_Shape = aDEFS->SHAPE_SQUARE; 
        if (!strcmp(token, "disk")) aVars->Flag_Shape = aDEFS->SHAPE_DISK; 
        if (!strcmp(token, "auto")) 
        { if (Flag_No) { aVars->Flag_Auto_Limits = 0; Flag_No = 0; }
          else aVars->Flag_Auto_Limits = 1; }
        if (!strcmp(token, "premonitor"))
        { if (Flag_No) { aVars->Flag_UsePreMonitor = 0; Flag_No = 0; }
        else aVars->Flag_UsePreMonitor == 1; } 
        if (!strcmp(token, "3He_pressure"))
        { if (!Flag_No)  Set_Coord_Mode = aDEFS->COORD_3HE; 
          aVars->He3_pressure = 3; }
        if (!strcmp(token, "intermediate"))
        { if (!Flag_No)  Set_Coord_Mode = aDEFS->COORD_INTERM; 
          aVars->Intermediate = 5; }
        if (!strcmp(token, "no") || !strcmp(token, "not")) Flag_No = 1;
  
        /* now look for variable names to monitor */
        Set_aVars_Coord_Type = aDEFS->COORD_NONE; lmin = 0; lmax = 0;

        if (!strcmp(token, "x")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_X; strcpy(Set_aVars_Coord_Label,"x [m]"); strcpy(Set_aVars_Coord_Var,"x"); lmin = m_xmin; lmax = m_xmax; }
        if (!strcmp(token, "y")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_Y; strcpy(Set_aVars_Coord_Label,"y [m]"); strcpy(Set_aVars_Coord_Var,"y"); lmin = m_ymin; lmax = m_ymax; }
        if (!strcmp(token, "z")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_Z; strcpy(Set_aVars_Coord_Label,"z [m]"); strcpy(Set_aVars_Coord_Var,"z"); lmin = 0; lmax = 100; }
        if (!strcmp(token, "k") || !strcmp(token, "wavevector")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_K; strcpy(Set_aVars_Coord_Label,"|k| [Angs-1]"); strcpy(Set_aVars_Coord_Var,"k"); lmin = 0; lmax = 10; }
        if (!strcmp(token, "v"))
          { Set_aVars_Coord_Type = aDEFS->COORD_V; strcpy(Set_aVars_Coord_Label,"Velocity [m/s]"); strcpy(Set_aVars_Coord_Var,"v"); lmin = 0; lmax = 10000; }
        if (!strcmp(token, "t") || !strcmp(token, "time")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_T; strcpy(Set_aVars_Coord_Label,"TOF [s]"); strcpy(Set_aVars_Coord_Var,"t"); lmin = 0; lmax = .1; }
        if ((aVars->Coord_Number > 0) && (!strcmp(token, "p") || !strcmp(token, "intensity") || !strcmp(token, "flux")))
          { Set_aVars_Coord_Type = aDEFS->COORD_P;  
            if (aVars->Flag_per_cm2) strcpy(Set_aVars_Coord_Label,"Intensity [n/cm^2/s]");
            else strcpy(Set_aVars_Coord_Label,"Intensity [n/s]"); 
            strcpy(Set_aVars_Coord_Var,"I"); 
            lmin = 0; lmax = FLT_MAX; }

        if (!strcmp(token, "vx")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_VX; strcpy(Set_aVars_Coord_Label,"vx [m/s]"); strcpy(Set_aVars_Coord_Var,"vx"); lmin = -1000; lmax = 1000; }
        if (!strcmp(token, "vy")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_VY; strcpy(Set_aVars_Coord_Label,"vy [m/s]"); strcpy(Set_aVars_Coord_Var,"vy"); lmin = -1000; lmax = 1000; }
        if (!strcmp(token, "vz")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_VZ; strcpy(Set_aVars_Coord_Label,"vz [m/s]"); strcpy(Set_aVars_Coord_Var,"vz"); lmin = -10000; lmax = 10000; }
        if (!strcmp(token, "kx")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_KX; strcpy(Set_aVars_Coord_Label,"kx [Angs-1]"); strcpy(Set_aVars_Coord_Var,"kx"); lmin = -1; lmax = 1; }
        if (!strcmp(token, "ky")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_KY; strcpy(Set_aVars_Coord_Label,"ky [Angs-1]"); strcpy(Set_aVars_Coord_Var,"ky"); lmin = -1; lmax = 1; }
        if (!strcmp(token, "kz")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_KZ; strcpy(Set_aVars_Coord_Label,"kz [Angs-1]"); strcpy(Set_aVars_Coord_Var,"kz"); lmin = -10; lmax = 10; }
        if (!strcmp(token, "sx")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_SX; strcpy(Set_aVars_Coord_Label,"sx [1]"); strcpy(Set_aVars_Coord_Var,"sx"); lmin = -1; lmax = 1; }
        if (!strcmp(token, "sy")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_SY; strcpy(Set_aVars_Coord_Label,"sy [1]"); strcpy(Set_aVars_Coord_Var,"sy"); lmin = -1; lmax = 1; }
        if (!strcmp(token, "sz")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_SZ; strcpy(Set_aVars_Coord_Label,"sz [1]"); strcpy(Set_aVars_Coord_Var,"sz"); lmin = -1; lmax = 1; }

        if (!strcmp(token, "energy") || !strcmp(token, "omega")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_ENERGY; strcpy(Set_aVars_Coord_Label,"Energy [meV]"); strcpy(Set_aVars_Coord_Var,"E"); lmin = 0; lmax = 100; }
        if (!strcmp(token, "lambda") || !strcmp(token, "wavelength")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_LAMBDA; strcpy(Set_aVars_Coord_Label,"Wavelength [Angs]"); strcpy(Set_aVars_Coord_Var,"L"); lmin = 0; lmax = 100; }
        if (!strcmp(token, "radius")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_RADIUS; strcpy(Set_aVars_Coord_Label,"Radius [m]"); strcpy(Set_aVars_Coord_Var,"R"); lmin = 0; lmax = m_xmax; }
        if (!strcmp(token, "angle")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_ANGLE; strcpy(Set_aVars_Coord_Label,"Angle [deg]"); strcpy(Set_aVars_Coord_Var,"A"); lmin = -5; lmax = 5; }
        if (!strcmp(token, "hdiv")|| !strcmp(token, "divergence") || !strcmp(token, "xdiv") || !strcmp(token, "dx")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_HDIV; strcpy(Set_aVars_Coord_Label,"Hor. Divergence [deg]"); strcpy(Set_aVars_Coord_Var,"HD"); lmin = -5; lmax = 5; }
        if (!strcmp(token, "vdiv") || !strcmp(token, "ydiv") || !strcmp(token, "dy")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_VDIV; strcpy(Set_aVars_Coord_Label,"Vert. Divergence [deg]"); strcpy(Set_aVars_Coord_Var,"VD"); lmin = -5; lmax = 5; }
        if (!strcmp(token, "theta") || !strcmp(token, "longitude")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_THETA; strcpy(Set_aVars_Coord_Label,"Longitude [deg]"); strcpy(Set_aVars_Coord_Var,"th"); lmin = -180; lmax = 180; }
        if (!strcmp(token, "phi") || !strcmp(token, "lattitude")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_PHI; strcpy(Set_aVars_Coord_Label,"Lattitude [deg]"); strcpy(Set_aVars_Coord_Var,"ph"); lmin = -180; lmax = 180; }
        if (!strcmp(token, "ncounts")) 
          { Set_aVars_Coord_Type = aDEFS->COORD_NCOUNT; strcpy(Set_aVars_Coord_Label,"Neutrons [1]"); strcpy(Set_aVars_Coord_Var,"N"); lmin = 0; lmax = 1e10; }
              if (!strcmp(token, "user") || !strcmp(token, "user1"))
          { Set_aVars_Coord_Type = aDEFS->COORD_USER1; strncpy(Set_aVars_Coord_Label,aVars->UserName1,32); strcpy(Set_aVars_Coord_Var,"U1"); lmin = -1e10; lmax = 1e10; }
              if (!strcmp(token, "user2"))
          { Set_aVars_Coord_Type = aDEFS->COORD_USER2; strncpy(Set_aVars_Coord_Label,aVars->UserName2,32); strcpy(Set_aVars_Coord_Var,"U2"); lmin = -1e10; lmax = 1e10; }

        /* now stores variable keywords detected, if any */ 
        if (Set_aVars_Coord_Type != aDEFS->COORD_NONE)
        {
          if (aVars->Coord_Number < MONnD_COORD_NMAX) aVars->Coord_Number++;
          else if (aVars->Flag_Verbose) printf("Monitor_nD: %s reached max number of variables (%i).\n", aVars->compcurname, MONnD_COORD_NMAX);
          aVars->Coord_Type[aVars->Coord_Number] = Set_aVars_Coord_Type;
          strcpy(aVars->Coord_Label[aVars->Coord_Number], Set_aVars_Coord_Label); 
          strcpy(aVars->Coord_Var[aVars->Coord_Number], Set_aVars_Coord_Var);
          aVars->Coord_Min[aVars->Coord_Number] = lmin;
          aVars->Coord_Max[aVars->Coord_Number] = lmax;
          aVars->Coord_Bin[aVars->Coord_Number] = 20;
          Set_Coord_Mode = aDEFS->COORD_VAR;
          Flag_All = 0;
          Flag_No = 0;
        }
      carg++;
      } /* end if token */
    } /* end while carg */
    free(option_copy);
    if (carg == 128) printf("Monitor_nD: %s reached max number of tokens (%i). Skipping.\n", aVars->compcurname, 128);
    
    if (strstr(aVars->option,"unactivate") && aVars->Flag_Verbose)  printf("Monitor_nD: %s is unactivated (0D)\n", aVars->compcurname);

    /* now setting Monitor Name from variable labels */
    strcpy(aVars->Monitor_Label,"");
    for (i = 0; i <= aVars->Coord_Number; i++)
    {
      Set_aVars_Coord_Type = aVars->Coord_Type[i];
      if ((Set_aVars_Coord_Type == aDEFS->COORD_THETA)
       || (Set_aVars_Coord_Type == aDEFS->COORD_PHI)
       || (Set_aVars_Coord_Type == aDEFS->COORD_X)
       || (Set_aVars_Coord_Type == aDEFS->COORD_Y)
       || (Set_aVars_Coord_Type == aDEFS->COORD_Z)
       || (Set_aVars_Coord_Type == aDEFS->COORD_RADIUS))
       strcpy(Short_Label[i],"Position"); 
      else
      if ((Set_aVars_Coord_Type == aDEFS->COORD_VX)
       || (Set_aVars_Coord_Type == aDEFS->COORD_VY)
       || (Set_aVars_Coord_Type == aDEFS->COORD_VZ)
       || (Set_aVars_Coord_Type == aDEFS->COORD_V))
       strcpy(Short_Label[i],"Velocity"); 
      else
      if ((Set_aVars_Coord_Type == aDEFS->COORD_KX)
       || (Set_aVars_Coord_Type == aDEFS->COORD_KY)
       || (Set_aVars_Coord_Type == aDEFS->COORD_KZ)
       || (Set_aVars_Coord_Type == aDEFS->COORD_K))
       strcpy(Short_Label[i],"Wavevector"); 
      else
      if ((Set_aVars_Coord_Type == aDEFS->COORD_SX)
       || (Set_aVars_Coord_Type == aDEFS->COORD_SY)
       || (Set_aVars_Coord_Type == aDEFS->COORD_SZ))
       strcpy(Short_Label[i],"Spin");
      else
      if ((Set_aVars_Coord_Type == aDEFS->COORD_HDIV)
       || (Set_aVars_Coord_Type == aDEFS->COORD_VDIV)
       || (Set_aVars_Coord_Type == aDEFS->COORD_ANGLE))
       strcpy(Short_Label[i],"Divergence");
      else
      if (Set_aVars_Coord_Type == aDEFS->COORD_ENERGY)
       strcpy(Short_Label[i],"Energy"); 
      else
      if (Set_aVars_Coord_Type == aDEFS->COORD_LAMBDA)
       strcpy(Short_Label[i],"Wavelength"); 
      else
      if (Set_aVars_Coord_Type == aDEFS->COORD_NCOUNT)
       strcpy(Short_Label[i],"Neutron counts");
      else
      if (Set_aVars_Coord_Type == aDEFS->COORD_T)
          strcpy(Short_Label[i],"Time Of Flight");
      else
      if (Set_aVars_Coord_Type == aDEFS->COORD_P)
          strcpy(Short_Label[i],"Intensity");
      else
      if (Set_aVars_Coord_Type == aDEFS->COORD_USER1)
          strncpy(Short_Label[i],aVars->UserName1,32);
      else
      if (Set_aVars_Coord_Type == aDEFS->COORD_USER2)
          strncpy(Short_Label[i],aVars->UserName2,32);
      else
          strcpy(Short_Label[i],"Unknown"); 
          
      strcat(aVars->Monitor_Label, " ");
      strcat(aVars->Monitor_Label, Short_Label[i]);
    } /* end for Short_Label */
    strcat(aVars->Monitor_Label, " Monitor");
    if (aVars->Flag_Shape == aDEFS->SHAPE_SQUARE) strcat(aVars->Monitor_Label, " (Square)");
    if (aVars->Flag_Shape == aDEFS->SHAPE_DISK)   strcat(aVars->Monitor_Label, " (Disk)");
    if (aVars->Flag_Shape == aDEFS->SHAPE_SPHERE) strcat(aVars->Monitor_Label, " (Sphere)");
    if (aVars->Flag_Shape == aDEFS->SHAPE_CYLIND) strcat(aVars->Monitor_Label, " (Cylinder)");
    if (((aVars->Flag_Shape == aDEFS->SHAPE_CYLIND) || (aVars->Flag_Shape == aDEFS->SHAPE_SPHERE))
        && strstr(aVars->option, "outgoing"))
    {
      aVars->Flag_Shape *= -1;
      strcat(aVars->Monitor_Label, " [out]");
    }
    if (aVars->Flag_UsePreMonitor == 1)
    {
        strcat(aVars->Monitor_Label, " at ");
        strncat(aVars->Monitor_Label, aVars->UserName1,32);
    }
    
    /* aVars->Coord_Number  0   : intensity
     * aVars->Coord_Number  1:n : detector variables */
    
    /* now allocate memory to store variables in TRACE */
    if ((aVars->Coord_Number != 2) && !aVars->Flag_Multiple && !aVars->Flag_List) 
    { aVars->Flag_Multiple = 1; aVars->Flag_List = 0; } /* default is n1D */
    
   /* list and auto limits case : aVars->Flag_List or aVars->Flag_Auto_Limits 
    * -> Buffer to flush and suppress after aVars->Flag_Auto_Limits
    */
    if ((aVars->Flag_Auto_Limits || aVars->Flag_List) && aVars->Coord_Number)
    { /* Dim : (aVars->Coord_Number+2)*aVars->Buffer_Block matrix (for p, dp) */ 
      aVars->Mon2D_Buffer = (double *)malloc((aVars->Coord_Number+2)*aVars->Buffer_Block*sizeof(double));
      if (aVars->Mon2D_Buffer == NULL)
      { printf("Monitor_nD: %s cannot allocate aVars->Mon2D_Buffer (%li). No list and auto limits.\n", aVars->compcurname, aVars->Buffer_Block*(aVars->Coord_Number+2)*sizeof(double)); aVars->Flag_List = 0; aVars->Flag_Auto_Limits = 0; }
      aVars->Buffer_Size = aVars->Buffer_Block;
    }
    
    /* 1D and n1D case : aVars->Flag_Multiple */
    if (aVars->Flag_Multiple && aVars->Coord_Number)
    { /* Dim : aVars->Coord_Number*aVars->Coord_Bin[i] vectors */ 
      aVars->Mon2D_N  = (int **)malloc((aVars->Coord_Number)*sizeof(int *));
      aVars->Mon2D_p  = (double **)malloc((aVars->Coord_Number)*sizeof(double *));
      aVars->Mon2D_p2 = (double **)malloc((aVars->Coord_Number)*sizeof(double *));
      if ((aVars->Mon2D_N == NULL) || (aVars->Mon2D_p == NULL) || (aVars->Mon2D_p2 == NULL))
      { printf("Monitor_nD: %s n1D cannot allocate aVars->Mon2D_N/p/2p (%i). Fatal.\n", aVars->compcurname, (aVars->Coord_Number)*sizeof(double *)); exit(-1); }
      for (i= 1; i <= aVars->Coord_Number; i++)
      { 
        aVars->Mon2D_N[i-1]  = (int *)malloc(aVars->Coord_Bin[i]*sizeof(int));
        aVars->Mon2D_p[i-1]  = (double *)malloc(aVars->Coord_Bin[i]*sizeof(double));
        aVars->Mon2D_p2[i-1] = (double *)malloc(aVars->Coord_Bin[i]*sizeof(double));
        if ((aVars->Mon2D_N == NULL) || (aVars->Mon2D_p == NULL) || (aVars->Mon2D_p2 == NULL))
        { printf("Monitor_nD: %s n1D cannot allocate %s aVars->Mon2D_N/p/2p[%li] (%i). Fatal.\n", aVars->compcurname, aVars->Coord_Var[i], i, (aVars->Coord_Bin[i])*sizeof(double *)); exit(-1); }
      }
    }
    else /* 2D case : aVars->Coord_Number==2 and !aVars->Flag_Multiple and !aVars->Flag_List */
    if ((aVars->Coord_Number == 2) && !aVars->Flag_Multiple)
    { /* Dim : aVars->Coord_Bin[1]*aVars->Coord_Bin[2] matrix */ 
      aVars->Mon2D_N  = (int **)malloc((aVars->Coord_Bin[1])*sizeof(int *));
      aVars->Mon2D_p  = (double **)malloc((aVars->Coord_Bin[1])*sizeof(double *));
      aVars->Mon2D_p2 = (double **)malloc((aVars->Coord_Bin[1])*sizeof(double *));
      if ((aVars->Mon2D_N == NULL) || (aVars->Mon2D_p == NULL) || (aVars->Mon2D_p2 == NULL))
      { printf("Monitor_nD: %s 2D cannot allocate %s aVars->Mon2D_N/p/2p (%i). Fatal.\n", aVars->compcurname, aVars->Coord_Var[1], (aVars->Coord_Bin[1])*sizeof(double *)); exit(-1); }
      for (i= 0; i < aVars->Coord_Bin[1]; i++)
      { 
        aVars->Mon2D_N[i]  = (int *)malloc(aVars->Coord_Bin[2]*sizeof(int));
        aVars->Mon2D_p[i]  = (double *)malloc(aVars->Coord_Bin[2]*sizeof(double));
        aVars->Mon2D_p2[i] = (double *)malloc(aVars->Coord_Bin[2]*sizeof(double));
        if ((aVars->Mon2D_N == NULL) || (aVars->Mon2D_p == NULL) || (aVars->Mon2D_p2 == NULL))
        { printf("Monitor_nD: %s 2D cannot allocate %s aVars->Mon2D_N/p/2p[%li] (%i). Fatal.\n", aVars->compcurname, aVars->Coord_Var[1], i, (aVars->Coord_Bin[2])*sizeof(double *)); exit(-1); }
      }
    }      
      /* no Mon2D allocated for 
       * (aVars->Coord_Number != 2) && !aVars->Flag_Multiple && aVars->Flag_List */
    
    aVars->psum  = 0;
    aVars->p2sum = 0;
    aVars->Nsum  = 0;
    
    aVars->area  = (m_xmax - m_xmin)*(m_ymax - m_ymin)*1E4; /* in cm**2 for square shapes */
    aVars->Sphere_Radius = 0;
    if (fabs(m_xmin) > aVars->Sphere_Radius) aVars->Sphere_Radius = fabs(m_xmin);
    if (fabs(m_xmax) > aVars->Sphere_Radius) aVars->Sphere_Radius = fabs(m_xmax);
    if ((abs(aVars->Flag_Shape) == aDEFS->SHAPE_DISK) || (abs(aVars->Flag_Shape) == aDEFS->SHAPE_SPHERE))
    {
      if (fabs(m_ymin) > aVars->Sphere_Radius) aVars->Sphere_Radius = fabs(m_ymin);
      if (fabs(m_ymax) > aVars->Sphere_Radius) aVars->Sphere_Radius = fabs(m_ymax);
      aVars->area = PI*aVars->Sphere_Radius*aVars->Sphere_Radius; /* disk shapes */
    }
    aVars->Cylinder_Height = fabs(m_ymax-m_ymin);
    
    if (aVars->Intermediate < 0) aVars->Intermediate = 0;
    if (aVars->Intermediate > 1) aVars->Intermediate /= 100;
    aVars->IntermediateCnts = aVars->Intermediate*mcget_ncount();
  } 
  
void Monitor_nD_Trace(aDEFS, aVars)
  MonitornD_Defines_type *aDEFS;
  MonitornD_Variables_type *aVars;
{

  double  XY=0;
  double  t0 = 0;
  double  t1 = 0;
  long    i,j;
  double  pp;
  double  Coord[MONnD_COORD_NMAX];
  long    Coord_Index[MONnD_COORD_NMAX];
  char    While_End   =0;
  long    While_Buffer=0;
  int     intersect = 0;
  char    Set_aVars_Coord_Type = aDEFS->COORD_NONE;
  
  pp = aVars->cp;
  
  if (aVars->Coord_Number > 0)
    {
      /* aVars->Flag_Auto_Limits */
      if ((aVars->Buffer_Counter >= aVars->Buffer_Block) && (aVars->Flag_Auto_Limits == 1))
      {
        /* auto limits case : get limits in Buffer for each variable */ 
              /* Dim : (aVars->Coord_Number+2)*aVars->Buffer_Block matrix (for p, dp) */ 
        if (aVars->Flag_Verbose) printf("Monitor_nD: %s getting %i Auto Limits from List (%li).\n", aVars->compcurname, aVars->Coord_Number, aVars->Buffer_Counter);
        for (i = 1; i <= aVars->Coord_Number; i++)
        {
          aVars->Coord_Min[i] = FLT_MAX;
          aVars->Coord_Max[i] = -FLT_MAX;
          for (j = 0; j < aVars->Buffer_Block; j++)
          { 
                  XY = aVars->Mon2D_Buffer[j*(aVars->Coord_Number+2) + (i-1)];  /* scanning variables in Buffer */
            if (XY < aVars->Coord_Min[i]) aVars->Coord_Min[i] = XY;
            if (XY > aVars->Coord_Max[i]) aVars->Coord_Max[i] = XY;
          }
        }
        aVars->Flag_Auto_Limits = 2;  /* pass to 2nd auto limits step */
      }


      /* manage realloc for list all if Buffer size exceeded */
      if ((aVars->Buffer_Counter >= aVars->Buffer_Block) && (aVars->Flag_List == 2))
      {
        aVars->Mon2D_Buffer  = (double *)realloc(aVars->Mon2D_Buffer, (aVars->Coord_Number+2)*(aVars->Neutron_Counter+aVars->Buffer_Block)*sizeof(double));
        if (aVars->Mon2D_Buffer == NULL)
              { printf("Monitor_nD: %s cannot reallocate aVars->Mon2D_Buffer[%li] (%li). Skipping.\n", aVars->compcurname, i, (aVars->Neutron_Counter+aVars->Buffer_Block)*sizeof(double)); aVars->Flag_List = 1; }
        else { aVars->Buffer_Counter = 0; aVars->Buffer_Size = aVars->Neutron_Counter+aVars->Buffer_Block; }
      }

      while (!While_End)
      { /* we generate Coord[] and Coord_index[] from Buffer (auto limits) or passing neutron */
        if (aVars->Flag_Auto_Limits == 2)
        {
          if (While_Buffer < aVars->Buffer_Block)
          {
            /* first while loops (While_Buffer) */
            /* auto limits case : scan Buffer within limits and store in Mon2D */ 
            for (i = 1; i <= aVars->Coord_Number; i++)
            {
              /* scanning variables in Buffer */
              XY = (aVars->Coord_Max[i]-aVars->Coord_Min[i]);
              Coord[i] = aVars->Mon2D_Buffer[While_Buffer*(aVars->Coord_Number+2) + (i-1)];
              Coord[0] = aVars->Mon2D_Buffer[While_Buffer*(aVars->Coord_Number+2) + (aVars->Coord_Number)];
              pp = Coord[0];
              if (XY > 0) Coord_Index[i] = floor((aVars->Mon2D_Buffer[(i-1) + While_Buffer*(aVars->Coord_Number+2)]-aVars->Coord_Min[i])*aVars->Coord_Bin[i]/XY);
              else Coord_Index[i] = 0;
              if (aVars->Flag_With_Borders)
              {
                if (Coord_Index[i] < 0) Coord_Index[i] = 0;
                if (Coord_Index[i] >= aVars->Coord_Bin[i]) Coord_Index[i] = aVars->Coord_Bin[i] - 1;
              }
            } /* end for */
            While_Buffer++;
          } /* end if in Buffer */
          else /* (While_Buffer >= aVars->Buffer_Block) && (aVars->Flag_Auto_Limits == 2) */ 
          {
            aVars->Flag_Auto_Limits = 0;
            if (!aVars->Flag_List) /* free Buffer not needed (no list to output) */
            { /* Dim : (aVars->Coord_Number+2)*aVars->Buffer_Block matrix (for p, dp) */ 
              free(aVars->Mon2D_Buffer);
            }
          }
        }
        else /* aVars->Flag_Auto_Limits == 0 or 1 */
        {
          for (i = 0; i <= aVars->Coord_Number; i++)
          { /* handle current neutron : last while */

            pp = aVars->cp;

            XY = 0;
            Set_aVars_Coord_Type = aVars->Coord_Type[i];
            if (Set_aVars_Coord_Type == aDEFS->COORD_X) XY = aVars->cx; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_Y) XY = aVars->cy; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_Z) XY = aVars->cz; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_VX) XY = aVars->cvx; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_VY) XY = aVars->cvy; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_VZ) XY = aVars->cvz; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_KX) XY = V2K*aVars->cvx; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_KY) XY = V2K*aVars->cvy; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_KZ) XY = V2K*aVars->cvz; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_SX) XY = aVars->csx; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_SY) XY = aVars->csy; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_SZ) XY = aVars->csz; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_T) XY = aVars->ct; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_P) XY = pp; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_HDIV) XY = RAD2DEG*atan2(aVars->cvx,aVars->cvz); 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_VDIV) XY = RAD2DEG*atan2(aVars->cvy,aVars->cvz); 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_V) XY = sqrt(aVars->cvx*aVars->cvx+aVars->cvy*aVars->cvy+aVars->cvz*aVars->cvz); 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_RADIUS) XY = sqrt(aVars->cx*aVars->cx+aVars->cy*aVars->cy); 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_K) { XY = sqrt(aVars->cvx*aVars->cvx+aVars->cvy*aVars->cvy+aVars->cvz*aVars->cvz);  XY *= V2K; }
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_ENERGY) { XY = aVars->cvx*aVars->cvx+aVars->cvy*aVars->cvy+aVars->cvz*aVars->cvz;  XY *= VS2E; }
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_LAMBDA) { XY = sqrt(aVars->cvx*aVars->cvx+aVars->cvy*aVars->cvy+aVars->cvz*aVars->cvz);  XY *= V2K; if (XY != 0) XY = 2*PI/XY; }
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_NCOUNT) XY = Coord[i]+1; 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_ANGLE) 
            {  XY = sqrt(aVars->cvx*aVars->cvx+aVars->cvy*aVars->cvy+aVars->cvz*aVars->cvz);
               if (aVars->cvz != 0) 
               {
                 XY= RAD2DEG*atan2(XY,aVars->cvz);
               } else XY = 0;
            }
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_THETA)  { if (aVars->cz != 0) XY = RAD2DEG*atan2(aVars->cx,aVars->cz); } 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_PHI) { if (aVars->cz != 0) XY = RAD2DEG*atan2(aVars->cy,aVars->cz); } 
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_USER1) XY = aVars->UserVariable1;
                  else
            if (Set_aVars_Coord_Type == aDEFS->COORD_USER2) XY = aVars->UserVariable2;
                  else
            XY = 0;

            Coord[i] = XY;
            if (!aVars->Flag_Auto_Limits)
            {
              XY = (aVars->Coord_Max[i]-aVars->Coord_Min[i]);
              if (XY > 0) Coord_Index[i] = floor((Coord[i]-aVars->Coord_Min[i])*aVars->Coord_Bin[i]/XY);
              else Coord_Index[i] = 0;
              if (aVars->Flag_With_Borders)
              {
                if (Coord_Index[i] < 0) Coord_Index[i] = 0;
                if (Coord_Index[i] >= aVars->Coord_Bin[i]) Coord_Index[i] = aVars->Coord_Bin[i] - 1;
              }
            } /* else Auto_Limits will get Index later from Buffer */
          } /* end for i */
          While_End = 1;
        } /* end else if aVars->Flag_Auto_Limits == 2 */

        if (aVars->Flag_Auto_Limits != 2) /* not when reading auto limits Buffer */
        { /* now store Coord into Buffer (no index needed) if necessary */
          if ((aVars->Buffer_Counter < aVars->Buffer_Block) && ((aVars->Flag_List) || (aVars->Flag_Auto_Limits == 1)))
          {
            for (i = 0; i < aVars->Coord_Number; i++)
            {
              aVars->Mon2D_Buffer[i + aVars->Neutron_Counter*(aVars->Coord_Number+2)] = Coord[i+1];
            }
            aVars->Mon2D_Buffer[aVars->Coord_Number + aVars->Neutron_Counter*(aVars->Coord_Number+2)]   = pp;
            aVars->Mon2D_Buffer[(aVars->Coord_Number+1) + aVars->Neutron_Counter*(aVars->Coord_Number+2)] = pp*pp;
            aVars->Buffer_Counter++;
            if (aVars->Flag_Verbose && (aVars->Buffer_Counter >= aVars->Buffer_Block) && (aVars->Flag_List == 1)) printf("Monitor_nD: %s %li neutrons stored in List.\n", aVars->compcurname, aVars->Buffer_Counter);
          }
          aVars->Neutron_Counter++;
        } /* end (aVars->Flag_Auto_Limits != 2) */

        /* store n1d/2d section for Buffer or current neutron in while */

        if (aVars->Flag_Auto_Limits != 1) /* not when storing auto limits Buffer */
        {
        /* 1D and n1D case : aVars->Flag_Multiple */
          if (aVars->Flag_Multiple)
          { /* Dim : aVars->Coord_Number*aVars->Coord_Bin[i] vectors (intensity is not included) */ 
            for (i= 0; i < aVars->Coord_Number; i++)
            {
              j = Coord_Index[i+1];
              if (j >= 0 && j < aVars->Coord_Bin[i+1])
              {
                aVars->Mon2D_N[i][j]++;
                      aVars->Mon2D_p[i][j] += pp;
                      aVars->Mon2D_p2[i][j] += pp*pp;
              }
            }
          }
          else /* 2D case : aVars->Coord_Number==2 and !aVars->Flag_Multiple and !aVars->Flag_List */
          if ((aVars->Coord_Number == 2) && !aVars->Flag_Multiple)
          { /* Dim : aVars->Coord_Bin[1]*aVars->Coord_Bin[2] matrix */
            i = Coord_Index[1];
            j = Coord_Index[2];
            if (i >= 0 && i < aVars->Coord_Bin[1] && j >= 0 && j < aVars->Coord_Bin[2])
            {
              aVars->Mon2D_N[i][j]++;
              aVars->Mon2D_p[i][j] += pp;
              aVars->Mon2D_p2[i][j] += pp*pp;
            }
          }
        } /* end (aVars->Flag_Auto_Limits != 1) */
      } /* end while */
    } /* end if aVars->Coord_Number */
  }
  
#endif
  
  MonitornD_Defines_type DEFS;
  MonitornD_Variables_type Vars;

%}

INITIALIZE
%{

strcpy(Vars.compcurname, mccompcurname);
strcpy(Vars.option, options);

Monitor_nD_Init(&DEFS, &Vars, xmin, xmax, ymin, ymax);

%}
TRACE
%{    
  double  XY=0;
  double  t0 = 0;
  double  t1 = 0;
  long    i,j;
  double  pp;
  double  Coord[MONnD_COORD_NMAX];
  long    Coord_Index[MONnD_COORD_NMAX];
  char    While_End   =0;
  long    While_Buffer=0;
  int     intersect = 0;
  char    Set_Vars_Coord_Type = DEFS.COORD_NONE;

  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SQUARE) /* square xy */
    intersect = (x>=xmin && x<=xmax && y>=ymin && y<=ymax);
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK)   /* disk xy */
    intersect = ((x*x + y*y) <= Vars.Sphere_Radius*Vars.Sphere_Radius);
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) /* sphere */
  {
    intersect = sphere_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius);
  /*      intersect = (intersect && t0 > 0); */
  }
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) /* cylinder */
  {
    intersect = cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius, Vars.Cylinder_Height);
  }

  if (intersect)
  {
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND))
    {
      if (t0 < 0 && t1 > 0)
        t0 = 0;  /* neutron was already inside ! */
      if (t1 < 0 && t0 > 0)
        t1 = 0;
      /* t0 is now time of incoming intersection with the sphere. */
      if ((Vars.Flag_Shape < 0) && (t1 > 0))
        PROP_DT(t1); /* t1 outgoing beam */
      else
        PROP_DT(t0); /* t0 incoming beam */
    }
    else
      PROP_Z0; 

    /* Now get the data to monitor: curent or keep from PreMonitor */
    if (Vars.Flag_UsePreMonitor != 1)
    {
      Vars.cp = p;
      Vars.cx = x;
      Vars.cvx = vx;
      Vars.csx = sx;
      Vars.cy = y;
      Vars.cvy = vy;
      Vars.csy = sy;
      Vars.cz = z;
      Vars.cvz = vz;
      Vars.csz = sz;
      Vars.ct = t;
    }

    if ((Vars.He3_pressure > 0) && (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND))
    {
      XY = exp(-7.417*Vars.He3_pressure*fabs(t1-t0)*2*PI/V2K);
      /* will monitor the absorbed part */
      Vars.cp *= 1-XY;
      /* and modify the neutron weight after monitor, only remains 1-p_detect */
      p *= XY;
    }

    if (Vars.Flag_per_cm2 && Vars.area != 0) Vars.cp /= Vars.area;
    Vars.Nsum++;
    Vars.psum += Vars.cp;
    Vars.p2sum += Vars.cp*Vars.cp;

    Monitor_nD_Trace(&DEFS, &Vars);
    
    /* now handles intermediate results saving */
    if ((Vars.Intermediate > 0) && (mcget_run_num() > Vars.IntermediateCnts))
    {
      Vars.IntermediateCnts += Vars.Intermediate*mcget_ncount();
      /* save results, but do not free pointers */
      Monitor_nD_OutPut(&DEFS, &Vars, 0);
      
    }
    
  } /* end if intersection */
  else if (Vars.Flag_Absorb) ABSORB;
  
 %}
 
FINALLY
 %{
    /* save results, and free pointers */
    Monitor_nD_OutPut(&DEFS, &Vars, 1);
%}

MCDISPLAY
%{
  double radius, h;
  
  radius = Vars.Sphere_Radius;
  h = Vars.Cylinder_Height;
  
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE)
  {
    magnify("");
    circle("xy",0,0,0,radius);
    circle("xz",0,0,0,radius);
    circle("yz",0,0,0,radius);
  }
  else
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK)
  {
    magnify("");
    circle("xy",0,0,0,radius);
  }
  else
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SQUARE)
  {
    magnify("xy");
    multiline(5, (double)xmin, (double)ymin, 0.0,
           (double)xmax, (double)ymin, 0.0,
           (double)xmax, (double)ymax, 0.0,
           (double)xmin, (double)ymax, 0.0,
           (double)xmin, (double)ymin, 0.0);
  }
  else
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND)
  {
    magnify("xyz");
    circle("xz", 0,  h/2.0, 0, radius);
    circle("xz", 0, -h/2.0, 0, radius);
    line(-radius, -h/2.0, 0, -radius, +h/2.0, 0);
    line(+radius, -h/2.0, 0, +radius, +h/2.0, 0);
    line(0, -h/2.0, -radius, 0, +h/2.0, -radius);
    line(0, -h/2.0, +radius, 0, +h/2.0, +radius);
  }
%}

END