Esempio n. 1
0
QPointF QxrdCenterFinder::getXY(double tth, double chi)
{
  double x,y;
  double beta = get_DetectorTilt()*M_PI/180.0;
  double rot  = get_TiltPlaneRotation()*M_PI/180.0;

  if (get_ImplementTilt()) {

    QxrdDetectorGeometry::getXY(get_CenterX(), get_CenterY(), get_DetectorDistance(),
          get_Energy(),
          convertTwoThetaToQ(tth, convertEnergyToWavelength(get_Energy())), chi,
          get_DetectorXPixelSize(), get_DetectorYPixelSize(),
          rot, cos(beta), sin(beta), 1.0, 0.0, cos(rot), sin(rot),
          &x, &y);
  } else {
    QxrdDetectorGeometry::getXY(get_CenterX(), get_CenterY(), get_DetectorDistance(),
          get_Energy(),
          convertTwoThetaToQ(tth, convertEnergyToWavelength(get_Energy())), chi,
          get_DetectorXPixelSize(), get_DetectorYPixelSize(),
          rot, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0,
          &x, &y);
  }

  return QPointF(x,y);
}
static PyObject * DiffractionAnalysisWrap_convertEnergyToWavelength(
        PyObject *self, PyObject *args) {
    double energy,wavelength;
    PyArg_ParseTuple(args,"d",&energy);
    wavelength = convertEnergyToWavelength(energy);
    return Py_BuildValue("d",wavelength);
}
static PyObject * DiffractionAnalysisWrap_integrate(PyObject *self, PyObject *args) {
    PyArrayObject *diffractionData;
    PyArrayObject *values;
    PyArrayObject *integratedIntensity;

    int dimensions[1]; // the dimensions of the integrated intensity

    double centerX,centerY,distance,energy,alpha,beta,rotation;
    double lower,upper;
    int num;

    double constraintLower,constraintUpper;

    double pixelLength,pixelHeight;
    double cos_beta,sin_beta,cos_alpha,sin_alpha,cos_rotation,sin_rotation;
    unsigned int * total;
    int i; 
    double x,y; 
    double q,twoTheta,chi;
    int qBin,twoThetaBin,chiBin;
    double step;
    double intensity;
    char *type;
    char *constraintType;
    int doPolarizationCorrection;
    int doConstraint;
    double P;
    int verbose;

    int doGreaterThanMask;
    double greaterThanMask;
    int doLessThanMask;
    double lessThanMask;
   
    int doPolygonMask;
    PyArrayObject * polygonsX;
    PyArrayObject * polygonsY;
    PyArrayObject * polygonBeginningsIndex;
    PyArrayObject * polygonNumberOfItems;

    verbose = 0;

    // get the parameters out of the python call
    PyArg_ParseTuple(args,"O!dddddddddiddiidididiO!O!O!O!ddss",
            &PyArray_Type,&diffractionData,
            &centerX,&centerY,
            &distance,
            &energy,
            &alpha,&beta,&rotation,
            &lower,&upper,
            &num,
            &constraintLower,&constraintUpper,
            &doConstraint,
            &doPolarizationCorrection,&P,
            &doGreaterThanMask,&greaterThanMask,
            &doLessThanMask,&lessThanMask,
            &doPolygonMask,
            &PyArray_Type,&polygonsX,
            &PyArray_Type,&polygonsY,
            &PyArray_Type,&polygonBeginningsIndex,
            &PyArray_Type,&polygonNumberOfItems,
            &pixelLength,
            &pixelHeight,
            &type,
            &constraintType);

    // the types of integration
    // Remeber, strcmp returns 0 when they equal
    if (strcmp(type,"Q") != 0 && strcmp(type,"2theta") != 0 && strcmp(type,"chi") != 0) {
        PyErr_SetString( PyExc_Exception, "The type of integration must be Q, 2theta, or chi");
        return 0;
    }

    if (verbose) {
        printf("Doing Intensity Integration");
        printf("  The integration is over '%s'\n",type);
        printf("  Constrain the integration? %i\n",doConstraint);
        if (doConstraint) {
            printf("  The Type of constraint is '%s'\n",constraintType);
        }
    }

    if (doConstraint) {
        if (doConstraint && strcmp(type,"Q")==0 && strcmp(constraintType,"chi")!=0) {
            PyErr_SetString( PyExc_Exception, 
                "Cannot perform the desired integration. If the integration type is Q, the constrain integration type must be chi");
            return 0;
        }
        if (doConstraint && strcmp(type,"2theta")==0 && strcmp(constraintType,"chi")!=0) {
            PyErr_SetString( PyExc_Exception, 
                "Cannot perform the desired integration. If the integration type is 2theta, the constrain integration type must be chi");
            return 0;
        }
        if (doConstraint && strcmp(type,"chi")==0 && strcmp(constraintType,"Q")!=0 && strcmp(constraintType,"2theta")!=0) {
            PyErr_SetString( PyExc_Exception, 
                "Cannot perform the desired integration. If the integration type is chi, the constrain integration type must be either Q or 2theta");
            return 0;
        }
    }

    // passed array has to be 2 dimensional ints
    if (diffractionData->nd != 2 || diffractionData->descr->type_num != PyArray_INT) {
        PyErr_SetString(PyExc_Exception,"diffractionData must be two-dimensional and of type integer");
        return 0;
    }

    // create a new Numeric data structure to hold the integrated intensity
    dimensions[0]=num;
    integratedIntensity=(PyArrayObject *)PyArray_FromDims(1,dimensions,PyArray_DOUBLE);
    values = (PyArrayObject *)PyArray_FromDims(1,dimensions,PyArray_DOUBLE);


    // store totals also in a regular c data structure.
    total = malloc(num*sizeof(unsigned int) );
    if (total == NULL) {
        PyErr_SetString(PyExc_MemoryError,"No Memeory to create temporary data structure");
        return 0;
    }

    // initialize the data to 0
    for (i=0;i<num;i++) {
            total[i]=0;
            *(double *)(integratedIntensity->data + i*integratedIntensity->strides[0])=0;
    }

    // calculate sin & cos for later use.
    cos_beta  = cos(beta*PI/180.0);
    sin_beta  = sin(beta*PI/180.0);
    cos_alpha = cos(alpha*PI/180.0);
    sin_alpha = sin(alpha*PI/180.0);
    cos_rotation = cos(rotation*PI/180.0);
    sin_rotation = sin(rotation*PI/180.0); 

    // calulate the step size between different bins
    step = (upper-lower)*1.0/(num-1.0);

    if (verbose) {
        printf("  lower = %f, upper = %f\n",lower,upper);
        printf("  num = %d,  step = %f\n",num,step);
    }

    for (x=0.0;x<diffractionData->dimensions[0];x++) {
        for (y=0.0;y<diffractionData->dimensions[1];y++) {
            // treat each type of integration differently
            if (strcmp(type,"Q")==0) {
                // calculate the q chi cordiante for each pixel
                getQChi(centerX,centerY,distance,energy,x,y,pixelLength,
                        pixelHeight,rotation,cos_beta,sin_beta,cos_alpha,
                        sin_alpha,cos_rotation,sin_rotation,&q,&chi);

                // find the right bin to put it in
                qBin = (int)((q-lower)*1.0/step);

                // if the bin exists, put it into the bin
                if (qBin >=0 && qBin < num) {

                    // constraint must be of the chi value
                    // if chi is out of the constraint range, then ignore this value
                    if (doConstraint && (chi < constraintLower || chi > constraintUpper)) 
                        continue;

                    intensity = (double)*(int *)(diffractionData->data + 
                            ((int)x)*diffractionData->strides[0] + 
                            ((int)y)*diffractionData->strides[1]); 

                    if (doPolarizationCorrection)
                        intensity = polarizationCorrection(intensity,P,twoTheta,chi);

                    // if we are doing maskinging, make sure the intensity has the 
                    // right bounds and is not in a polygon mask. Otherwise, ignore 
                    // the current pixel
                    if ( (doGreaterThanMask && intensity > greaterThanMask) ||
                            (doLessThanMask && intensity < lessThanMask) || 
                            (doPolygonMask && isInPolygons(polygonsX,polygonsY,
                            polygonBeginningsIndex,polygonNumberOfItems,x,y)))
                        continue;

                    total[qBin]+=1;
                    *(double *)(integratedIntensity->data + 
                            qBin*integratedIntensity->strides[0]) += intensity;
                }
            } else if (strcmp(type,"2theta")==0) {
                getTwoThetaChi(centerX,centerY,distance,x,y,pixelLength,
                        pixelHeight,rotation,cos_beta,sin_beta,cos_alpha,
                        sin_alpha,cos_rotation,sin_rotation,&twoTheta,&chi);

                // find the right bin to put it in
                twoThetaBin = (int)((twoTheta-lower)*1.0/step);

                // if the bin exists, put it into the bin
                if (twoThetaBin >=0 && twoThetaBin < num) {

                    // constraint must be of the chi value
                    // if chi is out of the constraint range, then ignore this value
                    if (doConstraint && (chi < constraintLower || chi > constraintUpper))
                        continue;

                    intensity = (double)*(int *)(diffractionData->data + 
                            ((int)x)*diffractionData->strides[0] + 
                            ((int)y)*diffractionData->strides[1]); 

                    if (doPolarizationCorrection) 
                        intensity = polarizationCorrection(intensity,P,twoTheta,chi);

                    // if we are doing maskinging, make sure the intensity has the 
                    // right bounds and is not in a polygon mask. Otherwise, ignore 
                    // the current pixel
                    if ( (doGreaterThanMask && intensity > greaterThanMask) ||
                            (doLessThanMask && intensity < lessThanMask) || 
                            (doPolygonMask && isInPolygons(polygonsX,polygonsY,
                            polygonBeginningsIndex,polygonNumberOfItems,x,y)))
                        continue;

                    total[twoThetaBin]+=1;
                    *(double *)(integratedIntensity->data + 
                            twoThetaBin*integratedIntensity->strides[0]) += (double)intensity;

                }
            } else if (strcmp(type,"chi")==0) {
                getTwoThetaChi(centerX,centerY,distance,x,y,pixelLength,
                        pixelHeight,rotation,cos_beta,sin_beta,cos_alpha,
                        sin_alpha,cos_rotation,sin_rotation,&twoTheta,&chi);

                q = convertTwoThetaToQ(twoTheta,convertEnergyToWavelength(energy));

                // find the right bin to put it in
                chiBin = (int)((chi-lower)*1.0/step);

                // chi values can vary from -360 to 360. If our value is not in a bin, check
                // if 360-chi fall in a bin. Since the chi range is at most 360 degrees,
                // we will never have to bin something in two places.
                if (chiBin <0 || chiBin >= num) {
                    chi-=360;
                    chiBin = (int)((chi-lower)*1.0/step);
                }

                // if the bin exists, put it into the bin
                if (chiBin >=0 && chiBin < num) {

                    // if chi is out of the constraint range, then ignore this value
                    if (doConstraint && strcmp(constraintType,"Q")==0 && 
                            (q < constraintLower || q > constraintUpper))
                        continue;
                    if (doConstraint && strcmp(constraintType,"2theta")==0 && 
                            (twoTheta < constraintLower || twoTheta > constraintUpper))
                        continue;

                    intensity = (double)*(int *)(diffractionData->data + 
                            (int)x*diffractionData->strides[0] + 
                            ((int)y)*diffractionData->strides[1]); 

                    if (doPolarizationCorrection) 
                        intensity = polarizationCorrection(intensity,P,twoTheta,chi);

                    // if we are doing masking, make sure the intensity has the 
                    // right bounds and is not in a polygon mask. Otherwise, ignore 
                    // the current pixel
                    if ( (doGreaterThanMask && intensity > greaterThanMask) ||
                            (doLessThanMask && intensity < lessThanMask) || 
                            (doPolygonMask && isInPolygons(polygonsX,polygonsY,
                            polygonBeginningsIndex,polygonNumberOfItems,x,y)))
                        continue;

                    total[chiBin]+=1;
                    *(double *)(integratedIntensity->data + 
                            chiBin*integratedIntensity->strides[0]) += intensity;
                }
            }
        }
    }

    for (i=0;i<num;i++) {
        // set the values values
        *(double *)(values->data + i*values->strides[0]) = (lower + (i+0.5)*step);

        if (total[i]>=1) {
            *(double *)(integratedIntensity->data + i*integratedIntensity->strides[0]) /= total[i];

            // clip all intensity values to be at least 0.
            if (*(double *)(integratedIntensity->data + i*integratedIntensity->strides[0]) < 0)
                *(double *)(integratedIntensity->data + i*integratedIntensity->strides[0]) = 0;
                
        } else {
            // -1 means nothing was put into the bin
            *(double *)(integratedIntensity->data + i*integratedIntensity->strides[0]) = -1;
        }
    }

    // free the array we created so that we do not cause a memory leak
    free(total);

    // Why I have to do this is described http://mail.python.org/pipermail/python-list/2002-October/167549.html
    return Py_BuildValue("NN",values,integratedIntensity);
}
/*
 * This function does the caking.
 */
