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, ¢erX,¢erY, &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, ¢erX,¢erY,&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); }