/*-------------------------------------------------------------------------
                                  M E S U R E
                                
  An object for doing simple four circle diffractometer measurements with 
  a single counter.
  
  copyright: see copyright.h
  
  Mark Koennecke, April 1998
---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <tcl.h>
#include <assert.h>
#include "fortify.h"
#include "sics.h"
#include "motor.h"
#include "o2t.h"
#include "scan.h"
#include "scan.i"
#include "danu.h"
#include "integrate.h"
#include "hkl.h"
#include "sicsvar.h"
#include "evcontroller.h"
#include "mesure.h"

  extern void SNXFormatTime(char *pBueffel, int iLen);
#define ANGERR 0.2

/* nxutil.h
 */


/*
#define MESSDEBUG 1

  define MESSDEBUG for simulated peaks. This helps in debugging
   this code and the initial data correction code
*/   

  extern void SNXFormatTime(char *pBueffel, int iLen); /* nxutil.c */

/*------------------- the data structure -----------------------------------*/
  typedef struct __Mesure 
  {
      pObjectDescriptor pDes; /* standard object descriptor */
      pICallBack    pCall;    /* callback interface for automatic notification */
      pScanData pScanner;     /* scan object to use for scans */
      pHKL  pCryst;           /* hkl object for crystallographic calc 
                                 and reflection driving */                                                            
      pMotor pOmega;          /* motor for omega scans */  
      char *pCOmega;           /* name of omega motor */
      char *pO2T;             /* name of omega 2 theta virtual motor */
      char *pFileRoot;        /* where to write files */
      pDataNumber pDanu;      /* where to get data file number */
      FILE       *fRefl;      /* reflection profile file */ 
      FILE       *fHKL;       /* integrated intensity file */
      int        iLogFile;    /* log file num at connection */
      SConnection *pCon;     /* log file owning connection */
      char    *pCurrentFile; /* current file root */
      int iCount;             /* count of reflection */
      int CountMode;          /* timer or preset */
      int np;                 /* number of scan points */
      float fPreset;          /* counting preset */
      float fStep;            /* omega step widths */
      int iMode;             /* omega or omega 2 theta scan flag */
      long *lCounts;        /* array to store counting values */
      float fPosition[4];   /* the real positions after driving */
      int iCompact;           /* true if compact scan ouput. */
  } Mesure;
/*--------------------------------------------------------------------------*/
  pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega,
                       char *pOm, char *po2t, char *pFileRoot, 
                       pDataNumber pDanu)
  {
     pMesure pNew = NULL;
     
     assert(pCryst);
     assert(pScanner);
     assert(pOmega);
     assert(pFileRoot);
     assert(pDanu);
     
     /* allocate space............. */
     pNew = (pMesure)malloc(sizeof(Mesure));
     if(!pNew)
     {
       return NULL;
     }
     memset(pNew,0,sizeof(Mesure));
     
     pNew->pDes = CreateDescriptor("Mesure");
     pNew->pCall = CreateCallBackInterface();
     if( !pNew->pDes || !pNew->pCall)
     {
       free(pNew);
       return NULL;
     }
     
     /* asssign defaults */
     pNew->pScanner  = pScanner;
     pNew->pCryst    = pCryst;
     pNew->pOmega    = pOmega;
     pNew->pCOmega   = strdup(pOm);
     pNew->pO2T      = strdup(po2t); 
     pNew->pFileRoot = strdup(pFileRoot);
     pNew->pDanu     = pDanu;
     pNew->iCount    = 0;
     pNew->CountMode = 0;
     pNew->np        = 50;
     pNew->fStep     = 0.05;
     pNew->fPreset   = 2;
     pNew->iMode     = 0;
     pNew->iCompact = 1;
#ifdef MESSDEBUG
     pNew->lCounts = (long *)malloc(90*sizeof(long));
#endif     
     pNew->lCounts = (long *)malloc(50*sizeof(long));
     return pNew;
  }    
/*------------------------------------------------------------------------*/
  void DeleteMesure(void *pData)
  {
     pMesure self = NULL;
     
     self = (pMesure)pData;
     
     if(!pData)
     {
       return;
     }
     
     if(self->pDes)
        DeleteDescriptor(self->pDes);
     
     if(self->pCall)
        DeleteCallBackInterface(self->pCall);
     if(self->pFileRoot)
        free(self->pFileRoot);
     if(self->pCOmega)
        free(self->pCOmega);
     if(self->pO2T)
        free(self->pO2T);
     if(self->fRefl)
            MesureClose(self);  
     if(self->lCounts)
            free(self->lCounts);       
     free(self);
   }             
