/* * Wrap the getQChi function so that it can be called from python */ static PyObject * DiffractionAnalysisWrap_getQChi( PyObject *self, PyObject *args) { double centerX, centerY,distance,energy,alpha,beta,rotation; double xPixel,yPixel; double pixelLength,pixelHeight; double cos_beta,sin_beta; double cos_alpha,sin_alpha; double cos_rotation,sin_rotation; double q,chi; cos_beta = sin_beta=-10; cos_alpha=sin_alpha = -10; cos_rotation=sin_rotation= -10; PyArg_ParseTuple(args,"ddddddddddd|dddddd",¢erX, ¢erY,&distance,&energy,&alpha,&beta,&rotation,&xPixel, &yPixel,&pixelLength,&pixelHeight,&cos_beta, &sin_beta,&cos_alpha,&sin_alpha,&cos_rotation,&sin_rotation); if (cos_beta == -10) cos_beta = cos(beta*PI/180.0); if (sin_beta == -10) sin_beta = sin(beta*PI/180.0); if (cos_alpha == -10) cos_alpha = cos(alpha*PI/180.0); if (sin_alpha == -10) sin_alpha = sin(alpha*PI/180.0); if (cos_rotation == -10) cos_rotation = cos(rotation*PI/180.0); if (sin_rotation == -10) sin_rotation = sin(rotation*PI/180.0); getQChi(centerX,centerY,distance,energy, xPixel,yPixel,pixelLength,pixelHeight,rotation, cos_beta,sin_beta,cos_alpha,sin_alpha, cos_rotation,sin_rotation,&q,&chi); return Py_BuildValue("dd",q,chi); }
void residual(double *p, double *qFit, int m, int n, void *data) { register int i; struct everything * useful; double q,chi; double rotation; double cos_beta,sin_beta; double cos_alpha,sin_alpha; double cos_rotation,sin_rotation; useful = (struct everything *)(data); // calculate sin & cos for later use. cos_alpha = cos(p[4]*PI/180.0); sin_alpha = sin(p[4]*PI/180.0); cos_beta = cos(p[5]*PI/180.0); sin_beta = sin(p[5]*PI/180.0); rotation = p[6]; cos_rotation = cos(p[6]*PI/180.0); sin_rotation = sin(p[6]*PI/180.0); for (i=0;i<n;i++) { getQChi(p[0],p[1],p[2],p[3],useful->x[i],useful->y[i], useful->pixelLength,useful->pixelHeight,rotation,cos_beta, sin_beta,cos_alpha,sin_alpha,cos_rotation, sin_rotation,&q,&chi); qFit[i] = q; } }
double QxrdCenterFinder::getChi(double x, double y) const { double q,chi; double beta = get_DetectorTilt()*M_PI/180.0; double rot = get_TiltPlaneRotation()*M_PI/180.0; if (get_ImplementTilt()) { getQChi(get_CenterX(), get_CenterY(), get_DetectorDistance(), get_Energy(), x, y, get_DetectorXPixelSize(), get_DetectorYPixelSize(), rot, cos(beta), sin(beta), 1.0, 0.0, cos(rot), sin(rot), &q, &chi); } else { getQChi(get_CenterX(), get_CenterY(), get_DetectorDistance(), get_Energy(), x, y, get_DetectorXPixelSize(), get_DetectorYPixelSize(), 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, &q, &chi); } return chi; }
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); }
/* * Finds one particular peak and returns the x,y cordinates of it * by modifying peakX and peakY */ struct both * constantChiSlice(PyArrayObject * diffractionData,double xCenter, double yCenter,double distance,double energy,double pixelLength, double pixelHeight,double alpha,double beta,double rotation,double qLower, double qUpper, double chi,int * numValues) { double x1,y1; double x2,y2; double cos_beta,sin_beta,cos_alpha,sin_alpha,cos_rotation,sin_rotation; double m; int xSize,ySize; double xUpperFirst,yUpperFirst,xLowerFirst,yLowerFirst; double xUpperSecond,yUpperSecond,xLowerSecond,yLowerSecond; double xCurrent,yCurrent; int dataLow,dataHigh; int xLow,xHigh,yLow,yHigh; int counter; double qCurrent,chiCurrent; double dataInterpolate; struct both * vals; 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); // find the beginning & ending pixel values for our Q,chi range. getXY(xCenter,yCenter,distance,energy,qLower,chi, pixelLength,pixelHeight,rotation,cos_beta,sin_beta, cos_alpha,sin_alpha,cos_rotation,sin_rotation,&x1,&y1); getXY(xCenter,yCenter,distance,energy,qUpper,chi, pixelLength,pixelHeight,rotation,cos_beta,sin_beta, cos_alpha,sin_alpha,cos_rotation,sin_rotation,&x2,&y2); xSize = diffractionData->dimensions[0]; ySize = diffractionData->dimensions[0]; // If the two points to find values between are off the image, // Point the answer to nothing. if (ceil(x1)<0 || floor(x1)>xSize || ceil(y1)<0 || floor(y1)>=ySize || ceil(x2)<0 || floor(x2) >= xSize || ceil(y2)<0 || floor(y2)>=ySize) { return NULL; } // Make sure that xLower < xUpper for our first sweep if (x1>x2) { xUpperFirst=x1;yUpperFirst=y1; xLowerFirst=x2;yLowerFirst=y2; } else { xLowerFirst=x1;yLowerFirst=y1; xUpperFirst=x2;yUpperFirst=y2; } // Make sure that yLower < yUpperfor our second sweep if (y1 > y2) { xUpperSecond=x1;yUpperSecond=y1; xLowerSecond=x2;yLowerSecond=y2; } else { xLowerSecond=x1;yLowerSecond=y1; xUpperSecond=x2;yUpperSecond=y2; } // figure out all the data points to sample *numValues = ( (int)floor(xUpperFirst)-(int)ceil(xLowerFirst) +1 ); if (yUpperSecond != yLowerSecond) *numValues += ( (int)floor(yUpperSecond)-(int)ceil(yLowerSecond) +1 ); vals=malloc( sizeof(struct both) ); vals->first = malloc( (*numValues)*sizeof(double) ); vals->second = malloc( (*numValues)*sizeof(double) ); m=(yUpperFirst-yLowerFirst)*1.0/(xUpperFirst-xLowerFirst); counter=0; for(xCurrent=ceil(xLowerFirst);xCurrent<=floor(xUpperFirst);xCurrent++) { // get all points that lie on constant integer y values in the image yCurrent=yLowerFirst +m*(xCurrent-xLowerFirst); yHigh = (int)ceil(yCurrent); yLow = (int)floor(yCurrent); dataLow=*(int *)(diffractionData->data + ((int)xCurrent)*diffractionData->strides[0] + yLow*diffractionData->strides[1]); dataHigh=*(int *)(diffractionData->data + ((int)xCurrent)*diffractionData->strides[0] + yHigh*diffractionData->strides[1]); dataInterpolate = dataLow + (yCurrent-yLow)*(dataHigh-dataLow); getQChi(xCenter,yCenter,distance,energy,xCurrent,yCurrent, pixelLength,pixelHeight,rotation,cos_beta,sin_beta,cos_alpha, sin_alpha,cos_rotation,sin_rotation,&qCurrent,&chiCurrent); vals->first[counter] = qCurrent; vals->second[counter] = dataInterpolate; counter++; } if (yUpperSecond - yLowerSecond > .00001 ) { m=(xUpperSecond-xLowerSecond)*1.0/(yUpperSecond-yLowerSecond); for (yCurrent=(int)ceil(yLowerSecond);yCurrent<=(int)floor(yUpperSecond);yCurrent++) { // get all points that lie on constant integer x values in the image xCurrent = xLowerSecond + m*(yCurrent-yLowerSecond); xHigh=(int)ceil(xCurrent); xLow=(int)floor(xCurrent); dataLow=*(int *)(diffractionData->data + xLow*diffractionData->strides[0] + ((int)yCurrent)*diffractionData->strides[1]); dataHigh=*(int *)(diffractionData->data + xHigh*diffractionData->strides[0] + ((int)yCurrent)*diffractionData->strides[1]); dataInterpolate = dataLow + (xCurrent-xLow)*(dataHigh-dataLow); getQChi(xCenter,yCenter,distance,energy,xCurrent,yCurrent, pixelLength,pixelHeight,rotation,cos_beta,sin_beta,cos_alpha, sin_alpha,cos_rotation,sin_rotation,&qCurrent,&chiCurrent); vals->first[counter] = qCurrent; vals->second[counter] = dataInterpolate; counter++; } } // now, counter must equal *numValues. Return success return vals; }