/** Called when asyn clients call pasynFloat64->write(). * This function performs actions for some parameters. * For all parameters it sets the value in the parameter library and calls any registered callbacks.. * \param[in] pasynUser pasynUser structure that encodes the reason and address. * \param[in] value Value to write. */ asynStatus NDPluginStats::writeFloat64(asynUser *pasynUser, epicsFloat64 value) { int function = pasynUser->reason; asynStatus status = asynSuccess; int computeCentroid, computeProfiles; static const char *functionName = "writeFloat64"; /* Set the parameter and readback in the parameter library. This may be overwritten when we read back the * status at the end, but that's OK */ status = setDoubleParam(function, value); if (function == NDPluginStatsCentroidThreshold) { getIntegerParam(NDPluginStatsComputeCentroid, &computeCentroid); if (computeCentroid && this->pArrays[0]) { doComputeCentroid(this->pArrays[0]); getIntegerParam(NDPluginStatsComputeProfiles, &computeProfiles); if (computeProfiles) doComputeProfiles(this->pArrays[0]); } } else { /* If this parameter belongs to a base class call its method */ if (function < FIRST_NDPLUGIN_STATS_PARAM) status = NDPluginDriver::writeFloat64(pasynUser, value); } /* Do callbacks so higher layers see any changes */ callParamCallbacks(); if (status) asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s:%s: error, status=%d function=%d, value=%f\n", driverName, functionName, status, function, value); else asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, value=%f\n", driverName, functionName, function, value); return status; }
TPoint computeCentroid(const TRaster32P &r) { TPoint ret(1, 1); TRasterGR8P raux(r->getLx() + 2, r->getLy() + 2); if (fillByteRaster(r, raux)) doComputeCentroid(raux, ret); ret.x--; ret.y--; /* per il bordo aggiunto */ return ret; }
/** Callback function that is called by the NDArray driver with new NDArray data. * Does image statistics. * \param[in] pArray The NDArray from the callback. */ void NDPluginStats::processCallbacks(NDArray *pArray) { /* This function does array statistics. * It is called with the mutex already locked. It unlocks it during long calculations when private * structures don't need to be protected. */ NDDimension_t bgdDims[ND_ARRAY_MAX_DIMS], *pDim; size_t bgdPixels; int bgdWidth; int dim; NDStats_t stats, *pStats=&stats, statsTemp, *pStatsTemp=&statsTemp; double bgdCounts, avgBgd; NDArray *pBgdArray=NULL; int computeStatistics, computeCentroid, computeProfiles, computeHistogram; size_t sizeX=0, sizeY=0; int i; int itemp; int numTSPoints, currentTSPoint, TSAcquiring; NDArrayInfo arrayInfo; const char* functionName = "processCallbacks"; /* Call the base class method */ NDPluginDriver::processCallbacks(pArray); pArray->getInfo(&arrayInfo); getIntegerParam(NDPluginStatsComputeStatistics, &computeStatistics); getIntegerParam(NDPluginStatsComputeCentroid, &computeCentroid); getIntegerParam(NDPluginStatsComputeProfiles, &computeProfiles); getIntegerParam(NDPluginStatsComputeHistogram, &computeHistogram); if (pArray->ndims > 0) sizeX = pArray->dims[0].size; if (pArray->ndims == 1) sizeY = 1; if (pArray->ndims > 1) sizeY = pArray->dims[1].size; if (sizeX != this->profileSizeX) { this->profileSizeX = sizeX; setIntegerParam(NDPluginStatsProfileSizeX, (int)this->profileSizeX); for (i=0; i<MAX_PROFILE_TYPES; i++) { if (this->profileX[i]) free(this->profileX[i]); this->profileX[i] = (double *)malloc(this->profileSizeX * sizeof(double)); } } if (sizeY != this->profileSizeY) { this->profileSizeY = sizeY; setIntegerParam(NDPluginStatsProfileSizeY, (int)this->profileSizeY); for (i=0; i<MAX_PROFILE_TYPES; i++) { if (this->profileY[i]) free(this->profileY[i]); this->profileY[i] = (double *)malloc(this->profileSizeY * sizeof(double)); } } if (computeStatistics) { getIntegerParam(NDPluginStatsBgdWidth, &bgdWidth); doComputeStatistics(pArray, pStats); /* If there is a non-zero background width then compute the background counts */ if (bgdWidth > 0) { bgdPixels = 0; bgdCounts = 0.; /* Initialize the dimensions of the background array */ for (dim=0; dim<pArray->ndims; dim++) { pArray->initDimension(&bgdDims[dim], pArray->dims[dim].size); } for (dim=0; dim<pArray->ndims; dim++) { pDim = &bgdDims[dim]; pDim->offset = 0; pDim->size = MIN((size_t)bgdWidth, pDim->size); this->pNDArrayPool->convert(pArray, &pBgdArray, pArray->dataType, bgdDims); pDim->size = pArray->dims[dim].size; if (!pBgdArray) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s, error allocating array buffer in convert\n", driverName, functionName); continue; } doComputeStatistics(pBgdArray, pStatsTemp); pBgdArray->release(); bgdPixels += pStatsTemp->nElements; bgdCounts += pStatsTemp->total; pDim->offset = MAX(0, pDim->size - 1 - bgdWidth); pDim->size = MIN((size_t)bgdWidth, pArray->dims[dim].size - pDim->offset); this->pNDArrayPool->convert(pArray, &pBgdArray, pArray->dataType, bgdDims); pDim->offset = 0; pDim->size = pArray->dims[dim].size; if (!pBgdArray) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s, error allocating array buffer in convert\n", driverName, functionName); continue; } doComputeStatistics(pBgdArray, pStatsTemp); pBgdArray->release(); bgdPixels += pStatsTemp->nElements; bgdCounts += pStatsTemp->total; } if (bgdPixels < 1) bgdPixels = 1; avgBgd = bgdCounts / bgdPixels; pStats->net = pStats->total - avgBgd*pStats->nElements; } setDoubleParam(NDPluginStatsMinValue, pStats->min); setDoubleParam(NDPluginStatsMinX, (double)pStats->minX); setDoubleParam(NDPluginStatsMinY, (double)pStats->minY); setDoubleParam(NDPluginStatsMaxValue, pStats->max); setDoubleParam(NDPluginStatsMaxX, (double)pStats->maxX); setDoubleParam(NDPluginStatsMaxY, (double)pStats->maxY); setDoubleParam(NDPluginStatsMeanValue, pStats->mean); setDoubleParam(NDPluginStatsSigmaValue, pStats->sigma); setDoubleParam(NDPluginStatsTotal, pStats->total); setDoubleParam(NDPluginStatsNet, pStats->net); asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, (char *)pArray->pData, arrayInfo.totalBytes, "%s:%s min=%f, max=%f, mean=%f, total=%f, net=%f", driverName, functionName, pStats->min, pStats->max, pStats->mean, pStats->total, pStats->net); } if (computeCentroid) { doComputeCentroid(pArray); setDoubleParam(NDPluginStatsCentroidX, this->centroidX); setDoubleParam(NDPluginStatsCentroidY, this->centroidY); setDoubleParam(NDPluginStatsSigmaX, this->sigmaX); setDoubleParam(NDPluginStatsSigmaY, this->sigmaY); setDoubleParam(NDPluginStatsSigmaXY, this->sigmaXY); } if (computeProfiles) { doComputeProfiles(pArray); } if (computeHistogram) { getIntegerParam(NDPluginStatsHistSize, &itemp); this->histSizeNew = itemp; getDoubleParam (NDPluginStatsHistMin, &this->histMin); getDoubleParam (NDPluginStatsHistMax, &this->histMax); doComputeHistogram(pArray); setDoubleParam(NDPluginStatsHistEntropy, this->histEntropy); doCallbacksFloat64Array(this->histogram, this->histogramSize, NDPluginStatsHistArray, 0); } getIntegerParam(NDPluginStatsTSCurrentPoint, ¤tTSPoint); getIntegerParam(NDPluginStatsTSNumPoints, &numTSPoints); getIntegerParam(NDPluginStatsTSAcquiring, &TSAcquiring); if (TSAcquiring) { timeSeries[TSMinValue][currentTSPoint] = pStats->min; timeSeries[TSMinX][currentTSPoint] = (double)pStats->minX; timeSeries[TSMinY][currentTSPoint] = (double)pStats->minY; timeSeries[TSMaxValue][currentTSPoint] = pStats->max; timeSeries[TSMaxX][currentTSPoint] = (double)pStats->maxX; timeSeries[TSMaxY][currentTSPoint] = (double)pStats->maxY; timeSeries[TSMeanValue][currentTSPoint] = pStats->mean; timeSeries[TSSigmaValue][currentTSPoint] = pStats->sigma; timeSeries[TSTotal][currentTSPoint] = pStats->total; timeSeries[TSNet][currentTSPoint] = pStats->net; timeSeries[TSCentroidX][currentTSPoint] = this->centroidX; timeSeries[TSCentroidY][currentTSPoint] = this->centroidY; timeSeries[TSSigmaX][currentTSPoint] = this->sigmaX; timeSeries[TSSigmaY][currentTSPoint] = this->sigmaY; timeSeries[TSSigmaXY][currentTSPoint] = this->sigmaXY; currentTSPoint++; setIntegerParam(NDPluginStatsTSCurrentPoint, currentTSPoint); if (currentTSPoint >= numTSPoints) { setIntegerParam(NDPluginStatsTSAcquiring, 0); doTimeSeriesCallbacks(); } } /* Save a copy of this array for calculations when cursor is moved or threshold is changed */ if (this->pArrays[0]) this->pArrays[0]->release(); this->pArrays[0] = this->pNDArrayPool->copy(pArray, NULL, 1); callParamCallbacks(); }