From ac10723d74b560ae6a4654d4943438a295a93453 Mon Sep 17 00:00:00 2001 From: cvs Date: Fri, 7 Feb 2003 15:20:19 +0000 Subject: [PATCH] - TDC histogram memory driver sort of working - New class for scripting datafiles - SANS-II almost complete initialization file --- Makefile | 2 +- SCinter.h | 6 + conman.c | 5 +- doc/manager/nxscript.htm | 131 +++ ecb.c | 2 +- ecbdriv.c | 12 + histmem.c | 3 + macro.c | 5 - motor.c | 4 +- motreg.c | 14 +- napi.c | 2022 ++++++++++---------------------------- napi.h | 209 ++-- napi4.c | 52 +- napi5.c | 351 ++++--- nxdict.c | 3 +- nxscript.c | 716 ++++++++++++++ nxscript.h | 20 + nxscript.w | 48 + ofac.c | 3 + sans.tcl | 1 + sans2.dic | 139 +++ sans2.tcl | 599 +++++++++++ sans2com.tcl | 261 +++++ sicsstat.tcl | 37 + tdchm.c | 31 +- 25 files changed, 2965 insertions(+), 1711 deletions(-) create mode 100644 doc/manager/nxscript.htm create mode 100644 nxscript.c create mode 100644 nxscript.h create mode 100644 nxscript.w create mode 100644 sans2.dic create mode 100644 sans2.tcl create mode 100644 sans2com.tcl diff --git a/Makefile b/Makefile index 80e124c7..3b44d34c 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \ polterwrite.o fourlib.o motreg.o motreglist.o anticollider.o \ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) ecb.o ecbdriv.o \ - ecbcounter.o hmdata.o tdchm.o + ecbcounter.o hmdata.o tdchm.o nxscript.o MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/SCinter.h b/SCinter.h index e5ae3dce..34e96501 100644 --- a/SCinter.h +++ b/SCinter.h @@ -10,6 +10,7 @@ #ifndef SICSINTERPRETER #define SICSINTERPRETER #include "Scommon.h" +#include /* M.Z. */ #include "definealias.i" @@ -141,5 +142,10 @@ typedef struct __SINTER ------------------------------------------------------------------------*/ void *FindDrivable(SicsInterp *pics, char *name); + +/*----------------------------------------------------------------------- + Get a copy of the Tcl interpreter + ------------------------------------------------------------------------*/ +Tcl_Interp *InterpGetTcl(SicsInterp *pSics); #endif diff --git a/conman.c b/conman.c index 4e8a188b..a2a542b0 100644 --- a/conman.c +++ b/conman.c @@ -1276,9 +1276,8 @@ extern pServer pServ; strtolower(argv[1]); if(strcmp(argv[1],"list") == 0) { - sprintf(pBueffel,"OutCode = %s",pCode[pCon->iOutput]); - SCWrite(pCon,pBueffel,eStatus); - sprintf(pBueffel,"UserRights = %d",SCGetRights(pCon)); + sprintf(pBueffel,"OutCode = %s\nUserRights = %d", + pCode[pCon->iOutput], SCGetRights(pCon)); SCWrite(pCon,pBueffel,eStatus); return 1; } diff --git a/doc/manager/nxscript.htm b/doc/manager/nxscript.htm new file mode 100644 index 00000000..91a99e7e --- /dev/null +++ b/doc/manager/nxscript.htm @@ -0,0 +1,131 @@ + + +Scripting NeXus Files + + +

Scripting NeXus Files

+

+This section describes the scripting interface to NeXus +files, called nxscript. Scripting the generation of NeXus files has +the advantage that +it can be customised very quickly to special needs. Moreover it might +help to reduce the amount of instrument specific code required for an +instrument. This scripting interface uses the NeXus dictionary API for +the actual writing process. This has the following consequences: +

+

+

Usage

+

+Before this facility can be used nxscript has to be installed into the +SICServer from the instrument configuration file. This is done through +the command: +

+
MakeNXScript ?name? +
This creates a NeXus scripting object. If the name is omitted, an +object named nxscript is created. If a name is given, this name is +used for the scripting object. Having scripting objects with different +names is also the only possibility to have more then one NeXus file +writing operation going at a given time. +
+In the following sections it is assumed that an object nxscript +had been configured into SICS. +

+

File Opening and Closing

+

+

+
nxscript create5 nexusFile dictFile +
Creates a new NeXus file based on HDF-5 with the name +nexusFile. The dictionary file dictFile is used. +
nxscript create4 nexusFile dictFile +
Creates a new NeXus file based on HDF-4 with the name +nexusFile. The dictionary file dictFile is used. +
nxscript reopen nexusFile dictFile +
Reopens an existing NeXus with the name +nexusFile for modification or appending. +The dictionary file dictFile is used. +
nxscript close +
Closes the current NeXus file. This command MUST be given at the +end of each script in order to make sure that all data is written +properly to disk. +
+

+

Writing Things

+

+

+
nxscript puttext alias bla bla bla .... +
Writes everything after alias as text data to the alias. The +definition string for the alias should not contain a dimension +description, this is automatically appended. +
nxscript putfloat alias value +
Writes a single floating point value to alias alias. +
nscript putmot aliasName motorName +
Writes the position of the motor motorName into the NeXus file as +described by aliasName. Theposition is a zero point corrected position. If +another alias aliasname_null exists in the dictionary, the zero +point of the motor is also written to file. +
nxscript putcounter aliasBase counterName +
Writes counter data to a NeXus file. Data is taken from the single +counter counterName. What is written depends on the aliases present in +the dictionary file: +
+
aliasBase_preset +
The preset value. +
aliasBase_mode +
The counter mode +
aliasBase_time +
The actual time counted, without breaks due to insufficient beam. +
aliasbase_00 ... aliasBase_09 +
The monitor readings for monitors 0 to 9. Please note that 00 +would denote the normal counting tube at a scanning type of +experiment. +
+
nxscript puthm hmAlias hmName ?start? ?length? +
Writes data from the histogram memory hmName to a NeXus file using +the alias hmAlias. The definition string for the alias should not +contain neither -rank nor -dim information as this will be appended by +nxscript. If the optional parameters start and end are given, a +subset of the data is written. It is the users responsability that the +values requested make sense to the histogram memory. In the case of +subset writing, the dimensions have to be specified in the definition +string belonging to the alias. Nxscript sets a variable timedim in the +dictionary though which contains the length of a time binning if +appropriate. This is a special help for writing extra detectors at +SANS and AMOR. +
nxscript puttimebinning aliasName hmName +
Writes the time binning at histogram memory hmName to file using +the alias aliasName. The length of the time binning data is +automatically appended to the definition string for the alias. +
nxscript putarray aliasName arrayName length +
Writes the Tcl array arrayName to file using the aliasName. The +definiton string belonging to aliasName does not need to contain a +-dim argument as this is set by this routine. The parameter length is +the length of the array. Only rank 1 arrays are supported. +
nxsript putglobal attName bla bla bla +
This writes an global attribute attName. Everything after attName +is concatenated to a string which then respresents the value of the +attribute. +
nxscript makelink targetAlias victimAlias +
This creates a symbolic link for victimAlias in the group +designated by targetAlias. +
+

