/** 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;
}
Example #2
0
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,     &currentTSPoint);
    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();
}