/*------------------------------------------------------------------------*/
   int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
                     int argc, char *argv[])
   {
      pMesure pNew = NULL;
      pHKL pCryst = NULL;
      pScanData pScan = NULL; 
      CommandList *pCom = NULL;
      pMotor pMot = NULL;
      pDataNumber pDanu = NULL;
      pSicsO2T pO2T = NULL;
      char pBueffel[512];
      pDummy pDum = NULL;
      int iRet;
      
      assert(pCon);
      assert(pSics);
      
      /* check no of parameters 
      inicom name hkl scan omega o2t root danu 
      */
      if(argc < 8)
      {
         SCWrite(pCon,
               "ERROR: Insufficient number of parameters to MesureFactory",eError);
         return 0;
      } 
      
      /* work parameters one by one, first hkl */
      pCom = FindCommand(pSics,argv[2]);
      if(pCom)
      {
        pDum = (pDummy)pCom->pData;
        if(pDum)
        {
           if(strcmp(pDum->pDescriptor->name,"4-Circle-Calculus") == 0)
           {
             pCryst = (pHKL)pCom->pData;
           }
        }
      }
      if(!pCryst)
      {
       sprintf(pBueffel,"ERROR: %s is no four circle calculus object",argv[2]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
      }
      
      /* scanner */
      pCom = FindCommand(pSics,argv[3]);
      if(pCom)
      {
        pDum = (pDummy)pCom->pData;
        if(pDum)
        {
           if(strcmp(pDum->pDescriptor->name,"ScanObject") == 0)
           {
             pScan = (pScanData)pCom->pData;
           }
        }
      }
      if(!pScan)
      {
       sprintf(pBueffel,"ERROR: %s is no scan object",argv[3]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
      }
      
      /* omega */
      pMot = FindMotor(pSics,argv[4]);
      if(!pMot)
      {
       sprintf(pBueffel,"ERROR: %s is no motor object ",argv[4]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
      }
      
      /* o2t */
      pCom = FindCommand(pSics,argv[5]);
      if(pCom)
      {
        pDum = (pDummy)pCom->pData;
        if(pDum)
        {
           if(strcmp(pDum->pDescriptor->name,"Omega2Theta") == 0)
           {
             pO2T = (pSicsO2T)pCom->pData;
           }
        }
      }
      if(!pO2T)
      {
       sprintf(pBueffel,"ERROR: %s is no omega 2 theta object",argv[5]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
      }

      /* Data Number */
      pCom = FindCommand(pSics,argv[7]);
      if(pCom)
      {
        pDum = (pDummy)pCom->pData;
        if(pDum)
        {
           if(strcmp(pDum->pDescriptor->name,"DataNumber") == 0)
           {
             pDanu = (pDataNumber)pCom->pData;
           }
        }
      }
      if(!pDanu)
      {
       sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[7]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
      }
      
      /* finally create the thing */
      pNew = CreateMesure(pCryst,pScan,pMot,argv[4],argv[5],argv[6],pDanu);
      if(!pNew)
      {
        SCWrite(pCon,"ERROR: no meory in MesureFactory",eError);
        return 0;
      }
      
      /* add the new command */
      iRet = AddCommand(pSics,argv[1],MesureAction,DeleteMesure,pNew);
      if(!iRet)
      {
        sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
        SCWrite(pCon,pBueffel,eError);
        return 0;
      }
      return 1;
   }          
/*------------------------------------------------------------------------
  This implements the compact scan output for TRICS scans
*/
  static int CompactScanData(pScanData self, int iPoint)
  {
     pVarEntry pVar = NULL;
     void *pDings;
     int i, iRet, status;
     float fVal;
     char pStatus[512], pItem[20];
     char pHead[512];
     CountEntry sCount;
     char *pAns = NULL, *pPtr = NULL ;
     Tcl_Interp *pTcl;

     assert(self);
     assert(self->pCon);
     
     /* loop over all scan variables */
     status = 1;
     for(i = 0; i < self->iScanVar; i++)
     {
        DynarGet(self->pScanVar,i,&pDings);
        pVar = (pVarEntry)pDings;
        if(pVar)
        {
           fVal = pVar->pInter->GetValue(pVar->pObject,self->pCon);
           pVar->fData[iPoint] = fVal;
           sprintf(pItem,"%-10.10s",pVar->Name);
           strcat(pHead,pItem);
           sprintf(pItem,"%-10.3f",fVal);
           strcat(pStatus,pItem);
        }
     }
  
     /* store counter data */
     /* monitors */
     for(i = 1; i < 10; i++)
     {
        sCount.Monitors[i-1] = GetMonitor((pCounter)self->pCounterData,i,
                                        self->pCon);
     }
     if( self->iChannel != 0 && self->iChannel != -10 )
     {
       sCount.Monitors[self->iChannel - 1] = 
           GetCounts((pCounter)self->pCounterData,
                                                   self->pCon);     
     }
     if(self->iChannel == 0)
     {
        sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon);
     }
     else
     {
        sCount.lCount = GetMonitor((pCounter)self->pCounterData,
                                  self->iChannel, self->pCon);
     }
     
     /* stow away */
     DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry));
     self->iCounts++;

     return 1;
  }  
/*--------------------------------------------------------------------------*/
   int MesureReflection(pMesure self, float fHKL[3], SConnection *pCon)
   {
      int iRet, i;
      float fStart;
      float fDelta, fSet[4];
      char pBueffel[132];      

      assert(self);
      
      /* drive to reflection */
      iRet = DriveHKL(self->pCryst,fHKL,0.,0,pCon);
      if(!iRet)
      {
        return iRet;
      }

      /* store achieved position for reporting */
      iRet = GetCurrentPosition(self->pCryst,pCon,self->fPosition);
      if(iRet != 1)
      {
        return iRet;
      }

      /* 
        check if we are really there. All this only because Jurg 
        does not fix his rotten cradle.
       */
       CalculateSettings(self->pCryst,fHKL,0.,0,fSet,pCon);
       for(i = 0; i < 4; i++)
       {
         fDelta = fSet[i] - self->fPosition[i];
         if(fDelta < 0.)
            fDelta = -fDelta;
         if(fDelta > ANGERR)
	 {
           sprintf(pBueffel,
             "ERROR: angle %d positioned badly, aborting Reflection",
              i);
            SCWrite(pCon,pBueffel,eError);
            return 0;          
         }
       }
      
      /* calculate scan start */
      iRet = MotorGetSoftPosition(self->pOmega,pCon,&fStart);
      if(!iRet)
      {
        return iRet;
      }
      fStart -= (self->np/2)*self->fStep;
      
      /* set the scan up */
      ClearScanVar(self->pScanner);
      if(self->iMode == 0)
      {
        AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega,
                   fStart, self->fStep);
      }
      else
      {
        AddScanVar(self->pScanner, pServ->pSics,pCon,self->pO2T,
                   fStart, self->fStep);
      }
      
      /* do the scan */
      if(self->iCompact)
      {
         self->pScanner->CollectScanData = CompactScanData;
      }
      iRet = SilentScan(self->pScanner,self->np,self->CountMode,
                        self->fPreset,pServ->pSics,pCon);

      ResetScanFunctions(self->pScanner);
      
      return iRet;                  
   }             
