/*******************************************************************************
*
* McXtrace, x-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: DivE_monitor
*
* %Identification
* Written by: Erik B Knudsen
* Based on neutron component by Kristian Nielsen
* Date: Jun. 2016
* Origin: DTU Physics
*
* Divergence/Energy monitor.
*
* %Description
* 2D detector for intensity as a function of both horizontal divergence
* and Energy.
*
* Example: DivE_monitor(nE=20, nh=20, filename="Output.div",
*           xwidth=0.1, yheight=0.1,
*           maxdiv_h=2, Emin=2, Emax=10)
*
* %Parameters
* INPUT PARAMETERS:
*
* xwidth:  [m] Width of detector. 
* yheight: [m] Height of detector. 
* nE:      [1] Number of bins in energy
* nh:      [1] Number of bins in divergence
* nx:      [1]
* ny:      [1] Vector definition of "forward" direction wrt. divergence, to be used e.g. when the monitor is rotated into the horizontal plane.
* nz:      [1] 
* maxdiv_h: [deg] Maximal horizontal divergence detected
* Emin:    [keV] Minimum energy detected
* Emax:    [keV] Maximum energy detected
* filename: [str] Name of file in which to store the detector image
* restore_xray: [1] If set, the monitor does not influence the photon state
* nowritefile: [1]  If set, monitor will skip writing to disk.
*
* %End
*******************************************************************************/

DEFINE COMPONENT DivE_monitor
DEFINITION PARAMETERS ()
SETTING PARAMETERS (int nE=20, int nh=20, string filename=0, xwidth=0.1, yheight=0.1, 
  maxdiv_h=2, Emin, Emax, restore_xray=0, nx=0, ny=0, nz=1, int nowritefile=0)
OUTPUT PARAMETERS ()
/* X-ray  parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 

DECLARE
%{
  DArray2d DivE_N;
  DArray2d DivE_p;
  DArray2d DivE_p2;
  double xmin;
  double xmax;
  double ymin;
  double ymax;
%}

INITIALIZE
%{
    int i,j;

    xmax = xwidth/2;  xmin = -xmax;
    ymax = yheight/2; ymin = -ymax;

    if ((xmin >= xmax) || (ymin >= ymax)) {
      printf("ERROR: (%s): Null detection area! Exiting.\n",NAME_CURRENT_COMP);
      exit(-1);
    }
    DivE_N = create_darr2d(nE, nh);
    DivE_p = create_darr2d(nE, nh);
    DivE_p2 = create_darr2d(nE, nh);
    NORM(nx,ny,nz);

    // Use instance name for monitor output if no input was given
    if (!strcmp(filename,"\0")) sprintf(filename,"%s",NAME_CURRENT_COMP);
%}

TRACE
%{
    int i,j;
    double div;
    double e;
    double k, kn;

    PROP_Z0;
    e = K2E*sqrt(kx*kx + ky*ky + kz*kz);
    if (x>xmin && x<xmax && y>ymin && y<ymax &&
        e > Emin && e < Emax)
    {
      /* Find length of projection onto the [nx ny nz] axis */
      kn = scalar_prod(kx, ky, kz, nx, ny, nz);
      div = RAD2DEG*atan2(kx,kn);

      if (div < maxdiv_h && div > -maxdiv_h)
      {
        i = floor((e -Emin)*nE/(Emax - Emin));
        j = floor((div + maxdiv_h)*nh/(2.0*maxdiv_h));
        DivE_N[i][j]++;
        DivE_p[i][j] += p;
        DivE_p2[i][j] += p*p;
        SCATTER;
      }
    }
    if (restore_xray) {
        RESTORE_XRAY(INDEX_CURRENT_COMP, x, y, z, kx, ky, kz, phi, t, Ex, Ey, Ez, p);
    }
%}

SAVE
%{
  if(!nowritefile){
    DETECTOR_OUT_2D(
        "Energy-divergence monitor",
        "Energy [keV]",
        "divergence [deg]",
        Emin, Emax, -maxdiv_h, maxdiv_h,
        nE, nh,
        &DivE_N[0][0],&DivE_p[0][0],&DivE_p2[0][0],
        filename);
  }
%}

FINALLY
%{
  destroy_darr2d(DivE_N);
  destroy_darr2d(DivE_p);
  destroy_darr2d(DivE_p2);
%}

MCDISPLAY
  %{
    
    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);
%}

END
