Skip to content

Commit 7ec0540

Browse files
committed
deal sensibly if PyCifRW (CifFile) not installed; minor cleanup for importer package install
1 parent 48f69ea commit 7ec0540

File tree

8 files changed

+104
-48
lines changed

8 files changed

+104
-48
lines changed

GSASII/GSASIIctrlGUI.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9646,9 +9646,9 @@ def ImportMsg(parent,msgs):
96469646
could not be installed (due to uninstalled Python packages). Then
96479647
offer the chance to install GSAS-II packages using :func:`SelectPkgInstall`
96489648
'''
9649-
text = ('Message(s) from load of importers\n\n '+
9650-
'\n\n'.join(msgs)+
9651-
'\n\nNote: These errors only need to be addressed if you want to use the importers listed above')
9649+
text = ('Warnings message(s) from load of importers:\n\n * '+
9650+
'\n\n * '.join(msgs)+
9651+
'\n\n\tTo use any of these importers, press the "Install packages" button\n\tbelow. It is fine to ignore these warnings if you will not need to read\n\tthat file type.')
96529652
ShowScrolledInfo(parent,text,
96539653
header='Importer load problems',
96549654
width=650,
@@ -9678,17 +9678,22 @@ def SelectPkgInstall(event):
96789678
dlg = event.GetEventObject().GetParent()
96799679
dlg.EndModal(wx.ID_OK)
96809680
G2frame = wx.App.GetMainTopWindow()
9681-
choices = []
9681+
9682+
choices = {}
96829683
for key in G2fil.condaRequestList:
96839684
for item in G2fil.condaRequestList[key]:
9684-
choices.append((item,key))
9685-
msg = 'Select packages to install'
9685+
if item in choices:
9686+
choices[item] += f', {key}'
9687+
else:
9688+
choices[item] = key
9689+
msg = 'Select package(s) to install'
96869690
if GSASIIpath.condaTest():
96879691
msg += ' using conda'
96889692
else:
96899693
msg += ' using pip'
96909694
sel = MultiColMultiSelDlg(G2frame, 'Install packages?', msg,
9691-
[('package',120,0),('needed by',300,0)], choices)
9695+
[('package',120,0),('needed by',300,0)],
9696+
[i for i in choices.items()])
96929697
if sel is None: return
96939698
if not any(sel): return
96949699
pkgs = [choices[i][0] for i,f in enumerate(sel) if f]

GSASII/GSASIIobj.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,22 @@ def ReadCIF(URLorFile):
229229
(from James Hester).
230230
The open routine gets confused with DOS names that begin with a letter and colon
231231
"C:\\dir\" so this routine will try to open the passed name as a file and if that
232-
fails, try it as a URL
232+
fails, try it as a URL.
233+
234+
Used for CIF imports and for reading CIF templates for project CIF exports
233235
234236
:param str URLorFile: string containing a URL or a file name. Code will try first
235237
to open it as a file and then as a URL.
236238
237-
:returns: a PyCifRW CIF object.
239+
:returns: a PyCifRW CIF object or an empty string if PyCifRW is not accessible
238240
'''
239-
import CifFile as cif # PyCifRW from James Hester
241+
try:
242+
import CifFile as cif # PyCifRW from James Hester as a package
243+
except ImportError:
244+
try:
245+
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
246+
except ImportError:
247+
return ''
240248

241249
# alternate approach:
242250
#import urllib