/*------------------------------------------------------------------------*/
  int MesureGenReflection(pMesure self, float fHKL[3], float fSet[4],
                          SConnection *pCon)
  {
    
      int iRet, i;
      float fStart, fDelta;
      char pBueffel[132];
      
      assert(self);
      
      /* drive to reflection */
      iRet = DriveSettings(self->pCryst,fSet,pCon);
      if(!iRet)
      {
        return iRet;
      }

      /* store achieved position for reporting */
      iRet = GetCurrentPosition(self->pCryst,pCon,self->fPosition);
      if(iRet != 1)
      {
        return iRet;
      }

      /* 
        check if we are really there. All this only because Jurg 
        does not fix his rotten cradle.
       */
       for(i = 0; i < 4; i++)
       {
         fDelta = fSet[i] - self->fPosition[i];
         if(fDelta < 0.)
            fDelta = -fDelta;
         if(fDelta > ANGERR)
	 {
           sprintf(pBueffel,
             "ERROR: angle %d positioned badly, aborting Reflection",
              i);
            SCWrite(pCon,pBueffel,eError);
            return 0;          
         }
       }
      
      /* calculate scan start */
      iRet = MotorGetSoftPosition(self->pOmega,pCon,&fStart);
      if(!iRet)
      {
        return iRet;
      }
      fStart -= (self->np/2)*self->fStep;
      
      /* set the scan up */
      ClearScanVar(self->pScanner);
      if(self->iMode == 0)
      {
        AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega,
                   fStart, self->fStep);
      }
      else
      {
        AddScanVar(self->pScanner, pServ->pSics,pCon,self->pO2T,
                   fStart, self->fStep);
      }
      
      /* do the scan */
      if(self->iCompact)
      {
         self->pScanner->CollectScanData = CompactScanData;
      }
      iRet = SilentScan(self->pScanner,self->np,self->CountMode,
                        self->fPreset,pServ->pSics,pCon);
      ResetScanFunctions(self->pScanner);

      return iRet;                  
  }                           
