/*--------------------------------------------------------------------------
         
                             N X A M O R

  Routines for writing NeXus files for the reflectometer AMOR at PSI.

  copyright: see copyright.h


  Mark Koennecke, September 1999
  Updated, Mark Koennecke, August 2001
  Updated to store TOF-monitor, Mark Koennecke, September 2002
--------------------------------------------------------------------------*/
 
#include <stdlib.h>
#include <assert.h>
#include "fortify.h"
#include "sics.h"
#include "nxdict.h"
#include "nxutil.h"
#include "scan.h"
#include "scan.i"
#include "HistMem.h"
#include "counter.h"
#include "nxamor.h"
#include "obpar.h"
#include "motor.h"
#include "status.h"

#define MAXMOT 13 /* must be same as in amor2t.c */
#include "amor2t.i"
#include "amor2t.h"

/* some defines for some names */
#define AMORDICT "amor.dic"
#define INSTNAME "AMOR at SINQ, PSI"
#define SOURCENAME "Spallation source SINQ"
#define SOURCETYPE "Continous flux spallation source"
#define CHOPPERNAME "Dornier Chopper System"

/*
  The rough size of each detector chunk to write in TOF mode
  (currently 16MB)
#define TOFBLOCK 8192000
*/
#define TOFBLOCK 16384000

/*
  a pointer to amor2t which we need for a couple of parameters
*/
pAmor2T pAmor = NULL;

/*
  if to save psd data in TOF mode or not. This is in order to save time
  when measureing TOF with a single detector only.
*/

static int psdSave = 1;

/*------------------------------------------------------------------------*/
  static void WriteDiaphragm(NXhandle hfil, NXdict hdict, int i, 
                             SConnection *pCon)
  {
    char pThing[30];


    sprintf(pThing,"d%1.1dt",i);
    SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,pThing,pThing);
    sprintf(pThing,"d%1.1db",i);
    SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,pThing,pThing);
    sprintf(pThing,"d%1.1dl",i);
    SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,pThing,pThing);
    sprintf(pThing,"d%1.1dr",i);
    SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,pThing,pThing);
  }