+ + diff --git a/ecb.c b/ecb.c index 4173d560..cc5ed1e5 100644 --- a/ecb.c +++ b/ecb.c @@ -344,7 +344,7 @@ int ECBAction(SConnection *pCon, SicsInterp *pSics, void *pData, SCWrite(pCon,pError,eError); return 0; } - sprintf(pBuffer,"%x %x %x %x", + sprintf(pBuffer,"%d %d %d %d", out.d, out.e, out.b, out.c); SCWrite(pCon,pBuffer,eValue); return 1; diff --git a/ecbdriv.c b/ecbdriv.c index 0d3c53ed..c1be5d8c 100644 --- a/ecbdriv.c +++ b/ecbdriv.c @@ -1177,3 +1177,15 @@ MotorDriver *CreateECBMotor(SConnection *pCon, int argc, char *argv[]){ self->errorCode = 0; return (MotorDriver *)self; } +/*=======================================================================*/ +void KillECBMotor(void *pDriver){ + int i; + pECBMotDriv self = (pECBMotDriv)pDriver; + + for(i = 0; i < MAXPAR; i++){ + if(self->driverPar[i].name != NULL){ + free(self->driverPar[i].name); + } + } + free(self); +} diff --git a/histmem.c b/histmem.c index 8d7bd5b5..5ccad538 100644 --- a/histmem.c +++ b/histmem.c @@ -10,6 +10,9 @@ added getzip: Mark Koennecke, October 2000 + Refactored data handling into separater HMdata class. + Mark Koennecke, January 2003 + Copyright: Labor fuer Neutronenstreuung diff --git a/macro.c b/macro.c index bb1a9c3b..1119e05e 100644 --- a/macro.c +++ b/macro.c @@ -70,11 +70,6 @@ #include "servlog.h" #define SICSERROR "005567SICS" - -/* in SCinter.c, but only used here */ - -extern Tcl_Interp *InterpGetTcl(SicsInterp *pSics); - /*---------------------------------------------------------------------------- SICS Macro uses the Tcl "unknown" mechanism to access the Sics-objects. The Tcl algorithm is to call a command called unknown when it cannot diff --git a/motor.c b/motor.c index f6a7ad6e..e1ea8f1f 100644 --- a/motor.c +++ b/motor.c @@ -57,6 +57,7 @@ #include "splitter.h" #include "status.h" #include "servlog.h" +#include "ecbdriv.h" /*------------------------------------------------------------------------- some lokal defines @@ -468,7 +469,7 @@ extern void KillPiPiezo(void *pData); } else if(strcmp(pM->drivername,"ECB") == 0) { - free(pM->pDriver); + KillECBMotor( (void *)pM->pDriver); } free(pM->drivername); } @@ -876,7 +877,6 @@ extern void KillPiPiezo(void *pData); */ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); -extern MotorDriver *CreateECBMotor(SConnection *pCon, int argc, char *argv[]); int MotorCreate(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) diff --git a/motreg.c b/motreg.c index c6c93214..348f833b 100644 --- a/motreg.c +++ b/motreg.c @@ -108,9 +108,11 @@ int StartRegMot(pMotReg self, SConnection *pCon, float fValue){ self->motorData, pCon, fValue); + /* sprintf(pBueffel,"anticollision started %s to %f",self->motorName, fValue); SCWrite(pCon,pBueffel,eValue); + */ pDriv->SetValue = oldSet; self->iActive = 1; @@ -121,9 +123,13 @@ int CheckRegMot(pMotReg self, SConnection *pCon){ int stat; assert(self); - stat = self->originalCheckStatus(self->motorData,pCon); - if(stat != HWBusy){ - self->iActive = 0; + if(self->iActive){ + stat = self->originalCheckStatus(self->motorData,pCon); + if(stat != HWBusy){ + self->iActive = 0; + } + } else { + return HWIdle; } - return stat; } + diff --git a/napi.c b/napi.c index 97310d98..e75f665c 100644 --- a/napi.c +++ b/napi.c @@ -19,331 +19,547 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Contact : Mark Koennecke - Labor fuer Neutronenstreuung - Paul Scherrer Institut - CH-5232 Villigen-PSI - Switzerland - - Przemek Klosowski - NIST Center for Neutron Research - 100 Bureau Drive, Stop 8562 - Gaithersburg, MD 20899-8562 - USA - For further information, see ----------------------------------------------------------------------------*/ -static const char* rscid = "$Id: napi.c,v 1.5 2001/10/25 13:58:00 cvs Exp $"; /* Revision interted by CVS */ +static const char* rscid = "$Id: napi.c,v 1.6 2003/02/07 15:20:20 cvs Exp $"; /* Revision interted by CVS */ #include #include #include #include -#include #include "napi.h" -#define NXMAXSTACK 50 -#define NXSIGNATURE 959697 - - typedef struct __NexusFile { - struct iStack { - int32 *iRefDir; - int32 *iTagDir; - int32 iVref; - int32 __iStack_pad; /* for 64 bit alignment */ - int iNDir; - int iCurDir; - } iStack[NXMAXSTACK]; - struct iStack iAtt; - int32 iVID; - int32 iSID; - int32 iCurrentVG; - int32 iCurrentSDS; - int iNXID; - int iStackPtr; - char iAccess[2]; - } NexusFile, *pNexusFile; - - - /*---------------------------------------------------------------------*/ - static void NXNXNXReportError(void *pData, char *string) - { -#if defined(_WIN32) && ( defined(_DLL) || defined(_HDFDLL_) ) && !defined(_CONSOLE) && !defined(JNEXUS) /* - * printf() output may get lost in Windows applications without a console ... this code - * makes them appear in Dialog boxes. To use printf(), you would probably have to create - * a console window with AllocConsole(), or get hold of "stdout" from the main program - * and then use fprintf(main_program_stdout, ... ) rather then printf(...) + * We need to include CALLING_STYLE in the function pointer definition + * or else we get a type mismatch on Win32 */ - MessageBeep(MB_ICONEXCLAMATION); - MessageBox(NULL, string, "NeXus Error", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); -#else - printf("%s \n",string); -#endif /* _WIN32 */ - } - /*---------------------------------------------------------------------*/ - void *NXpData = NULL; - void (*NXIReportError)(void *pData, char *string) = NXNXNXReportError; - /*---------------------------------------------------------------------*/ - void CALLING_STYLE NXMSetError(void *pData, void (*NewError)(void *pD, char *text)) - { - NXpData = pData; - NXIReportError = NewError; - } + typedef struct { + NXhandle *pNexusData; + NXstatus (CALLING_STYLE *nxclose)(NXhandle* pHandle); + NXstatus (CALLING_STYLE *nxflush)(NXhandle* pHandle); + NXstatus (CALLING_STYLE *nxmakegroup) (NXhandle handle, CONSTCHAR *name, char* NXclass); + NXstatus (CALLING_STYLE *nxopengroup) (NXhandle handle, CONSTCHAR *name, char* NXclass); + NXstatus (CALLING_STYLE *nxclosegroup)(NXhandle handle); + NXstatus (CALLING_STYLE *nxmakedata) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); + NXstatus (CALLING_STYLE *nxcompmakedata) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]); + NXstatus (CALLING_STYLE *nxcompress) (NXhandle handle, int compr_type); + NXstatus (CALLING_STYLE *nxopendata) (NXhandle handle, CONSTCHAR* label); + NXstatus (CALLING_STYLE *nxclosedata)(NXhandle handle); + NXstatus (CALLING_STYLE *nxputdata)(NXhandle handle, void* data); + NXstatus (CALLING_STYLE *nxputattr)(NXhandle handle, CONSTCHAR* name, void* data, int iDataLen, int iType); + NXstatus (CALLING_STYLE *nxputslab)(NXhandle handle, void* data, int start[], int size[]); + NXstatus (CALLING_STYLE *nxgetdataID)(NXhandle handle, NXlink* pLink); + NXstatus (CALLING_STYLE *nxmakelink)(NXhandle handle, NXlink* pLink); + NXstatus (CALLING_STYLE *nxgetdata)(NXhandle handle, void* data); + NXstatus (CALLING_STYLE *nxgetinfo)(NXhandle handle, int* rank, int dimension[], int* datatype); + NXstatus (CALLING_STYLE *nxgetnextentry)(NXhandle handle, NXname name, NXname nxclass, int* datatype); + NXstatus (CALLING_STYLE *nxgetslab)(NXhandle handle, void* data, int start[], int size[]); + NXstatus (CALLING_STYLE *nxgetnextattr)(NXhandle handle, NXname pName, int *iLength, int *iType); + NXstatus (CALLING_STYLE *nxgetattr)(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); + NXstatus (CALLING_STYLE *nxgetattrinfo)(NXhandle handle, int* no_items); + NXstatus (CALLING_STYLE *nxgetgroupID)(NXhandle handle, NXlink* pLink); + NXstatus (CALLING_STYLE *nxgetgroupinfo)(NXhandle handle, int* no_items, NXname name, NXname nxclass); + NXstatus (CALLING_STYLE *nxsameID)(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID); + NXstatus (CALLING_STYLE *nxinitgroupdir)(NXhandle handle); + NXstatus (CALLING_STYLE *nxinitattrdir)(NXhandle handle); + } NexusFunction, *pNexusFunction; - /*--------------------------------------------------------------------*/ - static pNexusFile NXIassert(NXhandle fid) - { - pNexusFile pRes; + static int iFortifyScope; +/*------------------------------------------------------------------------ + HDF-5 cache size special stuff + -------------------------------------------------------------------------*/ +static long cacheSize = 1024000; /* 1MB, HDF-5 default */ + +NXstatus CALLING_STYLE NXsetcache(long newVal) +{ + if(newVal > 0) + { + cacheSize = newVal; + return NX_OK; + } + return NX_ERROR; +} + + + /*---------------------------------------------------------------------*/ + + static void NXNXNXReportError(void *pData, char *string) + { + printf("%s \n",string); + } + + /*---------------------------------------------------------------------*/ + + void *NXpData = NULL; + void (*NXIReportError)(void *pData, char *string) = NXNXNXReportError; + + /*---------------------------------------------------------------------*/ + + void CALLING_STYLE NXMSetError(void *pData, void (*NewError)(void *pD, char *text)) + { + NXpData = pData; + NXIReportError = NewError; + } - assert(fid != NULL); - pRes = (pNexusFile)fid; - assert(pRes->iNXID == NXSIGNATURE); - return pRes; - } +#ifdef HDF5 +#include "napi5.h" +#endif +#ifdef HDF4 +#include "napi4.h" +#endif + + + /* ---------------------------------------------------------------------- + + Definition of NeXus API + + ---------------------------------------------------------------------*/ + + + NXstatus CALLING_STYLE NXopen(CONSTCHAR *filename, NXaccess am, NXhandle *gHandle) + { + int hdf_type=0; + int iRet=0; + NXhandle hdf5_handle; + NXhandle hdf4_handle; + pNexusFunction fHandle; + + /* configure fortify + iFortifyScope = Fortify_EnterScope(); + Fortify_CheckAllMemory(); + */ + + fHandle = (pNexusFunction)malloc(sizeof(NexusFunction)); + if (fHandle == NULL) { + NXIReportError (NXpData,"ERROR: no memory to create Function structure"); + return NX_ERROR; + } + if (am==NXACC_CREATE) { + /* HDF4 will be used ! */ + hdf_type=1; + } else if (am==NXACC_CREATE4) { + /* HDF4 will be used ! */ + hdf_type=1; + } else if (am==NXACC_CREATE5) { + /* HDF5 will be used ! */ + hdf_type=2; + } else { + /* check file type hdf4/hdf5 for reading */ +#ifdef HDF5 + iRet=H5Fis_hdf5((const char*)filename); +#endif + if (iRet>0) { + hdf_type=2; + } else { +#ifdef HDF4 + iRet=Hishdf((const char*)filename); +#endif + if (iRet>0) { + hdf_type=1; + } + } + } + if (hdf_type==1) { + /* HDF4 type */ +#ifdef HDF4 + NX4open((const char *)filename,am,&hdf4_handle); + fHandle->pNexusData=hdf4_handle; + fHandle->nxclose=NX4close; + fHandle->nxflush=NX4flush; + fHandle->nxmakegroup=NX4makegroup; + fHandle->nxopengroup=NX4opengroup; + fHandle->nxclosegroup=NX4closegroup; + fHandle->nxmakedata=NX4makedata; + fHandle->nxcompmakedata=NX4compmakedata; + fHandle->nxcompress=NX4compress; + fHandle->nxopendata=NX4opendata; + fHandle->nxclosedata=NX4closedata; + fHandle->nxputdata=NX4putdata; + fHandle->nxputattr=NX4putattr; + fHandle->nxputslab=NX4putslab; + fHandle->nxgetdataID=NX4getdataID; + fHandle->nxmakelink=NX4makelink; + fHandle->nxgetdata=NX4getdata; + fHandle->nxgetinfo=NX4getinfo; + fHandle->nxgetnextentry=NX4getnextentry; + fHandle->nxgetslab=NX4getslab; + fHandle->nxgetnextattr=NX4getnextattr; + fHandle->nxgetattr=NX4getattr; + fHandle->nxgetattrinfo=NX4getattrinfo; + fHandle->nxgetgroupID=NX4getgroupID; + fHandle->nxgetgroupinfo=NX4getgroupinfo; + fHandle->nxsameID=NX4sameID; + fHandle->nxinitgroupdir=NX4initgroupdir; + fHandle->nxinitattrdir=NX4initattrdir; +#endif + *gHandle = fHandle; + return NX_OK; + } else if (hdf_type==2) { + /* HDF5 type */ +#ifdef HDF5 + NX5open(filename,am,&hdf5_handle); + fHandle->pNexusData=hdf5_handle; + fHandle->nxclose=NX5close; + fHandle->nxflush=NX5flush; + fHandle->nxmakegroup=NX5makegroup; + fHandle->nxopengroup=NX5opengroup; + fHandle->nxclosegroup=NX5closegroup; + fHandle->nxmakedata=NX5makedata; + fHandle->nxcompmakedata=NX5compmakedata; + fHandle->nxcompress=NX5compress; + fHandle->nxopendata=NX5opendata; + fHandle->nxclosedata=NX5closedata; + fHandle->nxputdata=NX5putdata; + fHandle->nxputattr=NX5putattr; + fHandle->nxputslab=NX5putslab; + fHandle->nxgetdataID=NX5getdataID; + fHandle->nxmakelink=NX5makelink; + fHandle->nxgetdata=NX5getdata; + fHandle->nxgetinfo=NX5getinfo; + fHandle->nxgetnextentry=NX5getnextentry; + fHandle->nxgetslab=NX5getslab; + fHandle->nxgetnextattr=NX5getnextattr; + fHandle->nxgetattr=NX5getattr; + fHandle->nxgetattrinfo=NX5getattrinfo; + fHandle->nxgetgroupID=NX5getgroupID; + fHandle->nxgetgroupinfo=NX5getgroupinfo; + fHandle->nxsameID=NX5sameID; + fHandle->nxinitgroupdir=NX5initgroupdir; + fHandle->nxinitattrdir=NX5initattrdir; +#endif + *gHandle = fHandle; + return NX_OK; + } else { + NXIReportError (NXpData,"ERROR: Format not readable by this NeXus library"); + *gHandle = NULL; + return NX_ERROR; + } + } + +/* ------------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXclose (NXhandle *fid) + { + NXhandle hfil; + int status; + + pNexusFunction pFunc=NULL; + pFunc = (pNexusFunction)*fid; + hfil = pFunc->pNexusData; + status = pFunc->nxclose(&hfil); + pFunc->pNexusData = hfil; + free(pFunc); + /* + Fortify_CheckAllMemory(); + */ + return status; + } + + /*-----------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXmakegroup (NXhandle fid, CONSTCHAR *name, char *nxclass) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxmakegroup(pFunc->pNexusData, name, nxclass); + } + + /*------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXopengroup (NXhandle fid, CONSTCHAR *name, char *nxclass) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxopengroup(pFunc->pNexusData, name, nxclass); + } + + /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXclosegroup (NXhandle fid) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxclosegroup(pFunc->pNexusData); + } + + /* --------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXmakedata (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int dimensions[]) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxmakedata(pFunc->pNexusData, name, datatype, rank, dimensions); + } + + + /* --------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXcompmakedata (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int dimensions[],int compress_type, int chunk_size[]) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxcompmakedata (pFunc->pNexusData, name, datatype, rank, dimensions, compress_type, chunk_size); + } + + + /* --------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXcompress (NXhandle fid, int compress_type) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxcompress (pFunc->pNexusData, compress_type); + } + + + /* --------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXopendata (NXhandle fid, CONSTCHAR *name) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxopendata(pFunc->pNexusData, name); + } + + + /* ----------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXclosedata (NXhandle fid) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxclosedata(pFunc->pNexusData); + } + + /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXputdata (NXhandle fid, void *data) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxputdata(pFunc->pNexusData, data); + } + + /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXputattr (NXhandle fid, CONSTCHAR *name, void *data, + int datalen, int iType) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxputattr(pFunc->pNexusData, name, data, datalen, iType); + } + + /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXputslab (NXhandle fid, void *data, int iStart[], int iSize[]) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxputslab(pFunc->pNexusData, data, iStart, iSize); + } + + /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXgetdataID (NXhandle fid, NXlink* sRes) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxgetdataID(pFunc->pNexusData, sRes); + } + + + /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NXmakelink (NXhandle fid, NXlink* sLink) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxmakelink(pFunc->pNexusData, sLink); + } + /*----------------------------------------------------------------------*/ - static int32 - NXIFindVgroup (pNexusFile pFile, char *name, char *nxclass) + + NXstatus CALLING_STYLE NXflush(NXhandle *pHandle) { - int32 iNew, iRef, iTag; - int iN, i; - int32 *pArray = NULL; - NXname pText; - - assert (pFile != NULL); - - if (pFile->iCurrentVG == 0) { /* root level */ - /* get the number and ID's of all lone Vgroups in the file */ - iN = Vlone (pFile->iVID, NULL, 0); - if(iN == 0) { - return NX_EOD; - } - pArray = (int32 *) malloc (iN * sizeof (int32)); - if (!pArray) { - NXIReportError (NXpData, "ERROR: out of memory in NXIFindVgroup"); - return NX_EOD; - } - Vlone (pFile->iVID, pArray, iN); - - /* loop and check */ - for (i = 0; i < iN; i++) { - iNew = Vattach (pFile->iVID, pArray[i], "r"); - Vgetname (iNew, pText); - if (strcmp (pText, name) == 0) { - Vgetclass (iNew, pText); - if (strcmp (pText, nxclass) == 0) { - /* found ! */ - Vdetach (iNew); - iNew = pArray[i]; - free (pArray); - return iNew; - } - } - Vdetach (iNew); - } - /* nothing found */ - free (pArray); - return NX_EOD; - } else { /* case in Vgroup */ - iN = Vntagrefs (pFile->iCurrentVG); - for (i = 0; i < iN; i++) { - Vgettagref (pFile->iCurrentVG, i, &iTag, &iRef); - if (iTag == DFTAG_VG) { - iNew = Vattach (pFile->iVID, iRef, "r"); - Vgetname (iNew, pText); - if (strcmp (pText, name) == 0) { - Vgetclass (iNew, pText); - if (strcmp (pText, nxclass) == 0) { - /* found ! */ - Vdetach (iNew); - return iRef; - } - } - Vdetach (iNew); - } - } /* end for */ - } /* end else */ - /* not found */ - return NX_EOD; + NXhandle hfil; + int status; + + pNexusFunction pFunc=NULL; + pFunc = (pNexusFunction)*pHandle; + hfil = pFunc->pNexusData; + status = pFunc->nxflush(&hfil); + pFunc->pNexusData = hfil; + return status; } + + + /*-------------------------------------------------------------------------*/ - static int32 - NXIFindSDS (NXhandle fid, CONSTCHAR *name) - { - pNexusFile self; - int32 iNew, iRet, iTag, iRef; - int32 i, iN, iA, iD1, iD2; - NXname pNam; - int32 iDim[MAX_VAR_DIMS]; - - self = NXIassert (fid); - - /* root level search */ - if (self->iCurrentVG == 0) { - i = SDfileinfo (self->iSID, &iN, &iA); - if (i < 0) { - NXIReportError (NXpData, "ERROR: failure to read file information"); - return NX_EOD; - } - for (i = 0; i < iN; i++) { - iNew = SDselect (self->iSID, i); - SDgetinfo (iNew, pNam, &iA, iDim, &iD2, &iD2); - if (strcmp (pNam, name) == 0) { - iRet = SDidtoref (iNew); - SDendaccess (iNew); - return iRet; - } else { - SDendaccess (iNew); - } - } - /* not found */ - return NX_EOD; - } - /* end root level */ - else { /* search in a Vgroup */ - iN = Vntagrefs (self->iCurrentVG); - for (i = 0; i < iN; i++) { - Vgettagref (self->iCurrentVG, i, &iTag, &iRef); - /* we are now writing using DFTAG_NDG, but need others for backward compatability */ - if ((iTag == DFTAG_SDG) || (iTag == DFTAG_NDG) || (iTag == DFTAG_SDS)) { - iNew = SDreftoindex (self->iSID, iRef); - iNew = SDselect (self->iSID, iNew); - SDgetinfo (iNew, pNam, &iA, iDim, &iD2, &iD2); - if (strcmp (pNam, name) == 0) { - SDendaccess (iNew); - return iRef; - } - SDendaccess (iNew); - } - } /* end for */ - } /* end Vgroup */ - /* we get here, only if nothing found */ - return NX_EOD; - } - - static int - NXIInitDir (pNexusFile self) + NXstatus CALLING_STYLE NXmalloc (void** data, int rank, int dimensions[], int datatype) { int i; - int32 iTag, iRef; - int iStackPtr, iCurDir; - -/* - * Note: the +1 to various malloc() operations is to avoid a - * malloc(0), which is an error on some operating systems - */ - iStackPtr = self->iStackPtr; - if (self->iCurrentVG == 0 && - self->iStack[iStackPtr].iRefDir == NULL) { /* root level */ - /* get the number and ID's of all lone Vgroups in the file */ - self->iStack[iStackPtr].iNDir = Vlone (self->iVID, NULL, 0); - self->iStack[iStackPtr].iRefDir = - (int32 *) malloc (self->iStack[iStackPtr].iNDir * sizeof (int32) + 1); - if (!self->iStack[iStackPtr].iRefDir) { - NXIReportError (NXpData, "ERROR: out of memory in NXIInitDir"); - return NX_EOD; + size_t size = 1; + *data = NULL; + for(i=0; iiVID, - self->iStack[self->iStackPtr].iRefDir, - self->iStack[self->iStackPtr].iNDir); - } else { - /* Vgroup level */ - self->iStack[iStackPtr].iNDir = Vntagrefs (self->iCurrentVG); - self->iStack[iStackPtr].iRefDir = - (int32 *) malloc (self->iStack[iStackPtr].iNDir * sizeof (int32) + 1); - self->iStack[iStackPtr].iTagDir = - (int32 *) malloc (self->iStack[iStackPtr].iNDir * sizeof (int32) + 1); - if ((!self->iStack[iStackPtr].iRefDir) || - (!self->iStack[iStackPtr].iTagDir)) { - NXIReportError (NXpData, "ERROR: out of memory in NXIInitDir"); - return NX_EOD; - } - for (i = 0; i < self->iStack[self->iStackPtr].iNDir; i++) { - Vgettagref (self->iCurrentVG, i, &iTag, &iRef); - self->iStack[iStackPtr].iRefDir[i] = iRef; - self->iStack[iStackPtr].iTagDir[i] = iTag; + else if ((datatype == NX_INT16) || (datatype == NX_UINT16)) { + size *= 2; + } + else if ((datatype == NX_INT32) || (datatype == NX_UINT32) || (datatype == NX_FLOAT32)) { + size *= 4; + } + else if (datatype == NX_FLOAT64) { + size *= 8; } + else { + NXIReportError (NXpData, "ERROR: NXmalloc - unknown data type in array"); + return NX_ERROR; } - self->iStack[iStackPtr].iCurDir = 0; - return 1; + *data = (void*)malloc(size); + memset(*data,0,size); + return NX_OK; + } + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXfree (void** data) + { + if (data == NULL) { + NXIReportError (NXpData, "ERROR: passing NULL to NXfree"); + return NX_ERROR; + } + if (*data == NULL) { + NXIReportError (NXpData,"ERROR: passing already freed pointer to NXfree"); + return NX_ERROR; + } + free(*data); + *data = NULL; + return NX_OK; + } + + /* --------------------------------------------------------------------- */ + + + NXstatus CALLING_STYLE NXgetnextentry (NXhandle fid, NXname name, NXname nxclass, int *datatype) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxgetnextentry(pFunc->pNexusData, name, nxclass, datatype); + } + + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXgetdata (NXhandle fid, void *data) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxgetdata(pFunc->pNexusData, data); } - static void - NXIKillDir (pNexusFile self) + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXgetinfo (NXhandle fid, int *rank, int dimension[], int *iType) { - if (self->iStack[self->iStackPtr].iRefDir) { - free (self->iStack[self->iStackPtr].iRefDir); - self->iStack[self->iStackPtr].iRefDir = NULL; - } - if (self->iStack[self->iStackPtr].iTagDir) { - free (self->iStack[self->iStackPtr].iTagDir); - self->iStack[self->iStackPtr].iTagDir = NULL; - } - self->iStack[self->iStackPtr].iCurDir = 0; - self->iStack[self->iStackPtr].iNDir = 0; + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxgetinfo(pFunc->pNexusData, rank, dimension, iType); } /*-------------------------------------------------------------------------*/ - static int - NXIInitAttDir (pNexusFile pFile) + + NXstatus CALLING_STYLE NXgetslab (NXhandle fid, void *data, int iStart[], int iSize[]) { - int iRet; - int32 iData, iAtt, iRank, iType; - int32 iDim[MAX_VAR_DIMS]; - NXname pNam; - - pFile->iAtt.iCurDir = 0; - if (pFile->iCurrentSDS != 0) { /* SDS level */ - iRet = SDgetinfo (pFile->iCurrentSDS, pNam, &iRank, iDim, &iType, - &iAtt); - } else { /* global level */ - iRet = SDfileinfo (pFile->iSID, &iData, &iAtt); - } - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot read attribute numbers"); - pFile->iAtt.iNDir = 0; - return NX_ERROR; - } - pFile->iAtt.iNDir = iAtt; - return NX_OK; + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxgetslab(pFunc->pNexusData, data, iStart, iSize); } - static void - NXIKillAttDir (pNexusFile self) + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXgetnextattr (NXhandle fileid, NXname pName, + int *iLength, int *iType) { - if (self->iAtt.iRefDir) { - free (self->iAtt.iRefDir); - self->iAtt.iRefDir = NULL; - } - if (self->iAtt.iTagDir) { - free (self->iAtt.iTagDir); - self->iAtt.iTagDir = NULL; - } - self->iAtt.iCurDir = 0; - self->iAtt.iNDir = 0; + pNexusFunction pFunc = (pNexusFunction)fileid; + return pFunc->nxgetnextattr(pFunc->pNexusData, pName, iLength, iType); + } + + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXgetattr (NXhandle fid, char *name, void *data, int* datalen, int* iType) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxgetattr(pFunc->pNexusData, name, data, datalen, iType); + } + + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXgetattrinfo (NXhandle fid, int *iN) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxgetattrinfo(pFunc->pNexusData, iN); + } + + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXgetgroupID (NXhandle fileid, NXlink* sRes) + { + pNexusFunction pFunc = (pNexusFunction)fileid; + return pFunc->nxgetgroupID(pFunc->pNexusData, sRes); + } + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXgetgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxgetgroupinfo(pFunc->pNexusData, iN, pName, pClass); + } + + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXsameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) + { + pNexusFunction pFunc = (pNexusFunction)fileid; + return pFunc->nxsameID(pFunc->pNexusData, pFirstID, pSecondID); + } + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXinitattrdir (NXhandle fid) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxinitattrdir(pFunc->pNexusData); } + + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXinitgroupdir (NXhandle fid) + { + pNexusFunction pFunc = (pNexusFunction)fid; + return pFunc->nxinitgroupdir(pFunc->pNexusData); + } +/*---------------------------------------------------------------------- + F77 - API - Support - Routines + ----------------------------------------------------------------------*/ /* * We store the whole of the NeXus file in the array - that way * we can just pass the array name to C as it will be a valid * NXhandle. We could store the NXhandle value in the FORTRAN array * instead, but that would mean writing far more wrappers */ - NXstatus CALLING_STYLE NXfopen(char * filename, NXaccess* am, NexusFile* pHandle) + NXstatus CALLING_STYLE NXfopen(char * filename, NXaccess* am, + NexusFunction* pHandle) { NXstatus ret; NXhandle fileid = NULL; ret = NXopen(filename, *am, &fileid); if (ret == NX_OK) { - memcpy(pHandle, fileid, sizeof(NexusFile)); + memcpy(pHandle, fileid, sizeof(NexusFunction)); } else { - memset(pHandle, 0, sizeof(NexusFile)); + memset(pHandle, 0, sizeof(NexusFunction)); } if (fileid != NULL) { @@ -351,434 +567,34 @@ static const char* rscid = "$Id: napi.c,v 1.5 2001/10/25 13:58:00 cvs Exp $"; /* } return ret; } - -/* - * On Open VMS prior to version 7.0 timezone support wasn't complete and gmtime() always returned NULL - */ -#if (defined(__VMS) && (__VMS_VER < 70000000)) -# define USE_FTIME /* use ftime() function */ -# include -#endif /* __VMS && __VMS_VER < 70000000 */ - -/* #define NEED_TZSET /* probably not needed now as we do not use the "timezone" external variable */ - - NXstatus CALLING_STYLE NXopen(CONSTCHAR * filename, NXaccess am, NXhandle* pHandle) - { - pNexusFile pNew = NULL; - char pBuffer[512], time_buffer[64]; - int iRet; - int32 file_id, an_id, ann_id; - time_t timer; - struct tm *time_info; - const char* time_format; - long gmt_offset; -#ifdef USE_FTIME - struct timeb timeb_struct; -#endif /* USE_FTIME */ - - *pHandle = NULL; - /* get memory */ - pNew = (pNexusFile) malloc (sizeof (NexusFile)); - if (!pNew) { - NXIReportError (NXpData, "ERROR: no memory to create File datastructure"); - return NX_ERROR; - } - memset (pNew, 0, sizeof (NexusFile)); -/* - * get time in ISO 8601 format - */ -#ifdef NEED_TZSET - tzset(); -#endif /* NEED_TZSET */ - time(&timer); -#ifdef USE_FTIME - ftime(&timeb_struct); - gmt_offset = -timeb_struct.timezone * 60; - if (timeb_struct.dstflag != 0) - { - gmt_offset += 3600; - } -#else - time_info = gmtime(&timer); - if (time_info != NULL) - { - gmt_offset = difftime(timer, mktime(time_info)); - } - else - { - NXIReportError(NXpData, "Your gmtime() function does not work ... timezone information will be incorrect\n"); - gmt_offset = 0; - } -#endif /* USE_FTIME */ - time_info = localtime(&timer); - if (time_info != NULL) - { - if (gmt_offset < 0) - { - time_format = "%04d-%02d-%02d %02d:%02d:%02d-%02d%02d"; - } - else - { - time_format = "%04d-%02d-%02d %02d:%02d:%02d+%02d%02d"; - } - sprintf(time_buffer, time_format, - 1900 + time_info->tm_year, - 1 + time_info->tm_mon, - time_info->tm_mday, - time_info->tm_hour, - time_info->tm_min, - time_info->tm_sec, - abs(gmt_offset / 3600), - abs((gmt_offset % 3600) / 60) - ); - } - else - { - strcpy(time_buffer, "1970-01-01 00:00:00+0000"); - } - -#if WRITE_OLD_IDENT /* not used at moment */ -/* - * write something that can be used by OLE - */ - if (am == NXACC_CREATE) - { - if ( (file_id = Hopen(filename, am, 0)) == -1 ) - { - sprintf (pBuffer, "ERROR: cannot open file: %s", filename); - NXIReportError (NXpData, pBuffer); - free (pNew); - return NX_ERROR; - } - an_id = ANstart(file_id); - ann_id = ANcreatef(an_id, AN_FILE_LABEL); /* AN_FILE_DESC */ - ANwriteann(ann_id, "NeXus", 5); - ANendaccess(ann_id); - ANend(an_id); - if (Hclose(file_id) == -1) - { - sprintf (pBuffer, "ERROR: cannot close file: %s", filename); - NXIReportError (NXpData, pBuffer); - free (pNew); - return NX_ERROR; - } - am = NXACC_RDWR; - } -#endif /* WRITE_OLD_IDENT */ - - /* start SDS interface */ - pNew->iSID = SDstart (filename, am); - if (pNew->iSID <= 0) { - sprintf (pBuffer, "ERROR: cannot open file: %s", filename); - NXIReportError (NXpData, pBuffer); - free (pNew); - return NX_ERROR; - } -/* - * need to create global attributes file_name file_time NeXus_version - * at some point for new files - */ - if (am != NXACC_READ) - { - if (SDsetattr(pNew->iSID, "NeXus_version", DFNT_CHAR8, strlen(NEXUS_VERSION), NEXUS_VERSION) < 0) - { - NXIReportError (NXpData, "ERROR: HDF failed to store NeXus_version attribute "); - return NX_ERROR; - } - } - if (am == NXACC_CREATE) - { - if (SDsetattr(pNew->iSID, "file_name", DFNT_CHAR8, strlen(filename), (char*)filename) < 0) - { - NXIReportError (NXpData, "ERROR: HDF failed to store file_name attribute "); - return NX_ERROR; - } - if (SDsetattr(pNew->iSID, "file_time", DFNT_CHAR8, strlen(time_buffer), time_buffer) < 0) - { - NXIReportError (NXpData, "ERROR: HDF failed to store file_time attribute "); - return NX_ERROR; - } - } - - /* - * Otherwise we try to create the file two times which makes HDF - * Throw up on us. - */ - if (am == NXACC_CREATE) { - am = NXACC_RDWR; - } - - /* Set Vgroup access mode */ - if (am == NXACC_READ) { - strcpy(pNew->iAccess,"r"); - } else { - strcpy(pNew->iAccess,"w"); - } - - /* start Vgroup API */ - pNew->iVID = Hopen (filename, am, 100); - if (pNew->iVID <= 0) { - sprintf (pBuffer, "ERROR: cannot open file: %s", filename); - NXIReportError (NXpData, pBuffer); - free (pNew); - return NX_ERROR; - } - Vstart (pNew->iVID); - pNew->iNXID = NXSIGNATURE; - pNew->iStack[0].iVref = 0; /* root! */ - - *pHandle = (NXhandle)pNew; - return NX_OK; - } - - /* * The pHandle from FORTRAN is a pointer to a static FORTRAN - * array holding the NexusFile structure. We need to malloc() + * array holding the NexusFunction structure. We need to malloc() * a temporary copy as NXclose will try to free() this */ - NXstatus CALLING_STYLE NXfclose (NexusFile* pHandle) + NXstatus CALLING_STYLE NXfclose (NexusFunction* pHandle) { NXhandle h; NXstatus ret; - h = (NXhandle)malloc(sizeof(NexusFile)); - memcpy(h, pHandle, sizeof(NexusFile)); + h = (NXhandle)malloc(sizeof(NexusFunction)); + memcpy(h, pHandle, sizeof(NexusFunction)); ret = NXclose(&h); /* does free(h) */ - memset(pHandle, 0, sizeof(NexusFile)); + memset(pHandle, 0, sizeof(NexusFunction)); return ret; } - - NXstatus CALLING_STYLE NXclose (NXhandle* fid) - { - pNexusFile pFile = NULL; - int iRet; - pFile = NXIassert(*fid); - iRet = 0; - /* close links into vGroups or SDS */ - if (pFile->iCurrentVG != 0) { - Vdetach (pFile->iCurrentVG); - } - if (pFile->iCurrentSDS != 0) { - iRet = SDendaccess (pFile->iCurrentSDS); - } - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: ending access to SDS"); - } - /* close the SDS and Vgroup API's */ - Vend (pFile->iVID); - iRet = SDend (pFile->iSID); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot close SDS interface"); - } - iRet = Hclose (pFile->iVID); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot close HDF file"); - } - /* release memory */ - NXIKillDir (pFile); - free (pFile); - *fid = NULL; - return NX_OK; - } -/*--------------------------------------------------------------------------- - For the same reasons as stated above we need a wrapper for the fortran - version of NXFlush - ---------------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NXfflush(NexusFile* pHandle) +/*---------------------------------------------------------------------*/ + NXstatus CALLING_STYLE NXfflush(NexusFunction* pHandle) { NXhandle h; NXstatus ret; - h = (NXhandle)malloc(sizeof(NexusFile)); - memcpy(h, pHandle, sizeof(NexusFile)); + h = (NXhandle)malloc(sizeof(NexusFunction)); + memcpy(h, pHandle, sizeof(NexusFunction)); ret = NXflush(&h); /* modifies and reallocates h */ - memcpy(pHandle, h, sizeof(NexusFile)); + memcpy(pHandle, h, sizeof(NexusFunction)); return ret; } - /*----------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NXflush(NXhandle *pHandle) - { - char *pFileName, *pCopy = NULL; - int access, dummy, iRet, i, iStack; - pNexusFile pFile = NULL; - NXaccess ac; - int *iRefs = NULL; - - pFile = NXIassert(*pHandle); - - /* - The HDF4-API does not support a flush. We help ourselves with - inquiring the name and access type of the file, closing it and - opening it again. This is also the reason why this needs a pointer - to the handle structure as the handle changes. The other thing we - do is to store the refs of all open vGroups in a temporary array - in order to recover the position in the vGroup hierarchy before the - flush. - */ - iRet = Hfidinquire(pFile->iVID,&pFileName,&access,&dummy); - if (iRet < 0) { - NXIReportError (NXpData, - "ERROR: Failed to inquire file name for HDF file"); - return NX_ERROR; - } - if(pFile->iAccess[0] == 'r') { - ac = NXACC_READ; - }else if(pFile->iAccess[0] == 'w') { - ac = NXACC_RDWR; - } - pCopy = (char *)malloc((strlen(pFileName)+10)*sizeof(char)); - if(!pCopy) { - NXIReportError (NXpData, - "ERROR: Failed to allocate data for filename copy"); - return NX_ERROR; - } - memset(pCopy,0,strlen(pFileName)+10); - strcpy(pCopy,pFileName); - - /* get refs for recovering vGroup position */ - iStack = 0; - if(pFile->iStackPtr > 0) { - iStack = pFile->iStackPtr + 1; - iRefs = (int *)malloc(iStack*sizeof(int)); - if(!iRefs){ - NXIReportError (NXpData, - "ERROR: Failed to allocate data for hierarchy copy"); - return NX_ERROR; - } - for(i = 0; i < iStack; i++){ - iRefs[i] = pFile->iStack[i].iVref; - } - } - - iRet = NXclose(pHandle); - if(iRet != NX_OK) { - return iRet; - } - - iRet = NXopen(pCopy, ac, pHandle); - free(pCopy); - - /* return to position in vGroup hierarchy */ - pFile = NXIassert(*pHandle); - if(iStack > 0){ - pFile->iStackPtr = iStack - 1; - for(i = 0; i < iStack; i++){ - pFile->iStack[i].iVref = iRefs[i]; - } - free(iRefs); - pFile->iCurrentVG = Vattach(pFile->iVID, - pFile->iStack[pFile->iStackPtr].iVref, - pFile->iAccess); - } - - return iRet; - } -/*-----------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NXmakegroup (NXhandle fid, CONSTCHAR *name, char *nxclass) - { - pNexusFile pFile; - int32 iNew, iRet; - char pBuffer[256]; - - pFile = NXIassert (fid); - /* - * Make sure that a group with the same name and nxclass does not - * already exist. - */ - if ((iRet = NXIFindVgroup (pFile, (char*)name, nxclass)) >= 0) { - sprintf (pBuffer, "ERROR: Vgroup %s, class %s already exists", - name, nxclass); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - - /* create and configure the group */ - iNew = Vattach (pFile->iVID, -1, "w"); - if (iNew < 0) { - NXIReportError (NXpData, "ERROR: HDF could not create Vgroup"); - return NX_ERROR; - } - Vsetname (iNew, name); - Vsetclass (iNew, nxclass); - - /* Insert it into the hierarchy, when appropriate */ - iRet = 0; - if (pFile->iCurrentVG != 0) { - iRet = Vinsert (pFile->iCurrentVG, iNew); - } - Vdetach (iNew); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF failed to insert Vgroup"); - return NX_ERROR; - } - return NX_OK; - } - - - /*------------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NXopengroup (NXhandle fid, CONSTCHAR *name, char *nxclass) - { - pNexusFile pFile; - int32 iNew, iRef; - char pBuffer[256]; - - pFile = NXIassert (fid); - - iRef = NXIFindVgroup (pFile, (char*)name, nxclass); - if (iRef < 0) { - sprintf (pBuffer, "ERROR: Vgroup %s, class %s NOT found", name, nxclass); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - /* are we at root level ? */ - if (pFile->iCurrentVG == 0) { - pFile->iCurrentVG = Vattach (pFile->iVID, iRef,pFile->iAccess); - pFile->iStackPtr++; - pFile->iStack[pFile->iStackPtr].iVref = iRef; - } else { - Vdetach (pFile->iCurrentVG); - pFile->iStackPtr++; - pFile->iStack[pFile->iStackPtr].iVref = iRef; - pFile->iCurrentVG = Vattach (pFile->iVID, - pFile->iStack[pFile->iStackPtr].iVref, - pFile->iAccess); - } - NXIKillDir (pFile); - return NX_OK; - } - - - NXstatus CALLING_STYLE NXclosegroup (NXhandle fid) - { - pNexusFile pFile; - - pFile = NXIassert (fid); - - /* first catch the trivial case: we are at root and cannot get - deeper into a negative directory hierarchy (anti-directory) - */ - if (pFile->iCurrentVG == 0) { - NXIKillDir (pFile); - return NX_OK; - } else { /* Sighhh. Some work to do */ - /* close the current VG and decrement stack */ - Vdetach (pFile->iCurrentVG); - NXIKillDir (pFile); - pFile->iStackPtr--; - if (pFile->iStackPtr <= 0) { /* we hit root */ - pFile->iStackPtr = 0; - pFile->iCurrentVG = 0; - } else { - /* attach to the lower Vgroup */ - pFile->iCurrentVG = Vattach (pFile->iVID, - pFile->iStack[pFile->iStackPtr].iVref, - pFile->iAccess); - } - } - return NX_OK; - } - NXstatus CALLING_STYLE NXfmakedata(NXhandle fid, char *name, int *pDatatype, int *pRank, int dimensions[]) { @@ -788,7 +604,9 @@ static const char* rscid = "$Id: napi.c,v 1.5 2001/10/25 13:58:00 cvs Exp $"; /* reversed_dimensions = (int*)malloc(*pRank * sizeof(int)); if (reversed_dimensions == NULL) { - sprintf (buffer, "ERROR: Cannot allocate space for array rank of %d in NXfmakedata", *pRank); + sprintf (buffer, + "ERROR: Cannot allocate space for array rank of %d in NXfmakedata", + *pRank); NXIReportError (NXpData, buffer); return NX_ERROR; } @@ -804,819 +622,47 @@ static const char* rscid = "$Id: napi.c,v 1.5 2001/10/25 13:58:00 cvs Exp $"; /* return ret; } - NXstatus CALLING_STYLE NXmakedata (NXhandle fid, CONSTCHAR *name, int datatype, int rank, - int dimensions[]) + + NXstatus CALLING_STYLE NXfcompmakedata(NXhandle fid, char *name, + int *pDatatype, + int *pRank, int dimensions[], + int *compression_type, int chunk[]) { - pNexusFile pFile; - int32 iNew; - char pBuffer[256]; - int i, iRet; - int32 myDim[MAX_VAR_DIMS]; - - pFile = NXIassert (fid); - - - if ((iNew = NXIFindSDS (fid, name))>=0) { - sprintf (pBuffer, "ERROR: SDS %s already exists at this level", name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - - - /* Do some argument checking */ - switch (datatype) { - case DFNT_FLOAT32: break; - case DFNT_FLOAT64: break; - case DFNT_INT8: break; - case DFNT_UINT8: break; - case DFNT_CHAR8: break; - case DFNT_UCHAR8: break; - case DFNT_INT16: break; - case DFNT_UINT16: break; - case DFNT_INT32: break; - case DFNT_UINT32: break; - default: - sprintf (pBuffer, "ERROR: unknown datatype specified for SDS %s", - name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - - if (rank <= 0) { - sprintf (pBuffer, "ERROR: invalid rank specified for SDS %s", - name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - - /* - Check dimensions for consistency. The first dimension may be 0 - thus denoting an unlimited dimension. - */ - for (i = 1; i < rank; i++) { - if (dimensions[i] <= 0) { - sprintf (pBuffer, - "ERROR: invalid dimension %d, value %d given for SDS %s", - i, dimensions[i], name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - } - - /* cast the dimensions array properly for non 32-bit ints */ - for(i = 0; i < rank; i++) + NXstatus ret; + static char buffer[256]; + int i, *reversed_dimensions, *reversed_chunk; + reversed_dimensions = (int*)malloc(*pRank * sizeof(int)); + reversed_chunk = (int*)malloc(*pRank * sizeof(int)); + if (reversed_dimensions == NULL || reversed_chunk == NULL) { - myDim[i] = (int32)dimensions[i]; + sprintf (buffer, + "ERROR: Cannot allocate space for array rank of %d in NXfcompmakedata", + *pRank); + NXIReportError (NXpData, buffer); + return NX_ERROR; } - - - /* behave nicely, if there is still an SDS open */ - if (pFile->iCurrentSDS != 0) { - SDendaccess (pFile->iCurrentSDS); - pFile->iCurrentSDS = 0; +/* + * Reverse dimensions array as FORTRAN is column major, C row major + */ + for(i=0; i < *pRank; i++) + { + reversed_dimensions[i] = dimensions[*pRank - i - 1]; + reversed_chunk[i] = chunk[*pRank - i - 1]; } - - /* Do not allow creation of SDS's at the root level */ - if (pFile->iCurrentVG == 0) { - sprintf(pBuffer, "ERROR: SDS creation at root level is not permitted"); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - - /* dataset creation */ - iNew = SDcreate (pFile->iSID, (char*)name, (int32)datatype, - (int32)rank, myDim); - if (iNew < 0) { - sprintf (pBuffer, "ERROR: cannot create SDS %s, check arguments", - name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - /* link into Vgroup, if in one */ - if (pFile->iCurrentVG != 0) { - iRet = Vaddtagref (pFile->iCurrentVG, DFTAG_NDG, SDidtoref (iNew)); - } - iRet = SDendaccess (iNew); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot end access to SDS"); - return NX_ERROR; - } - return NX_OK; + ret = NXcompmakedata(fid, name, *pDatatype, *pRank, + reversed_dimensions,*compression_type, reversed_chunk); + free(reversed_dimensions); + free(reversed_chunk); + return ret; } - - - NXstatus CALLING_STYLE NXopendata (NXhandle fid, CONSTCHAR *name) - { - pNexusFile pFile; - int32 iNew; - char pBuffer[256]; - int iRet; - - pFile = NXIassert (fid); - - /* First find the reference number of the SDS */ - iNew = NXIFindSDS (fid, name); - if (iNew < 0) { - sprintf (pBuffer, "ERROR: SDS %s not found at this level", name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - /* Be nice: properly close the old open SDS silently if there is - * still an SDS open. - */ - if (pFile->iCurrentSDS) { - iRet = SDendaccess (pFile->iCurrentSDS); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot end access to SDS"); - } - } - /* clear pending attribute directories first */ - NXIKillAttDir (pFile); - - /* open the SDS */ - iNew = SDreftoindex (pFile->iSID, iNew); - pFile->iCurrentSDS = SDselect (pFile->iSID, iNew); - if (pFile->iCurrentSDS < 0) { - NXIReportError (NXpData, "ERROR: HDF error opening SDS"); - pFile->iCurrentSDS = 0; - return NX_ERROR; - } - return NX_OK; - } - - +/*-----------------------------------------------------------------------*/ NXstatus CALLING_STYLE NXfcompress(NXhandle fid, int *compr_type) { return NXcompress(fid,*compr_type); } - - NXstatus CALLING_STYLE NXcompress (NXhandle fid, int compress_type) - { - pNexusFile pFile; - int32 iRank, iAtt, iType, iRet, i, e; - int32 iSize[MAX_VAR_DIMS]; - NXname pBuffer; - char pError[512]; - comp_info compstruct; - char *str; - - pFile = NXIassert (fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - - /* first read dimension information */ - SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); - - /* - according to compression type initialize compression - information - */ - if(compress_type == NX_COMP_LZW) - { - compstruct.deflate.level = 6; - } - else if(compress_type == NX_COMP_HUF) - { - compstruct.skphuff.skp_size = DFKNTsize(iType); - } - - iRet = SDsetcompress(pFile->iCurrentSDS, compress_type, &compstruct); - if (iRet < 0) { - sprintf (pError, "ERROR: failure to compress data to %s", pBuffer); - NXIReportError (NXpData, pError); - return NX_ERROR; - } - return NX_OK; - } - - NXstatus CALLING_STYLE NXclosedata (NXhandle fid) - { - pNexusFile pFile; - int iRet; - - pFile = NXIassert (fid); - - if (pFile->iCurrentSDS != 0) { - iRet = SDendaccess (pFile->iCurrentSDS); - pFile->iCurrentSDS = 0; - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot end access to SDS"); - return NX_ERROR; - } - } else { - NXIReportError (NXpData, "ERROR: no SDS open --> nothing to do"); - return NX_ERROR; - } - NXIKillAttDir (pFile); /* for attribute data */ - return NX_OK; - } - - - NXstatus CALLING_STYLE NXgetdata (NXhandle fid, void *data) - { - pNexusFile pFile; - int32 iStart[MAX_VAR_DIMS], iSize[MAX_VAR_DIMS]; - NXname pBuffer; - int32 iRank, iAtt, iType; - - pFile = NXIassert (fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - /* first read dimension information */ - memset (iStart, 0, MAX_VAR_DIMS * sizeof (int32)); - SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); - /* actually read */ - SDreaddata (pFile->iCurrentSDS, iStart, NULL, iSize, data); - return NX_OK; - } - - - NXstatus CALLING_STYLE NXgetslab (NXhandle fid, void *data, int iStart[], int iSize[]) - { - pNexusFile pFile; - int32 myStart[MAX_VAR_DIMS], mySize[MAX_VAR_DIMS]; - int32 i, iRank, iType, iAtt; - NXname pBuffer; - - pFile = NXIassert (fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - - /* if an int is not 32-bit we have to cast them properly in order - to kill a bug. - */ - if(sizeof(int) != 4) - { - SDgetinfo (pFile->iCurrentSDS, pBuffer, - &iRank, myStart, &iType, &iAtt); - for(i = 0; i < iRank; i++) - { - myStart[i] = (int32)iStart[i]; - mySize[i] = (int32)iSize[i]; - } - /* finally read */ - SDreaddata (pFile->iCurrentSDS, myStart, NULL, - mySize, data); - return NX_OK; - } - else - { - /* read directly */ - SDreaddata (pFile->iCurrentSDS, (int32*)iStart, NULL, - (int32*)iSize, data); - return NX_OK; - } - } - - - NXstatus CALLING_STYLE NXgetattr (NXhandle fid, char *name, void *data, int* datalen, int* iType) - { - pNexusFile pFile; - int32 iNew, iType32; - void *pData = NULL; - int32 iLen, iRet; - char pBuffer[256]; - NXname pNam; - - *datalen = (*datalen) * DFKNTsize(*iType); - pFile = NXIassert (fid); - - /* find attribute */ - if (pFile->iCurrentSDS != 0) { - /* SDS attribute */ - iNew = SDfindattr (pFile->iCurrentSDS, name); - } else { - /* global attribute */ - iNew = SDfindattr (pFile->iSID, name); - } - if (iNew < 0) { - sprintf (pBuffer, "ERROR: attribute %s not found", name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - /* get more info, allocate temporary data space */ - iType32 = (int32)*iType; - if (pFile->iCurrentSDS != 0) { - iRet = SDattrinfo (pFile->iCurrentSDS, iNew, pNam, &iType32, &iLen); - } else { - iRet = SDattrinfo (pFile->iSID, iNew, pNam, &iType32, &iLen); - } - *iType = (int)iType32; - if (iRet < 0) { - sprintf (pBuffer, "ERROR: HDF could not read attribute info"); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - iLen = iLen * DFKNTsize (*iType); - pData = (void *) malloc (iLen); - if (!pData) { - NXIReportError (NXpData, "ERROR: allocating memory in NXgetattr"); - return NX_ERROR; - } - memset (pData, 0, iLen); - - /* finally read the data */ - if (pFile->iCurrentSDS != 0) { - iRet = SDreadattr (pFile->iCurrentSDS, iNew, pData); - } else { - iRet = SDreadattr (pFile->iSID, iNew, pData); - } - if (iRet < 0) { - sprintf (pBuffer, "ERROR: HDF could not read attribute data"); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - /* copy data to caller */ - memset (data, 0, *datalen); - if ((*datalen <= iLen) && (*iType == DFNT_UINT8 || *iType == DFNT_CHAR8 || *iType == DFNT_UCHAR8)) { - iLen = *datalen - 1; - } - memcpy (data, pData, iLen); - *datalen = iLen / DFKNTsize(*iType); - free (pData); - return NX_OK; - } - - - NXstatus CALLING_STYLE NXputdata (NXhandle fid, void *data) - { - pNexusFile pFile; - int32 iStart[MAX_VAR_DIMS], iSize[MAX_VAR_DIMS], iStride[MAX_VAR_DIMS]; - NXname pBuffer; - int32 iRank, iAtt, iType, iRet, i, e; - char pError[512]; - char *str; - - pFile = NXIassert (fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - /* first read dimension information */ - memset (iStart, 0, MAX_VAR_DIMS * sizeof (int32)); - SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); - - /* initialise stride to 1 */ - for (i = 0; i < iRank; i++) { - iStride[i] = 1; - } - - /* actually write */ - iRet = SDwritedata (pFile->iCurrentSDS, iStart, iStride, iSize, data); - if (iRet < 0) { - sprintf (pError, "ERROR: failure to write data to %s", pBuffer); - NXIReportError (NXpData, pError); - return NX_ERROR; - } - return NX_OK; - } - - NXstatus CALLING_STYLE NXputslab (NXhandle fid, void *data, int iStart[], int iSize[]) - { - pNexusFile pFile; - int iRet; - int32 iStride[MAX_VAR_DIMS]; - int32 myStart[MAX_VAR_DIMS], mySize[MAX_VAR_DIMS]; - int32 i, iRank, iType, iAtt; - NXname pBuffer; - - - pFile = NXIassert (fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - /* initialise stride to 1 */ - for (i = 0; i < MAX_VAR_DIMS; i++) { - iStride[i] = 1; - } - - /* if an int is not 32-bit we have to cast them properly in order - to kill a bug. - */ - if(sizeof(int) != 4) - { - SDgetinfo (pFile->iCurrentSDS, pBuffer, - &iRank, myStart, &iType, &iAtt); - for(i = 0; i < iRank; i++) - { - myStart[i] = (int32)iStart[i]; - mySize[i] = (int32)iSize[i]; - } - /* finally write */ - iRet = SDwritedata (pFile->iCurrentSDS, myStart, - iStride, mySize, data); - - } - else - { - /* write directly */ - iRet = SDwritedata (pFile->iCurrentSDS,(int32*)iStart, - iStride, (int32*)iSize, data); - } - - /* deal with HDF errors */ - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: writing slab failed"); - return NX_ERROR; - } - return NX_OK; - } - - NXstatus CALLING_STYLE NXfputattr(NXhandle fid, char *name, void *data, int *pDatalen, int *pIType) +/*-----------------------------------------------------------------------*/ + NXstatus CALLING_STYLE NXfputattr(NXhandle fid, char *name, void *data, + int *pDatalen, int *pIType) { return NXputattr(fid, name, data, *pDatalen, *pIType); } - - NXstatus - CALLING_STYLE NXputattr (NXhandle fid, CONSTCHAR *name, void *data, int datalen, int iType) - { - pNexusFile pFile; - int iRet; - - pFile = NXIassert (fid); - - if (pFile->iCurrentSDS != 0) { - /* SDS attribute */ - iRet = SDsetattr (pFile->iCurrentSDS, (char*)name, (int32)iType, - (int32)datalen, data); - } else { - /* global attribute */ - iRet = SDsetattr (pFile->iSID, (char*)name, (int32)iType, - (int32)datalen, data); - - } - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDf failed to store attribute "); - return NX_ERROR; - } - return NX_OK; - } - - - NXstatus - CALLING_STYLE NXgetinfo (NXhandle fid, int *rank, int dimension[], int *iType) - { - pNexusFile pFile; - NXname pBuffer; - int32 iAtt, myDim[MAX_VAR_DIMS], i, iRank, mType; - - pFile = NXIassert (fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - /* read information */ - SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, myDim, - &mType, &iAtt); - - /* conversion to proper ints for the platform */ - *iType = (int)mType; - *rank = (int)iRank; - for(i = 0; i < iRank; i++) - { - dimension[i] = (int)myDim[i]; - } - return NX_OK; - } - - /*-------------------------------------------------------------------------*/ - NXstatus - CALLING_STYLE NXgetgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) - { - pNexusFile pFile; - - pFile = NXIassert (fid); - /* check if there is a group open */ - if (pFile->iCurrentVG == 0) { - *iN = Vlone (pFile->iVID, NULL, 0); - strcpy (pName, "root"); - strcpy (pClass, "NXroot"); - } - else { - *iN = Vntagrefs (pFile->iCurrentVG); - Vgetname (pFile->iCurrentVG, pName); - Vgetclass (pFile->iCurrentVG, pClass); - } - return NX_OK; - } - - /*-------------------------------------------------------------------------*/ - NXstatus - CALLING_STYLE NXgetattrinfo (NXhandle fid, int *iN) - { - pNexusFile pFile; - int iRet; - int32 iData, iAtt, iRank, iType; - int32 iDim[MAX_VAR_DIMS]; - NXname pNam; - - pFile = NXIassert (fid); - if (pFile->iCurrentSDS != 0) { /* SDS level */ - iRet = SDgetinfo (pFile->iCurrentSDS, pNam, &iRank, iDim, &iType, - &iAtt); - } else { /* global level */ - iRet = SDfileinfo (pFile->iSID, &iData, &iAtt); - } - if (iRet < 0) { - NXIReportError (NXpData, "NX_ERROR: HDF cannot read attribute numbers"); - *iN = 0; - return NX_ERROR; - } - *iN = iAtt; - return iRet; - } - - NXstatus - CALLING_STYLE NXinitgroupdir (NXhandle fid) - { - pNexusFile pFile; - int iRet; - - pFile = NXIassert (fid); - NXIKillDir (fid); - iRet = NXIInitDir (pFile); - if (iRet < 0) { - NXIReportError (NXpData, - "NX_ERROR: no memory to store directory info"); - return NX_EOD; - } - return NX_OK; - } - - /*-------------------------------------------------------------------------*/ - NXstatus - CALLING_STYLE NXgetnextentry (NXhandle fid, NXname name, NXname nxclass, int *datatype) - { - pNexusFile pFile; - int iRet, iStackPtr, iCurDir; - int32 iTemp, iD1, iD2, iA; - int32 iDim[MAX_VAR_DIMS]; - - pFile = NXIassert (fid); - - iStackPtr = pFile->iStackPtr; - iCurDir = pFile->iStack[pFile->iStackPtr].iCurDir; - - /* first case to check for: no directory entry */ - if (pFile->iStack[pFile->iStackPtr].iRefDir == NULL) { - iRet = NXIInitDir (pFile); - if (iRet < 0) { - NXIReportError (NXpData, - "ERROR: no memory to store directory info"); - return NX_EOD; - } - } - /* Next case: end of directory */ - if (iCurDir >= pFile->iStack[pFile->iStackPtr].iNDir) { - NXIKillDir (pFile); - return NX_EOD; - } - /* Next case: we have data! supply it and increment counter */ - if (pFile->iCurrentVG == 0) { /* root level */ - iTemp = Vattach (pFile->iVID, - pFile->iStack[iStackPtr].iRefDir[iCurDir], "r"); - if (iTemp < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot attach to Vgroup"); - return NX_ERROR; - } - Vgetname (iTemp, name); - Vgetclass (iTemp, nxclass); - *datatype = DFTAG_VG; - pFile->iStack[pFile->iStackPtr].iCurDir++; - Vdetach (iTemp); - return NX_OK; - } else { /* in Vgroup */ - if (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_VG) {/* Vgroup */ - iTemp = Vattach (pFile->iVID, - pFile->iStack[iStackPtr].iRefDir[iCurDir], "r"); - if (iTemp < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot attach to Vgroup"); - return NX_ERROR; - } - Vgetname (iTemp, name); - Vgetclass (iTemp, nxclass); - *datatype = DFTAG_VG; - pFile->iStack[pFile->iStackPtr].iCurDir++; - Vdetach (iTemp); - return NX_OK; - /* we are now writing using DFTAG_NDG, but need others for backward compatability */ - } else if ((pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_SDG) || - (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_NDG) || - (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_SDS)) { - iTemp = SDreftoindex (pFile->iSID, - pFile->iStack[iStackPtr].iRefDir[iCurDir]); - iTemp = SDselect (pFile->iSID, iTemp); - SDgetinfo (iTemp, name, &iA, iDim, &iD1, &iD2); - strcpy (nxclass, "SDS"); - *datatype = iD1; - SDendaccess (iTemp); - pFile->iStack[pFile->iStackPtr].iCurDir++; - return NX_OK; - } else { /* unidentified */ - strcpy (name, "UNKNOWN"); - strcpy (nxclass, "UNKNOWN"); - *datatype = pFile->iStack[iStackPtr].iTagDir[iCurDir]; - pFile->iStack[pFile->iStackPtr].iCurDir++; - return NX_OK; - } - } - return NX_ERROR; /* not reached */ - } - - /*-------------------------------------------------------------------------*/ - NXstatus - CALLING_STYLE NXinitattrdir (NXhandle fid) - { - pNexusFile pFile; - int iRet; - - pFile = NXIassert (fid); - NXIKillAttDir (fid); - iRet = NXIInitAttDir (pFile); - if (iRet == NX_ERROR) - return NX_ERROR; - return NX_OK; - } - - /*-------------------------------------------------------------------------*/ - NXstatus - CALLING_STYLE NXgetnextattr (NXhandle fileid, NXname pName, - int *iLength, int *iType) - { - pNexusFile pFile; - int iRet; - int32 iPType, iCount; - - pFile = NXIassert (fileid); - - /* first check if we have to start a new attribute search */ - if (pFile->iAtt.iNDir == 0) { - iRet = NXIInitAttDir (pFile); - if (iRet == NX_ERROR) { - return NX_ERROR; - } - } - /* are we done ? */ - if (pFile->iAtt.iCurDir >= pFile->iAtt.iNDir) { - NXIKillAttDir (pFile); - return NX_EOD; - } - /* well, there must be data to copy */ - if (pFile->iCurrentSDS == 0) { /* global attribute */ - iRet = SDattrinfo (pFile->iSID, pFile->iAtt.iCurDir, - pName, &iPType, &iCount); - } else { - iRet = SDattrinfo (pFile->iCurrentSDS, pFile->iAtt.iCurDir, - pName, &iPType, &iCount); - } - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot read attribute info"); - return NX_ERROR; - } - *iLength = iCount; - *iType = iPType; - pFile->iAtt.iCurDir++; - return NX_OK; - } - - - NXstatus - CALLING_STYLE NXgetgroupID (NXhandle fileid, NXlink* sRes) - { - pNexusFile pFile; - - pFile = NXIassert (fileid); - - if (pFile->iCurrentVG == 0) { - sRes->iTag = NX_ERROR; - return NX_ERROR; - } else { - sRes->iTag = DFTAG_VG; - sRes->iRef = pFile->iStack[pFile->iStackPtr].iVref; - return NX_OK; - } - /* not reached */ - sRes->iTag = NX_ERROR; - return NX_ERROR; - } - - - NXstatus - CALLING_STYLE NXgetdataID (NXhandle fid, NXlink* sRes) - { - pNexusFile pFile; - - pFile = NXIassert (fid); - - if (pFile->iCurrentSDS == 0) { - sRes->iTag = NX_ERROR; - return NX_ERROR; - } else { - sRes->iTag = DFTAG_NDG; - sRes->iRef = SDidtoref (pFile->iCurrentSDS); - return NX_OK; - } - sRes->iTag = NX_ERROR; - return NX_ERROR; /* not reached */ - } - - NXstatus CALLING_STYLE NXmakelink (NXhandle fid, NXlink* sLink) - { - pNexusFile pFile; - int32 iVG, iRet; - - pFile = NXIassert (fid); - - if (pFile->iCurrentVG == 0) { /* root level, can not link here */ - return NX_ERROR; - } - if(sLink->iTag == DFTAG_VG) - { - iVG = Vattach (pFile->iVID, sLink->iRef,pFile->iAccess); - iRet = Vinsert(pFile->iCurrentVG,iVG); - iRet = Vdetach(iVG); - } - else - { - Vaddtagref (pFile->iCurrentVG, sLink->iTag, sLink->iRef); - } - return NX_OK; - } - -/* allocate space for an array of given dimensions and type */ - NXstatus CALLING_STYLE NXmalloc (void** data, int rank, int dimensions[], int datatype) - { - int i; - size_t size = 1; - *data = NULL; - for(i=0; i - Uwe Filges - Labor fuer Neutronenstreuung - Paul Scherrer Institut - CH-5232 Villigen-PSI - Switzerland - - For further information, see ----------------------------------------------------------------------------*/ @@ -35,22 +27,30 @@ #define NEXUSAPI /* NeXus HDF45 */ -#define NEXUS_VERSION "2.1.0." /* major.minor.patch */ +#define NEXUS_VERSION "2.0.0." /* major.minor.patch */ -#define CONSTCHAR char +#define CONSTCHAR const char -#define NX_EXTERNAL +#if defined(_WIN32) && defined(_DLL) +# ifdef NX45DLL_EXPORTS +# define NX_EXTERNAL __declspec(dllexport) +# else +# define NX_EXTERNAL __declspec(dllimport) +# endif +#else +# define NX_EXTERNAL +#endif -typedef void* NXhandle; /* really a pointer to a NexusFile structure */ +typedef void* NXhandle; /* really a pointer to a NexusFile structure */ typedef int NXstatus; typedef char NXname[128]; -typedef enum {NXACC_READ=1, NXACC_RDWR=2, NXACC_CREATE=3, NXACC_CREATE5=4} NXaccess; +typedef enum {NXACC_READ=1, NXACC_RDWR=2, NXACC_CREATE=3, NXACC_CREATE4=4, NXACC_CREATE5=5} NXaccess; typedef struct { - char *iname; - int type; - }info_type, *pinfo; + char *iname; + int type; + }info_type, *pinfo; #define NX_OK 1 #define NX_ERROR 0 @@ -79,22 +79,19 @@ typedef struct { NX_UINT32 32 bit unsigned integer NX_CHAR 8 bit character - This list is a edited version of the one found in the HDF header file - htndefs.h. That source will always be the real reference, this is - documented here for your convenience. --------------------------------------------------------------------------*/ /* Map NeXus to HDF types */ #define NX_FLOAT32 5 #define NX_FLOAT64 6 -#define NX_INT8 20 +#define NX_INT8 20 #define NX_UINT8 21 -#define NX_INT16 22 +#define NX_INT16 22 #define NX_UINT16 23 #define NX_INT32 24 #define NX_UINT32 25 -#define NX_CHAR 4 +#define NX_CHAR 4 /* Map NeXus compression methods to HDF compression methods */ #define NX_COMP_NONE 100 @@ -107,6 +104,10 @@ typedef struct { #include #endif +#ifdef HDF5 +#include +#endif + typedef struct { #ifdef HDF4 int32 iTag; /* HDF4 variable */ @@ -124,57 +125,138 @@ typedef struct { #define NXMAXSTACK 50 -#define CONCAT(__a,__b) __a##__b /* token concatenation */ +#define CONCAT(__a,__b) __a##__b /* token concatenation */ -#define MANGLE(__arg) CONCAT(__arg,_) +#if defined(__unix) || defined(__unix__) || defined (__VMS) -#define CALLING_STYLE /* blank */ +# ifdef __VMS +# define MANGLE(__arg) __arg +# else +# define MANGLE(__arg) CONCAT(__arg,_) +# endif -# define NXopen MANGLE(nxiopen) -# define NXclose MANGLE(nxiclose) -# define NXmakegroup MANGLE(nximakegroup) -# define NXopengroup MANGLE(nxiopengroup) -# define NXclosegroup MANGLE(nxiclosegroup) -# define NXmakedata MANGLE(nximakedata) -# define NXcompmakedata MANGLE(nxicompmakedata) -# define NXcompress MANGLE(nxicompress) -# define NXopendata MANGLE(nxiopendata) -# define NXclosedata MANGLE(nxiclosedata) -# define NXputdata MANGLE(nxiputdata) -# define NXputslab MANGLE(nxiputslab) -# define NXputattr MANGLE(nxiputattr) -# define NXgetdataID MANGLE(nxigetdataid) -# define NXmakelink MANGLE(nximakelink) -# define NXmalloc MANGLE(nximalloc) -# define NXfree MANGLE(nxifree) +# define CALLING_STYLE /* blank */ + +# define NXopen MANGLE(nxiopen) +# define NXclose MANGLE(nxiclose) +# define NXmakegroup MANGLE(nximakegroup) +# define NXopengroup MANGLE(nxiopengroup) +# define NXclosegroup MANGLE(nxiclosegroup) +# define NXmakedata MANGLE(nximakedata) +# define NXcompmakedata MANGLE(nxicompmakedata) +# define NXcompress MANGLE(nxicompress) +# define NXopendata MANGLE(nxiopendata) +# define NXclosedata MANGLE(nxiclosedata) +# define NXputdata MANGLE(nxiputdata) +# define NXputslab MANGLE(nxiputslab) +# define NXputattr MANGLE(nxiputattr) +# define NXgetdataID MANGLE(nxigetdataid) +# define NXmakelink MANGLE(nximakelink) +# define NXmalloc MANGLE(nximalloc) +# define NXfree MANGLE(nxifree) # define NXflush MANGLE(nxiflush) -# define NXgetinfo MANGLE(nxigetinfo) -# define NXgetnextentry MANGLE(nxigetnextentry) -# define NXgetdata MANGLE(nxigetdata) +# define NXgetinfo MANGLE(nxigetinfo) +# define NXgetnextentry MANGLE(nxigetnextentry) +# define NXgetdata MANGLE(nxigetdata) -# define NXgetslab MANGLE(nxigetslab) -# define NXgetnextattr MANGLE(nxigetnextattr) -# define NXgetattr MANGLE(nxigetattr) -# define NXgetattrinfo MANGLE(nxigetattrinfo) -# define NXgetgroupID MANGLE(nxigetgroupid) -# define NXgetgroupinfo MANGLE(nxigetgroupinfo) -# define NXinitgroupdir MANGLE(nxiinitgroupdir) -# define NXinitattrdir MANGLE(nxiinitattrdir) -# define NXsetcache MANGLE(nxisetcache) +# define NXgetslab MANGLE(nxigetslab) +# define NXgetnextattr MANGLE(nxigetnextattr) +# define NXgetattr MANGLE(nxigetattr) +# define NXgetattrinfo MANGLE(nxigetattrinfo) +# define NXgetgroupID MANGLE(nxigetgroupid) +# define NXgetgroupinfo MANGLE(nxigetgroupinfo) +# define NXsameID MANGLE(nxisameid) +# define NXinitgroupdir MANGLE(nxiinitgroupdir) +# define NXinitattrdir MANGLE(nxiinitattrdir) +# define NXsetcache MANGLE(nxisetcache) /* FORTRAN helpers - for NeXus internal use only */ -# define NXfopen MANGLE(nxifopen) -# define NXfclose MANGLE(nxifclose) +# define NXfopen MANGLE(nxifopen) +# define NXfclose MANGLE(nxifclose) # define NXfflush MANGLE(nxifflush) -# define NXfmakedata MANGLE(nxifmakedata) -# define NXfcompmakedata MANGLE(nxifcompmakedata) -# define NXfcompress MANGLE(nxifcompress) -# define NXfputattr MANGLE(nxifputattr) +# define NXfmakedata MANGLE(nxifmakedata) +# define NXfcompmakedata MANGLE(nxifcompmakedata) +# define NXfcompress MANGLE(nxifcompress) +# define NXfputattr MANGLE(nxifputattr) + +#elif defined(_WIN32) +/* + * START OF WINDOWS SPECIFIC CONFIGURATION + * + * Added by Freddie Akeroyd 9/8/2002 + * + * Various PC calling conventions - you need only uncomment one of the following definitions of MANGLE() + * anlong with the appropriate CALLING_STYLE + * The choice arises because under Windows the default way FORTRAN calls FORTRAN is different + * from the dafault way C calls C, and so when you need to have FORTRAN calling C you must + * force them to use the same convention. Notice the use of "default way" above ... by choice + * of compiler options (or compiler vendor) you may actually have FORTRAN calling in the C way + * etc., so you might need to experiment with the options below until you get no "unresolved symbols" + * + * Choice 1: Should allow both FORTRAN and C NeXus interfaces to work in a "default" setup + * Choice 2: For when choice 1: gives problems and you only require the C interface + * Choice 3: An alternative to 1: which may allow both FORTRAN and C in a non-default setup + */ +# define MANGLE(__arg) __arg /* Choice 1 */ +# define CALLING_STYLE __stdcall /* Choice 1 */ +/* # define MANGLE(__arg) __arg /* Choice 2 */ +/* # define CALLING_STYLE /* Choice 2 */ +/* # define MANGLE(__arg) CONCAT(__arg,_) /* Choice 3 */ +/* # define CALLING_STYLE __stdcall /* Choice 3 */ +/* + * END OF WINDOWS SPECIFIC CONFIGURATION + */ +# define NXopen MANGLE(NXIOPEN) +# define NXclose MANGLE(NXICLOSE) +# define NXflush MANGLE(NXIFLUSH) +# define NXmakegroup MANGLE(NXIMAKEGROUP) +# define NXopengroup MANGLE(NXIOPENGROUP) +# define NXclosegroup MANGLE(NXICLOSEGROUP) +# define NXmakedata MANGLE(NXIMAKEDATA) +# define NXcompress MANGLE(NXICOMPRESS) +# define NXopendata MANGLE(NXIOPENDATA) +# define NXclosedata MANGLE(NXICLOSEDATA) +# define NXgetdata MANGLE(NXIGETDATA) +# define NXgetslab MANGLE(NXIGETSLAB) +# define NXgetattr MANGLE(NXIGETATTR) +# define NXgetdim MANGLE(NXIGETDIM) +# define NXputdata MANGLE(NXIPUTDATA) +# define NXputslab MANGLE(NXIPUTSLAB) +# define NXputattr MANGLE(NXIPUTATTR) +# define NXputdim MANGLE(NXIPUTDIM) +# define NXgetinfo MANGLE(NXIGETINFO) +# define NXgetgroupinfo MANGLE(NXIGETGROUPINFO) +# define NXsameID MANGLE(NXISAMEID) +# define NXinitgroupdir MANGLE(NXIINITGROUPDIR) +# define NXgetnextentry MANGLE(NXIGETNEXTENTRY) +# define NXgetattrinfo MANGLE(NXIGETATTRINFO) +# define NXinitattrdir MANGLE(NXIINITATTRDIR) +# define NXgetnextattr MANGLE(NXIGETNEXTATTR) +# define NXgetgroupID MANGLE(NXIGETGROUPID) +# define NXgetdataID MANGLE(NXIGETDATAID) +# define NXmakelink MANGLE(NXIMAKELINK) +# define NXmalloc MANGLE(NXIMALLOC) +# define NXfree MANGLE(NXIFREE) +/* FORTRAN helpers - for NeXus internal use only */ +# define NXfopen MANGLE(NXIFOPEN) +# define NXfclose MANGLE(NXIFCLOSE) +# define NXfflush MANGLE(NXIFFLUSH) +# define NXfmakedata MANGLE(NXIFMAKEDATA) +# define NXfcompmakedata MANGLE(NXIFCOMPMAKEDATA) +# define NXfcompress MANGLE(NXIFCOMPRESS) +# define NXfputattr MANGLE(NXIFPUTATTR) +#else +# error Cannot compile - unknown operating system +#endif + /* * Standard interface */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ NX_EXTERNAL NXstatus CALLING_STYLE NXopen(CONSTCHAR * filename, NXaccess access_method, NXhandle* pHandle); NX_EXTERNAL NXstatus CALLING_STYLE NXclose(NXhandle* pHandle); NX_EXTERNAL NXstatus CALLING_STYLE NXflush(NXhandle* pHandle); @@ -206,6 +288,7 @@ NX_EXTERNAL NXstatus CALLING_STYLE NXgetattr(NXhandle handle, char* name, void* NX_EXTERNAL NXstatus CALLING_STYLE NXgetattrinfo(NXhandle handle, int* no_items); NX_EXTERNAL NXstatus CALLING_STYLE NXgetgroupID(NXhandle handle, NXlink* pLink); NX_EXTERNAL NXstatus CALLING_STYLE NXgetgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass); +NX_EXTERNAL NXstatus CALLING_STYLE NXsameID(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID); NX_EXTERNAL NXstatus CALLING_STYLE NXinitgroupdir(NXhandle handle); NX_EXTERNAL NXstatus CALLING_STYLE NXinitattrdir(NXhandle handle); @@ -224,5 +307,9 @@ NX_EXTERNAL void CALLING_STYLE NXMSetError(void *pData, void (*ErrFunc)(void *p */ NX_EXTERNAL NXstatus CALLING_STYLE NXsetcache(long newVal); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + #endif /*NEXUSAPI*/ diff --git a/napi4.c b/napi4.c index e4d3a64a..4da84b52 100644 --- a/napi4.c +++ b/napi4.c @@ -1,3 +1,27 @@ +/*--------------------------------------------------------------------------- + NeXus - Neutron & X-ray Common Data Format + + Application Program Interface (HDF4) Routines + + Copyright (C) 1997-2002 Mark Koennecke, Przemek Klosowski + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information, see + +----------------------------------------------------------------------------*/ #include #include #include @@ -290,6 +314,8 @@ /* map Nexus NXaccess types to HDF4 types */ if (am == NXACC_CREATE) { am1 = DFACC_CREATE; + } else if (am == NXACC_CREATE4) { + am1 = DFACC_CREATE; } else if (am == NXACC_READ) { am1 = DFACC_READ; } else if (am == NXACC_RDWR) { @@ -318,7 +344,7 @@ #else time_info = gmtime(&timer); if (time_info != NULL) { - gmt_offset = difftime(timer, mktime(time_info)); + gmt_offset = (long)difftime(timer, mktime(time_info)); } else { NXIReportError(NXpData, "Your gmtime() function does not work ... timezone information will be incorrect\n"); gmt_offset = 0; @@ -350,7 +376,7 @@ * write something that can be used by OLE */ - if (am == NXACC_CREATE) { + if (am == NXACC_CREATE || am == NXACC_CREATE4) { if ( (file_id = Hopen(filename, am1, 0)) == -1 ) { sprintf (pBuffer, "ERROR: cannot open file_a: %s", filename); NXIReportError (NXpData, pBuffer); @@ -395,7 +421,7 @@ return NX_ERROR; } } - if (am == NXACC_CREATE) { + if (am == NXACC_CREATE || am == NXACC_CREATE4) { if (SDsetattr(pNew->iSID, "file_name", DFNT_CHAR8, strlen(filename), (char*)filename) < 0) { NXIReportError (NXpData, "ERROR: HDF failed to store file_name attribute "); return NX_ERROR; @@ -410,7 +436,7 @@ * Otherwise we try to create the file two times which makes HDF * Throw up on us. */ - if (am == NXACC_CREATE) { + if (am == NXACC_CREATE || am == NXACC_CREATE4) { am = NXACC_RDWR; am1 = DFACC_RDWR; } @@ -424,7 +450,7 @@ /* start Vgroup API */ - pNew->iVID = Hopen (filename, am1, 100); + pNew->iVID = Hopen(filename, am1, 100); if (pNew->iVID <= 0) { sprintf (pBuffer, "ERROR: cannot open file_c: %s", filename); NXIReportError (NXpData, pBuffer); @@ -1644,7 +1670,7 @@ return NX_ERROR; } *iN = iAtt; - return iRet; + return NX_OK; } /*-------------------------------------------------------------------------*/ @@ -1690,6 +1716,20 @@ return NX_OK; } + /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NX4sameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) + { + pNexusFile pFile; + + pFile = NXIassert (fileid); + if ((pFirstID->iTag == pSecondID->iTag) & (pFirstID->iRef == pSecondID->iRef)) { + return NX_OK; + } else { + return NX_ERROR; + } + } + /*-------------------------------------------------------------------------*/ diff --git a/napi5.c b/napi5.c index 85365191..56144a42 100644 --- a/napi5.c +++ b/napi5.c @@ -1,3 +1,27 @@ +/*--------------------------------------------------------------------------- + NeXus - Neutron & X-ray Common Data Format + + Application Program Interface (HDF5) Routines + + Copyright (C) 1997-2002 Mark Koennecke, Przemek Klosowski + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information, see + +----------------------------------------------------------------------------*/ #include #include #include @@ -9,17 +33,15 @@ int *iTagDir; char irefn[1024]; int iVref; + int iCurrentIDX; } iStack5[NXMAXSTACK]; struct iStack5 iAtt5; int iVID; int iFID; - int fapl; int iCurrentG; int iCurrentD; int iCurrentS; int iCurrentT; - int iCurrentIDX; - unsigned int iCurrentA_IDX; int iCurrentA; int iNX; int iNXID; @@ -56,6 +78,7 @@ free (self->iStack5[self->iStackPtr].iTagDir); self->iStack5[self->iStackPtr].iTagDir = NULL; } + self->iStack5[self->iStackPtr].iCurrentIDX = 0; } /*--------------------------------------------------------------------*/ @@ -70,6 +93,7 @@ free (self->iAtt5.iTagDir); self->iAtt5.iTagDir = NULL; } + self->iAtt5.iCurrentIDX = 0; } /* ---------------------------------------------------------------------- @@ -78,7 +102,7 @@ ---------------------------------------------------------------------*/ - NXstatus NX5open(CONSTCHAR *filename, NXaccess am, NXhandle* pHandle) + NXstatus CALLING_STYLE NX5open(CONSTCHAR *filename, NXaccess am, NXhandle* pHandle) { hid_t attr1,aid1, aid2; pNexusFile5 pNew = NULL; @@ -90,6 +114,7 @@ const char* time_format; long gmt_offset; unsigned int vers_major, vers_minor, vers_release, am1 ; + hid_t fapl; int mdc_nelmts, rdcc_nelmts; size_t rdcc_nbytes; double rdcc_w0; @@ -126,7 +151,7 @@ time_info = gmtime(&timer); if (time_info != NULL) { - gmt_offset = difftime(timer, mktime(time_info)); + gmt_offset = (long)difftime(timer, mktime(time_info)); } else { @@ -163,12 +188,12 @@ } /* start HDF5 interface */ if (am == NXACC_CREATE5) { - pNew->fapl = H5Pcreate(H5P_FILE_ACCESS); - iRet=H5Pget_cache(pNew->fapl,&mdc_nelmts,&rdcc_nelmts,&rdcc_nbytes,&rdcc_w0); + fapl = H5Pcreate(H5P_FILE_ACCESS); + iRet=H5Pget_cache(fapl,&mdc_nelmts,&rdcc_nelmts,&rdcc_nbytes,&rdcc_w0); rdcc_nbytes=(size_t)cacheSize; - iRet = H5Pset_cache(pNew->fapl,mdc_nelmts,rdcc_nelmts,rdcc_nbytes,rdcc_w0); + iRet = H5Pset_cache(fapl,mdc_nelmts,rdcc_nelmts,rdcc_nbytes,rdcc_w0); am1 = H5F_ACC_TRUNC; - pNew->iFID = H5Fcreate (filename, am1, H5P_DEFAULT, pNew->fapl); + pNew->iFID = H5Fcreate (filename, am1, H5P_DEFAULT, fapl); } else { if (am == NXACC_READ) { am1 = H5F_ACC_RDONLY; @@ -289,14 +314,8 @@ pNexusFile5 pFile = NULL; int iRet; - pFile = NXI5assert(*fid); - if (pFile->fapl != NULL) { - iRet = H5Pclose(pFile->fapl); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot close plist."); - } - } - iRet = 0; + pFile=NXI5assert(*fid); + iRet=0; iRet = H5Fclose(pFile->iFID); if (iRet < 0) { NXIReportError (NXpData, "ERROR: HDF cannot close HDF file"); @@ -305,11 +324,6 @@ NXI5KillDir (pFile); free (pFile); *fid = NULL; - iRet = 0; - iRet = H5close(); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot close HDF library"); - } return NX_OK; } @@ -364,7 +378,7 @@ herr_t attr_check (hid_t loc_id, const char *member_name, void *opdata) { - char attr_name[8]; + char attr_name[8+1]; /* need to leave space for \0 as well */ strcpy(attr_name,"NX_class"); return strstr(member_name, attr_name) ? 1 : 0; @@ -391,7 +405,7 @@ /* check group attribute */ iRet = H5Aiterate(pFile->iCurrentG,NULL,attr_check,NULL); if (iRet < 0) { - NXIReportError (NXpData, "ERROR iterating thourgh group!"); + NXIReportError (NXpData, "ERROR iterating through group!"); return NX_ERROR; } else if (iRet == 1) { /* group attribute was found */ @@ -400,7 +414,7 @@ NXIReportError (NXpData, "No group attribute available"); return NX_ERROR; } - /* check contains of group attribute */ + /* check contents of group attribute */ attr1 = H5Aopen_name(pFile->iCurrentG, "NX_class"); atype=H5Tcopy(H5T_C_S1); H5Tset_size(atype,128); @@ -433,7 +447,7 @@ /* check group attribute */ iRet=H5Aiterate(pFile->iCurrentG,NULL,attr_check,NULL); if (iRet < 0) { - NXIReportError (NXpData, "ERROR iterating thourgh group!"); + NXIReportError (NXpData, "ERROR iterating through group!"); return NX_ERROR; } else if (iRet == 1) { /* group attribute was found */ @@ -461,8 +475,7 @@ pFile->iStackPtr++; pFile->iStack5[pFile->iStackPtr].iVref=pFile->iCurrentG; strcpy(pFile->iStack5[pFile->iStackPtr].irefn,name); - pFile->iCurrentIDX=0; - pFile->iCurrentA_IDX=0; + pFile->iAtt5.iCurrentIDX=0; pFile->iCurrentLGG = strdup(name); NXI5KillDir (pFile); return NX_OK; @@ -502,7 +515,7 @@ for (i=0; iname_ref,""); strcpy(pFile->name_tmp,""); } + NXI5KillDir (pFile); pFile->iStackPtr--; if (pFile->iStackPtr>0) { pFile->iCurrentG=pFile->iStack5[pFile->iStackPtr].iVref; } else { pFile->iCurrentG=0; } - NXI5KillDir (pFile); } - pFile->iCurrentIDX=0; - pFile->iCurrentA_IDX=0; return NX_OK; } - /* --------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NX5makedata (NXhandle fid, CONSTCHAR *name, int datatype, - int rank, int dimensions[]) - { - pNexusFile5 pFile; - int chunk_size[H5S_MAX_RANK]; - int i; - - pFile = NXI5assert (fid); - memset(chunk_size,0,H5S_MAX_RANK*sizeof(int)); - if (dimensions[0] == NX_UNLIMITED) - { - for (i = 0; i < H5S_MAX_RANK; i++) - { - chunk_size[i]= 1; - } - } - return NX5compmakedata (fid, name, datatype, rank, dimensions, NX_COMP_NONE, chunk_size); - - return NX_OK; - } - /* --------------------------------------------------------------------- */ NXstatus CALLING_STYLE NX5compmakedata (NXhandle fid, CONSTCHAR *name, int datatype, @@ -659,7 +647,7 @@ cparms = H5Pcreate(H5P_DATASET_CREATE); iNew = H5Pset_chunk(cparms,rank,chunkdims); if (iNew < 0) { - NXIReportError (NXpData, "ERROR: Size of chuncks could not be set!"); + NXIReportError (NXpData, "ERROR: Size of chunks could not be set!"); return NX_ERROR; } H5Pset_deflate(cparms,6); @@ -669,7 +657,7 @@ cparms = H5Pcreate(H5P_DATASET_CREATE); iNew = H5Pset_chunk(cparms,rank,chunkdims); if (iNew < 0) { - NXIReportError (NXpData, "ERROR: Size1 of chuncks could not be set!"); + NXIReportError (NXpData, "ERROR: Size of chunks could not be set!"); return NX_ERROR; } iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, dataspace, cparms); @@ -677,11 +665,11 @@ iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT); } } else { - NXIReportError (NXpData, "HDF5 don't support selected compression method! Dataset was saved without compression"); + NXIReportError (NXpData, "HDF5 doesn't support selected compression method! Dataset was saved without compression"); iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT); } if (iRet < 0) { - NXIReportError (NXpData, "ERROR: Creating chuncked Dataset failed!"); + NXIReportError (NXpData, "ERROR: Creating chunked dataset failed!"); return NX_ERROR; } else { pFile->iCurrentD = iRet; @@ -709,12 +697,37 @@ return NX_OK; } + + /* --------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NX5makedata (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int dimensions[]) + { + pNexusFile5 pFile; + int chunk_size[H5S_MAX_RANK]; + int i; + + pFile = NXI5assert (fid); + memset(chunk_size,0,H5S_MAX_RANK*sizeof(int)); + if (dimensions[0] == NX_UNLIMITED) + { + for (i = 0; i < H5S_MAX_RANK; i++) + { + chunk_size[i]= 1; + } + } + return NX5compmakedata (fid, name, datatype, rank, dimensions, NX_COMP_NONE, chunk_size); + + return NX_OK; + } + + /* --------------------------------------------------------------------- */ NXstatus CALLING_STYLE NX5compress (NXhandle fid, int compress_type) { - printf(" NXcompress ERROR: NeXus API based on HDF5 don't supports\n"); - printf(" NXcompress function! Using HDF5 library\n"); + printf(" NXcompress ERROR: NeXus API based on HDF5 doesn't support\n"); + printf(" NXcompress function! Using HDF5 library,\n"); printf(" the NXcompmakedata function can be applied\n"); printf(" for compression of data!\n"); return NX_ERROR; @@ -782,27 +795,15 @@ { pNexusFile5 pFile; NXname pBuffer; - hid_t iRet, xfer_plist; - size_t size; + hid_t iRet; char pError[512]; pFile = NXI5assert (fid); - /* set buffer size to 16 MB */ - - xfer_plist = H5Pcreate(H5P_DATASET_XFER); - size = 16000000; - iRet = H5Pset_buffer(xfer_plist, size, NULL, NULL); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: Buffer size can not be set to 16 MB"); - return NX_ERROR; - } - /* actually write */ iRet = H5Dwrite (pFile->iCurrentD, pFile->iCurrentT, H5S_ALL, H5S_ALL, - xfer_plist, data); - H5Pclose(xfer_plist); + H5P_DEFAULT, data); if (iRet < 0) { sprintf (pError, "ERROR: failure to write data to %s", pBuffer); NXIReportError (NXpData, pError); @@ -882,7 +883,7 @@ } if (H5Awrite(attr1,aid1,data) < 0) { - NXIReportError (NXpData, "ERROR: HDf failed to store attribute "); + NXIReportError (NXpData, "ERROR: HDF failed to store attribute "); return NX_ERROR; } /* Close attribute dataspace */ @@ -934,38 +935,18 @@ { pNexusFile5 pFile; int iRet, i; - int rank, size_id; + int rank; hssize_t myStart[H5S_MAX_RANK]; hsize_t mySize[H5S_MAX_RANK]; hsize_t size[1],maxdims[H5S_MAX_RANK]; - size_t buff_size; - hid_t filespace, dataspace, xfer_plist; + hid_t filespace,dataspace; pFile = NXI5assert (fid); /* check if there is an Dataset open */ if (pFile->iCurrentD == 0) { - NXIReportError (NXpData, "ERROR: no Dataset open"); + NXIReportError (NXpData, "ERROR: no dataset open"); return NX_ERROR; } - /* set buffer size to 16 MB */ - buff_size = 16000000; - - /* - size_id = H5Tget_size(pFile->iCurrentT); - buff_size = 1; - for(i = 0; i < rank;i++){ - buff_size *= iSize[i]; - } - buff_size *= size_id; - */ - - xfer_plist = H5Pcreate(H5P_DATASET_XFER); - iRet = H5Pset_buffer(xfer_plist, buff_size, NULL, NULL); - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: Buffer size can not be set to 16 MB"); - return NX_ERROR; - } - rank = H5Sget_simple_extent_ndims(pFile->iCurrentS); for(i = 0; i < rank; i++) { @@ -991,7 +972,7 @@ } /* write slab */ iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace, - filespace, xfer_plist, data); + filespace, H5P_DEFAULT,data); iRet = H5Sclose(filespace); } else { /* define slab */ @@ -1005,10 +986,9 @@ } /* write slab */ iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace, - pFile->iCurrentS, xfer_plist, data); + pFile->iCurrentS, H5P_DEFAULT,data); } /* deal with HDF errors */ - H5Pclose(xfer_plist); iRet = H5Sclose(dataspace); if (iRet < 0) { @@ -1035,7 +1015,7 @@ NXstatus CALLING_STYLE NX5makelink (NXhandle fid, NXlink* sLink) { pNexusFile5 pFile; - int iRet; +/* int iRet; */ herr_t status; int size_type; @@ -1137,7 +1117,7 @@ pFile = NXI5assert (fid); op_data.iname = NULL; - idx=pFile->iCurrentIDX; + idx=pFile->iStack5[pFile->iStackPtr].iCurrentIDX; if (strlen(pFile->name_ref) == 0) { /* root group */ strcpy(pFile->name_ref,"/"); @@ -1146,7 +1126,7 @@ strcpy(nxclass,""); if (iRet > 0) { - pFile->iCurrentIDX++; + pFile->iStack5[pFile->iStackPtr].iCurrentIDX++; strcpy(name,op_data.iname); if (op_data.iname != NULL) { free(op_data.iname); @@ -1233,7 +1213,8 @@ { if (op_data.iname != NULL) { free(op_data.iname); - } + } + pFile->iStack5[pFile->iStackPtr].iCurrentIDX = 0; return NX_EOD; } else @@ -1253,18 +1234,69 @@ { pNexusFile5 pFile; int iStart[H5S_MAX_RANK]; - + hid_t data_id, memtype_id, size_id, sign_id; + int dims; + pFile = NXI5assert (fid); /* check if there is an Dataset open */ if (pFile->iCurrentD == 0) - { - NXIReportError (NXpData, "ERROR: no Dataset open"); - return NX_ERROR; - } + { + NXIReportError (NXpData, "ERROR: no Dataset open"); + return NX_ERROR; + } memset (iStart, 0, H5S_MAX_RANK * sizeof(int)); - /* actually read */ - - H5Dread (pFile->iCurrentD, pFile->iCurrentT, H5S_ALL, H5S_ALL,H5P_DEFAULT, data); + /* map datatypes of other plateforms */ + data_id = H5Tget_class(pFile->iCurrentT); + if (data_id==H5T_STRING) + { + dims = H5Tget_size(pFile->iCurrentT); + memtype_id = H5Tcopy(H5T_C_S1); + H5Tset_size(memtype_id, dims); + } + if (data_id==H5T_INTEGER) + { + size_id=H5Tget_size(pFile->iCurrentT); + sign_id=H5Tget_sign(pFile->iCurrentT); + if (size_id==1) + { + if (sign_id==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT8; + } else { + memtype_id = H5T_NATIVE_UINT8; + } + } + else if (size_id==2) + { + if (sign_id==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT16; + } else { + memtype_id = H5T_NATIVE_UINT16; + } + } + else if (size_id==4) + { + if (sign_id==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT32; + } else { + memtype_id = H5T_NATIVE_UINT32; + } + } + } else if (data_id==H5T_FLOAT) + { + size_id=H5Tget_size(pFile->iCurrentT); + if (size_id==4) + { + memtype_id = H5T_NATIVE_FLOAT; + } else if (size_id==8) { + memtype_id = H5T_NATIVE_DOUBLE; + } + } + + /* actually read */ + H5Dread (pFile->iCurrentD, memtype_id, H5S_ALL, H5S_ALL,H5P_DEFAULT, data); return NX_OK; } @@ -1360,9 +1392,10 @@ hsize_t mySize[H5S_MAX_RANK]; hssize_t mStart[H5S_MAX_RANK]; hid_t memspace, iRet, data_id; + hid_t memtype_id, size_id, sign_id; char *tmp_data; char *data1; - int i, iRank, mtype = 0; + int i, dims, iRank, mtype = 0; pFile = NXI5assert (fid); /* check if there is an Dataset open */ @@ -1408,16 +1441,64 @@ NXIReportError (NXpData, "ERROR: Select memspace failed"); return NX_ERROR; } - + /* map datatypes of other plateforms */ + if (data_id==H5T_STRING) + { + dims = H5Tget_size(pFile->iCurrentT); + memtype_id = H5Tcopy(H5T_C_S1); + H5Tset_size(memtype_id, dims); + } + if (data_id==H5T_INTEGER) + { + size_id=H5Tget_size(pFile->iCurrentT); + sign_id=H5Tget_sign(pFile->iCurrentT); + if (size_id==1) + { + if (sign_id==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT8; + } else { + memtype_id = H5T_NATIVE_UINT8; + } + } + else if (size_id==2) + { + if (sign_id==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT16; + } else { + memtype_id = H5T_NATIVE_UINT16; + } + } + else if (size_id==4) + { + if (sign_id==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT32; + } else { + memtype_id = H5T_NATIVE_UINT32; + } + } + } else if (data_id==H5T_FLOAT) + { + size_id=H5Tget_size(pFile->iCurrentT); + if (size_id==4) + { + memtype_id = H5T_NATIVE_FLOAT; + } else if (size_id==8) { + memtype_id = H5T_NATIVE_DOUBLE; + } + } + /* read slab */ if (mtype == NX_CHAR) { - iRet = H5Dread(pFile->iCurrentD, pFile->iCurrentT, H5S_ALL, + iRet = H5Dread(pFile->iCurrentD, memtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT,tmp_data); data1 = tmp_data + myStart[0]; strncpy(data,data1,(hsize_t)iSize[0]); free(tmp_data); } else { - iRet = H5Dread(pFile->iCurrentD, pFile->iCurrentT, memspace, + iRet = H5Dread(pFile->iCurrentD, memtype_id, memspace, pFile->iCurrentS, H5P_DEFAULT,data); } @@ -1450,18 +1531,18 @@ unsigned int idx; pFile = NXI5assert (fileid); - idx=pFile->iCurrentA_IDX; + idx=pFile->iAtt5.iCurrentIDX; if ((pFile->iCurrentD == 0) && (pFile->iCurrentG==0)) { /* global attribute */ pFile->iVID=H5Gopen(pFile->iFID,"/"); iRet=H5Aiterate(pFile->iVID,&idx,attr_info,&iname); } else { - iRet=H5Aiterate(pFile->iCurrentD,&idx,attr_info,&iname); + iRet=H5Aiterate(pFile->iCurrentD,&idx,attr_info,&iname); } if (iRet>0) { - pFile->iCurrentA_IDX++; + pFile->iAtt5.iCurrentIDX++; strcpy(pName, iname); if (iname != NULL) { free(iname); @@ -1545,10 +1626,10 @@ } if (idx == 0) { - NXIReportError (NXpData, "Dataset has no attributes!"); - return NX_EOD; + pFile->iAtt5.iCurrentIDX = 0; + return NX_EOD; } - + pFile->iAtt5.iCurrentIDX = 0; return NX_EOD; } else @@ -1812,7 +1893,23 @@ return NX_ERROR; } - /*-------------------------------------------------------------------------*/ + /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NX5sameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) + { + pNexusFile5 pFile; + + pFile = NXI5assert (fileid); + if ((strcmp(pFirstID->iTag5,pSecondID->iTag5) == 0) & + (strcmp(pFirstID->iRef5,pSecondID->iRef5) == 0) & + (strcmp(pFirstID->iRefd,pSecondID->iRefd) == 0)) { + return NX_OK; + } else { + return NX_ERROR; + } + } + + /*-------------------------------------------------------------------------*/ NXstatus CALLING_STYLE NX5initattrdir (NXhandle fid) { @@ -1820,10 +1917,9 @@ pFile = NXI5assert (fid); NXI5KillAttDir (fid); - pFile->iCurrentA_IDX=0; return NX_OK; } - + /*-------------------------------------------------------------------------*/ NXstatus CALLING_STYLE NX5initgroupdir (NXhandle fid) @@ -1832,6 +1928,5 @@ pFile = NXI5assert (fid); NXI5KillDir (fid); - pFile->iCurrentIDX=0; return NX_OK; } diff --git a/nxdict.c b/nxdict.c index 64a2efd3..2ebea057 100644 --- a/nxdict.c +++ b/nxdict.c @@ -34,8 +34,9 @@ #include #include #include +#include #include "lld.h" -#include "napi.h" +#include "../napi.h" #include "stringdict.h" #include "dynstring.h" #include "nxdict.h" diff --git a/nxscript.c b/nxscript.c new file mode 100644 index 00000000..76c3a633 --- /dev/null +++ b/nxscript.c @@ -0,0 +1,716 @@ +/*----------------------------------------------------------------------- + N X S C R I P T + + This is a class for scripting the contents of NeXus files from + SICS. + + copyright: see file COPYRIGHT + + Mark Koennecke, February 2003 +------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include "fortify.h" +#include "sics.h" +#include "splitter.h" +#include "HistMem.h" +#include "motor.h" +#include "counter.h" +#include "nxdict.h" +#include "nxscript.h" +/*============== a personal data structure ============================*/ +typedef struct { + pObjectDescriptor pDes; + NXhandle fileHandle; + NXdict dictHandle; +} NXScript, *pNXScript; +/*======================== Action =======================================*/ +static int handleFileOperations(SConnection *pCon, pNXScript self, + int argc, char *argv[]){ + int status; + NXaccess access; + char buffer[512]; + + if(strcmp(argv[1],"close") == 0){ + NXclose(&self->fileHandle); + NXDclose(self->dictHandle,NULL); + self->fileHandle = NULL; + self->dictHandle = NULL; + SCSendOK(pCon); + return 1; + } else if(strcmp(argv[1],"reopen") == 0){ + access = NXACC_RDWR; + } else if(strcmp(argv[1],"create4") == 0){ + access = NXACC_CREATE4; + } else if(strcmp(argv[1],"create5") == 0){ + access = NXACC_CREATE5; + } else { + return 0; + } + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments for file operation", + eError); + return 1; + } + /* + be considerate: close files left open + */ + if(self->fileHandle != NULL){ + NXclose(&self->fileHandle); + self->fileHandle = NULL; + } + if(self->dictHandle != NULL){ + NXDclose(self->dictHandle, NULL); + self->dictHandle = NULL; + } + /* + now initialize ourselves + */ + unlink(argv[2]); /* kill file for overwrite */ + status = NXopen(argv[2],access,&self->fileHandle); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to open %s",argv[2]); + SCWrite(pCon,buffer,eError); + } + status = NXDinitfromfile(argv[3],&self->dictHandle); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to open dictionary %s",argv[3]); + SCWrite(pCon,buffer,eError); + } + SCSendOK(pCon); + return 1; +} +/*----------------------------------------------------------------------*/ +static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self, + int argc, char *argv[]){ + int status; + pMotor brumm = NULL; + float fVal; + char buffer[132], dummy[256]; + + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to putmotor", + eError); + return; + } + + /* + find motor + */ + brumm = (pMotor)FindCommandData(pSics,argv[3],"Motor"); + if(!brumm){ + sprintf(buffer,"ERROR: motor %s not found!", argv[3]); + SCWrite(pCon,buffer,eError); + return; + } + + /* + do position + */ + status = MotorGetSoftPosition(brumm, pCon,&fVal); + if(!status){ + sprintf(buffer,"ERROR: failed to read position of %s", argv[3]); + SCWrite(pCon,buffer,eError); + return; + } + status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],&fVal); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write %s with alias %s", + argv[3],argv[2]); + SCWrite(pCon,buffer,eError); + return; + } + + /* + if alias_null is available: write zero point + */ + strcpy(buffer,argv[2]); + strcat(buffer,"_null"); + if(NXDget(self->dictHandle,buffer,dummy,255)){ + MotorGetPar(brumm,"softzero",&fVal); + status = NXDputalias(self->fileHandle,self->dictHandle,buffer, &fVal); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write %s zero with alias %s", + argv[3],argv[2]); + SCWrite(pCon,buffer,eError); + return; + } + } +} +/*---------------------------------------------------------------------*/ +static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self, + int argc, char *argv[]){ + pCounter cter = NULL; + float fVal; + long counts; + char buffer[256], newAlias[256], dummy[80]; + int status, i, icounts; + CounterMode eMode; + + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to putcounter", + eError); + return; + } + + /* + find counter + */ + cter = (pCounter)FindCommandData(pSics,argv[3],"SingleCounter"); + if(!cter){ + sprintf(buffer,"ERROR: counter %s not found!", argv[3]); + SCWrite(pCon,buffer,eError); + return; + } + + /* + do preset + */ + fVal = GetCounterPreset(cter); + strcpy(newAlias,argv[2]); + strcat(newAlias,"_preset"); + status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write preset to %s", newAlias); + SCWrite(pCon,buffer,eError); + } + + /* + do countmode + */ + eMode = GetCounterMode(cter); + strcpy(newAlias,argv[2]); + strcat(newAlias,"_mode"); + if(eMode == eTimer){ + strcpy(dummy,"timer"); + } else { + strcpy(dummy,"monitor"); + } + status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,dummy); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write counter mode to %s", newAlias); + SCWrite(pCon,buffer,eError); + } + + /* + do time + */ + fVal = GetCountTime(cter,pCon); + strcpy(newAlias,argv[2]); + strcat(newAlias,"_time"); + if(NXDget(self->dictHandle,newAlias,dummy,79)){ + status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write count time to %s", newAlias); + SCWrite(pCon,buffer,eError); + } + } + + + /* + do counter and monitors + */ + for(i = 0; i < 10; i++){ + sprintf(newAlias,"%s_%2.2d",argv[2],i); + if(NXDget(self->dictHandle,newAlias,dummy,79)){ + counts = GetMonitor(cter,i,pCon); + icounts = (int)counts; + status = NXDputalias(self->fileHandle,self->dictHandle,newAlias, + &icounts); + } + } + + return; +} +/*----------------------------------------------------------------------*/ +static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, + pNXScript self, + int argc, char *argv[]){ + pHistMem mem = NULL; + int status, start, length, iDim[MAXDIM], rank, i, subset = 0; + HistInt *iData = NULL; + char buffer[256], defString[512], dummy[40]; + const float *timeBin; + int timeLength; + + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to puthm", + eError); + return; + } + + /* + find Histogram Memory + */ + mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem"); + if(!mem){ + sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]); + SCWrite(pCon,buffer,eError); + return; + } + + /* + default: everything + */ + start = 0; + length = GetHistLength(mem); + + /* + check for further arguments specifying a subset + */ + if(argc > 5){ + subset = 1; + status = Tcl_GetInt(InterpGetTcl(pSics),argv[4],&start); + if(status != TCL_OK){ + sprintf(buffer,"ERROR: failed to convert %s to integer", + argv[4]); + SCWrite(pCon,buffer,eError); + return; + } + status = Tcl_GetInt(InterpGetTcl(pSics),argv[5],&length); + if(status != TCL_OK){ + sprintf(buffer,"ERROR: failed to convert %s to integer", + argv[5]); + SCWrite(pCon,buffer,eError); + return; + } + } + + /* + now get some memory + */ + iData = (HistInt *)malloc(length*sizeof(HistInt)); + if(!iData){ + SCWrite(pCon,"ERROR: out of memory for reading histogram memory", + eError); + return; + } + + /* + build the definition string + */ + status = NXDget(self->dictHandle,argv[2],buffer,254); + if(!status){ + sprintf(buffer,"ERROR: alias %s for histogram memory not found", + argv[2]); + SCWrite(pCon,buffer,eError); + free(iData); + return; + } + if(subset){ + strcpy(defString,buffer); + timeBin = GetHistTimeBin(mem,&timeLength); + if(timeLength > 2){ + sprintf(dummy,"%d",timeLength); + NXDupdate(self->dictHandle,"timedim",dummy); + } + } else { + strcpy(defString,buffer); + GetHistDim(mem,iDim,&rank); + sprintf(dummy," -rank %d", rank); + strcat(defString,dummy); + strcat(defString," -dim { "); + sprintf(dummy,"%d",iDim[0]); + strcat(defString,dummy); + for(i = 1; i < rank; i++){ + sprintf(dummy,", %d",iDim[i]); + strcat(defString,dummy); + } + strcat(defString," } "); + } + + /* + read HM + */ + if(subset){ + status = GetHistogramDirect(mem,pCon,0,start,length,iData, + length*sizeof(HistInt)); + }else{ + status = GetHistogram(mem,pCon,0,start,length,iData, + length*sizeof(HistInt)); + } + if(!status){ + SCWrite(pCon,"ERROR: failed to read histogram memory",eError); + free(iData); + return; + } + + /* + finally: write + */ + status = NXDputdef(self->fileHandle, self->dictHandle,defString,iData); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write histogram memory data"); + SCWrite(pCon,buffer,eError); + } + + free(iData); + SCSendOK(pCon); + + return; +} +/*-------------------------------------------------------------------*/ +static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, + pNXScript self, + int argc, char *argv[]){ + pHistMem mem = NULL; + int status, timeLength; + char buffer[256], defString[512], dummy[40]; + const float *timeBin; + + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to puttimebinning", + eError); + return; + } + + /* + find Histogram Memory + */ + mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem"); + if(!mem){ + sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]); + SCWrite(pCon,buffer,eError); + return; + } + + + /* + build definition string + */ + status = NXDget(self->dictHandle,argv[2],buffer,254); + if(!status){ + sprintf(buffer,"ERROR: alias %s for time binning not found", + argv[2]); + SCWrite(pCon,buffer,eError); + return; + } + timeBin = GetHistTimeBin(mem,&timeLength); + sprintf(defString,"%s -dim {%d} ",buffer,timeLength); + + /* + write + */ + status = NXDputdef(self->fileHandle, self->dictHandle, + defString,(void *)timeBin); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write time binning"); + SCWrite(pCon,buffer,eError); + } + SCSendOK(pCon); + return; +} +/*----------------------------------------------------------------------*/ +static void putArray(SConnection *pCon, SicsInterp *pSics, + pNXScript self, + int argc, char *argv[]){ + float *data = NULL; + int length, i, status; + char num[20]; + char buffer[256], defString[512], *varData; + Tcl_Interp *tcl = NULL; + double dVal; + + if(argc < 5){ + SCWrite(pCon,"ERROR: insufficient number of arguments to array", + eError); + return; + } + tcl = InterpGetTcl(pSics); + assert(tcl != NULL); + + /* + get array length + */ + status = Tcl_GetInt(tcl,argv[4],&length); + if(status = TCL_OK){ + sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]); + SCWrite(pCon,buffer,eError); + return; + } + + /* + allocate + */ + if(length > 0){ + data = (float *)malloc(length*sizeof(float)); + } + if(data == NULL){ + SCWrite(pCon,"ERROR: out of memory or invalid length",eError); + return; + } + memset(data,0,length*sizeof(float)); + + /* + try getting data + */ + for(i = 0; i < length; i++){ + sprintf(num,"%d",i); + varData = Tcl_GetVar2(tcl,argv[3],num,0); + if(varData != NULL){ + status = Tcl_GetDouble(tcl,varData,&dVal); + if(status = TCL_OK){ + sprintf(buffer,"ERROR: failed to convert %s to double", + varData); + SCWrite(pCon,buffer,eError); + } + data[i] = (float)dVal; + } else { + sprintf(buffer,"WARNING: failed to find array element %d", i); + SCWrite(pCon,buffer,eError); + } + } + + /* + build definition string + */ + status = NXDget(self->dictHandle,argv[2],buffer,254); + if(!status){ + sprintf(buffer,"ERROR: alias %s for array not found", + argv[2]); + SCWrite(pCon,buffer,eError); + free(data); + return; + } + sprintf(defString,"%s -dim {%d} ",buffer,length); + + /* + write it! + */ + status = NXDputdef(self->fileHandle,self->dictHandle,defString,data); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write array"); + SCWrite(pCon,buffer,eError); + } + free(data); + SCSendOK(pCon); +} +/*----------------------------------------------------------------------*/ +static void putGlobal(SConnection *pCon, SicsInterp *pSics, + pNXScript self, + int argc, char *argv[]){ + char value[1024]; + int status; + + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to putglobal", + eError); + return; + } + + Arg2Text(argc-3,&argv[3],value,1023); + status = NXputattr(self->fileHandle,argv[2],value,strlen(value), + NX_CHAR); + if(status != NX_OK){ + SCWrite(pCon,"ERROR: failed to write attribute",eError); + } + SCSendOK(pCon); +} +/*-----------------------------------------------------------------------*/ +static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, + int argc, char *argv[]){ + int status; + char buffer[1024], defString[1024], numBuf[25]; + double dVal; + float fVal; + + /*============ */ + if(strcmp(argv[1],"putfloat") == 0){ + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to putfloat", + eError); + return 1; + } + status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&dVal); + if(status != TCL_OK){ + sprintf(buffer,"ERROR: failed to convert %s to float", + argv[3]); + SCWrite(pCon,buffer,eError); + return 1; + } + fVal = (float)dVal; + status = NXDputalias(self->fileHandle, self->dictHandle, + argv[2],&fVal); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write %f to alias %s", + fVal, argv[2]); + SCWrite(pCon,buffer,eError); + } + return 1; + } else if (strcmp(argv[1],"puttext") == 0){ + /*====================*/ + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to putfloat", + eError); + return 1; + } + Arg2Text(argc-3,&argv[3],buffer,1023); + status = NXDget(self->dictHandle,argv[2],defString,1023); + if(status != NX_OK){ + sprintf(buffer,"ERROR: alias %s not found in puttext", + argv[2]); + SCWrite(pCon,buffer,eError); + return 1; + } + if(strlen(defString) < 900){ + strcat(defString," -dim {"); + sprintf(numBuf,"%d",strlen(buffer)+1); + strcat(defString,numBuf); + strcat(defString," }"); + } else { + SCWrite(pCon,"ERROR: out of definition string space in puttext", + eError); + return 1; + } + status = NXDputdef(self->fileHandle,self->dictHandle, + defString,buffer); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write alias %s", + fVal, argv[2]); + SCWrite(pCon,buffer,eError); + } + return 1; + } else if(strcmp(argv[1],"putmot") == 0){ + /*=========== */ + putMotor(pCon,pSics,self,argc,argv); + return 1; + } else if(strcmp(argv[1],"putcounter") == 0){ + /* ================*/ + putCounter(pCon,pSics,self, argc,argv); + return 1; + }else if(strcmp(argv[1],"puthm") == 0){ + /*=================*/ + putHistogramMemory(pCon,pSics,self,argc, argv); + return 1; + }else if(strcmp(argv[1],"puttimebinning") == 0){ + /*=================*/ + putTimeBinning(pCon,pSics,self,argc,argv); + }else if(strcmp(argv[1],"putarray") == 0){ + /*================*/ + putArray(pCon,pSics,self,argc,argv); + }else if(strcmp(argv[1],"putglobal") == 0){ + /*===============*/ + putGlobal(pCon,pSics,self,argc,argv); + } else { + SCWrite(pCon,"ERROR: put command not recognised",eError); + } + return 0; +} +/*----------------------------------------------------------------------*/ +static void makeLink(SConnection *pCon, SicsInterp *pSics, + pNXScript self, + int argc, char *argv[]){ + int status; + + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to makelink", + eError); + return; + } + + status = NXDaliaslink(self->fileHandle, self->dictHandle, + argv[2],argv[3]); + if(status != NX_OK){ + SCWrite(pCon,"ERROR: linking failed",eError); + return; + } + + SCSendOK(pCon); +} + +/*-----------------------------------------------------------------------*/ +int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pNXScript self = (pNXScript)pData; + + /* + preliminary checks + */ + assert(self); + if(!SCMatchRights(pCon,usUser)){ + return 1; + } + if(argc < 2){ + SCWrite(pCon,"ERROR: no keyword found",eError); + return 1; + } + strtolower(argv[1]); + + if(handleFileOperations(pCon,self,argc,argv)){ + return 1; + } + + /* + if we are here, we can only continue if files are open + */ + if(self->fileHandle == NULL || self->dictHandle == NULL){ + SCWrite(pCon,"ERROR: cannot write, files not open",eError); + return 1; + } + + if(strstr(argv[1],"put") != NULL){ + handlePut(pCon,pSics,self,argc,argv); + return 1; + } + + if(strcmp(argv[1],"makelink") == 0){ + makeLink(pCon,pSics,self,argc,argv); + return 1; + } + return 1; +} +/*=============== make it ==============================================*/ +static void KillNXScript(void *pData){ + pNXScript self = (pNXScript)pData; + if(self == NULL){ + return; + } + if(self->pDes){ + DeleteDescriptor(self->pDes); + } + if(self->fileHandle){ + NXclose(&self->fileHandle); + } + if(self->dictHandle){ + NXDclose(self->dictHandle, NULL); + } + free(self); +} +/*----------------------------------------------------------------------*/ +int MakeNXScript(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pNXScript self = NULL; + int status; + + self = (pNXScript)malloc(sizeof(NXScript)); + if(self == NULL){ + SCWrite(pCon,"ERROR: no memory for NXscript creation",eError); + return 0; + } + memset(self,0,sizeof(NXScript)); + self->pDes = CreateDescriptor("NXScript"); + if(self->pDes == NULL){ + SCWrite(pCon,"ERROR: no memory for NXscript creation",eError); + free(self); + return 0; + } + + /* + create with with a default name if none specified + */ + if(argc > 1){ + status = AddCommand(pSics,argv[1],NXScriptAction,KillNXScript,self); + } else { + status = AddCommand(pSics,"nxscript",NXScriptAction,KillNXScript,self); + } + if(!status){ + SCWrite(pCon,"ERROR: duplicate NXScript object not created",eError); + KillNXScript(self); + return 0; + } + return 1; +} + diff --git a/nxscript.h b/nxscript.h new file mode 100644 index 00000000..860a67c0 --- /dev/null +++ b/nxscript.h @@ -0,0 +1,20 @@ + +/*----------------------------------------------------------------------- + N X S C R I P T + + This is a class for scripting the contents of NeXus files from + SICS. + + copyright: see file COPYRIGHT + + Mark Koennecke, February 2003 +------------------------------------------------------------------------*/ +#ifndef NXSCRIPT +#define NXSCRIPT + +int MakeNXScript(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); +int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + +#endif diff --git a/nxscript.w b/nxscript.w new file mode 100644 index 00000000..d539ce3a --- /dev/null +++ b/nxscript.w @@ -0,0 +1,48 @@ +\subsection{nxscript} +Nxscript is a facility for scripting the contents of SICS NeXus +files. For the actual writing bit the NXdict library is used. This +means that nxscript needs both a filename and a dictionary filename +when opening a new file. Then functions are provided for writing +values, motors, histogram memories etc. This module should serve two +purposes: +\begin{itemize} +\item Replace the instrument specific codes for NeXus file writing. +\item Enable the user to quickly modify the contents of data files by +defining an new dictionary entry and adding another line to the +instrument script. +\end{itemize} + +The general policy with errors while writing data files is to ignore +them and to write as much as possible. Thus this module will moan and +complain but always return success. + +The module is designed for writing one NeXus file at a time. However +it will be possible to create several instances of this class in order +to support the unlikely event that several files have to be written at +the same time. + +As this is mostly a scripting facility the only interface exposed is +the interface to the interpreter. + +@o nxscript.h @{ +/*----------------------------------------------------------------------- + N X S C R I P T + + This is a class for scripting the contents of NeXus files from + SICS. + + copyright: see file COPYRIGHT + + Mark Koennecke, February 2003 +------------------------------------------------------------------------*/ +#ifndef NXSCRIPT +#define NXSCRIPT + +int MakeNXScript(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); +int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + +#endif +@} + diff --git a/ofac.c b/ofac.c index 25168d3e..1deb7b9b 100644 --- a/ofac.c +++ b/ofac.c @@ -110,6 +110,7 @@ #include "anticollider.h" #include "gpibcontroller.h" #include "ecb.h" +#include "nxscript.h" /*----------------------- Server options creation -------------------------*/ static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -295,6 +296,7 @@ AddCommand(pInter,"AntiCollisionInstall",AntiColliderFactory,NULL,NULL); AddCommand(pInter,"MakeGPIB",MakeGPIB,NULL,NULL); AddCommand(pInter,"MakeECB",MakeECB,NULL,NULL); + AddCommand(pInter,"MakeNXScript",MakeNXScript,NULL,NULL); } /*---------------------------------------------------------------------------*/ static void KillIniCommands(SicsInterp *pSics) @@ -357,6 +359,7 @@ RemoveCommand(pSics,"AntiColliderInstall"); RemoveCommand(pSics,"MakeGPIB"); RemoveCommand(pSics,"MakeECB"); + RemoveCommand(pSics,"MakeNXScript"); } diff --git a/sans.tcl b/sans.tcl index b4a856f6..41bf129a 100644 --- a/sans.tcl +++ b/sans.tcl @@ -206,3 +206,4 @@ Publish LogBook User source $root/bin/count.tcl Publish count User Publish Repeat User + diff --git a/sans2.dic b/sans2.dic new file mode 100644 index 00000000..09d1f9cc --- /dev/null +++ b/sans2.dic @@ -0,0 +1,139 @@ +##NXDICT-1.0 +#---------------------------------------------------------------------------- +# NeXus dictionary file for SANS-II at SINQ, PSI +# +# DO NOT MODIFY OR YOUR DATA MAY NEVER BE RECOVERED AGAIN! +# DO NOT MODIFY! YOU RISK ETERNAL DAMNATION! +# +# Mark Koennecke, February 2003 +#--------------------------------------------------------------------------- +#--------- NXentry +etitle = /entry1,NXentry/SDS title -type DFNT_CHAR -rank 1 +etime = /entry1,NXentry/SDS start_time -type DFNT_CHAR -rank 1 +endtime = /entry1,NXentry/SDS end_time -type DFNT_CHAR -rank 1 +#----------- NXinstrument +iname = /entry1,NXentry/SANS-II,NXinstrument/SDS name -type DFNT_CHAR \ + -rank 1 +#----------------------NXSource +sname = /entry1,NXentry/SANS-II,NXinstrument/SINQ,NXsource/SDS name \ + -type DFNT_CHAR -rank 1 +stype = /entry1,NXentry/SANS-II,NXinstrument/SINQ,NXsource/SDS type \ + -type DFNT_CHAR -rank 1 +#---------------------Selector +vname = /entry1,NXentry/SANS-II,NXinstrument/Dornier-VS,NXchopper/SDS type \ + -type DFNT_CHAR -rank 1 +vrot = /entry1,NXentry/SANS-II,NXinstrument/Dornier-VS,NXchopper/SDS \ + rotation_speed -attr {units,RPM} +vtilt = /entry1,NXentry/SANS-II,NXinstrument/Dornier-VS,NXchopper/SDS \ + tilt_angle -attr {units,degree} +vlambda = /entry1,NXentry/SANS-II,NXinstrument/Dornier-VS,NXchopper/SDS \ + lambda -attr {units,nm} +#-------------------- monitor 1 +cter_01 = /entry1,NXentry/SANS-II,NXinstrument/monitor1,NXmonitor/SDS \ + counts -type DFNT_INT32 +#-------------------- proton monitor +cter_04 = /entry1,NXentry/SANS-II,NXinstrument/integrated_beam,NXmonitor/SDS \ + counts -type DFNT_INT32 +#--------------------- collimator +colli = /entry1,NXentry/SANS-II,NXinstrument/collimator,NXcollimator/SDS \ + length -attr {units,m} +#--------------------- attenuator +atti = /entry1,NXentry/SANS-II,NXinstrument/attenuator,NXattenuator/SDS \ + selection +#-------------------- BeamStop +bspos= /entry1,NXentry/SANS-II,NXinstrument/beam_stop,NXstop/SDS out_flag +vsx = /entry1,NXentry/SANS-II,NXinstrument/beam_stop,NXstop/SDS x_position \ + -attr {units,mm} +vsx_null = /entry1,NXentry/SANS-II,NXinstrument/beam_stop,NXstop/SDS x_null \ + -attr {units,mm} +vsy = /entry1,NXentry/SANS-II,NXinstrument/beam_stop,NXstop/SDS y_position \ + -attr {units,mm} +vsy_null = /entry1,NXentry/SANS-II,NXinstrument/beam_stop,NXstop/SDS y_null \ + -attr {units,mm} +#--------------------- Detector +ddx = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS x_position \ + -attr {units,mm} +ddx_null = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS \ + x_null -attr {units,mm} +cter_mode = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS \ + count_mode -type DFNT_CHAR -rank 1 -dim {30} +cter_preset = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS \ + preset -attr {units,secORcounts} +cter_01 = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS \ + monitor_counts -type DFNT_UINT32 -rank 1 -dim {1} +cter_time = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS \ + counting_time -attr {units,seconds} +ddcounts = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS counts -type DFNT_UINT32 -LZW -attr {signal,1} +ddcx = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS \ + detector_x -type DFNT_FLOAT32 -rank 1 -attr {axis,1} +ddcy = /entry1,NXentry/SANS-II,NXinstrument/detector,NXdetector/SDS \ + detector_y -type DFNT_INT32 -rank 1 -attr {axis,2} +#--------Sample +san = /entry1,NXentry/sample,NXsample/SDS name -type DFNT_CHAR -rank 1 +stable = /entry1,NXentry/sample,NXsample/SDS active_sample_table\ + -type DFNT_CHAR -rank 1 +charo = /entry1,NXentry/sample,NXsample/SDS chamber_rotation \ + -attr {units,degree} +charo_null = /entry1,NXentry/sample,NXsample/SDS chamber_rotation_null \ + -attr {units,degree} +chax = /entry1,NXentry/sample,NXsample/SDS chamber_x \ + -attr {units,mm} +chax_null = /entry1,NXentry/sample,NXsample/SDS chamber_x_null \ + -attr {units,mm} +chaz = /entry1,NXentry/sample,NXsample/SDS chamber_z \ + -attr {units,mm} +chaz_null = /entry1,NXentry/sample,NXsample/SDS chamber_z_null \ + -attr {units,mm} +chac = /entry1,NXentry/sample,NXsample/SDS chamber_changer \ + -attr {units,mm} +chac_null = /entry1,NXentry/sample,NXsample/SDS chamber_changer_null \ + -attr {units,mm} +goniox = /entry1,NXentry/sample,NXsample/SDS goniometer_x \ + -attr {units,mm} +goniox_null = /entry1,NXentry/sample,NXsample/SDS goniometer_x_null \ + -attr {units,mm} +gonioy = /entry1,NXentry/sample,NXsample/SDS goniometer_y \ + -attr {units,mm} +gonioy_null = /entry1,NXentry/sample,NXsample/SDS goniometer_y_null \ + -attr {units,mm} +goniochi = /entry1,NXentry/sample,NXsample/SDS goniometer_chi \ + -attr {units,degree} +goniochi_null = /entry1,NXentry/sample,NXsample/SDS goniometer_chi_null \ + -attr {units,degree} +goniophi = /entry1,NXentry/sample,NXsample/SDS goniometer_phi \ + -attr {units,degree} +goniophi_null = /entry1,NXentry/sample,NXsample/SDS goniometer_phi_null \ + -attr {units,degree} +tablex = /entry1,NXentry/sample,NXsample/SDS table_x \ + -attr {units,mm} +tabley = /entry1,NXentry/sample,NXsample/SDS table_y \ + -attr {units,mm} +tablez = /entry1,NXentry/sample,NXsample/SDS table_z \ + -attr {units,mm} +tableom = /entry1,NXentry/sample,NXsample/SDS table_omega \ + -attr {units,degree} +tablex_null = /entry1,NXentry/sample,NXsample/SDS table_x_null \ + -attr {units,mm} +tabley_null = /entry1,NXentry/sample,NXsample/SDS table_null \ + -attr {units,mm} +tablez_null = /entry1,NXentry/sample,NXsample/SDS table_z_null \ + -attr {units,mm} +sans1om = /entry1,NXentry/sample,NXsample/SDS sans1_omega \ + -attr {units,degree} +sans1om_null = /entry1,NXentry/sample,NXsample/SDS sans1_omega_null \ + -attr {units,degree} +sans1chi = /entry1,NXentry/sample,NXsample/SDS sans1_chi \ + -attr {units,degree} +sans1chi_null = /entry1,NXentry/sample,NXsample/SDS sans1_chi_null \ + -attr {units,degree} +satemp = /entry1,NXentry/sample,NXsample/SDS temperature -attr {units,Kelvin} +samag = /entry1,NXentry/sample,NXsample/SDS magnetic_field \ + -attr {units,A} +saenv = /entry1,NXentry/sample,NXsample/SDS environment \ + -type DFNT_CHAR -rank 1 -dim {256} +#-------data +dan = /entry1,NXentry/data1,NXdata/NXVGROUP + + + + diff --git a/sans2.tcl b/sans2.tcl new file mode 100644 index 00000000..db92e962 --- /dev/null +++ b/sans2.tcl @@ -0,0 +1,599 @@ +# -------------------------------------------------------------------------- +# Initialization script for the instrument SANSII at SINQ +# +# Dr. Mark Koennecke, January - ???? 2003 +#--------------------------------------------------------------------------- +# O P T I O N S +set root "/afs/psi.ch/user/k/koennecke/src/sics" +# first all the server options are set + +ServerOption SaveFile $root/tmp/sans2stat.tcl +# File to save the status of the instrument too + +ServerOption ReadTimeOut 10 +# timeout when checking for commands. In the main loop SICS checks for +# pending commands on each connection with the above timeout, has +# PERFORMANCE impact! + +ServerOption AcceptTimeOut 10 +# timeout when checking for connection req. +# Similar to above, but for connections + +ServerOption ReadUserPasswdTimeout 500000 +# time to wiat for a user/passwd to be sent from a client. Increase this +# if there is a problem connecting to a server due to network overload\ + +ServerOption LogFileBaseName $root/tmp/sans2log +# the path and base name of the internal server logfile to which all +# activity will be logged. + +ServerOption ServerPort 2915 +# the port number the server is going to listen at. The client MUST know +# this number in order to connect. It is in client.ini + +ServerOption InterruptPort 2917 +# The UDP port where the server will wait for Interrupts from clients. +# Obviously, clients wishing to interrupt need to know this number. +# Telnet Options +ServerOption TelnetPort 1301 +ServerOption TelWord sicslogin + +# The token system +TokenInit connan + +#--------------------------------------------------------------------------- +# U S E R S + +# than the SICS users are specified +# Syntax: SicsUser name password userRightsCode +SicsUser Manager Joachim 1 +SicsUser User Kohl 2 +SicsUser Spy 007 1 + +#-------------------------------------------------------------------------- +# S I M P L E V A R I A B L E S + +# now a few general variables are created +# Syntax: VarMake name type access +# type can be one of: Text, Int, Float +#access can be one of: Internal, Mugger, user, Spy + +VarMake Instrument Text Internal +Instrument "SANS-II at SINQ,PSI" +#initialisation +Instrument lock + +VarMake title Text User +VarMake User Text User +VarMake SubTitle Text User +VarMake environment Text User +VarMake comment Text User +VarMake samplename Text User +VarMake email Text User +VarMake fax Text User +VarMake phone Text User +VarMake adress Text User +VarMake sample Text User +VarMake BatchRoot Text User +VarMake starttime Text User +BatchRoot $root + +VarMake sampletable Text User + +#----------- Initialize data storage stuff +VarMake SicsDataPath Text Mugger +SicsDataPath $root/tmp/ +SicsDataPath lock +VarMake SicsDataPrefix Text Mugger +SicsDataPrefix sansII +SicsDataPrefix lock +VarMake SicsDataPostFix Text Mugger +SicsDataPostFix ".hdf" +SicsDataPostFix lock +MakeDataNumber SicsDataNumber $root/tmp/DataNumber + +#========================================================================= +# Initialize ECB system +#======================================================================== + +#--------- GPIB Controller with National Instruments driver +MakeGPIB gpib ni + +#-------- MakeECB name gpib-controller board-number gpib-address +MakeECB ecb1 gpib 0 5 + +#--------- Function to switch ecb to automatic control +proc ecbauto {} { + ecb1 func 162 1 0 0 0 +} +Publish ecbauto User + +ecbauto + +#-------------- ECB Motors +# Motor name ecb ecb-controller ecb-motor-index hardlowerlimit hardupperlimit + +Motor sr ecb ecb1 1 -10000. 10000. +sr encoder 0 +sr control 0 +sr range 1 +sr multi 0 +sr multchan 0 +sr acceleration 1000 +sr rotation_dir -1 +sr startspeed 330 +sr maxspeed 1000 +sr auto 330 +sr manuell 50 +sr delay 50 +sr offset 0 +sr dtolerance .01 +sr step2deg 1 +sr step2dig 0 +sr backlash .15 + +Motor stx ecb ecb1 2 -16000. 16000. +stx encoder 0 +stx control 0 +stx range 1 +stx multi 0 +stx multchan 0 +stx acceleration 500 +stx rotation_dir -1 +stx startspeed 330 +stx maxspeed 1000 +stx auto 500 +stx manuell 50 +stx delay 50 +stx offset 0 +stx dtolerance .01 +stx step2deg 1 +stx step2dig 0 +stx backlash .15 + +Motor stz ecb ecb1 3 6500. 20000. +stz encoder 0 +stz control 0 +stz range 1 +stz multi 0 +stz multchan 0 +stz acceleration 500 +stz rotation_dir -1 +stz startspeed 330 +stz maxspeed 1000 +stz auto 500 +stz manuell 50 +stz delay 50 +stz offset 0 +stz dtolerance .01 +stz step2deg 1 +stz step2dig 0 +stz backlash .15 + +Motor sc ecb ecb1 4 -2000. 70000. +sc encoder 0 +sc control 0 +sc range 1 +sc multi 0 +sc multchan 0 +sc acceleration 500 +sc rotation_dir -1 +sc startspeed 330 +sc maxspeed 1000 +sc auto 500 +sc manuell 50 +sc delay 50 +sc offset 0 +sc dtolerance .01 +sc step2deg 1 +sc step2dig 0 +sc backlash .15 + +Motor gu ecb ecb1 5 -10000. 10000. +gu encoder 0 +gu control 0 +gu range 1 +gu multi 0 +gu multchan 0 +gu acceleration 500 +gu rotation_dir -1 +gu startspeed 330 +gu maxspeed 1000 +gu auto 500 +gu manuell 40 +gu delay 50 +gu offset 0 +gu dtolerance .02 +gu step2deg 1 +gu step2dig 0 +gu backlash .15 + +Motor gl ecb ecb1 6 -10000. 10000. +gl encoder 0 +gl control 0 +gl range 1 +gl multi 0 +gl multchan 0 +gl acceleration 500 +gl rotation_dir -1 +gl startspeed 330 +gl maxspeed 1000 +gl auto 500 +gl manuell 40 +gl delay 50 +gl offset 0 +gl dtolerance .02 +gl step2deg 1 +gl step2dig 0 +gl backlash .15 + + +Motor tu ecb ecb1 7 -10000. 10000. +tu encoder 0 +tu control 0 +tu range 1 +tu multi 0 +tu multchan 0 +tu acceleration 500 +tu rotation_dir 1 +tu startspeed 330 +tu maxspeed 1000 +tu auto 330 +tu manuell 40 +tu delay 50 +tu offset 0 +tu dtolerance .01 +tu step2deg 1 +tu step2dig 0 +tu backlash .15 + + +Motor tl ecb ecb1 8 -10000. 10000. +tl encoder 0 +tl control 0 +tl range 1 +tl multi 0 +tl multchan 0 +tl acceleration 500 +tl rotation_dir 1 +tl startspeed 330 +tl maxspeed 1000 +tl auto 330 +tl manuell 40 +tl delay 50 +tl offset 0 +tl dtolerance .01 +tl step2deg 1 +tl step2dig 0 +tl backlash .15 + +Motor om ecb ecb1 9 -10000. 10000. +om encoder 1 +om control 1 +om range 1 +om multi 0 +om multchan 0 +om acceleration 500 +om rotation_dir 1 +om startspeed 330 +om maxspeed 1000 +om auto 100 +om manuell 40 +om delay 50 +om offset 0 +om dtolerance .01 +om step2deg 1 +om step2dig 10 +om backlash .15 + +Motor sz ecb ecb1 10 -10000. 10000. +sz encoder 0 +sz control 0 +sz range 1 +sz multi 0 +sz multchan 0 +sz acceleration 500 +sz rotation_dir 1 +sz startspeed 330 +sz maxspeed 1000 +sz auto 500 +sz manuell 40 +sz delay 50 +sz offset 0 +sz dtolerance .001 +sz step2deg 1 +sz step2dig 0 +sz backlash .15 + +Motor sx ecb ecb1 11 -10000. 10000. +sx encoder 0 +sx control 0 +sx range 1 +sx multi 0 +sx multchan 0 +sx acceleration 500 +sx rotation_dir 1 +sx startspeed 330 +sx maxspeed 1000 +sx auto 500 +sx manuell 40 +sx delay 50 +sx offset 0 +sx dtolerance .01 +sx step2deg 1 +sx step2dig 0 +sx backlash .15 + +Motor sy ecb ecb1 12 -10000. 10000. +sy encoder 0 +sy control 0 +sy range 1 +sy multi 0 +sy multchan 0 +sy acceleration 500 +sy rotation_dir 1 +sy startspeed 330 +sy maxspeed 1000 +sy auto 500 +sy manuell 50 +sy delay 50 +sy offset 0 +sy dtolerance .001 +sy step2deg 1 +sy step2dig 0 +sy backlash .15 + +Motor dz ecb ecb1 13 1.05 6.0 +dz encoder 0 +dz control 0 +dz range 1 +dz multi 0 +dz multchan 0 +dz acceleration 2000 +dz rotation_dir -1 +dz startspeed 330 +dz maxspeed 1000 +dz auto 500 +dz manuell 40 +dz delay 1000 +dz offset 0 +dz dtolerance .001 +dz step2deg 53076 +dz step2dig 0 +dz backlash .15 + +Motor dh ecb ecb1 14 -14000. 16000. +dh encoder 0 +dh control 0 +dh range 1 +dh multi 0 +dh multchan 0 +dh acceleration 1000 +dh rotation_dir -1 +dh startspeed 330 +dh maxspeed 1000 +dh auto 500 +dh manuell 40 +dh delay 50 +dh offset 0 +dh dtolerance .001 +dh step2deg 1 +dh step2dig 0 +dh backlash .15 + +Motor dv ecb ecb1 15 -14000. 25000. +dv encoder 0 +dv control 0 +dv range 1 +dv multi 0 +dv multchan 0 +dv acceleration 2000 +dv rotation_dir -1 +dv startspeed 330 +dv maxspeed 1000 +dv auto 500 +dv manuell 40 +dv delay 50 +dv offset 0 +dv dtolerance .001 +dv step2deg 1 +dv step2dig 0 +dv backlash .15 + +Motor az1 ecb ecb1 16 -3900. 0. +az1 encoder 0 +az1 control 0 +az1 range 1 +az1 multi 0 +az1 multchan 0 +az1 acceleration 1000 +az1 rotation_dir -1 +az1 startspeed 330 +az1 maxspeed 1000 +az1 auto 330 +az1 manuell 40 +az1 delay 50 +az1 offset 0 +az1 dtolerance .001 +az1 step2deg 1 +az1 step2dig 0 +az1 backlash .15 + +Motor atz ecb ecb1 17 -3900. 0. +atz encoder 0 +atz control 0 +atz range 1 +atz multi 0 +atz multchan 0 +atz acceleration 1000 +atz rotation_dir -1 +atz startspeed 330 +atz maxspeed 1000 +atz auto 330 +atz manuell 40 +atz delay 50 +atz offset 0 +atz dtolerance .001 +atz step2deg 1 +atz step2dig 0 +atz backlash .15 + +#=========================================================================== +# The ECB system has the drawback that only one out of 8 motors in a rack +# can run at any given time. Access to such motors has to be serialized. +# This is done through the anticollision system originally developed for +# TRICS. This system registers requests from motors to run and then calls +# a script which serializes the running of motors. This system is used at +# SANS to deal with the rack logic. This section installs the necessary +# scripts and configures the system. +#=========================================================================== +AntiCollisionInstall +anticollision register sr +anticollision register stx +anticollision register stz +anticollision register sc +anticollision register gu +anticollision register gl +anticollision register tu +anticollision register tl +anticollision register om +anticollision register sz +anticollision register sx +anticollision register sy +anticollision register dz +anticollision register dh +anticollision register dv +anticollision register az1 +anticollision register atz + +#------------ assignment which motors belong into which rack +set rack1 [list sr stx sty sc gu gl tu tl] +set rack2 [list om sz sx dz dh dv az1 atz] +set rack3 [list sy] + +proc sans2rack args { + global rack1 rack2 rack3 + set length [ expr [llength $args]/2.] +#-------- make list which motors have to be run in each rack + for { set i 0} { $i < $length} {incr i} { + set mot [lindex $args [expr $i * 2]] + set target [lindex $args [expr ($i *2) + 1]] + if { [lsearch $rack1 $mot] >= 0} { + lappend rack1mot $mot + lappend rack1target $target + } + if { [lsearch $rack2 $mot] >= 0} { + lappend rack2mot $mot + lappend rack2target $target + } + if { [lsearch $rack3 $mot] >= 0} { + lappend rack3mot $mot + lappend rack3target $target + } + } +#------- append a dummy to each in order to ensure existence + lappend rack1mot dummy + lappend rack1target 0.0 + lappend rack2mot dummy + lappend rack2target 0.0 + lappend rack3mot dummy + lappend rack3target 0.0 +#-------- how many levels do we have? + set level -1 + if { [llength $rack1mot] > $level} { + set level [llength $rack1mot] + } + if { [llength $rack2mot] > $level} { + set level [llength $rack2mot] + } + if { [llength $rack3mot] > $level} { + set level [llength $rack3mot] + } + if { $level <= 1} { + error "Nothing to do" + } +#------------ we are set to serialize + anticollision clear + for {set i 0} {$i < $level} {incr i} { + set tst [expr $i + 1] + if { [llength $rack1mot] > $tst} { + anticollision add $i [lindex $rack1mot $i] \ + [lindex $rack1target $i] + } + if { [llength $rack2mot] > $tst } { + anticollision add $i [lindex $rack2mot $i] \ + [lindex $rack2target $i] + } + if { [llength $rack3mot] > $tst } { + anticollision add $i [lindex $rack3mot $i] \ + [lindex $rack3target $i] + } + } + return +} +Publish sans2rack User #---------for testing purposes +anticollision script sans2rack +#====================== PSI Motoren =================================== +Motor ome SIM -180. 180. .1 -.1 +Motor chi SIM -20. 20. .1 -.1 +#====================== Multi Motor Setup ============================== +MakeMulti detector +detector alias dz x +detector endconfig +SicsAlias detector dt + +MakeMulti bs +bs alias dh x +bs alias dv y +bs endconfig + +MakeMulti chamber +chamber alias sr omega +chamber alias stx x +chamber alias sty y +chamber alias sc c +chamber endconfig + +MakeMulti gonio +gonio alias gu chi +gonio alias gl phi +gonio alias tu xu +gonio alias tl yu +gonio endconfig + +MakeMulti table +table alias om om +table alias sz z +table alias sx x +table alias sy y +table endconfig +#====================== HISTOGRAM MEMORY ================================ +MakeCounter counter ecb ecb1 +MakeECB tdc gpib 0 7 +MakeHM banana tdc +banana configure dim0 128 +banana configure dim1 128 +banana configure rank 2 +banana configure Counter counter +banana configure bank 0 +banana configure map 9 +banana configure range 0 +banana configure n 0 +banana configure ecb tdc +banana configure fill 0 +banana configure mode HMXY +banana init +banana exponent 6 +banana CountMode timer +banana preset 100 +#===================================== data file writing ================ +MakeNXScript +#===================================== install commands ================== +MakeDrive +MakeRuenBuffer +commandlog auto +#=================================== load specific command file =========== +source $root/sans2com.tcl + + + diff --git a/sans2com.tcl b/sans2com.tcl new file mode 100644 index 00000000..5558f928 --- /dev/null +++ b/sans2com.tcl @@ -0,0 +1,261 @@ +#----------------------------------------------------------------------- +# Scripts for the SANS-II Risoe instrument as installed at PSI. +# +# Initial version: Mark Koennecke, Febrary 2003 +#---------------------------------------------------------------------- +#source $root/log.tcl +#source $root/batch.tcl +source $root/nxsupport.tcl + +if { [info exists sansinit] == 0 } { + set sansinit 1 + Publish beamstop Spy + Publish stopmot User +# Publish collRead Spy #-----for debugging +# Publish collSet Spy #-----for debugging + Publish collimator Spy + Publish coll Spy +# Publis att Spy + Publish batchrun User + Publish LogBook User + Publish count User + Publish Repeat User + Publish storedata User +} +#======================== general useful stuff ====================== +proc SplitReply { text } { + set l [split $text =] + return [lindex $l 1] +} +#======================== Collimator stuff =========================== +proc collRead args { + set res [ecb1 func 164 0 0 0 0] + set l [split $res] + return [expr ([lindex $l 1] << 8) + [lindex $l 0]] +} +#-------------------------------------------------------------------- +proc collSet {val} { + switch $val { + 1 { set d 0} + 2 { set d 01} + 3 { set d 03} + 4 { set d 07} + 5 { set d 017} + 6 { set d 037} + default { + error "Invalid collimation length requested" + } + } + ecb1 func 148 $d 0 0 0 + return OK +} +#-------------------------------------------------------------------- +proc collimator args { + if { [llength $args ] < 1} { +#------------- read case + set res [collRead] + set res [expr $res & 255] + set length -1 + switch $res { + 0 { set length 1} + 1 { set length 2} + 3 { set length 3} + 7 { set length 4} + 15 { set length 5} + 31 { set length 6} + default { + error "Unknown reply $res from colRead" + } + } + return [format "collimator = %f" $length] + } else { +#------------- set case + set rights [SplitReply [config myrights]] + if {$rights > 2} { + error "Insufficient rights to drive collimator" + } + return [collSet [lindex $args 0]] + } +} +#---------------------------------------------------------------------- +proc coll args { + return coliimator $args +} +#======================== Beamstop stuff ============================== +proc beamstop args { +#----- without arguments: request + if { [llength $args] < 1} { + set res [collRead 0] + if { ($res & 256) > 0 } { + return "0 in" + } else { + return "1 out" + } + } +#---- with arguments: change, but only with at least user privilege + set rights [SplitReply [config myrights]] + if {$rights > 2} { + error "Insufficient rights to drive beamstop" + } + switch [lindex $args 0] { + 0 { set d 1} + in {set d 1} + 1 {set d 0} + out {set d 0} + default{ + error "Invalid beamstop requested" + } + } + ecb1 func 160 $d 0 0 0 + return OK +} +#================================ stopmot ================================ +proc stopmot args { + ecb1 func 132 0 0 0 0 +} +#=============================== counting =============================== +proc count { {mode NULL } { preset NULL } } { +#----- deal with mode + set mode2 [string toupper $mode] + set mode3 [string trim $mode2] + set mc [string index $mode2 0] + if { [string compare $mc T] == 0 } { + banana CountMode Timer + } elseif { [string compare $mc M] == 0 } { + banana CountMode Monitor + } +#------ deal with preset + if { [string compare $preset NULL] != 0 } { + banana preset $preset + } +#------ prepare a count message + set ret [catch {Success} msg] + set a [banana preset] + set aa [SplitReply $a] + set b [banana CountMode] + set bb [SplitReply $b] + set tt [sicstime] + set sn [sample] + starttime [sicstime] + ClientPut [format " Starting counting in %s mode with a preset of %s" \ + $bb $aa ] + ClientPut [format "Count started at %s" $tt] + ClientPut [format " sample name: %s" $sn] +#------- count + banana InitVal 0 + wait 1 + set ret [catch {Success} msg] + banana count + set ret [catch {Success} msg] +#------- StoreData + storedata + set ttt [sicstime] + if { $ret != 0 } { + ClientPut [format "Counting ended at %s" $ttt] + error [format "Counting ended with error: %s" $msg] + } + ClientPut [format "Counting ended at %s" $ttt] + ClientPut "Total Counts: [SplitReply [banana sum 0 128 0 128]]" +} +#---------------- Repeat ----------------------------------------------- +proc repeat { num {mode NULL} {preset NULL} } { + for { set i 0 } { $i < $num } { incr i } { + count $mode $preset + } +} +#=================== Data File Writing ================================= +proc writeBeforeSample args { + writeTextVar etitle title + writeTextVar etime starttime + nxscript puttext endtime [sicstime] + writeTextVar iname instrument + nxscript puttext sname SINQ, Paul Scherrer Institut + nxscript puttext stype Continuous flux spallation source + nxscript puttext vname Dornier velocity selector +# writeFloatVar vrot velo +# writeFloatVar vtilt tilt +# writeFloatvar vlambda lambda + writeFloatVar colli collimator +# writeFloatVar atti attenuator +} +#-------------------------------------------------------------------- +proc writeSample args { + writeTextVar san sample + writeTextVar stable sampletable +#------------- sample chamber + nxscript putmot charo sr + nxscript putmot chax stx + nxscript putmot chaz stz + nxscript putmot chac sc +#------------- goniometer + nxscript putmot goniox tu + nxscript putmot gonioy tl + nxscript putmot goniochi gu + nxscript putmot goniophi gl +#------------- xyz-table + nxscript putmot tablex sx + nxscript putmot tabley sy + nxscript putmot tablez sz + nxscript putmot tableom om +#------------ sans1table + nxscript putmot sans1chi chi + nxscript putmot sans1om ome +#---------- environment + if { [catch {set tmp [SplitReply [temperature]]} tmp] == 0} { + nxscript putfloat satemp $tmp + } + if { [catch {set tmp [SplitReply [magnet]]} tmp] == 0} { + nxscript putfloat samag $tmp + } + writeTextVar saenv environment +} +#---------------------------------------------------------------------- +proc writeAfterSample args { +#-------- beamstop + nxscript putmot vsx dh + nxscript putmot vsy dv + set tst [beamstop] + if { [string first in $tst] >= 0} { + nxscript putfloat bspos 0 + } else { + nxscript putfloat bspos 1. + } +#------- counter + nxscript putcounter cter counter +#------- detector + nxscript putmot ddx dz + nxscript puthm ddcounts banana + for { set i 0} { $i < 128} {incr i} { + set detar($i) [expr -64. + $i] + } + nxscript putarray ddcx detar 128 + nxscript putarray ddcy detar 128 +} +#---------------------------------------------------------------------- +proc makeLinks args { + nxscript makelink dan ddcounts + nxscript makelink dan ddcx + nxscript makelink dan ddcy +} +#----------------------------------------------------------------------- +proc storedata args { + global root + set filnam [makeFileName] + clientput [format "Writing %s" $filnam] + nxscript create5 $filnam $root/sans2.dic + writeStandardAttributes $filnam + + writeBeforeSample + + writeSample + + writeAfterSample + + makeLinks + + nxscript close +} + + + + diff --git a/sicsstat.tcl b/sicsstat.tcl index 060930d9..008c022f 100644 --- a/sicsstat.tcl +++ b/sicsstat.tcl @@ -1,3 +1,24 @@ +banana CountMode timer +banana preset 100.000000 +# Counter counter +counter SetPreset 12.000000 +counter SetMode Timer +# Motor chi +chi sign 1.000000 +chi SoftZero 0.000000 +chi SoftLowerLim -20.000000 +chi SoftUpperLim 20.000000 +chi Fixed -1.000000 +chi InterruptMode 0.000000 +chi AccessCode 2.000000 +# Motor ome +ome sign 1.000000 +ome SoftZero 0.000000 +ome SoftLowerLim -180.000000 +ome SoftUpperLim 180.000000 +ome Fixed -1.000000 +ome InterruptMode 0.000000 +ome AccessCode 2.000000 # Motor atz atz sign 1.000000 atz SoftZero 0.000000 @@ -134,6 +155,22 @@ sr SoftUpperLim 10000.000000 sr Fixed -1.000000 sr InterruptMode 0.000000 sr AccessCode 2.000000 +sampletable UNKNOWN +sampletable setAccess 2 +starttime UNKNOWN +starttime setAccess 2 +batchroot /afs/psi.ch/user/k/koennecke/src/sics +batchroot setAccess 2 +sample Wurstbroetchen +sample setAccess 2 +adress UNKNOWN +adress setAccess 2 +phone UNKNOWN +phone setAccess 2 +fax UNKNOWN +fax setAccess 2 +email UNKNOWN +email setAccess 2 samplename KohlSulfid samplename setAccess 2 comment UNKNOWN diff --git a/tdchm.c b/tdchm.c index b7f874a0..15768905 100644 --- a/tdchm.c +++ b/tdchm.c @@ -73,7 +73,7 @@ static int downloadConfiguration(pTdc self){ case HMY: function = 130; break; - caseHMXY: + case HMXY: function = 128; break; default: @@ -154,12 +154,6 @@ static int TDCConfigure(pHistDriver self, SConnection *pCon, tdc->fillByte = 0; - status = downloadConfiguration(tdc); - if(!status){ - tdc->errorCode = status; - return 0; - } - status = StringDictGet(pOpt,"ecb",pValue,79); assert(status); tdc->tdc = FindCommandData(pSics,pValue,"ECB"); @@ -168,6 +162,13 @@ static int TDCConfigure(pHistDriver self, SConnection *pCon, return 0; } + status = downloadConfiguration(tdc); + if(!status){ + tdc->errorCode = status; + return 0; + } + + self->iReconfig = 0; return 1; @@ -265,13 +266,21 @@ static int TDCCountStatus(pHistDriver self, SConnection *pCon){ assert(tdc); if(tdc->counter != NULL){ - return tdc->counter->pDriv->GetStatus(tdc->counter->pDriv,&fControl); + status = tdc->counter->pDriv->GetStatus(tdc->counter->pDriv,&fControl); } /* The TDC does not seem to have a means to figure if it is counting or not - or to do some sort of progress report. + or to do some sort of progress report. So it has to have an associated + counter in order to stop it at the end. */ - return HWIdle; + if(status != HWBusy){ + status = disableTdc(tdc); + if(status != 1){ + tdc->errorCode = COMMERROR; + return HWFault; + } + } + return status; } /*=====================================================================*/ static int TDCGetError(pHistDriver self, int *iCode, char *perror, @@ -472,7 +481,7 @@ static int TDCGetHistogram(pHistDriver self, SConnection *pCon, tdc = (pTdc)self->pPriv; assert(tdc); - if(length >= MAXTDCCHANNELS){ + if(length > MAXTDCCHANNELS){ tdc->errorCode = MAXEXCEEDED; return HWFault; }