/*--------------------------------------------------------------------------*/
  int MesureStart(pMesure self, SConnection *pCon)
  {
      char pFilename[512], pRoot[512];
      char pBueffel[1024];
      char pBuff[132];
      int iYear, iNum;
      float fVal, fUB[9];
      pSicsVariable pVar = NULL;
      
      assert(self);
      assert(pCon);
      
      /* close open files if so */
      if(self->fRefl != NULL)
      {
        MesureClose(self);
      }
      
      /* create filename root */
      iNum = IncrementDataNumber(self->pDanu,&iYear);
      sprintf(pRoot,"%s/trics%5.5d%4.4d.",self->pFileRoot,iNum,iYear);
      self->pCurrentFile = strdup(pRoot);
      
      /* do the logfile */
      strcpy(pFilename,pRoot);
      strcat(pFilename,"log");
      self->iLogFile = SCAddLogFile(pCon,pFilename);
      self->pCon = pCon;
      sprintf(pBueffel,"Writing to %s.log, .ccl, .rfl",pRoot);
      SCWrite(pCon,pBueffel,eValue);
      
      /* open the reflection file */
      strcpy(pFilename,pRoot);
      strcat(pFilename,"ccl");
      self->fRefl = fopen(pFilename,"w");
      if(!self->fRefl)
      {
         sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!",
                pFilename);
         SCWrite(pCon,pBueffel,eError);
         SCSetInterrupt(pCon,eAbortBatch);
         return 0;       
      }
/*    put filename
      fputs(pFilename,self->fRefl);
      fputs("\n",self->fRefl);
*/

      /* open hkl-data file */
      strcpy(pFilename,pRoot);
      strcat(pFilename,"rfl");
      self->fHKL = fopen(pFilename,"w");
      if(!self->fHKL)
      {
         sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!",
                pFilename);
         SCWrite(pCon,pBueffel,eError);
         SCSetInterrupt(pCon,eAbortBatch);
         return 0;       
      }
      fputs(pFilename,self->fHKL);
      fputs("\n",self->fHKL);
      
      /* write some header data */
      SNXFormatTime(pBueffel,1024);
 /*     fprintf(self->fRefl,"filetime = %s\n",pBueffel); */
      fprintf(self->fHKL,"filetime = %s\n",pBueffel);
      GetLambda(self->pCryst,&fVal);
/*      fprintf(self->fRefl,"lambda = %f Angstroem\n",fVal); */
      fprintf(self->fHKL,"lambda = %f Angstroem\n",fVal);
      GetUB(self->pCryst,fUB);
/*      fprintf(self->fRefl,
       "UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n",
       fUB[0], fUB[1],fUB[2],fUB[3],fUB[4],fUB[5],fUB[6],fUB[7],fUB[8]); */
      fprintf(self->fHKL,
       "UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n",
       fUB[0], fUB[1],fUB[2],fUB[3],fUB[4],fUB[5],fUB[6],fUB[7],fUB[8]);
      
      /* write sample & user info */
      strcpy(pBueffel,"CCL, Instr=TRICS, ");
      pVar = FindVariable(pServ->pSics,"sample");
      if(pVar)
      {
        fprintf(self->fHKL,"sample = %s\n",pVar->text); 
        sprintf(pBuff,"sample = %s, ",pVar->text);
        strcat(pBueffel,pBuff);
      }
      pVar = FindVariable(pServ->pSics,"user");
      if(pVar)
      {
        fprintf(self->fHKL,"user = %s \n",pVar->text); 
        sprintf(pBuff,"user = %s",pVar->text);
        strcat(pBueffel,pBuff);
      }
      fprintf(self->fRefl,"%s\n",pBueffel);


      return 1; 
  }
/*---------------------------------------------------------------------------*/
  int MesureReopen(pMesure self, char *fileroot, SConnection *pCon)
  {
    char pBueffel[1024];
    char pFile[512];
  
    assert(self);
    assert(fileroot);
    assert(pCon);

   /* close pending files */
    if(self->fRefl != NULL)
    {
      MesureClose(self);
    }
    
    /* check if this is possible */
    strcpy(pFile,self->pFileRoot);
    strcat(pFile,"/");
    strcat(pFile,fileroot);
    strcat(pFile,".col");
    self->fRefl = fopen(pFile,"r");
    if(!self->fRefl)
    {
      fclose(self->fRefl);
      sprintf(pBueffel,"ERROR: there is no such measurement at %s",fileroot);
      SCWrite(pCon,pBueffel,eError);
      return 0;
    }
    fclose(self->fRefl);
    
    /* well seems to exist, open for append */
    self->fRefl = fopen(pFile,"a");
    
    /* rfl file */
    strcpy(pFile,self->pFileRoot);
    strcat(pFile,"/");
    strcat(pFile,fileroot);
    self->pCurrentFile = strdup(pFile);
    strcat(pFile,".rfl");
    self->fHKL = fopen(pFile,"a");
    
    /* log file */
    strcpy(pFile,self->pFileRoot);
    strcat(pFile,"/");
    strcat(pFile,fileroot);
    strcat(pFile,".log");
    self->iLogFile = SCAddLogFile(pCon,pFile);
    self->pCon = pCon;
    
    return 1; 
  }
/*------------------------------------------------------------------------*/
  int MesureClose(pMesure self)
  {
      assert(self);
      
      if(self->fRefl)
      {
        fclose(self->fRefl);
        self->fRefl = NULL;
      }
      if(self->fHKL)
      {
        fclose(self->fHKL);
        self->fHKL = NULL;
      }
      SCDelLogFile(self->pCon,self->iLogFile);
      self->pCon = NULL;
      self->iLogFile = -1;
      if(self->pCurrentFile)
         free(self->pCurrentFile);
      
      return 1;
  }   