/*----------------------------------------------------------------------*/
  int WriteAmorHeader(char *file, SConnection *pCon)
  {
       NXhandle hfil;
       NXdict hdict;
       int iRet;
       char pBueffel[512], pThing[80];
       CounterMode eMode;
       CommandList *pCom = NULL;
       float fVal;

       /* open files */
       NXsetcache(TOFBLOCK);
       iRet = NXopen(file,NXACC_CREATE5,&hfil);
       if(iRet != NX_OK)
       {
	   sprintf(pBueffel,"ERROR: cannot open file %s for writing",file);
           SCWrite(pCon,pBueffel,eError);
           return 0;
       }
       iRet = NXDinitfromfile(AMORDICT,&hdict);
       if(iRet != NX_OK)
       {
	   sprintf(pBueffel,"ERROR: cannot open dictionary file %s",AMORDICT);
           SCWrite(pCon,pBueffel,eError);
           return 0;
       }
 
       /* put some global information */
       SNXSPutGlobals(hfil,file,"AMOR",pCon);
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"etitle","title");
       SNXFormatTime(pBueffel,512);
       NXDputalias(hfil,hdict,"estart",pBueffel);

       /* instrument vGroup */
       NXDputalias(hfil,hdict,"iname",INSTNAME);

       /* source */
       NXDputalias(hfil,hdict,"sname",SOURCENAME);
       NXDputalias(hfil,hdict,"stype",SOURCETYPE);

       /* chopper */
       NXDputalias(hfil,hdict,"cname",CHOPPERNAME);
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"crot",
                       "chopperrotation");

       /* frame overlap mirror */
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"fomname",
                       "fomname");
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"fodist",
                       "fomdist");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"fomh","ftz");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"fomom","fom");

       /* first Diaphragm */
       WriteDiaphragm(hfil,hdict,1,pCon);
       sprintf(pThing,"d%1.1ddist",1);
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,pThing,pThing);

       /* polarizing, monochromating mirror */
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"polname",
                       "polname");
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"poldist",
                       "poldist");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"polz","moz");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"polom","mom");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"poly","mty");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"polzom","mtz");

       /* second Diaphragm */
       WriteDiaphragm(hfil,hdict,2,pCon);
       sprintf(pThing,"d%1.1ddist",2);
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,pThing,pThing);

       /* third Diaphragm */
       WriteDiaphragm(hfil,hdict,3,pCon);
       sprintf(pThing,"d%1.1ddist",3);
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,pThing,pThing);

       /* sample table */
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"saname",
                       "sample");
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"stdist",
                       "sampledist");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"somheight","stz");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"schi","sch");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"somega","som");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"stheight","soz");
       fVal = ObVal(pAmor->aParameter,PARDH);
       NXDputalias(hfil,hdict,"baseheight",&fVal);
       

       /* fourth Diaphragm */
       WriteDiaphragm(hfil,hdict,4,pCon);
       fVal = ObVal(pAmor->aParameter,PARDD4);
       NXDputalias(hfil,hdict,"d4dist",&fVal);
       fVal = ObVal(pAmor->aParameter,PARD4H);
       NXDputalias(hfil,hdict,"d4base",&fVal);
      
       /* analyzer */
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"anname",
                       "ananame");
       SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"andist",
                       "anadist");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"anoz","atz");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"anom","aom");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"antz","aoz");
       fVal = ObVal(pAmor->aParameter,PARADIS);
       NXDputalias(hfil,hdict,"adis",&fVal);
       fVal = ObVal(pAmor->aParameter,PARANA);
       NXDputalias(hfil,hdict,"abase",&fVal);


       /* fifth Diaphragm!!!!!!!!! */
       WriteDiaphragm(hfil,hdict,5,pCon);
       fVal = ObVal(pAmor->aParameter,PARDD5);
       NXDputalias(hfil,hdict,"d5dist",&fVal);
       fVal = ObVal(pAmor->aParameter,PARD5H);
       NXDputalias(hfil,hdict,"d5base",&fVal);
       
       /* counting data */
       pCom = FindCommand(pServ->pSics,"counter");
       if(pCom)
       {
         if(pCom->pData)
	 {
            eMode = GetCounterMode((pCounter)pCom->pData);
            if(eMode == eTimer)
            {
              strcpy(pBueffel,"timer");
            }           
            else
            {
              strcpy(pBueffel,"monitor");
            }
            NXDputalias(hfil,hdict,"cnmode",pBueffel);
            fVal = GetCounterPreset((pCounter)pCom->pData);
            NXDputalias(hfil,hdict,"cnpreset",&fVal);
	 }       
       }
       else
       {
           SCWrite(pCon,"WARNING: failed to find counter!",eWarning);
       }
       NXclose(&hfil);
       NXDclose(hdict,NULL);

       return 1;      
  }
