Skip to content

Commit eed51df

Browse files
committed
calculated hyperbola rings correctly plotted, but no observed points. No fitting of hyperbola rings possible - wrong math for locating points & for FitDetector - ellipse only.
1 parent 50e9f7d commit eed51df

File tree

2 files changed

+68
-25
lines changed

2 files changed

+68
-25
lines changed

GSASII/GSASIIimage.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def ellipse_axis_length( p ):
9797
down2=(b*b-a*c)*( (a-c)*np.sqrt(1+4*b*b/((a-c)*(a-c)))-(c+a))
9898
res1=np.sqrt(up/down1)
9999
res2=np.sqrt(up/down2)
100-
return np.array([ res2,res1])
100+
return np.array([ res2,res1,0.0])
101101

102102
xy = np.array(xy)
103103
x = np.asarray(xy.T[0])[:,np.newaxis]
@@ -371,22 +371,23 @@ def ellipseC():
371371
if debug:
372372
theta = npacosd(1./np.sqrt(1.+(radii[0]/radii[1])**2))
373373
print ('hyperbola:',theta)
374-
return 200.*np.pi
374+
return 720.
375375
apb = radii[1]+radii[0]
376376
amb = radii[1]-radii[0]
377377
return np.pi*apb*(1+3*(amb/apb)**2/(10+np.sqrt(4-3*(amb/apb)**2)))
378-
379378
cent,phi,radii = ellipse
379+
if radii[1] < 0.:
380+
return None
380381
cphi = cosd(phi-90.) #convert to major axis rotation
381382
sphi = sind(phi-90.)
382383
ring = []
383384
C = int(ellipseC())*mul #ring circumference in mm
384385
azm = []
385386
for i in range(0,C,1): #step around ring in 1mm increments
386387
a = 360.*i/C
387-
if radii[1] <= 0: #parabola or hyperbola
388-
x = radii[1]*coshd(a-phi+90.) #major axis
389-
y = radii[0]*sinhd(a-phi+90.)
388+
if radii[0] <= 0: #parabola or hyperbola
389+
x = -radii[0]/cosd(a-phi) #major axis
390+
y = radii[1]*tand(a-phi)
390391
else:
391392
x = radii[1]*cosd(a-phi+90.) #major axis
392393
y = radii[0]*sind(a-phi+90.)
@@ -412,7 +413,7 @@ def GetEllipse2(tth,dxy,dist,cent,tilt,phi):
412413
radii[0] (b-minor axis) set < 0. for hyperbola
413414
414415
'''
415-
radii = [0,0]
416+
radii = [0,0,0]
416417
stth = sind(tth)
417418
cosb = cosd(tilt)
418419
tanb = tand(tilt)
@@ -427,6 +428,7 @@ def GetEllipse2(tth,dxy,dist,cent,tilt,phi):
427428
vminus = d*(tanb+(1-tbp)/(1+tbp))*stth/(cosb-stth)
428429
radii[0] = np.sqrt((vplus+vminus)**2-(fplus+fminus)**2)/2. #+minor axis
429430
radii[1] = (vplus+vminus)/2. #major axis
431+
radii[2] = tth #save for ellipse; might be useful
430432
zdis = (fplus-fminus)/2.
431433
else: #hyperbola!
432434
f = d*abs(tanb)*stth/(cosb+stth)
@@ -435,10 +437,11 @@ def GetEllipse2(tth,dxy,dist,cent,tilt,phi):
435437
eps = (v-f)/(delt-v)
436438
radii[0] = -eps*(delt-f)/np.sqrt(eps**2-1.) #-minor axis
437439
radii[1] = eps*(delt-f)/(eps**2-1.) #major axis
440+
radii[2] = tth #save 2-theta for hyperbola
438441
if tilt > 0:
439442
zdis = f+radii[1]*eps
440443
else:
441-
zdis = -f
444+
zdis = -f-radii[1]*eps
442445
#NB: zdis is || to major axis & phi is rotation of minor axis
443446
#thus shift from beam to ellipse center is [Z*sin(phi),-Z*cos(phi)]
444447
elcent = [cent[0]+zdis*sind(phi),cent[1]-zdis*cosd(phi)]
@@ -457,21 +460,40 @@ def GetEllipse(dsp,data):
457460
dxy = peneCorr(tth,dep,dist)
458461
return GetEllipse2(tth,dxy,dist,cent,tilt,phi)
459462

463+
def LinePlaneCollision(planeNormal, planePoint, rayDirection, rayPoint, epsilon=1e-6):
464+
465+
ndotu = planeNormal.dot(rayDirection)
466+
if ndotu < epsilon:
467+
return None
468+
w = rayPoint - planePoint
469+
si = -planeNormal.dot(w) / ndotu
470+
Psi = w + si * rayDirection + planePoint
471+
return Psi
472+
473+
def GetDetSamAngle(x,y,data):
474+
def costth(xyz,d0):
475+
''' compute cos of angle between vectors; xyz not normalized, d0 normalized'''
476+
u = xyz/nl.norm(xyz,axis=-1)[:,:,nxs]
477+
return np.dot(u,d0)
478+
#zero detector 2-theta: tested with tilted images - perfect integrations
479+
dx = x-data['center'][0]
480+
dy = y-data['center'][1]
481+
tilt = data['tilt']
482+
dist = data['distance']/npcosd(tilt) #sample-beam intersection point on detector plane
483+
T = makeMat(tilt,0) #detector tilt matrix
484+
R = makeMat(data['rotation'],2) #rotation of tilt axis matrix
485+
MN = np.inner(R,np.inner(R,T)) #should be detector transformation matrix; why not np.inner(R,T)
486+
d001 = np.array([0.,0.,1.]) #vector along z (beam direction); normal to untilted detector plane
487+
r001 = np.inner(d001,MN) #should rotate vector same as detector
488+
dxyz0 = np.inner(np.dstack([dx,dy,np.zeros_like(dx)]),MN) #transform detector pixel x,y by tilt/rotate
489+
dxyz0 += np.array([0.,0.,dist]) #shift away from sample
490+
ctth0 = costth(dxyz0,r001) #cos of angle between detector normal & sample-pixel vector
491+
return ctth0
492+
460493
def GetDetectorXY(dsp,azm,data):
461494
'''Get detector x,y position from d-spacing (dsp), azimuth (azm,deg)
462495
& image controls dictionary (data) - new version
463496
'''
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-
475497
dist = data['distance']/npcosd(data['tilt']) #sample-beam intersection point on detector plane
476498
cent = data['center']
477499
phi = data['rotation']
@@ -699,7 +721,7 @@ def EdgeFinder(image,data):
699721
return zip(tax,tay)
700722

701723
def CalcRings(G2frame,ImageZ,data,masks):
702-
''' Not used anywhere?'''
724+
''' '''
703725
pixelSize = data['pixelSize']
704726
scalex = 1000./pixelSize[0]
705727
scaley = 1000./pixelSize[1]
@@ -730,7 +752,6 @@ def CalcRings(G2frame,ImageZ,data,masks):
730752
else:
731753
absent = ()
732754
HKL = G2lat.sortHKLd(HKL,True,False)
733-
wave = data['wavelength']
734755
frame = masks['Frames']
735756
tam = ma.make_mask_none(ImageZ.shape)
736757
if frame:
@@ -808,6 +829,7 @@ def ImageRecalibrate(G2frame,ImageZ,data,masks,getRingsOnly=False):
808829
tam = ma.make_mask_none(ImageZ.shape)
809830
if frame:
810831
tam = ma.mask_or(tam,ma.make_mask(np.abs(polymask(data,[frame,])-255)))
832+
hyperbola = False
811833
for iH,H in enumerate(HKL):
812834
if debug: print (H)
813835
dsp = H[3]
@@ -826,11 +848,14 @@ def ImageRecalibrate(G2frame,ImageZ,data,masks,getRingsOnly=False):
826848
continue
827849
else: #no more rings beyond edge of detector
828850
data['ellipses'].append([])
851+
if Ring is None:
852+
hyperbola = True
829853
continue
830854
if not data['rings']:
831855
G2fil.G2Print ('no rings found; try lower Min ring I/Ib',mode='warn')
832856
return []
833-
857+
if hyperbola:
858+
print('Hyperbola found, outer rings not fitted')
834859
rings = np.concatenate((data['rings']),axis=0)
835860
if getRingsOnly:
836861
return rings,HKL
@@ -1516,8 +1541,6 @@ def ImageIntegrate(image,data,masks,blkSize=128,returnN=False,useTA=None,useMask
15161541
H1 = LRazm
15171542
if 'SASD' not in data['type']:
15181543
H0 *= np.array(G2pwd.Polarization(data['PolaVal'][0],H2[:-1],0.)[0])
1519-
# if np.abs(data['det2theta']) < 1.0: #small angle approx only; not appropriate for detectors at large 2-theta
1520-
# H0 /= np.abs(npcosd(H2[:-1]+data['tilt']-np.abs(data['det2theta'])))**4 #parallax correction (why **4?)
15211544
if 'SASD' in data['type']:
15221545
H0 /= npcosd(H2[:-1]) #one more for small angle scattering data?
15231546
if data['Oblique'][1]:

GSASII/GSASIIplot.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5511,13 +5511,33 @@ def OnImRelease(event):
55115511
Plot.plot(xring,yring,'.',color=colors[N%NC])
55125512
N += 1
55135513
for ellipse in Data['ellipses']: #what about hyperbola?
5514-
cent,phi,[width,height],col = ellipse
5514+
try:
5515+
cent,phi,[width,height,tth],col = ellipse
5516+
except ValueError:
5517+
cent,phi,[width,height],col = ellipse
5518+
tth = 0.0
55155519
if width > 0: #ellipses
55165520
try: # angle was changed to a keyword at some point, needed in mpl 3.8
55175521
Plot.add_artist(Ellipse([cent[0],cent[1]],2*width,2*height,angle=phi,ec=col,fc='none'))
55185522
except: # but keep the old version as a patch (5/20/24) in case old call needed for old MPL
55195523
Plot.add_artist(Ellipse([cent[0],cent[1]],2*width,2*height,phi,ec=col,fc='none'))
55205524
Plot.text(cent[0],cent[1],'+',color=col,ha='center',va='center')
5525+
elif tth: #future hyperbola plot
5526+
dsp =0.5*Data['wavelength']/npsind(tth/2.0)
5527+
darc = Data['rotation']
5528+
# Azm = np.arange(-10.-darc,190.5-darc,.5)
5529+
Azm = np.arange(0.,360.5,.5)
5530+
xyH = []
5531+
for azm in Azm:
5532+
xy = G2img.GetDetectorXY(dsp,azm,Data)
5533+
if np.any(xy):
5534+
xyH.append(xy)
5535+
if len(xyH):
5536+
xyH = np.array(xyH)
5537+
xH,yH = xyH.T
5538+
Plot.plot(xH,yH,color=col)
5539+
Plot.text(cent[0],cent[1],'+',color=col,ha='center',va='center')
5540+
continue
55215541
if G2frame.PickId and G2frame.GPXtree.GetItemText(G2frame.PickId) in ['Stress/Strain',]:
55225542
for N,ring in enumerate(StrSta['d-zero']):
55235543
if 'ImxyCalc' in ring:

0 commit comments

Comments
 (0)