/*---------------------------------------------------------------------------*/
  static int WriteReflection(pMesure self, float fHKL[3],SConnection *pCon)
  {
    float fSum, fSigma, fSet[4], fTemp, fPreset, fStep;
    static float fMax = 10.;
    int iRet, i,ii, iLF, iNP;
    char pBueffel[512], pNum[10], pTime[132];
    pEVControl pEva = NULL;    

    assert(self);
    assert(pCon);
    
#ifdef MESSDEBUG
    self->np = 90;
    fMax += 10;
    SimScan(self->pScanner,14.,0.5,fMax);
    if(fMax > 1000)
    {
      fMax = 10.;
    }         
#endif
    
    /* get necessary data */
    fSum = 0.;
    fSigma = 0.;
    iRet = ScanIntegrate(self->pScanner,&fSum, &fSigma);
    if(iRet != 1)
    {
       switch(iRet)
       {
         case INTEGLEFT:
            sprintf(pBueffel,
                "WARNING: integration failed --> no left side to: %f %f %f",
                              fHKL[0], fHKL[1],fHKL[2]);
            break;
         case INTEGRIGHT:
            sprintf(pBueffel,
                 "WARNING: integration failed -->no right side to: %f %f %f",
                              fHKL[0], fHKL[1],fHKL[2]);
            break;
         case INTEGNOPEAK:
            sprintf(pBueffel,
                  "WARNING: integration failed -->no peak found: %f %f %f",
                              fHKL[0], fHKL[1],fHKL[2]);
            break;
         case INTEGFUNNYBACK:
            sprintf(pBueffel,
              "WARNING: integration problem, asymmetric background: %f %f %f",
                              fHKL[0], fHKL[1],fHKL[2]);
            break;
       }
       SCWrite(pCon,pBueffel,eWarning);        
    }
    GetScanCounts(self->pScanner,self->lCounts,self->np);
    
    /* write it */
    if(self->fRefl)
    {
      fprintf(self->fRefl,"%4d%8.3f%8.3f%8.3f%8.2f%8.2f%8.2f%8.2f%8.0f%8.2f\n",
             self->iCount, fHKL[0],fHKL[1],fHKL[2],
             self->fPosition[0], self->fPosition[1],
             self->fPosition[2],self->fPosition[3],
             fSum,fSigma);
    }    
    if(self->fHKL)
    {
      fprintf(self->fHKL,"%5d%7.2f%7.2f%7.2f%8.2f%8.2f%8.2f%8.2f%8.0f%8.2f\n",
             self->iCount, fHKL[0],fHKL[1],fHKL[2],
             self->fPosition[0], self->fPosition[1],
             self->fPosition[2],self->fPosition[3],
             fSum,fSigma);
    }    
    sprintf(pBueffel,"%5d%7.2f%7.2f%7.2f%8.2f%8.2f%8.2f%8.2f%8.0f%8.2f\n",
             self->iCount, fHKL[0],fHKL[1],fHKL[2],
             self->fPosition[0], self->fPosition[1],
             self->fPosition[2],self->fPosition[3],
             fSum,fSigma);
    SCWrite(pCon,pBueffel,eStatus);    

    /* get temperature */
    fTemp = -777.77;
    pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature",
                                      "Environment Controller");
    if(pEva)
    {
      iRet = EVCGetPos(pEva, pCon,&fTemp);
    }
    
    /* write profile */
    if(self->fRefl)
    {
      /* collect data */
      SNXFormatTime(pBueffel,512);
      GetScanVarStep(self->pScanner,0,&fStep);
      iNP = GetScanNP(self->pScanner);
      fPreset = GetScanPreset(self->pScanner); 
      fprintf(self->fRefl,"%3d%8.3f%10.0f%8.3f %s\n",iNP,fStep,
              fPreset,fTemp,pBueffel);
      for(i = 0; i < iNP; i++)
      {
        for(ii = 0; ii < 10 && i < iNP; ii++)
        {
          fprintf(self->fRefl,"%8d",self->lCounts[i]);
          iLF = 1;
          i++;
        }
        fprintf(self->fRefl,"\n");
        i--;
        iLF = 0;
      }
      if(iLF)
      {
        fprintf(self->fRefl,"\n");
      }
      fflush(self->fRefl);
    }
    
    /* write data if compact output */
    if(self->iCompact == 1)
    {
        strcpy(pTime,pBueffel);
        sprintf(pBueffel,"%3d%8.3f%10.0f%8.3f %s\n",iNP,fStep,
              fPreset,fTemp,pTime);
        SCWrite(pCon,pBueffel,eValue);
        pBueffel[0] = '\0';        
        for(i = 0; i < iNP; i++)
        {
          for(ii = 0; ii < 10 && i < iNP; ii++)
          {
            sprintf(pNum,"%7d",self->lCounts[i]);
            strcat(pBueffel,pNum);
            iLF = 1;
            i++;
          }
          SCWrite(pCon,pBueffel,eValue);
          pBueffel[0] = '\0';
          i--;
          iLF = 0;
        }
        if(iLF)
        {
          SCWrite(pCon,pBueffel,eValue);
        }
    }
    return 1;
  }         