static PyObject * DiffractionAnalysisWrap_cake(PyObject *self, PyObject *args) {
    PyArrayObject *diffractionData;
    PyArrayObject *cake;
    // the dimensions of the caked data
    int dimensions[2];

    double centerX,centerY,distance,energy,alpha,beta,rotation;
    double qOrTwoThetaLower,qOrTwoThetaUpper;
    int numQOrTwoTheta;
    double chiLower,chiUpper;
    int numChi;
    double pixelLength,pixelHeight;
    double cos_beta,sin_beta,cos_alpha,sin_alpha,cos_rotation,sin_rotation;
    double x,y;
    double q,chi; 
    double qOrTwoTheta; 
    int qOrTwoThetaBin,chiBin;
    double qOrTwoThetaStep,chiStep;
    double intensity;
    int doPolarizationCorrection;
    double P,twoTheta;
    int doGreaterThanMask;
    double greaterThanMask;
    int doLessThanMask;
    double lessThanMask;

    int doPolygonMask;
    PyArrayObject * polygonsX;
    PyArrayObject * polygonsY;
    PyArrayObject * polygonBeginningsIndex;
    PyArrayObject * polygonNumberOfItems;

    char *type;

    // get all of the parameters out of the python call
    PyArg_ParseTuple(args,"O!dddddddddiddiidididiO!O!O!O!dds",&PyArray_Type,&diffractionData,
        &centerX,&centerY,&distance,&energy,&alpha,&beta,&rotation,
        &qOrTwoThetaLower,&qOrTwoThetaUpper,&numQOrTwoTheta,
        &chiLower,&chiUpper,&numChi,
        &doPolarizationCorrection,&P,
        &doGreaterThanMask,&greaterThanMask,&doLessThanMask,&lessThanMask,
        &doPolygonMask,
        &PyArray_Type,&polygonsX,
        &PyArray_Type,&polygonsY,
        &PyArray_Type,&polygonBeginningsIndex,
        &PyArray_Type,&polygonNumberOfItems,
        &pixelLength,&pixelHeight,&type);


    // the types of integration
    // Remeber, strcmp returns 0 when they equal 
    if (strcmp(type,"Q") != 0 && strcmp(type,"2theta") != 0) {
        PyErr_SetString( PyExc_Exception, 
                "The type of integration must be Q, or 2theta");
        return 0;
    }

    // passed array has the diffraction data
    if (diffractionData->nd != 2 || 
            diffractionData->descr->type_num != PyArray_INT) {
        PyErr_SetString(PyExc_ValueError,
            "diffractionData must be two-dimensional and of type integer");
        return 0;
    }

    // create a new Numeric data structure to hold the cake
    dimensions[0]=numChi;
    dimensions[1]=numQOrTwoTheta;
    cake=(PyArrayObject *)PyArray_FromDims(2,dimensions,PyArray_DOUBLE);

    // calculate sin & cos for later use.
    cos_beta  = cos(beta*PI/180.0);
    sin_beta  = sin(beta*PI/180.0);
    cos_alpha = cos(alpha*PI/180.0);
    sin_alpha = sin(alpha*PI/180.0);
    cos_rotation = cos(rotation*PI/180.0);
    sin_rotation = sin(rotation*PI/180.0); 

    // calulate the step size between different bins
    qOrTwoThetaStep = (qOrTwoThetaUpper-qOrTwoThetaLower)/(numQOrTwoTheta-1);
    chiStep = (chiUpper-chiLower)/(numChi-1);

    // for each bin
    for (qOrTwoThetaBin = 0; qOrTwoThetaBin < numQOrTwoTheta; qOrTwoThetaBin += 1) {
        for (chiBin = 0; chiBin < numChi; chiBin += 1) {

            // get into the middle of the cell
            qOrTwoTheta = qOrTwoThetaLower + qOrTwoThetaBin*qOrTwoThetaStep + 
                    qOrTwoThetaStep/2.0;
            chi = chiLower + chiBin*chiStep + chiStep/2.0;

            if (strcmp(type,"Q")==0) {
                q = qOrTwoTheta;
            } else {
                q = convertTwoThetaToQ(qOrTwoTheta,convertEnergyToWavelength(energy)); 
            }

            getXY(centerX,centerY,distance,energy,q,chi,
                    pixelLength,pixelHeight,rotation,
                    cos_beta,sin_beta,cos_alpha,sin_alpha,
                    cos_rotation,sin_rotation,&x,&y);

            // if the qOrTwoTheta,chi value is in the diffraction 
            // image, then find the intensity. Note that there is 
            // only diffraction data up to (dimension-1)
            if (x >= 0 && x <= (diffractionData->dimensions[0]-1) &&
                    y >= 0 && y <= (diffractionData->dimensions[1]-1)) {

                intensity = bilinearInterpolation(diffractionData, x, y);

                // possibly do the polarization correction
                if (doPolarizationCorrection) {

                    twoTheta = convertQToTwoTheta(q,
                            convertEnergyToWavelength(energy));

                    intensity = polarizationCorrection(intensity,P,twoTheta,chi);
                }

                // clip all intensity values to be at least 0.
                if (intensity < 0) intensity = 0;
                
                if (doPolygonMask && isInPolygons(polygonsX,polygonsY,
                        polygonBeginningsIndex,polygonNumberOfItems,x,y)) {

                // if we are doing a polygon mask and our pixel is 
                // in one of the polygons, then we should assign its 
                // value to be -4 (by convention)
                *(double *)(cake->data + chiBin*cake->strides[0] + 
                        qOrTwoThetaBin*cake->strides[1]) = -4;

                } else if (doGreaterThanMask && intensity > greaterThanMask) {
                    // if we are doing the greater than mask, if the 
                    // current pixel is greater then the threshold, 
                    // then we should assign its value to be -2 
                    // (by convention).
                    *(double *)(cake->data + chiBin*cake->strides[0] + 
                            qOrTwoThetaBin*cake->strides[1]) = -2;
                } else if (doLessThanMask && intensity < lessThanMask) {
                    // if we are doing the lower than mask, if the 
                    // current pixel is less then the threshold, then 
                    // we should assign its value to be -3 (by convention)
                    *(double *)(cake->data + chiBin*cake->strides[0] + 
                            qOrTwoThetaBin*cake->strides[1]) = -3;
                } else {
                    *(double *)(cake->data + chiBin*cake->strides[0] + 
                            qOrTwoThetaBin*cake->strides[1]) = intensity;
                }

            } else { // otherwise, define outside the image as -1 intensity.
                *(double *)(cake->data + chiBin*cake->strides[0] + 
                        qOrTwoThetaBin*cake->strides[1]) = -1;
            }
        }
    }
    return Py_BuildValue("N",cake);
}