GSASII/exports/G2export_CIF.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
import wx.lib.scrolledpanel as wxscroll
1919
import wx.lib.resizewidget as rw
2020
interactive = True
21-
from . import GSASIIctrlGUI as G2G
21+
from .. import GSASIIctrlGUI as G2G
2222
except ImportError:
23+
G2G = None
2324
# Avoid wx dependency for Scriptable
2425
class Placeholder(object):
2526
def __init__(self):
@@ -1679,6 +1680,7 @@ def writeCIFtemplate(G2dict,tmplate,defaultname='',
16791680
In all cases the initial data_ header is stripped (there should only be one!)
16801681
'''
16811682
CIFobj = G2dict.get(cifKey)
1683+
if CIFobj is None: return
16821684
if defaultname:
16831685
defaultname = G2obj.StripUnicode(defaultname)
16841686
defaultname = re.sub(r'[^a-zA-Z0-9_-]','',defaultname)
@@ -4668,6 +4670,17 @@ def Exporter(self,event=None,seqData=None,Controls=None):
46684670
#print('reloaded GSASIImapvars')
46694671
#### end debug stuff ##############################
46704672

4673+
if G2G is None:
4674+
print('Unable to export without GUI access')
4675+
return
4676+
try:
4677+
import CifFile as cif # PyCifRW from James Hester as a package
4678+
except ImportError:
4679+
try:
4680+
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
4681+
except ImportError:
4682+
msg = 'The PyCifRW package is not installed. CIF templates cannot be accessed. Created CIFs will be incomplete'
4683+
G2G.G2MessageBox(self.G2frame,msg,'no PyCifRW')
46714684
self.CIFname = ''
46724685
self.seqData = seqData
46734686
self.Controls = Controls
@@ -5038,7 +5051,11 @@ def PickleCIFdict(fil):
50385051
try:
50395052
import CifFile as cif # PyCifRW from James Hester as a package
50405053
except ImportError:
5041-
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
5054+
try:
5055+
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
5056+
except ImportError:
5057+
print('Warning: Unable to import PyCifRW')
5058+
return {}
50425059
cifdic = {}
50435060
try:
50445061
fp = open(fil,'r') # patch: open file to avoid windows bug
@@ -5178,7 +5195,11 @@ def dict2CIF(dblk,loopstructure,blockname='Template'):
51785195
try:
51795196
import CifFile as cif # PyCifRW from James Hester as a package
51805197
except ImportError:
5181-
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
5198+
try:
5199+
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
5200+
except ImportError:
5201+
print('Warning: Unable to import PyCifRW')
5202+
return {}
51825203
# compile a 'list' of items in loops
51835204
loopnames = set()
51845205
for i in loopstructure:
@@ -5654,6 +5675,8 @@ def _onEditTemplateContents(self,event):
56545675
dblk,loopstructure = copy.deepcopy(self.CIF_template) # don't modify original
56555676
else:
56565677
cf = G2obj.ReadCIF(self.CIF_template)
5678+
if len(cf) == 0:
5679+
raise Exception("No CIF data_ blocks found")
56575680
dblk,loopstructure = CIF2dict(cf)
56585681
dlg = EditCIFtemplate(self.cifdefs,dblk,loopstructure,self.defaultname)
56595682
val = dlg.Post()

GSASII/imports/G2phase_CIF.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,29 @@
99
import re
1010
import copy
1111
import os.path
12+
from .. import GSASIIpath
1213
from .. import GSASIIobj as G2obj
1314
from .. import GSASIIspc as G2spc
1415
from .. import GSASIIElem as G2elem
1516
from .. import GSASIIlattice as G2lat
16-
from .. import GSASIIpath
1717
from .. import GSASIIfiles as G2fil
1818
try:
1919
import CifFile as cif # PyCifRW from James Hester as a package
2020
except ImportError:
21-
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
21+
try:
22+
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
23+
except ImportError:
24+
cif = None
2225
debug = GSASIIpath.GetConfigValue('debug')
2326
#debug = False
2427

2528
class CIFPhaseReader(G2obj.ImportPhase):
2629
'Implements a phase importer from a possibly multi-block CIF file'
2730
def __init__(self):
31+
if cif is None:
32+
self.UseReader = False
33+
msg = 'CIFPhase Reader skipped because PyCifRW (CifFile) module is not installed.'
34+
G2fil.ImportErrorMsg(msg,{'CIF Phase importer':['pycifrw']})
2835
super(self.__class__,self).__init__( # fancy way to say ImportPhase.__init__
2936
extensionlist=('.CIF','.cif','.mcif'),
3037
strictExtension=False,

GSASII/imports/G2pwd_BrukerBRML.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ def __init__(self):
2424
if xml is None:
2525
self.UseReader = False
2626
msg = 'Bruker .brml Reader skipped because xmltodict module is not installed.'
27-
if GSASIIpath.condaTest():
28-
msg += ' To fix this press "Install packages" button below'
2927
from .. import GSASIIfiles as G2fil
3028
G2fil.ImportErrorMsg(msg,{'Bruker .brml Importer':['xmltodict']})
3129
self.scriptable = True

GSASII/imports/G2pwd_CIF.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,25 @@
44
from __future__ import division, print_function
55
import numpy as np
66
import os.path
7-
from .. import GSASIIobj as G2obj
87
from .. import GSASIIpath
8+
from .. import GSASIIobj as G2obj
9+
from .. import GSASIIfiles as G2fil
910
try:
1011
import CifFile as cif # PyCifRW from James Hester as a package
1112
except ImportError:
12-
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
13+
try:
14+
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
15+
except ImportError:
16+
cif = None
1317
asind = lambda x: 180.*np.arcsin(x)/np.pi
1418

1519
class CIFpwdReader(G2obj.ImportPowderData):
1620
'Routines to import powder data from a CIF file'
1721
def __init__(self):
22+
if cif is None:
23+
self.UseReader = False
24+
msg = 'CIF PWDR Reader skipped because PyCifRW (CifFile) module is not installed.'
25+
G2fil.ImportErrorMsg(msg,{'CIF powder importer':['pycifrw']})
1826
super(self.__class__,self).__init__( # fancy way to self-reference
1927
extensionlist=('.CIF','.cif'),
2028
strictExtension=False,

GSASII/imports/G2pwd_MIDAS.py

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
from .. import GSASIIfiles as G2fil
1515
from .. import GSASIIpath
1616

17-
instprmList = [('Bank',1.0), ('Lam',0.413263), ('Polariz.',0.99),
18-
('SH/L',0.002), ('Type','PXC'), ('U',1.163), ('V',-0.126),
17+
instprmList = [('Bank',1.0), ('Lam',0.413263), ('Polariz.',0.99),
18+
('SH/L',0.002), ('Type','PXC'), ('U',1.163), ('V',-0.126),
1919
('W',0.063), ('X',0.0), ('Y',0.0), ('Z',0.0), ('Zero',0.0)]
2020
# comments
2121
# sample parameters
@@ -28,12 +28,12 @@
2828
# 'Thick': 1.0, 'Contrast': [0.0, 0.0], 'Trans': 1.0, 'SlitLen': 0.0}
2929

3030
class MIDAS_Zarr_Reader(G2obj.ImportPowderData):
31-
'''Routine to read multiple powder patterns from a Zarr file
32-
created by MIDAS. Perhaps in the future, other software might also
33-
use this file type as well.
31+
'''Routine to read multiple powder patterns from a Zarr file
32+
created by MIDAS. Perhaps in the future, other software might also
33+
use this file type as well.
3434
35-
For Midas, the main file is <file>.zip, but optionally sample and
36-
instrument parameters can be placed in <file>.samprm and <file>.instprm.
35+
For Midas, the main file is <file>.zip, but optionally sample and
36+
instrument parameters can be placed in <file>.samprm and <file>.instprm.
3737
Any parameters placed in those files will override values set in the .zip
3838
file.
3939
'''
@@ -43,8 +43,6 @@ def __init__(self):
4343
if zarr is None:
4444
self.UseReader = False
4545
msg = 'MIDAS_Zarr Reader skipped because zarr module is not installed.'
46-
if GSASIIpath.condaTest():
47-
msg += ' To fix this press "Install packages" button below'
4846
G2fil.ImportErrorMsg(msg,{'MIDAS Zarr importer':['zarr']})
4947
super(self.__class__,self).__init__( # fancy way to self-reference
5048
extensionlist=('.zarr.zip',),strictExtension=True,
@@ -68,18 +66,18 @@ def ContentsValidator(self, filename):
6866
return False
6967

7068
def Reader(self, filename, ParentFrame=None, **kwarg):
71-
'''Scan file for sections needed by defined file types (currently
69+
'''Scan file for sections needed by defined file types (currently
7270
only Midas) and then use appropriate routine to read the file.
73-
Most of the time the results are placed in the buffer arg (if supplied)
74-
so the file is not read on most calls.
71+
Most of the time the results are placed in the buffer arg (if supplied)
72+
so the file is not read on most calls.
7573
76-
For MIDAS, masking can eliminate some or all points in an azimuthal
77-
region. This will only return "lineouts" (aka diffractograms) that
78-
have 20 or more points in them.
74+
For MIDAS, masking can eliminate some or all points in an azimuthal
75+
region. This will only return "lineouts" (aka diffractograms) that
76+
have 20 or more points in them.
7977
80-
Note that if Reader.selections is used to select individual
81-
"lineouts", the selections are numbered against all possible
82-
"lineouts" not the ones that have 20 or more points.
78+
Note that if Reader.selections is used to select individual
79+
"lineouts", the selections are numbered against all possible
80+
"lineouts" not the ones that have 20 or more points.
8381
'''
8482
fpbuffer = kwarg.get('buffer',{})
8583
if not hasattr(self,'blknum'):
@@ -99,7 +97,7 @@ def Reader(self, filename, ParentFrame=None, **kwarg):
9997
return False
10098
finally:
10199
del fp
102-
100+
103101
if self.mode == 'midas':
104102
return self.readMidas(filename, fpbuffer)
105103

@@ -125,7 +123,7 @@ def readMidas(self, filename, fpbuffer={}):
125123
try:
126124
fp = zarr.open(filename, 'r')
127125
fpbuffer['REtaMap'] = np.array(fp['REtaMap']) # 4 x Nbins x Nazimuth
128-
# [0]: radius; [1] 2theta; [2] eta; [3] bin area
126+
# [0]: radius; [1] 2theta; [2] eta; [3] bin area
129127
# tabulate integrated intensities image & eta
130128
fpbuffer['intenArr'] = []
131129
fpbuffer['attributes'] = []
@@ -143,20 +141,20 @@ def readMidas(self, filename, fpbuffer={}):
143141
fpbuffer['unmasked'] = [(fpbuffer['REtaMap'][3][:,i] != 0) for i in range(Nazim)] # will be True if area is >0
144142
# find the azimuths with more than 20 points
145143
mAzm = [i for i in range(Nazim) if sum(fpbuffer['unmasked'][i]) > 20]
146-
144+
147145
# generate a list of lineouts to be read from selections
148146
if self.selections:
149147
sel = self.selections
150148
else:
151149
sel = range(Nimg*Nazim) # nothing selected, use all
152150
# fpbuffer['2Read'] is the list of lineouts to be read, where each entry
153151
# contains two values, the azumuth and the image number (iAzm,iImg)
154-
# defined points for each lineout are then
152+
# defined points for each lineout are then
155153
# intensities : fpbuffer['intenArr'][iImg][:,iAzm][unmasked[iAzm]]
156154
# 2thetas: fpbuffer['REtaMap'][1][:,iAzm][unmasked[iAzm]]
157155
fpbuffer['2Read'] = [(i%Nazim,i//Nazim) for i in sel if i%Nazim in mAzm]
158156
# xfrom Zarr dict into a native dict
159-
self.MIDASinstprm = {i:j[0] for i,j in fp['InstrumentParameters'].items()}
157+
self.MIDASinstprm = {i:j[0] for i,j in fp['InstrumentParameters'].items()}
160158
# change a few keys
161159
for key,newkey in [('Polariz','Polariz.'),('SH_L','SH/L')]:
162160
if key in self.MIDASinstprm:
@@ -167,7 +165,7 @@ def readMidas(self, filename, fpbuffer={}):
167165
return False
168166
finally:
169167
del fp
170-
# get overriding sample & instrument parameters
168+
# get overriding sample & instrument parameters
171169
self.MIDASsampleprm = {}
172170
samplefile = os.path.splitext(filename)[0] + '.samprm'
173171
if os.path.exists(samplefile):
@@ -189,7 +187,7 @@ def readMidas(self, filename, fpbuffer={}):
189187
fp.close()
190188
nbank,self.instvals = G2fil.ReadInstprm(instLines, None, self.Sample)
191189
#======================================================================
192-
# start reading
190+
# start reading
193191
#======================================================================
194192
# look for the next non-empty scan (lineout)
195193
iAzm,iImg = fpbuffer['2Read'][self.blknum]
@@ -211,16 +209,16 @@ def readMidas(self, filename, fpbuffer={}):
211209
omega = 999. # indicates an error
212210
try:
213211
omega = 0.5 * (
214-
fpbuffer['attributes'][iImg]['FirstOme'] +
212+
fpbuffer['attributes'][iImg]['FirstOme'] +
215213
fpbuffer['attributes'][iImg]['LastOme'])
216214
except:
217215
pass
218216
eta = sum(fpbuffer['REtaMap'][2][:,iAzm][unmasked])/sum(unmasked) # compute an averaged Phi value
219217
radius = 1000 # sample to detector distance (mm)
220218
if 'Distance' in self.MIDASinstprm:
221219
radius = self.MIDASinstprm['Distance']/1000 # convert from microns
222-
223-
# now transfer instprm & sample prms into current histogram
220+
221+
# now transfer instprm & sample prms into current histogram
224222
self.pwdparms['Instrument Parameters'] = [{}, {}]
225223
inst = {}
226224
inst.update(instprmList)

GSASII/imports/G2sfact_CIF.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,24 @@
66
from __future__ import division, print_function
77
import numpy as np
88
import os.path
9+
from .. import GSASIIpath
910
from .. import GSASIIobj as G2obj
11+
from .. import GSASIIfiles as G2fil
1012
try:
1113
import CifFile as cif # PyCifRW from James Hester as a package
1214
except ImportError:
13-
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
15+
try:
16+
from .. import CifFile as cif # PyCifRW, as distributed w/G2 (old)
17+
except ImportError:
18+
cif = None
1419

1520
class CIFhklReader(G2obj.ImportStructFactor):
1621
'Routines to import Phase information from a CIF file'
1722
def __init__(self):
23+
if cif is None:
24+
self.UseReader = False
25+
msg = 'CIF Xtal Reader skipped because PyCifRW (CifFile) module is not installed.'
26+
G2fil.ImportErrorMsg(msg,{'CIF HKLF importer':['pycifrw']})
1827
super(self.__class__,self).__init__( # fancy way to self-reference
1928
extensionlist = ('.CIF','.cif','.FCF','.fcf','.HKL','.hkl'),
2029
strictExtension = False,

0 commit comments

Comments
 (0)