/*------------------------------------------------------------------------*/
  int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon)
  {
     FILE *fd = NULL;
     char pBueffel[512], pTime[132];
     int i, iRet;
     float fHKL[3];
     
     assert(self);
     assert(pCon);
     
     /* well before doing a thing, open the list file */
     fd = fopen(pFile,"r");
     if(!fd)
     {
       sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }
     
     /* check that files are open, if not open */
     if(self->fRefl == NULL)
     {
        MesureStart(self,pCon);
     }
     
     /* make a mark */
     SNXFormatTime(pTime,131);
     sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime);
     SCWrite(pCon,pBueffel,eStatus);
     
     /* skippy! */
     for(i = 0; i < iSkip; i++)
     {
       fgets(pBueffel,510,fd);
     }
     self->iCount = iSkip;
     

     /* loop through space and measure! */
     while(fgets(pBueffel,510,fd) != NULL)
     {
         for(i = 0; i < 3;i++)
            fHKL[i] = 0.;
         iRet = sscanf(pBueffel,"%f%f%f",&fHKL[0],&fHKL[1],&fHKL[2]);
         self->iCount++;
         iRet = MesureReflection(self,fHKL,pCon);
         if(iRet == 0)
         {
            if(SCGetInterrupt(pCon) >= eAbortBatch)
            {
              return 0;
            }
            else
            {
              SCSetInterrupt(pCon,eContinue);
              continue;
            }
         }
         WriteReflection(self,fHKL,pCon); 
     }
     
     /* we are done */
     SNXFormatTime(pTime,131);
     sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime);
     SCWrite(pCon,pBueffel,eStatus);

     fclose(fd);
     return 1;
  }    
/*------------------------------------------------------------------------*/
  int MesureGenFile(pMesure self, char *pFile, int iSkip, SConnection *pCon)
  {
     FILE *fd = NULL;
     char pBueffel[512], pTime[132];
     int i, iRet, iH, iK, iL;
     float fHKL[3], fSet[4];
     char pDum[4];
     
     assert(self);
     assert(pCon);
     
     /* well before doing a thing, open the list file */
     fd = fopen(pFile,"r");
     if(!fd)
     {
       sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }
     
     /* check that files are open, if not open */
     if(self->fRefl == NULL)
     {
        MesureStart(self,pCon);
     }
     
     /* make a mark */
     SNXFormatTime(pTime,131);
     sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime);
     SCWrite(pCon,pBueffel,eStatus);
     
     /* skippy! */
     for(i = 0; i < iSkip; i++)
     {
       fgets(pBueffel,510,fd);
     }
     self->iCount = iSkip;
     

     /* loop through space and measure! */
     while(fgets(pBueffel,510,fd) != NULL)
     {
         for(i = 0; i < 3;i++)
            fHKL[i] = 0.;
         for(i = 0; i < 4;i++)
            fSet[i] = 0.;
         iRet = sscanf(pBueffel,"%4d%4d%4d%s%f%f%f%f",
                       &iH,&iK,&iL,pDum, 
                       &fSet[0], &fSet[1],&fSet[2],&fSet[3]);
         fHKL[0] = (float)iH;
         fHKL[1] = (float)iK;
         fHKL[2] = (float)iL;              
         self->iCount++;
         iRet = MesureGenReflection(self,fHKL,fSet,pCon);
         if(iRet == 0)
         {
            if(SCGetInterrupt(pCon) >= eAbortBatch)
            {
              return 0;
            }
            else
            {
              SCSetInterrupt(pCon,eContinue);
              continue;
            }
         }
         WriteReflection(self,fHKL,pCon); 
     }
     
     /* we are done */
     SNXFormatTime(pTime,131);
     sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime);
     SCWrite(pCon,pBueffel,eStatus);

     fclose(fd);
     return 1;
  }    