/*------------------------------------------------------------------------*/
  int WriteAmorScan(char *file, SConnection *pCon, pScanData pScan)
  {
       NXhandle hfil;
       NXdict hdict;
       int iRet, i;
       char pBueffel[512], pDefinition[1024];
       CommandList *pCom = NULL;
       float fVal;
       float *fAxis = NULL;
       long *lData  = NULL;
       int  *iData  = NULL;

       /* open files */
       iRet = NXopen(file,NXACC_RDWR,&hfil);
       if(iRet != NX_OK)
       {
	   sprintf(pBueffel,"ERROR: cannot open file %s for writing",file);
           SCWrite(pCon,pBueffel,eError);
           return 0;
       }
       iRet = NXDinitfromfile(AMORDICT,&hdict);
       if(iRet != NX_OK)
       {
	   sprintf(pBueffel,"ERROR: cannot open dictionary file %s",AMORDICT);
           SCWrite(pCon,pBueffel,eError);
           return 0;
       }


       /* allocate memory for writing scan data */
       fAxis = (float *)malloc(pScan->iNP*sizeof(float));       
       lData = (long *)malloc(pScan->iNP*sizeof(long));
       iData = (int *)malloc(pScan->iNP*sizeof(int));
       if( (!fAxis) || (!lData) || (!iData) )
       {
          SCWrite(pCon,"ERROR: out of memory in WriteAmorScan",eError);
          return 0;
       }       
       memset(fAxis,0,pScan->iNP*sizeof(float));
       memset(lData,0,pScan->iNP*sizeof(long));
       memset(iData,0,pScan->iNP*sizeof(int));

       /* write scan variables */
       for(i = 0; i < pScan->iScanVar; i++)
       {
	 /* build definition string */
          NXDget(hdict,"scanroot",pBueffel, 512);
          strcpy(pDefinition,pBueffel);
          strcat(pDefinition,"  ");
          GetScanVarName(pScan,i,pBueffel,512);
          strcat(pDefinition,pBueffel);
          sprintf(pBueffel," -rank 1 -dim {%d} ", pScan->iNP);
          strcat(pDefinition,pBueffel);
          if(i == 0)
          {
            strcat(pDefinition," -attr {axis,1}");
          }
          /* get data and write */
          GetScanVar(pScan,i,fAxis,pScan->iNP);
          NXDputdef(hfil,hdict,pDefinition,fAxis);
          if(i == 0)
          {
             NXDget(hdict,"sdana",pBueffel,512);
             NXDdeflink(hfil,hdict,pBueffel,pDefinition);
          }
       }

       /* 
          Write counted data: Here there is a convention which has to be
          valid in amorscan as well:  GetCounts gets the main detector.
          GetMonitor 0 the second detector, GetMonitor 1 the first detector
          other spin, GetMonitor 2, the second detector the other spin,
          getMonitor 3, the first monitor, getMonitor 4 the second monitor
        */
       sprintf(pBueffel,"%d",pScan->iNP);
       NXDupdate(hdict,"scanlength",pBueffel);
       GetScanCounts(pScan,lData,pScan->iNP);
       for(i = 0; i < pScan->iNP; i++)
       {
          iData[i] = (int)lData[i];
       }
       NXDputalias(hfil,hdict, "spinupup",iData);
       NXDaliaslink(hfil,hdict,"sdana","spinupup");
       GetScanMonitor(pScan,0,lData,pScan->iNP);
       for(i = 0; i < pScan->iNP; i++)
       {
          iData[i] = (int)lData[i];
       }
       NXDputalias(hfil,hdict, "spinuplo",iData);
       NXDaliaslink(hfil,hdict,"sdana","spinuplo");

       /* monitors */
       GetScanMonitor(pScan,3,lData,pScan->iNP);
       for(i = 0; i < pScan->iNP; i++)
       {
          iData[i] = (int)lData[i];
       }
       NXDputalias(hfil,hdict, "smonitor1",iData);
       GetScanMonitor(pScan,4,lData,pScan->iNP);
       for(i = 0; i < pScan->iNP; i++)
       {
          iData[i] = (int)lData[i];
       }
       NXDputalias(hfil,hdict, "smonitor2",iData);

       /* to be added: polarizing mode, possibly coz, cox, com etc. */
              
       /* a few motors which may or may not be useful */
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"sdetx","cox");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"sdetom","com");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"sdetheight","coz");
       
       /* close and go */
       NXclose(&hfil);
       NXDclose(hdict,NULL);
       free(fAxis);
       free(lData);
       free(iData); 

       return 1;      
  }
/*-----------------------------------------------------------------------
  WriteTOFDetector writes the histogram memory data in TOF mode. As 
  the histogram memory can become quite large at AMOR, the data is
  read and stored in chunks if it is to big. All this is handled
  in this routine.
  -------------------------------------------------------------------------*/
