Skip to content

Commit 741f916

Browse files
committed
bring up to date w/current master (c94f93a)
2 parents 9d5f764 + c94f93a commit 741f916

File tree

7 files changed

+144
-60
lines changed

7 files changed

+144
-60
lines changed

GSASII/GSASIIIntPDFtool.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ def ontblModeBtn(event):
498498
sizer.Add(self.readDir,1,wx.EXPAND,1)
499499
btn3 = wx.Button(mnpnl, wx.ID_ANY, "Browse")
500500
btn3.Bind(wx.EVT_BUTTON, self.SetSourceDir)
501-
sizer.Add(btn3,0,wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
501+
sizer.Add(btn3,0,wx.ALIGN_CENTER_VERTICAL)
502502
mnsizer.Add(sizer,0,wx.EXPAND,0)
503503
sizer = wx.BoxSizer(wx.HORIZONTAL)
504504
sizer.Add((-1,-1),1,wx.EXPAND,1)
@@ -522,7 +522,7 @@ def ontblModeBtn(event):
522522
sizer.Add(fInp3,1,wx.EXPAND)
523523
btn3 = wx.Button(mnpnl, wx.ID_ANY, "Browse")
524524
btn3.Bind(wx.EVT_BUTTON, OnBrowse)
525-
sizer.Add(btn3,0,wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
525+
sizer.Add(btn3,0,wx.ALIGN_CENTER_VERTICAL)
526526
lblsizr.Add(sizer,0,wx.EXPAND)
527527
sizer = wx.BoxSizer(wx.HORIZONTAL)
528528
sizer.Add(wx.StaticText(mnpnl, wx.ID_ANY,'Select format(s):'))

GSASII/GSASIIdataGUI.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6925,7 +6925,7 @@ def _makemenu(): # routine to create menu when first used
69256925
G2G.Define_wxId('wxID_IMCALIBRATE', 'wxID_IMRECALIBRATE', 'wxID_IMINTEGRATE', 'wxID_IMCLEARCALIB', 'wxID_IMRECALIBALL',
69266926
'wxID_IMCOPYCONTROLS', 'wxID_INTEGRATEALL', 'wxID_IMSAVECONTROLS', 'wxID_IMLOADCONTROLS', 'wxID_IMAUTOINTEG',
69276927
'wxID_IMCOPYSELECTED', 'wxID_SAVESELECTEDCONTROLS', 'wxID_IMXFERCONTROLS', 'wxID_IMRESETDIST', 'wxID_CALCRINGS',
6928-
'wxID_LOADELECTEDCONTROLS','wxID_IMDISTRECALIB', 'wxID_IMINTEGPDFTOOL')
6928+
'wxID_LOADELECTEDCONTROLS','wxID_IMDISTRECALIB', 'wxID_IMINTEGPDFTOOL','wxID_IMMULTGAINMAP')
69296929
G2G.Define_wxId('wxID_IMDRWPHS')
69306930
def _makemenu(): # routine to create menu when first used
69316931
self.ImageMenu = wx.MenuBar()
@@ -6938,6 +6938,7 @@ def _makemenu(): # routine to create menu when first used
69386938
self.ImageEdit.Append(G2G.wxID_CALCRINGS,'Calculate rings','Calculate rings from calibration parameters')
69396939
self.ImageEdit.Append(G2G.wxID_IMDISTRECALIB,'Multi-distance Recalibrate','Recalibrate all images varying delta-distance and fitting wavelength')
69406940
self.ImageEdit.Append(G2G.wxID_IMCLEARCALIB,'Clear calibration','Clear calibration data points and rings')
6941+
self.ImageEdit.Append(G2G.wxID_IMMULTGAINMAP,'Multiimage Gain map','Make gain map from multiple images')
69416942
ImageIntegrate = wx.Menu(title='')
69426943
self.ImageMenu.Append(menu=ImageIntegrate, title='Integration')
69436944
ImageIntegrate.Append(G2G.wxID_IMINTEGRATE,'Integrate','Integrate selected image')

GSASII/GSASIIimage.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -707,14 +707,19 @@ def costth(xyz):
707707
dxyz = dxyz0
708708
ctth = costth(dxyz)
709709
tth = npacosd(ctth)
710-
azm = (npatan2d(dxyz[:,:,1],dxyz[:,:,0])+data['azmthOff']+720.)%360.
711-
# G-calculation - use Law of sines
712-
distm = data['distance']/1000.0
713-
sinB2 = np.minimum(np.ones_like(tth),
714-
(data['distance']*npsind(tth))**2/(dx**2+dy**2))
715-
#sinB2 = (data['distance']*npsind(tth))**2/(dx**2+dy**2)
716-
C = 180.-tth-npacosd(np.sqrt(1.- sinB2))
717-
G = distm**2*sinB2/npsind(C)**2
710+
azm = (npatan2d(dxyz[:,:,1],dxyz[:,:,0])+data['azmthOff']+720.)%360.
711+
# old G-calculation
712+
x0 = data['distance']*nptand(tilt)
713+
x0x = x0*npcosd(data['rotation'])
714+
x0y = x0*npsind(data['rotation'])
715+
distsq = data['distance']**2
716+
G = ((dx-x0x)**2+(dy-x0y)**2+distsq)/distsq #for geometric correction = 1/cos(2theta)^2 if tilt=0.
717+
# # G-calculation - use Law of sines - wrong for nonzero det2theta!
718+
# distm = data['distance']/1000.0
719+
# sinB2 = np.minimum(np.ones_like(tth),
720+
# (data['distance']*npsind(tth))**2/(dx**2+dy**2))
721+
# C = 180.-tth-npacosd(np.sqrt(1.- sinB2))
722+
# G = distm**2*sinB2/npsind(C)**2
718723
return tth,azm,G
719724

720725
def meanAzm(a,b):
@@ -1468,7 +1473,7 @@ def MakeUseMask(data,masks,blkSize=128):
14681473

14691474
def MakeGainMap(image,Ix,Iy,data,blkSize=128):
14701475
import scipy.ndimage.filters as sdif
1471-
Iy *= npcosd(Ix[:-1])**3 #undo parallax
1476+
Iy /= npcosd(Ix[:-1]) #undo parallax
14721477
Iy *= (1000./data['distance'])**2 #undo r^2 effect
14731478
Iy /= np.array(G2pwd.Polarization(data['PolaVal'][0],Ix[:-1],0.)[0]) #undo polarization
14741479
if data['Oblique'][1]:
@@ -1687,7 +1692,8 @@ def ImageIntegrate(image,data,masks,blkSize=128,returnN=False,useTA=None,useMask
16871692
H1 = LRazm
16881693
if 'SASD' not in data['type']:
16891694
H0 *= np.array(G2pwd.Polarization(data['PolaVal'][0],H2[:-1],0.)[0])
1690-
H0 /= np.abs(npcosd(H2[:-1]-np.abs(data['det2theta']))) #parallax correction
1695+
if np.abs(data['det2theta']) < 1.0: #small angle approx only; not appropriate for detectors at large 2-theta
1696+
H0 /= np.abs(npcosd(H2[:-1]-np.abs(data['det2theta']))) #parallax correction
16911697
# H0 *= (data['distance']/1000.)**2 #remove r^2 effect - done earlier
16921698
if 'SASD' in data['type']:
16931699
H0 /= npcosd(H2[:-1]) #one more for small angle scattering data?

GSASII/GSASIIimgGUI.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,10 @@ def OnRecalibAll(event):
362362
G2frame.G2plotNB.Delete('Sequential refinement') #clear away probably invalid plot
363363
G2plt.PlotExposedImage(G2frame,event=None)
364364
if Id: G2frame.GPXtree.SelectItem(Id)
365-
365+
366+
def OnMultiGainMap(event):
367+
print('TBD - gain map from multiple images')
368+
366369
def OnCalcRings(event):
367370
'''Use existing calibration values to compute rings & display them
368371
'''
@@ -1679,6 +1682,7 @@ def computePhaseRings():
16791682
G2frame.Bind(wx.EVT_MENU, OnCalcRings, id=G2G.wxID_CALCRINGS)
16801683
G2frame.Bind(wx.EVT_MENU, OnDistRecalib, id=G2G.wxID_IMDISTRECALIB)
16811684
G2frame.Bind(wx.EVT_MENU, OnClearCalib, id=G2G.wxID_IMCLEARCALIB)
1685+
G2frame.Bind(wx.EVT_MENU, OnMultiGainMap, id=G2G.wxID_IMMULTGAINMAP)
16821686
# if data.get('calibrant'):
16831687
# mode = True
16841688
# else:

GSASII/imports/G2img_1TIF.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def GetTifData(filename):
208208
elif 270 in IFD:
209209
File.seek(IFD[270][2][0])
210210
S = File.read(IFD[273][2][0]-IFD[270][2][0])
211-
if b'Pilatus3' in S:
211+
if b'Pilatus3' in S or sizexy == [1475,1679]:
212212
tifType = 'Pilatus3'
213213
dataType = 0
214214
pixy = [172.,172.]

GSASII/imports/G2pwd_BrukerRAW.py

Lines changed: 92 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ def ContentsValidator(self, filename):
3737
self.formatName = 'Bruker RAW ver. 3'
3838
elif head == 'RAW4.00':
3939
self.formatName = 'Bruker RAW ver. 4'
40-
self.errors += "Sorry, this is a Version 4 Bruker file. "
41-
self.errors += "We need documentation for it so that it can be implemented in GSAS-II. "
42-
self.errors += "Use PowDLL (http://users.uoi.gr/nkourkou/powdll/) to convert it to ASCII xy."
43-
print(self.errors)
44-
fp.close()
45-
return False
40+
# self.errors += "Sorry, this is a Version 4 Bruker file. "
41+
# self.errors += "We need documentation for it so that it can be implemented in GSAS-II. "
42+
# self.errors += "Use PowDLL (http://users.uoi.gr/nkourkou/powdll/) to convert it to ASCII xy."
43+
# print(self.errors)
44+
# fp.close()
45+
# return False
4646
else:
4747
self.errors = 'Unexpected information in header: '
4848
if all([ord(c) < 128 and ord(c) != 0 for c in str(head)]): # show only if ASCII
@@ -161,38 +161,93 @@ def Reader(self,filename, ParentFrame=None, **kwarg):
161161
self.repeat = True
162162
fp.close()
163163

164-
elif 'ver. 4' in self.formatName: #does not work - format still elusive
164+
elif 'ver. 4' in self.formatName:
165+
driveNo = 0
165166
fp.seek(12) #ok
166-
self.comments.append('Date='+self.Read(fp,10))
167-
self.comments.append('Time='+self.Read(fp,10))
168-
fp.seek(144)
169-
self.comments.append('Sample='+self.Read(fp,60))
170-
fp.seek(564) # where is it?
171-
radius = st.unpack('<f',fp.read(4))[0]
172-
self.comments.append('Gonio. radius=%.2f'%(radius))
173-
self.Sample['Gonio. radius'] = radius
174-
fp.seek(516) #ok
175-
self.comments.append('Anode='+self.Read(fp,4))
176-
fp.seek(472) #ok
177-
self.comments.append('Ka mean=%.5f'%(st.unpack('<d',fp.read(8))[0]))
178-
self.comments.append('Ka1=%.5f'%(st.unpack('<d',fp.read(8))[0]))
179-
self.comments.append('Ka2=%.5f'%(st.unpack('<d',fp.read(8))[0]))
180-
self.comments.append('Kb=%.5f'%(st.unpack('<d',fp.read(8))[0]))
181-
self.comments.append('Ka2/Ka1=%.5f'%(st.unpack('<d',fp.read(8))[0]))
182-
fp.seek(pos) #deliberate fail here - pos not known from file contents
183-
self.idstring = os.path.basename(filename) + ' Scan '+str(1)
184-
nSteps = int(st.unpack('<i',fp.read(4))[0])
185-
st.unpack('<d',fp.read(8))[0]
186-
start2Th = st.unpack('<d',fp.read(8))[0]
187-
fp.seek(pos+176)
188-
step = st.unpack('<d',fp.read(8))[0]
189-
pos += headLen #position at start of data block
190-
fp.seek(pos)
191-
x = np.array([start2Th+i*step for i in range(nSteps)])
192-
y = np.array([max(1.,st.unpack('<f',fp.read(4))[0]) for i in range(nSteps)])
193-
w = 1./y
194-
self.powderdata = [x,y,w,np.zeros(nSteps),np.zeros(nSteps),np.zeros(nSteps)]
195-
fp.close()
167+
self.comments.append('Date='+self.Read(fp,12).strip('\x00'))
168+
self.comments.append('Time='+self.Read(fp,10).strip('\x00'))
169+
fp.seek(61) #start of header segments
170+
while True:
171+
segtype = st.unpack('<I',fp.read(4))[0]
172+
if not segtype or segtype == 160:
173+
break # done with header
174+
seglen = max(st.unpack('<I',fp.read(4))[0],8)
175+
if segtype == 10:
176+
fp.read(4) #skip these
177+
self.comments.append('%s=%s'%(self.Read(fp,24).strip('\x00'),self.Read(fp,seglen-36).strip('\x00')))
178+
elif segtype == 30: #x-ray source info
179+
fp.read(64)
180+
self.comments.append('Ka mean=%.5f'%(st.unpack('<d',fp.read(8))[0]))
181+
self.comments.append('Ka1=%.5f'%(st.unpack('<d',fp.read(8))[0]))
182+
self.comments.append('Ka2=%.5f'%(st.unpack('<d',fp.read(8))[0]))
183+
self.comments.append('Kb=%.5f'%(st.unpack('<d',fp.read(8))[0]))
184+
self.comments.append('Ka2/Ka1=%.5f'%(st.unpack('<d',fp.read(8))[0]))
185+
fp.read(4)
186+
self.comments.append('Anode='+self.Read(fp,4).strip('\x00'))
187+
fp.read(seglen-120)
188+
elif segtype == 60:
189+
alignFlag = st.unpack('<I',fp.read(4))[0]
190+
driveName = self.Read(fp,24).strip('\x00')
191+
fp.read(32)
192+
Delt = st.unpack('<d',fp.read(8))[0]
193+
fp.read(seglen-76)
194+
self.comments.append('Drive %s: align flag %d'%(driveName,alignFlag))
195+
self.comments.append('Drive %s: delta %f'%(driveName,Delt))
196+
driveNo += 1
197+
else:
198+
fp.read(seglen-8)
199+
while (segtype == 0 or segtype == 160):
200+
self.idstring = os.path.basename(filename) # + ' Scan '+str(blockNum)
201+
meta = {}
202+
fp.read(28)
203+
meta['ScanType'] = self.Read(fp,24).strip('\x00')
204+
if meta['ScanType'] not in ['Locked Coupled','Unlocked Coupled']:
205+
return False
206+
fp.read(16)
207+
startAngle = st.unpack('<d',fp.read(8))[0]
208+
meta['startAngle'] = '%.4f'%startAngle
209+
stepSize = st.unpack('<d',fp.read(8))[0]
210+
meta['stepSize'] = '%.4f'%stepSize
211+
Nsteps = st.unpack('<I',fp.read(4))[0]
212+
meta['Nsteps'] = '%d'%Nsteps
213+
meta['stepTime(ms)'] = st.unpack('<f',fp.read(4))[0]
214+
fp.read(4)
215+
meta['generatorVoltage(kV)'] = st.unpack('<f',fp.read(4))[0]
216+
meta['generatorCurrent(mA)'] = st.unpack('<f',fp.read(4))[0]
217+
fp.read(4)
218+
meta['usedWave'] = st.unpack('<d',fp.read(8))[0]
219+
fp.read(16)
220+
datumSize = st.unpack('<I',fp.read(4))[0]
221+
hdrSize = st.unpack('<I',fp.read(4))[0]
222+
fp.read(16)
223+
if meta['ScanType'] in ['Locked Coupled','Unlocked Coupled']:
224+
while hdrSize > 0:
225+
segtype = st.unpack('<I',fp.read(4))[0]
226+
seglen = max(st.unpack('<I',fp.read(4))[0],8)
227+
if segtype == 50:
228+
fp.read(4)
229+
segName = self.Read(fp,24).strip('\x00')
230+
if segName in ['Theta','2Theta','Chi','Phi','BeamTranslation','Z-Drive','Divergence Slit']:
231+
fp.read(20)
232+
meta['start %s'%segName] = '%.4f'%(st.unpack('<d',fp.read(8))[0])
233+
fp.read(seglen-64)
234+
else:
235+
fp.read(seglen-36)
236+
else:
237+
fp.read(seglen-8)
238+
hdrSize -= seglen
239+
#end of reading scan header
240+
x = np.array([startAngle+i*stepSize for i in range(Nsteps)])
241+
y = np.array([max(1.,st.unpack('<f',fp.read(4))[0]) for i in range(Nsteps)])
242+
w = 1./y
243+
self.powderdata = [x,y,w,np.zeros(Nsteps),np.zeros(Nsteps),np.zeros(Nsteps)]
244+
for item in meta:
245+
self.comments.append('%s = %s'%(item,str(meta[item])))
246+
fp.close()
247+
else:
248+
meta['Unknown range/scan type'] = True
249+
fp.read(hdrSize)
250+
fp.read(datumSize*Nsteps)
196251
else:
197252
return False
198253

docs/source/packages.rst

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,16 @@ as defined in variable :attr:`GSASIIdataGUI.versionDict`,
120120
but for new installations we are currently recommending the following
121121
interpreter/package versions:
122122

123-
* Python 3.11 is recommended. GSAS-II should run with any Python
123+
* Python 3.11, 3.12 or 3.13 is recommended. GSAS-II should run with any Python
124124
version from 3.7 or later, but you will need to locate (from the
125125
old subversion server) or locate binaries to match that Python version.
126126
* wxPython 4.2 or later is recommended, but with Python <=3.9 any
127127
wx4.x version should be OK. However, there may be problems with
128128
newer sections of the GUI with wx <4.0.
129-
* NumPy 1.26 recommended, but anything from 1.17 on is likely fine,
130-
but does need to approximately match the GSAS-II binaries.
129+
* NumPy 1.26 recommended with Python 3.11 and 2.2 with 3.12 or 3.13,
130+
but anything from 1.17 on is likely fine,
131+
but if you do not match the supplied GSAS-II binaries you will
132+
need to build them yourself.
131133
* matplotlib 3.6 is recommended, but 3.4 or later is preferred.
132134
* pyOpenGL: no version-related problems have been seen.
133135
* SciPy: no version-related problems have been seen, but in at least one
@@ -138,9 +140,13 @@ For more details on problems noted with specific versions of Python
138140
and Python packages, see comments below and details here:
139141
:attr:`GSASIIdataGUI.versionDict`,
140142

141-
Note that GSAS-II is currently being developed using Python 3.11. We
142-
are seeing compilation problems with Python 3.12 that will be addressed
143-
later via the build migration to meson. We are no longer
143+
Note that GSAS-II is currently being developed using Python 3.11 and 3.13. We
144+
have just adopted a build process using meson in place of scons for
145+
Python 3.12+ but this is not incorporated into the master branch and
146+
is not fully documented. If you need to build the GSAS-II binaries at
147+
this time, please contact Brian.
148+
149+
We are no longer
144150
supporting Python 2.7 and <=3.6, and strongly encourage that
145151
systems running GSAS-II under these older Python versions reinstall
146152
Python. Typically this is done by reinstalling GSAS-II from a current self-installer.
@@ -238,6 +244,9 @@ environment this command can be used::
238244
239245
conda env export --from-history -n <env>
240246

247+
Note that binaries for Python 3.12 and 3.13 are also now supplied,
248+
with numpy=2.2.
249+
241250
.. _ScriptingRequirements:
242251

243252

@@ -323,12 +332,17 @@ Required Binary Files
323332
As noted before, GSAS-II also requires that some code be compiled.
324333
For the following platforms, binary images are provided at
325334
https://github.com/AdvancedPhotonSource/GSAS-II-buildtools/releases/latest
326-
for Python 3.11 and NumPy 1.26:
335+
for Python 3.11 and NumPy 1.26, Python 3.12 and NumPy 2.2, and Python
336+
3.13 and NumPy 2.2 for these platforms:
327337

328338
* Windows-10: 64-bit Intel-compatible processors.
329339
* MacOS: Intel processors.
330340
* MacOS: ARM processors, aka Apple Silicon (M1, etc).
331-
* Linux: 64-bit Intel-compatible processors.
341+
* Linux: 64-bit Intel-compatible processors.
342+
343+
Some binaries are also supplied for Raspberry Pi, but may not be
344+
up-to-date. Please ask for newer if needed:
345+
332346
* Linux: ARM processors (64-bit and 32-bit Raspberry Pi OS and
333347
Ubuntu for Raspberry Pi).
334348

@@ -338,6 +352,10 @@ Should one wish to run GSAS-II where binary files are not
338352
supplied (such as 32-bit Windows or Linux) or with other combinations of
339353
Python/NumPy, compilation will be need to be done by the user. See
340354
the `compilation information <https://advancedphotonsource.github.io/GSAS-II-tutorials/compile.html>`_ for more information.
355+
We have just adopted a build process using meson in place of scons for
356+
Python 3.12+ but this is not incorporated into the master branch and
357+
is not fully documented. If you need to build the GSAS-II binaries at
358+
this time, please contact Brian.
341359

342360
Supported Externally-Developed Software
343361
----------------------------------------------------

0 commit comments

Comments
 (0)