/*--------------------------------------------------------------------------*/
  int MesureSetPar(pMesure self, char *name, float fVal)
  {
     if(strcmp(name,"np") == 0)
     {
#ifndef MESSDEBUG     
         self->np = (int)fVal;
         if(self->lCounts)
            free(self->lCounts);
         self->lCounts = (long *)malloc(self->np*sizeof(long));
         if(!self->lCounts)
         {
           return 0;
         }   
#else
      
#endif         
         return 1;
     }
     else if(strcmp(name,"step") == 0)
     {
       self->fStep = fVal;
       return 1;
     }
     else if(strcmp(name,"preset") == 0)
     {
       self->fPreset = fVal;
       return 1;
     }
     else if(strcmp(name,"mode") == 0)
     {
       if(fVal <= 0)
       {
         self->iMode = 0;
       }
       else
       {
         self->iMode = 1;
       }
       return 1;
     }
     else if(strcmp(name,"countmode") == 0)
     {
       if(fVal < 0.05)
       {
         self->CountMode = eTimer;
       }
       else
       {
         self->CountMode = ePreset;
       }
       return 1;
     }
     else if(strcmp(name,"compact") == 0)
     {
       if(fVal >= 1.)
       {
         self->iCompact = 1;
       }
       else
       {
         self->iCompact = 0;
       }
       return 1;
     }
     else
     {
       return 0;
     }
  }                               
/*-------------------------------------------------------------------------*/
  int MesureGetPar(pMesure self, char *name, float *fVal)
  {
     if(strcmp(name,"np") == 0)
     {
         *fVal = self->np;
         return 1;
     }
     else if(strcmp(name,"step") == 0)
     {
       *fVal = self->fStep;
       return 1;
     }
     else if(strcmp(name,"mode") == 0)
     {
       *fVal = self->iMode;
       return 1;
     }
     else if(strcmp(name,"preset") == 0)
     {
       *fVal = self->fPreset;
       return 1;
     }
     else if(strcmp(name,"countmode") == 0)
     {
       if(self->CountMode == eTimer)
       {
         *fVal = 0.;
       }
       else
       {
         *fVal = 1.0;
       }
       return 1;
     }
     else if(strcmp(name,"compact") == 0)
     {
       *fVal = self->iCompact;
       return 1;        
     }
     else
     {
       return 0;
     }
  }
/*---------------------------------------------------------------------------*/
  int MesureAction(SConnection *pCon, SicsInterp *pSics, void *pData,
                   int argc, char *argv[])
  {
    int iRet, iSkip;
    char pBueffel[1024];
    pMesure self = NULL;
    double d;
    float fVal, fHKL[3];
    
    self = (pMesure)pData;
    assert(self);
    assert(pCon);
    
     if(argc < 2) 
     {
         sprintf(pBueffel,"ERROR: Insufficient arguments to %s",argv[0]); 
         SCWrite(pCon,pBueffel,eError);
         return 0;
     }
     
      strtolower(argv[1]);
/*------ start */      
      if(strcmp(argv[1],"start") == 0)
      {
         if(!SCMatchRights(pCon,usUser))
         {
           return 0;
         }
         iRet = MesureStart(self,pCon);
         if(iRet)
         {
           SCSendOK(pCon);
         }
         return iRet;
      }
/*------ file */     
      else if(strcmp(argv[1],"file") == 0)
      {
        sprintf(pBueffel,"Currently writing to: %s",self->pCurrentFile);
        SCWrite(pCon,pBueffel,eValue);
        return 1; 
      }
/*------ nb */     
      else if(strcmp(argv[1],"nb") == 0)
      {
        if(!SCMatchRights(pCon,usUser))
        {
           return 0;
        }
        iRet = SetNOR(self->pCryst,1);
        if(!iRet)
	{
          SCWrite(pCon,
          "ERROR: nu motor not configured at hkl, cannot do normal beam",
          eError);
          return 0;
        }
        SCSendOK(pCon);
        return 1; 
      }
/*------ bi */     
      else if(strcmp(argv[1],"bi") == 0)
      {
        if(!SCMatchRights(pCon,usUser))
        {
           return 0;
        }
        iRet = SetNOR(self->pCryst,0);
        SCSendOK(pCon);
        return 1; 
      }
/*--------- close */
      else if(strcmp(argv[1],"close") == 0)
      {
         if(!SCMatchRights(pCon,usUser))
         {
           return 0;
         }
         MesureClose(self);
         return 1;
      }      
/*-------- reopen */      
      else if(strcmp(argv[1],"reopen") == 0)
      {
         if(!SCMatchRights(pCon,usUser))
         {
           return 0;
         }
         if(argc < 3)
         {
           SCWrite(pCon,"ERROR: expected filename as parameter for reopen",eError);
           return 0;
         }
         iRet = MesureReopen(self,argv[2],pCon);
         if(iRet)
         {
           SCSendOK(pCon);
         }
         return iRet;
      }
/*------- measure */
      else if(strcmp(argv[1],"measure") == 0)
      {
         iSkip = 0;
         if(!SCMatchRights(pCon,usUser))
         {
           return 0;
         }
         if(argc < 3)
         {
           SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError);
           return 0;
         }
         if(argc >= 4)
         {
           iRet = Tcl_GetInt(pSics->pTcl,argv[3],&iSkip);
           if(iRet != TCL_OK)
           {
             sprintf(pBueffel,"ERROR: expected integer, got %s",argv[3]);
             SCWrite(pCon,pBueffel,eError);
             return 0;
           }
         }
         iRet = MesureFile(self,argv[2],iSkip,pCon);
         if(iRet)
         {
           SCSendOK(pCon);
         }
         return iRet;
      }     