static int WriteTOFDetector(char *name, pHistMem pHM, int *iDim,
                            NXhandle hfil, NXdict hdict, 
                            SConnection *pCon)
{
  int iLength, nChunk, chunkSize, iChunk[3], i, iStart[3];
  HistInt *lData = NULL;
  char pBueffel[132];

  iLength = iDim[0]*iDim[1]*iDim[2];
  if( (iLength*4) < TOFBLOCK)
  {
     sprintf(pBueffel," -chunk {%d,%d,%d} ",iDim[0], iDim[1], iDim[2]);
     NXDupdate(hdict,"chunk",pBueffel);
     lData = (HistInt *)malloc(iLength*sizeof(HistInt));
     if(!lData)
     {
	 SCWrite(pCon,
		    "ERROR: out of memory, failed to write histogram",eError);
		 return 0;
      }
      memset(lData,0,iLength*sizeof(HistInt));
      GetHistogramDirect(pHM,pCon, 
		 0,0,iLength,lData,iLength*sizeof(HistInt));
      NXDputalias(hfil,hdict,name,lData);
      NXDputalias(hfil,hdict,"detchunk",iDim);
      NXDaliaslink(hfil,hdict,"dana",name);
  }
  else
  {
    /*
      implement chunked writing. We strive to write layers in Y. The 
      number of chunks needs to fulfill three conditions then:
      - multiple of xSize* timeBin;
      - close to TOFBLOCK in size
      - divide Y without remainder. 
    */
    iChunk[0] = iDim[0];
    iChunk[2] = iDim[2];
    iChunk[1] = 1;
    chunkSize = iDim[0]*iDim[2];
    for(i = 1; i < 64; i++)
    {
      if( (iDim[1] % i) == 0)
      {
	if(i*chunkSize*sizeof(HistInt) > TOFBLOCK)
	{
	  iChunk[1] = i;
	  break;
        }
      }
    }
    sprintf(pBueffel,"Segmented TOF data in %d chunks",iDim[1]/iChunk[1]);
    SCWrite(pCon,pBueffel,eWarning);
    /*
       now we have a chunkSize, lets go and write!
    */
    NXDputalias(hfil,hdict,"detchunk",iChunk);
    chunkSize = iChunk[1]*iChunk[0]*iChunk[2];
    sprintf(pBueffel," -chunk {%d,%d,%d} ",iChunk[0], iChunk[1], iChunk[2]);
    NXDupdate(hdict,"chunk",pBueffel);
    lData = (HistInt *)malloc(chunkSize*sizeof(HistInt));
    if(!lData)
    {
      SCWrite(pCon,"ERROR: out of memory while writing TOF data",
	      eError);
      return 0;
    }
    NXDopenalias(hfil,hdict,name);
    for(i = 0; i < iDim[1]/iChunk[1]; i++)
    {
      memset(lData,0,chunkSize*sizeof(HistInt));
      GetHistogramDirect(pHM,pCon, 
		 0,i*chunkSize,chunkSize,lData,chunkSize*sizeof(HistInt));
      /*
	yield a little in order to allow other clients to receive a
        response. Also allow for interrupting.
      */
      SicsWait(2);
      if(SCGetInterrupt(pCon) != eContinue)
      {
	SCWrite(pCon,
		"ERROR: dataset writing interrupted, data probably corrupted",
		eError);
	return 0;
      }

      iStart[0] = 0;
      iStart[1] = i*iChunk[1];
      iStart[2] = 0;
      NXputslab(hfil,lData,iStart, iChunk);
      sprintf(pBueffel,"Wrote chunk %d", i);
      SCWrite(pCon,pBueffel,eWarning);
      /*
	yield a little in order to allow other clients to receive a
        response. Also allow for interrupting.
      */
      SicsWait(2);
      if(SCGetInterrupt(pCon) != eContinue)
      {
	SCWrite(pCon,
		"ERROR: dataset writing interrupted, data probably corrupted",
		eError);
	return 0;
      }
    }
    /*
     close groups till root
    */
    NXclosedata(hfil);
    NXclosegroup(hfil);
    NXclosegroup(hfil);
    NXclosegroup(hfil);

    /*
      make link
    */
    NXDaliaslink(hfil,hdict,"dana",name);
    NXDaliaslink(hfil,hdict,"dana","detchunk");

  }
    if(lData)
      free(lData);
}
/*-----------------------------------------------------------------------*/
  int WriteAmorTOF(char *file, SConnection *pCon, pHistMem pHM)
  {
       NXhandle hfil;
       NXdict hdict;
       int iRet, i, iLength;
       char pBueffel[512];
       float fVal, *fAxis = NULL, *fTime2 = NULL;
       CommandList *pCom = NULL;
       const float *fTime;
       HistInt *lData = NULL, lVal;
       int detxsize, detysize, iDim[MAXDIM]; 


       /* open files */
       iRet = NXopen(file,NXACC_RDWR,&hfil);
       if(iRet != NX_OK)
       {
	   sprintf(pBueffel,"ERROR: cannot open file %s for writing",file);
           SCWrite(pCon,pBueffel,eError);
           return 0;
       }
       iRet = NXDinitfromfile(AMORDICT,&hdict);
       if(iRet != NX_OK)
       {
	   sprintf(pBueffel,"ERROR: cannot open dictionary file %s",AMORDICT);
           SCWrite(pCon,pBueffel,eError);
           return 0;
       }


       /* a few motors which may or may not be useful */
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"detx","cox");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"detom","com");
       SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"detheight","coz");
       
       /* write counter related stuff */
       pCom = FindCommand(pServ->pSics,"counter");
       if(pCom)
       {
         if(pCom->pData)
	 {
            fVal = GetCountTime((pCounter)pCom->pData,pCon);
            NXDputalias(hfil,hdict,"cntime",&fVal);

            /* the assignment of monitors has to be checked once
               the Schlumpf is done
	    */
            lVal = GetMonitor((pCounter)pCom->pData,2, pCon);
            NXDputalias(hfil,hdict,"cnmon1",&lVal);
            lVal = GetMonitor((pCounter)pCom->pData,3, pCon);
            NXDputalias(hfil,hdict,"cnmon2",&lVal);
	 }       
       }
       else
       {
           SCWrite(pCon,"WARNING: failed to find counter!",eWarning);
       }

       /*
          find dimensions of detector
       */      
       GetHistDim(pHM,iDim,&iLength);
       detxsize = iDim[0];
       detysize = iDim[1];       
       /* update detector size */
       sprintf(pBueffel,"%d",detxsize);
       NXDupdate(hdict,"detxsize",pBueffel);
       sprintf(pBueffel,"%d",detysize);
       NXDupdate(hdict,"detysize",pBueffel);


       /* write two axis */
       if(detxsize > detysize)
	 iLength = detxsize;
       else
	 iLength = detysize;

       fAxis = (float *)malloc(iLength*sizeof(float));
       if(!fAxis)
       {
         SCWrite(pCon,"ERROR: out of memory in WriteAmorTOF",eError);
         return 0;
       }
       for(i = 0; i < detxsize; i++)
       {
          fAxis[i] = (float)i;
       }
       NXDputalias(hfil,hdict,"detxx",fAxis);
       for(i = 0; i < detysize; i++)
       {
          fAxis[i] = (float)i;
       }
       NXDputalias(hfil,hdict,"dety",fAxis);
       NXDaliaslink(hfil,hdict,"dana","detxx");
       NXDaliaslink(hfil,hdict,"dana","dety");
       free(fAxis);


       /* add height and distances */
       fVal = ObVal(pAmor->aParameter,PARDS);
       NXDputalias(hfil,hdict,"detdist",&fVal);
       fVal = ObVal(pAmor->aParameter,PARDDH);
       NXDputalias(hfil,hdict,"detbase",&fVal);


       /* deal with time binning */
       fTime = GetHistTimeBin(pHM,&iLength);
       fTime2 = (float *)malloc(iLength*sizeof(float));
       if(fTime2)
       {
           for(i = 0; i < iLength; i++)
           {
               fTime2[i] = fTime[i]/10.;
           }
           sprintf(pBueffel,"%d",iLength);
           NXDupdate(hdict,"timebin",pBueffel);
           NXDputalias(hfil,hdict,"dettime",fTime2);
  	   NXDputalias(hfil,hdict,"singletime",fTime2);
           NXDaliaslink(hfil,hdict,"dana","dettime");
           free(fTime2);
           fTime2 = NULL;
       }
       else
       {
          SCWrite(pCon,"ERROR: out of memory while writing time binning",
                  eError);
       }

       /* finally get histogram */
       if(iDim[2] == 2) /* 2D data, no time binning on this detector */
       {
	 iLength = detxsize*detysize;
	  lData = (HistInt *)malloc(iLength*sizeof(HistInt));
	  if(!lData)
	  {
	      SCWrite(pCon,
		 "ERROR: out of memory, failed to write histogram",eError);
	      return 0;
	  }
	  memset(lData,0,iLength*sizeof(HistInt));
	  GetHistogram(pHM,pCon, 0,0,iLength,lData,iLength*sizeof(HistInt));
	  NXDputalias(hfil,hdict,"spinup2d",lData);
          NXDaliaslink(hfil,hdict,"dana","spinup2d");
       }
       else
       {
	 if(psdSave){
	   WriteTOFDetector("spinup",pHM, iDim,hfil,hdict,pCon);
	 } else {
	   SCWrite(pCon,"PSD writing supressed!",eWarning);
         }
#define MAXSINGLE 3
          /*
            now get and write single detectors
	  */
          iLength = iDim[0]*iDim[1]*iDim[2];
          lData = (HistInt *)malloc(MAXSINGLE*iDim[2]*sizeof(HistInt));
	  if(!lData)
	  {
            SCWrite(pCon,"ERROR: out of memory while writing single detectors",
                  eError);
          }
	  else
	  {
            memset(lData,0,MAXSINGLE*iDim[2]*sizeof(HistInt));
	    GetHistogramDirect(pHM,pCon,0,iLength,MAXSINGLE*iDim[2], 
                             lData, MAXSINGLE*iDim[2]*sizeof(HistInt));
	    NXDputalias(hfil,hdict,"singleup",lData);
            NXDaliaslink(hfil,hdict,"singledana","singleup");
            NXDaliaslink(hfil,hdict,"singledana","singletime");
	    /*
	      the TOF monitor
	    */
	    NXDputalias(hfil,hdict,"singletofmon",lData+2*iDim[2]);
            NXDaliaslink(hfil,hdict,"dana","singletofmon");
            NXDaliaslink(hfil,hdict,"singledana","singletofmon");
          }
       }

       /* to do: add polarizing code */

       if(lData)
           free(lData);

       NXclose(&hfil);
       NXDclose(hdict,NULL);

       return 1;      
  }
