/** * A special module for doing SANSLI rebinning. This is a fudge to make * the data from the new detector electronics look like the old one. * * copyright: see file COPYRIGHT * * Mark Koennecke, May 2007 */ #include #include #include #include #include #include #include #include "rebin.h" /*---------------------------------------------------------------------------*/ static char correctionFilePath[512]; static float runde(float v) { float ip, rund; rund = modff(v, &ip); if (rund > .5) { ip += 1.; } return ip; } /*---------------------------------------------------------------------------*/ static int loadCorrectionData(SConnection * pCon, double *xPos, double *yPos, int length) { pMotor dist = NULL; FILE *fd = NULL; float distance; char filename[1024]; int i; dist = (pMotor) FindCommandData(pServ->pSics, "dz", "Motor"); if (dist == NULL) { SCWrite(pCon, "ERROR: dz motor not found!, cannot correct", eError); return 0; } MotorGetSoftPosition(dist, pCon, &distance); snprintf(filename, 1023, "%s/%1.1dm-targetpos-final.txt", correctionFilePath, (int) runde(distance)); fd = fopen(filename, "r"); if (fd == NULL) { SCWrite(pCon, "ERROR: correction file not found!", eError); SCWrite(pCon, filename, eError); return 0; } for (i = 0; i < length; i++) { fscanf(fd, "%lf %lf", xPos + i, yPos + i); } fclose(fd); return 1; } /*---------------------------------------------------------------------------*/ static double sansround(double d) { double frac, low; low = floor(d); frac = d - low; if(frac > .5){ return low +1; } else { return low; } } /*---------------------------------------------------------------------------*/ typedef struct { int idx; double frac; }MediSort; /*---------------------------------------------------------------------------*/ static int MediCompare(const void *v1, const void *v2) { MediSort *m1, *m2; m1 = (MediSort *)v1; m2 = (MediSort *)v2; if(m1->frac > m2->frac){ return -1; } else if (m1->frac == m2->frac ){ return 0; } else { return 1; } } /*---------------------------------------------------------------------------*/ int SansliRebin(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pSICSData target = NULL, hmData = NULL; pNXDS dataset = NULL, weights = NULL; int ix, iy, pos, ival, xDetDim[2], yDetDim[2], nDetX, nDetY, posIdx; int64_t iDim[2]; long totalCounts = 0; double x, y, val, *xPos = NULL, *yPos = NULL, corrSum = .0, doubleCounts, sumFrac; double low, frac; float detectorDistance; MediSort *sortData; if (argc < 2) { SCWrite(pCon, "ERROR: Not enough arguments", eError); return 0; } xDetDim[0] = 108; xDetDim[1] = 413; nDetX = xDetDim[1] - xDetDim[0]; yDetDim[0] = 155; yDetDim[1] = 365; nDetY = yDetDim[1] - yDetDim[0]; hmData = (pSICSData) FindCommandData(pSics, argv[1], "SICSData"); if (hmData == NULL) { SCWrite(pCon, "ERROR: histogram memory data not found", eError); return 0; } target = (pSICSData) FindCommandData(pSics, argv[2], "SICSData"); if (target == NULL) { SCWrite(pCon, "ERROR: target sicsdata not found", eError); return 0; } iDim[0] = 128; iDim[1] = 128; dataset = createNXDataset(2, NX_FLOAT64, iDim); weights = createNXDataset(2, NX_FLOAT64, iDim); xPos = malloc(nDetX * nDetY * sizeof(double)); yPos = malloc(nDetX * nDetY * sizeof(double)); sortData = malloc(iDim[0]*iDim[1]*sizeof(MediSort)); if (dataset == NULL || weights == NULL || xPos == NULL || yPos == NULL || sortData == NULL) { SCWrite(pCon, "ERROR: out of memory allocating temporary data", eError); return 0; } memset(xPos, 0, nDetX * nDetY * sizeof(double)); memset(yPos, 0, nDetX * nDetY * sizeof(double)); if (!loadCorrectionData(pCon, xPos, yPos, nDetX * nDetY)) { dropNXDataset(dataset); dropNXDataset(weights); free(xPos); free(yPos); return 0; } for (ix = xDetDim[0]; ix < xDetDim[1]; ix++) { for (iy = yDetDim[0]; iy < yDetDim[1]; iy++) { posIdx = (iy - yDetDim[0]) * nDetX + (ix - xDetDim[0]); x = yPos[posIdx]; y = xPos[posIdx]; getSICSDataInt(hmData, 512 * iy + ix, &ival); totalCounts += ival; val = (double) ival; rebinPoint2D(dataset, x, y, val, TRILINEAR); rebinPoint2D(weights, x, y, 1.0, TRILINEAR); } } pos = 0; clearSICSData(target); if (argc > 3) { setSICSDataInt(target, 0, 128); setSICSDataInt(target, 1, 128); pos = 2; } /* * apply weights */ for (ix = 0; ix < 128 * 128; ix++) { if (weights->u.dPtr[ix] > .0) { dataset->u.dPtr[ix] /= weights->u.dPtr[ix]; } corrSum += dataset->u.dPtr[ix]; } doubleCounts = (double) totalCounts; /* * distribute counts */ sumFrac = .0; for (ix = 0; ix < 128 * 128; ix++, pos++) { if (corrSum > .01) { val = dataset->u.dPtr[ix] * doubleCounts / corrSum; low = floor(val); frac = val - low; sumFrac += frac; val = low; sortData[ix].idx = pos; sortData[ix].frac = frac; } else { val = .0; frac = .0; } setSICSDataInt(target, pos, (int) val); } /* * apply median correction */ qsort(sortData, iDim[0]*iDim[1], sizeof(MediSort), MediCompare); ix = 0; while(sumFrac > .0){ pos = sortData[ix].idx; getSICSDataInt(target,pos,&ival); setSICSDataInt(target,pos,ival+1); ix++; sumFrac -= 1.; } dropNXDataset(dataset); dropNXDataset(weights); free(xPos); free(yPos); free(sortData); SCSendOK(pCon); return 1; } /*---------------------------------------------------------------------------*/ int MakeSansliRebin(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { if (argc < 2) { SCWrite(pCon, "ERROR: need path to correction files as a parameter", eError); return 0; } strlcpy(correctionFilePath, argv[1], 512); AddCommand(pSics, "sanslirebin", SansliRebin, NULL, NULL); SCSendOK(pCon); return 1; }