|
42 | 42 | npatand = lambda x: 180.*np.arctan(x)/np.pi |
43 | 43 | npatan2d = lambda y,x: 180.*np.arctan2(y,x)/np.pi |
44 | 44 | nxs = np.newaxis |
45 | | -debug = True |
| 45 | +debug = False |
46 | 46 |
|
47 | 47 | def peneCorr(tth,dep,dist): |
48 | 48 | 'Compute empirical position correction due to detector absorption' |
@@ -457,94 +457,40 @@ def GetEllipse(dsp,data): |
457 | 457 | dxy = peneCorr(tth,dep,dist) |
458 | 458 | return GetEllipse2(tth,dxy,dist,cent,tilt,phi) |
459 | 459 |
|
460 | | -# def GetDetectorXY(dsp,azm,data): |
461 | | -# '''Get detector x,y position from d-spacing (dsp), azimuth (azm,deg) |
462 | | -# & image controls dictionary (data) - new version |
463 | | -# it seems to be only used in plotting & wrong |
464 | | -# ''' |
465 | | -# def LinePlaneCollision(planeNormal, planePoint, rayDirection, rayPoint, epsilon=1e-6): |
466 | | - |
467 | | -# ndotu = planeNormal.dot(rayDirection) |
468 | | -# if ndotu < epsilon: |
469 | | -# return None |
470 | | -# w = rayPoint - planePoint |
471 | | -# si = -planeNormal.dot(w) / ndotu |
472 | | -# Psi = w + si * rayDirection + planePoint |
473 | | -# return Psi |
474 | | - |
475 | | -# dist = data['distance'] |
476 | | -# cent = data['center'] |
477 | | -# phi = data['rotation']-90. #to give rotation of major axis |
478 | | -# T = makeMat(data['tilt'],0) #rotate about X |
479 | | -# R = makeMat(phi,2) #rotate about Z |
480 | | -# MN = np.inner(R,np.inner(R,T)) |
481 | | -# iMN= nl.inv(MN) |
482 | | -# tth = 2.0*npasind(data['wavelength']/(2.*dsp)) |
483 | | -# vect = np.array([npsind(tth)*npcosd(azm-phi),npsind(tth)*npsind(azm-phi),npcosd(tth)]) |
484 | | -# dxyz0 = np.inner(np.array([0.,0.,1.0]),MN) #tilt detector normal |
485 | | -# dxyz0 += np.array([0.,0.,dist]) #translate to distance |
486 | | -# dxyz0 = np.inner(dxyz0,makeMat(data['det2theta'],1).T) #rotate on 2-theta |
487 | | -# dxyz1 = np.inner(np.array([cent[0],cent[1],0.]),MN) #tilt detector cent |
488 | | -# dxyz1 += np.array([0.,0.,dist]) #translate to distance |
489 | | -# dxyz1 = np.inner(dxyz1,makeMat(data['det2theta'],1).T) #rotate on 2-theta |
490 | | -# xyz = LinePlaneCollision(dxyz1,dxyz0,vect,dist*vect) |
491 | | -# if xyz is None: |
492 | | -# return np.zeros(2) |
493 | | -# # return None |
494 | | -# xyz = np.inner(xyz,makeMat(data['det2theta'],1).T) |
495 | | -# xyz -= np.array([0.,0.,dist]) #translate back |
496 | | -# xyz = np.inner(xyz,iMN) |
497 | | -# return np.squeeze(xyz)[:2]+cent |
498 | | - |
499 | | -def GetDetectorXY2(dsp,azm,data): |
| 460 | +def GetDetectorXY(dsp,azm,data): |
500 | 461 | '''Get detector x,y position from d-spacing (dsp), azimuth (azm,deg) |
501 | | - & image controls dictionary (data) |
502 | | - it seems to be only used in plotting |
| 462 | + & image controls dictionary (data) - new version |
503 | 463 | ''' |
504 | | - elcent,phi,radii = GetEllipse(dsp,data) |
505 | | - phi = data['rotation']-90. #to give rotation of major axis |
506 | | - tilt = data['tilt'] |
507 | | - dist = data['distance'] |
| 464 | + |
| 465 | + def LinePlaneCollision(planeNormal, planePoint, rayDirection, rayPoint, epsilon=1e-6): |
| 466 | + |
| 467 | + ndotu = planeNormal.dot(rayDirection) |
| 468 | + if ndotu < epsilon: |
| 469 | + return None |
| 470 | + w = rayPoint - planePoint |
| 471 | + si = -planeNormal.dot(w) / ndotu |
| 472 | + Psi = w + si * rayDirection + planePoint |
| 473 | + return Psi |
| 474 | + |
| 475 | + dist = data['distance']/npcosd(data['tilt']) #sample-beam intersection point on detector plane |
508 | 476 | cent = data['center'] |
509 | | - tth = 2.0*asind(data['wavelength']/(2.*dsp)) |
510 | | - stth = sind(tth) |
511 | | - cosb = cosd(tilt) |
512 | | - if radii[0] > 0.: #ellipse - correct! |
513 | | - sinb = sind(tilt) |
514 | | - tanb = tand(tilt) |
515 | | - fplus = dist*tanb*stth/(cosb+stth) |
516 | | - fminus = dist*tanb*stth/(cosb-stth) |
517 | | - zdis = (fplus-fminus)/2. |
518 | | - rsqplus = radii[0]**2+radii[1]**2 |
519 | | - rsqminus = radii[0]**2-radii[1]**2 |
520 | | - R = rsqminus*cosd(2.*azm-2.*phi)+rsqplus |
521 | | - Q = np.sqrt(2.)*radii[0]*radii[1]*np.sqrt(R-2.*zdis**2*sind(azm-phi)**2) |
522 | | - if radii[0] <= 0.: |
523 | | - zdis *= -1. |
524 | | - P = 2.*radii[0]**2*zdis*cosd(azm-phi) |
525 | | - radius = (P+Q)/R |
526 | | - xy = np.array([radius*cosd(azm),radius*sind(azm)]) |
527 | | - xy += cent |
528 | | - else: #hyperbola - both branches (one is way off screen!) - not correct |
529 | | - sinb = abs(sind(tilt)) |
530 | | - tanb = abs(tand(tilt)) |
531 | | - f = dist*tanb*stth/(cosb+stth) |
532 | | - v = dist*(tanb+tand(tth-abs(tilt))) |
533 | | - delt = dist*stth*(1+stth*cosb)/(sinb*cosb*(stth+cosb)) |
534 | | - ecc = (v-f)/(delt-v) |
535 | | - R = radii[1]*(ecc**2-1)/(1-ecc*cosd(azm-phi)) |
536 | | - if tilt > 0.: |
537 | | - offset = 2.*radii[1]*ecc+f #select other branch |
538 | | - xy = [-R*cosd(azm-phi)-offset,-R*sind(azm-phi)] |
539 | | - else: |
540 | | - offset = -f |
541 | | - xy = [-R*cosd(azm-phi)-offset,2.*R*sind(azm-phi)] |
542 | | - print(azm,ecc,R,offset,cosd(azm-phi),sind(azm-phi),xy) |
543 | | - xy = -np.array([xy[0]*cosd(phi)+xy[1]*sind(phi),xy[0]*sind(phi)-xy[1]*cosd(phi)]) |
544 | | - xy += cent |
545 | | - if data['det2theta']: |
546 | | - xy[0] += dist*nptand(data['det2theta']+data['tilt']*npsind(data['rotation'])) |
547 | | - return xy |
| 477 | + phi = data['rotation'] |
| 478 | + T = makeMat(data['tilt'],0) #rotate about X |
| 479 | + R = makeMat(phi,2) #rotate about Z |
| 480 | + MN = np.inner(R,np.inner(R,T)) |
| 481 | + iMN= nl.inv(MN) |
| 482 | + tth = 2.0*npasind(data['wavelength']/(2.*dsp)) |
| 483 | + vect = np.array([npsind(tth)*npcosd(azm),npsind(tth)*npsind(azm),npcosd(tth)]) |
| 484 | + dxyzN = np.inner(np.array([0.,0.,1.0]),MN) #tilt detector normal |
| 485 | + dxyzO = np.array([0.,0.,dist]) #translate to distance |
| 486 | + dorig = np.zeros(3) |
| 487 | + xyz = LinePlaneCollision(dxyzN,dxyzO,vect,dorig) |
| 488 | + if xyz is None: |
| 489 | + return np.zeros(2) |
| 490 | + xyz = np.inner(xyz,makeMat(data['det2theta'],1).T) |
| 491 | + xyz -= np.array([0.,0.,dist]) #translate back |
| 492 | + xyz = np.inner(xyz,iMN) |
| 493 | + return np.squeeze(xyz)[:2]+cent |
548 | 494 |
|
549 | 495 | def GetTthAzmDsp2(x,y,data): #expensive |
550 | 496 | '''Computes a 2theta, etc. from a detector position and calibration constants - checked |
@@ -644,28 +590,6 @@ def GetAzm(x,y,data): |
644 | 590 | else: |
645 | 591 | return GetTthAzmDsp2(x,y,data)[1] |
646 | 592 | # these two are used only for integration & finding pixel masks |
647 | | -# def GetTthAzmG2(x,y,data): |
648 | | -# '''Give 2-theta, azimuth & geometric corr. values for detector x,y position; |
649 | | -# calibration info in data - only used in integration for detector 2-theta = 0 |
650 | | -# ''' |
651 | | -# tilt = data['tilt'] |
652 | | -# dist = data['distance']/npcosd(tilt) |
653 | | -# MN = -np.inner(makeMat(data['rotation'],2),makeMat(tilt,0)) |
654 | | -# dx = x-data['center'][0] |
655 | | -# dy = y-data['center'][1] |
656 | | -# dz = np.dot(np.dstack([dx.T,dy.T,np.zeros_like(dx.T)]),MN).T[2] |
657 | | -# xyZ = dx**2+dy**2-dz**2 |
658 | | -# tth0 = npatand(np.sqrt(xyZ)/(dist-dz)) |
659 | | -# dzp = peneCorr(tth0,data['DetDepth'],dist) |
660 | | -# tth = npatan2d(np.sqrt(xyZ),dist-dz+dzp) |
661 | | -# azm = (npatan2d(dy,dx)+data['azmthOff']+720.)%360. |
662 | | -# # G-calculation - use Law of sines |
663 | | -# distm = data['distance']/1000.0 |
664 | | -# sinB2 = np.minimum(np.ones_like(tth),(data['distance']*npsind(tth))**2/(dx**2+dy**2)) |
665 | | -# #sinB2 = (data['distance']*npsind(tth))**2/(dx**2+dy**2) |
666 | | -# C = 180.-tth-npacosd(np.sqrt(1.- sinB2)) |
667 | | -# G = distm**2*sinB2/npsind(C)**2 |
668 | | -# return tth,azm,G |
669 | 593 |
|
670 | 594 | def GetTthAzmG(x,y,data): |
671 | 595 | '''Give 2-theta, azimuth & geometric corr. values for detector x,y position; |
@@ -705,31 +629,11 @@ def costth(xyz,d0): |
705 | 629 | azm = (npatan2d(dxyz[:,:,1],dxyz[:,:,0])+data['azmthOff']+720.)%360. |
706 | 630 | # new G calculation - parallax & distance (in meters) |
707 | 631 | G = 1./ctth0*np.sum(dxyz0**2,axis=2)*1.e-6 #parallax*distance^2; convert to m^2 - correct! |
708 | | -# old G-calculation |
709 | | - # x0 = data['distance']*nptand(tilt) |
710 | | - # x0x = x0*npcosd(data['rotation']) |
711 | | - # x0y = x0*npsind(data['rotation']) |
712 | | - # distsq = data['distance']**2 |
713 | | - # G = ((dx-x0x)**2+(dy-x0y)**2+distsq)/distsq #for geometric correction = 1/cos(2theta)^2 if tilt=0. |
714 | | - # G *= ctth0 |
715 | | -# # G-calculation - use Law of sines - wrong for nonzero det2theta! |
716 | | -# distm = data['distance']/1000.0 |
717 | | -# sinB2 = np.minimum(np.ones_like(tth), |
718 | | -# (data['distance']*npsind(tth))**2/(dx**2+dy**2)) |
719 | | -# C = 180.-tth-npacosd(np.sqrt(1.- sinB2)) |
720 | | -# G = distm**2*sinB2/npsind(C)**2 |
721 | 632 | return tth,azm,G |
722 | 633 |
|
723 | 634 | def meanAzm(a,b): |
724 | 635 | AZM = lambda a,b: npacosd(0.5*(npsind(2.*b)-npsind(2.*a))/(np.pi*(b-a)/180.))/2. |
725 | 636 | azm = AZM(a,b) |
726 | | -# quad = int((a+b)/180.) |
727 | | -# if quad == 1: |
728 | | -# azm = 180.-azm |
729 | | -# elif quad == 2: |
730 | | -# azm += 180. |
731 | | -# elif quad == 3: |
732 | | -# azm = 360-azm |
733 | 637 | return azm |
734 | 638 |
|
735 | 639 | def ImageCompress(image,scale): |
@@ -761,7 +665,7 @@ def GetLineScan(image,data): |
761 | 665 | Tx = np.array([tth for tth in np.linspace(LUtth[0],LUtth[1],numChans+1)]) |
762 | 666 | Ty = np.zeros_like(Tx) |
763 | 667 | dsp = wave/(2.0*npsind(Tx/2.0)) |
764 | | - xy = [GetDetectorXY2(d,azm,data) for d in dsp] |
| 668 | + xy = [GetDetectorXY(d,azm,data) for d in dsp] |
765 | 669 | xy = np.array(xy).T |
766 | 670 | xy[1] *= scalex |
767 | 671 | xy[0] *= scaley |
@@ -833,10 +737,6 @@ def CalcRings(G2frame,ImageZ,data,masks): |
833 | 737 | for iH,H in enumerate(HKL): |
834 | 738 | if debug: print (H) |
835 | 739 | dsp = H[3] |
836 | | - tth = 2.0*asind(wave/(2.*dsp)) |
837 | | - # if tth+abs(data['tilt']) > 90.: |
838 | | - # G2fil.G2Print ('next line is a hyperbola - search stopped') |
839 | | - # break |
840 | 740 | ellipse = GetEllipse(dsp,data) |
841 | 741 | if iH not in absent and iH >= skip: |
842 | 742 | Ring = makeRing(dsp,ellipse,0,-1.,scalex,scaley,ma.array(ImageZ,mask=tam))[0] |
@@ -903,18 +803,13 @@ def ImageRecalibrate(G2frame,ImageZ,data,masks,getRingsOnly=False): |
903 | 803 | 'setdist':data.get('setdist',data['distance']), |
904 | 804 | 'tilt':data['tilt'],'phi':data['rotation'],'wave':data['wavelength'],'dep':data['DetDepth']} |
905 | 805 | Found = False |
906 | | - wave = data['wavelength'] |
907 | 806 | frame = masks['Frames'] |
908 | 807 | tam = ma.make_mask_none(ImageZ.shape) |
909 | 808 | if frame: |
910 | 809 | tam = ma.mask_or(tam,ma.make_mask(np.abs(polymask(data,frame)-255))) |
911 | 810 | for iH,H in enumerate(HKL): |
912 | 811 | if debug: print (H) |
913 | 812 | dsp = H[3] |
914 | | - tth = 2.0*asind(wave/(2.*dsp)) |
915 | | - # if tth+abs(data['tilt']) > 90.: |
916 | | - # G2fil.G2Print ('next line is a hyperbola - search stopped') |
917 | | - # break |
918 | 813 | ellipse = GetEllipse(dsp,data) |
919 | 814 | if iH not in absent and iH >= skip: |
920 | 815 | Ring = makeRing(dsp,ellipse,pixLimit,cutoff,scalex,scaley,ma.array(ImageZ,mask=tam))[0] |
@@ -1128,9 +1023,6 @@ def ImageCalibrate(G2frame,data): |
1128 | 1023 | for i,H in enumerate(HKL): |
1129 | 1024 | dsp = H[3] |
1130 | 1025 | tth = 2.0*asind(wave/(2.*dsp)) |
1131 | | - # if tth+abs(data['tilt']) > 90.: |
1132 | | - # G2fil.G2Print ('next line is a hyperbola - search stopped') |
1133 | | - # break |
1134 | 1026 | if debug: print ('HKLD:'+str(H[:4])+'2-theta: %.4f'%(tth)) |
1135 | 1027 | elcent,phi,radii = ellipse = GetEllipse(dsp,data) |
1136 | 1028 | data['ellipses'].append(copy.deepcopy(ellipse+('g',))) |
|
0 commit comments