/*-----------------------------------------------------------------------*/
  static pHistMem pMeme = NULL;

  int AmorStore(SConnection *pCon, SicsInterp *pSics, void *pData, 
                int argc, char *argv[])
  {
     char pBueffel[512], *pFile = NULL;
     int iRet, iFlag;
     Status oldStatus;
     
     /* 
	if arguments, check for psdsave
     */
     if(argc > 1){
       strtolower(argv[1]);
       if(strcmp(argv[1],"psdsave") == 0){
	 if(argc > 2){
	   psdSave = atof(argv[2]);
	   SCSendOK(pCon);
	   return 1;
	 } else {
	   sprintf(pBueffel,"storeamor.psdSave  = %d",psdSave);
	   SCWrite(pCon,pBueffel,eValue);
	   return 1;
	 }
       }
     }


     pFile = SNXMakeFileName(pSics,pCon);
     sprintf(pBueffel,"Writing file %s .....",pFile);
     SCWrite(pCon,pBueffel,eWarning);
     
     oldStatus = GetStatus();
     SetStatus(eWriting);
     LockDeviceExecutor(pServ->pExecutor);
     iRet =  WriteAmorHeader(pFile,pCon);
     if(iRet)
     {
        iRet = WriteAmorTOF(pFile,pCon,pMeme);
     }
     SetStatus(oldStatus);
     UnlockDeviceExecutor(pServ->pExecutor);
     free(pFile);
     SCSendOK(pCon);
     return iRet;
  }      
