/** * This is a second generation histogram memory object. In contrast * to counters and motors no attempt is made to provide backwards * compatability with the old SICS way of doing things. This * histogram memory object quite sensibly is derived from * the counter object. It adds a rank, dimensions and variable * data and a configuration method. For TOF, methods and variables * for generating and maintaining time binnings are provided too. * * copyright: see file COPYRIGHT * * Mark Koennecke, May 2009 */ #include #include #include #define CONFIG 1005 /* from countersec.c. */ int SecCtrInvokeFunction(pCounter self, SConnection *pCon, int code); /*-------------------------------------------------------------------------*/ static int initArray(pCounter self, int value) { pHdb rank = NULL, dim = NULL, data = NULL, datalength; int i, length; hdbValue v; rank = GetHipadabaNode(self->pDes->parNode,"rank"); assert(rank != NULL); dim = GetHipadabaNode(self->pDes->parNode,"dim"); assert(dim != NULL); data = GetHipadabaNode(self->pDes->parNode,"data"); assert(data != NULL); datalength = GetHipadabaNode(self->pDes->parNode,"datalength"); assert(datalength != NULL); length = dim->value.v.intArray[0]; for(i = 1; i < rank->value.v.intValue; i++){ length *= dim->value.v.intArray[i]; } v = MakeHdbInt(length); UpdateHipadabaPar(datalength, v, NULL); v = makeHdbValue(HIPINTVARAR, length); if(v.v.intArray == NULL){ return 0; } for(i = 0; i < length; i++){ v.v.intArray[i] = value; } UpdateHipadabaPar(data,v,NULL); ReleaseHdbValue(&v); return 1; } /*-------------------------------------------------------------------------*/ static hdbCallbackReturn HMDimCallback(pHdb currentNode, void *data, pHdbMessage message) { pHdbDataMessage update = NULL; if((update = GetHdbUpdateMessage(message)) != NULL){ copyHdbValue(update->v, ¤tNode->value); initArray((pCounter)data, 0); } return hdbContinue; } /*--------------------------------------------------------------------------*/ static int ResetCmd(pSICSOBJ ccmd, SConnection * pCon, Hdb * cmdNode, Hdb * par[], int nPar) { if(nPar < 1){ SCWrite(pCon, "ERROR: need a parameter to set", eError); return 0; } if(!initArray((pCounter) ccmd, par[0]->value.v.intValue )){ SCWrite(pCon,"ERROR: out of memory initializing HM", eError); return 0; } return 1; } /*--------------------------------------------------------------------------*/ static int GenbinCmd(pSICSOBJ ccmd, SConnection * pCon, Hdb * cmdNode, Hdb * par[], int nPar) { double start, step; int np, i; pHdb tof = NULL, dim = NULL; hdbValue v; if(nPar < 3){ SCWrite(pCon, "ERROR: need start step n parameters to gengin", eError); return 0; } start = par[0]->value.v.doubleValue; step = par[1]->value.v.doubleValue; np = par[2]->value.v.intValue; tof = GetHipadabaNode(ccmd->pDes->parNode,"time_binning"); assert(tof != NULL); dim = GetHipadabaNode(ccmd->pDes->parNode,"dim"); assert(dim != NULL); v = makeHdbValue(HIPFLOATVARAR,np ); if(v.v.floatArray == NULL){ SCWrite(pCon,"ERROR: out of memory in genbin", eError); return 0; } for(i = 0; i < np; i++){ v.v.floatArray[i] = start + i*step; } UpdateHipadabaPar(tof,v,pCon); ReleaseHdbValue(&v); GetHipadabaPar(dim,&v, pCon); v.v.intArray[v.arrayLength-1] = np; UpdateHipadabaPar(dim,v,pCon); return 1; } /*--------------------------------------------------------------------------*/ static int InitCmd(pSICSOBJ ccmd, SConnection * con, Hdb * cmdNode, Hdb * par[], int nPar) { return SecCtrInvokeFunction((pCounter)ccmd,con,CONFIG); } /*--------------------------------------------------------------------------*/ static int HMCtrTransferData(void *pData, SConnection *pCon) { pCounter self = (pCounter)pData; assert(self != NULL); pHdb node = NULL; hdbValue v; int status; node = GetHipadabaNode(self->pDes->parNode,"data"); assert(node != NULL); self->isUpToDate = 1; status = GetHipadabaPar(node,&v,pCon); ReleaseHdbValue(&v); return status; } /*------------------------------------------------------------------------- * automatically update the last entry of the dim variable when * setting time_binning --------------------------------------------------------------------------*/ static hdbCallbackReturn HMTOFCallback(pHdb currentNode, void *data, pHdbMessage message) { pHdbDataMessage update = NULL; hdbValue dim; pHdb dimNode = NULL; if((update = GetHdbUpdateMessage(message)) != NULL){ dimNode = GetHipadabaNode(currentNode->mama,"dim"); assert(dimNode != NULL); GetHipadabaPar(dimNode,&dim,NULL); dim.v.intArray[dim.arrayLength-1] = update->v->arrayLength; UpdateHipadabaPar(dimNode, dim, NULL); } return hdbContinue; } /*-------------------------------------------------------------------------- * Usage: * MakeSecHM name rank (tof) * -------------------------------------------------------------------------*/ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pCounter pRes = NULL; int rank, status; pHdb node = NULL, child = NULL; if(argc < 3) { SCWrite(pCon,"ERROR: need at least a name and rank to create a HM", eError); return 0; } rank = atoi(argv[2]); pRes = CreateSecCounter(pCon,"HistMemSec", argv[1], 2); if(pRes == NULL){ return 0; } pRes->pCountInt->TransferData = HMCtrTransferData; node = pRes->objectNode; child = GetHipadabaNode(node,"values"); if(child!= NULL){ DeleteHipadabaNode(child,pCon); } child = MakeSICSHdbPar("rank", usInternal, MakeHdbInt(rank)); if (child == NULL) { return 0; } AddHipadabaChild(node, child, NULL); child = MakeSICSHdbPar("dim", usMugger, makeHdbValue(HIPINTAR,rank)); if (child == NULL) { return 0; } AppendHipadabaCallback(child, MakeHipadabaCallback(HMDimCallback, pRes, NULL)); AddHipadabaChild(node, child, NULL); child = MakeSICSHdbPar("datalength", usInternal, MakeHdbInt(100)); if (child == NULL) { return 0; } AddHipadabaChild(node, child, NULL); child = MakeSICSHdbPar("data", usMugger, makeHdbValue(HIPINTVARAR,100)); if (child == NULL) { return 0; } AddHipadabaChild(node, child, NULL); child = AddSICSHdbPar(node,"set", usMugger, MakeSICSFunc(ResetCmd)); AddSICSHdbPar(child, "value", usUser, MakeHdbInt(0)); child = AddSICSHdbPar(node,"init", usMugger, MakeSICSFunc(InitCmd)); /* * test TOF option */ if(argc > 3){ if(strcmp(argv[3],"tof") == 0){ child = MakeSICSHdbPar("time_binning", usMugger, makeHdbValue(HIPFLOATVARAR,100)); if (child == NULL) { return 0; } AddHipadabaChild(node, child, NULL); AppendHipadabaCallback(child, MakeHipadabaCallback(HMTOFCallback, NULL, NULL)); child = AddSICSHdbPar(node,"genbin", usMugger, MakeSICSFunc(GenbinCmd)); AddSICSHdbPar(child, "start", usMugger, MakeHdbFloat(10.)); AddSICSHdbPar(child, "step", usMugger, MakeHdbFloat(10.)); AddSICSHdbPar(child, "np", usMugger, MakeHdbInt(10)); } } status = AddCommand(pSics, argv[1], InterInvokeSICSOBJ, DeleteCounter, (void *) pRes); if (status != 1) { SCPrintf(pCon,eError, "ERROR: duplicate command %s not created", argv[1]); return 0; } return 1; }