/*------- genlist */
      else if(strcmp(argv[1],"genlist") == 0)
      {
         iSkip = 0;
         if(!SCMatchRights(pCon,usUser))
         {
           return 0;
         }
         if(argc < 3)
         {
           SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError);
           return 0;
         }
         if(argc >= 4)
         {
           iRet = Tcl_GetInt(pSics->pTcl,argv[3],&iSkip);
           if(iRet != TCL_OK)
           {
             sprintf(pBueffel,"ERROR: expected integer, got %s",argv[3]);
             SCWrite(pCon,pBueffel,eError);
             return 0;
           }
         }
         iRet = MesureGenFile(self,argv[2],iSkip,pCon);
         if(iRet)
         {
           SCSendOK(pCon);
         }
         return iRet;
      }     
/* ------ writereflection*/
     else if(strcmp(argv[1],"writereflection") == 0)
     {
        GetCurrentHKL(self->pCryst,fHKL);
        WriteReflection(self,fHKL,pCon);
        SCSendOK(pCon);
        return 1;
     }      
/* ------ count mode */
     else if(strcmp(argv[1],"countmode") == 0)
     {
        if(argc > 2) /* set case */
        {
          /* check rights */
          if(!SCMatchRights(pCon,usUser))
          {
             SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError);
             return 0;
          }
          if(strcmp(argv[2],"timer") == 0)
          {
            fVal = 0.;
          }
          else if(strcmp(argv[2],"monitor") == 0)
          {
            fVal = 1.;
          }
          else
          {
            SCWrite(pCon,"ERROR: Invalid parameter for countmode",eError);
            return 0;
          }
          MesureSetPar(self,"countmode",fVal);
          SCSendOK(pCon);
          return 1;
        }
        else /* get case */
        {
          MesureGetPar(self,"countmode",&fVal);
          if(fVal < 0.05)
          {
            sprintf(pBueffel,"%s.countmode = timer",argv[0]);
          }
          else
          {
            sprintf(pBueffel,"%s.countmode = monitor", argv[0]);
          }
          SCWrite(pCon,pBueffel,eValue);
          return 1;
        }
     }  
/*------- mode */
     if(strcmp(argv[1],"mode") == 0)
     {
        if(argc > 2) /* set case */
        {
          /* check rights */
          if(!SCMatchRights(pCon,usUser))
          {
             SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError);
             return 0;
          }
          if(strcmp(argv[2],"omega") == 0)
          {
            fVal = 0.;
          }
          else if(strcmp(argv[2],"omega2theta") == 0)
          {
            fVal = 1.;
          }
          else
          {
            SCWrite(pCon,"ERROR: Invalid parameter for mode",eError);
            return 0;
          }
          MesureSetPar(self,"mode",fVal);
          SCSendOK(pCon);
          return 1;
        }
        else /* get case */
        {
          MesureGetPar(self,"mode",&fVal);
          if(fVal < 0.05)
          {
            sprintf(pBueffel,"%s.countmode = omega",argv[0]);
          }
          else
          {
            sprintf(pBueffel,"%s.countmode = omega2theta", argv[0]);
          }
          SCWrite(pCon,pBueffel,eValue);
          return 1;
        }
     }  
/*------ can be other pars */
     else
     {
        if(argc > 2) /* set case */
        {
          /* check rights */
          if(!SCMatchRights(pCon,usUser))
          {
             SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError);
             return 0;
          }
          iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&d);
          if(iRet != TCL_OK)
          {
            sprintf(pBueffel,"ERROR: expected numeric value for %s but got %s",
                    argv[1],argv[2]);
            SCWrite(pCon,pBueffel,eError);
            return 0;        
          }
          fVal = (float)d;
          
          iRet = MesureSetPar(self,argv[1],fVal);
          if(iRet)
          {
              SCSendOK(pCon);
              return 1;
          }
          else
          {
            sprintf(pBueffel,"ERROR: parameter %s not known",argv[1]);
            SCWrite(pCon,pBueffel,eError);
            return 0;
          }    
        }
        else /* get case */
        {
          iRet = MesureGetPar(self,argv[1],&fVal);
          if(!iRet)
          {
            sprintf(pBueffel,"ERROR: parameter %s not known",argv[1]);
            SCWrite(pCon,pBueffel,eError);
            return 0;
          }    
          sprintf(pBueffel,"%s.%s = %f",argv[0],argv[1],fVal);
          SCWrite(pCon,pBueffel,eValue);
          return 1;
        }
     }        
  }