/*---------------------------------------------------------------------*/
  int AmorStoreMake(SConnection *pCon, SicsInterp *pSics, void *pData, 
                int argc, char *argv[])
  {
     CommandList *pCom = NULL;
     char pBueffel[512];
     int iRet;

     if(argc < 3)
     {
        SCWrite(pCon,
         "ERROR: insufficient number of arguments to AmorStoreMake",
          eError);
        return 0;
     }

     /* we need a parameter which is the name of the histogram memory*/
     pCom = FindCommand(pServ->pSics,argv[1]);
     if(!pCom)
     {
       sprintf(pBueffel,"ERROR: Histogram memory %s NOT found", argv[1]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }
     if(!pCom->pData)
     {
       sprintf(pBueffel,"ERROR: Histogram memory %s NOT found", argv[1]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }
     pMeme = (pHistMem)pCom->pData;

     /* we need another  parameter which is the name of the 
        2theta calculation module
     */
     pCom = FindCommand(pServ->pSics,argv[2]);
     if(!pCom)
     {
       sprintf(pBueffel,"ERROR: amor2T module %s NOT found", argv[2]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }
     if(!pCom->pData)
     {
       sprintf(pBueffel,"ERROR: amor2t module %s NOT found", argv[2]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }
     pAmor = (pAmor2T)pCom->pData;


     /* install command */
     iRet = AddCommand(pSics,"storeamor",
                        AmorStore,NULL,NULL);
     if(!iRet)
     {
         sprintf(pBueffel,"ERROR: duplicate command amorstore NOT created");
         SCWrite(pCon,pBueffel,eError);
         return 0;
     }
     return 1;
  }      



