Skip to content

Commit 6ff18b6

Browse files
committed
put the __init__ files back, but do allow for user-defined routines
1 parent 56ec784 commit 6ff18b6

File tree

5 files changed

+289
-69
lines changed

5 files changed

+289
-69
lines changed

GSASII/GSASIIfiles.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -596,9 +596,8 @@ def LoadImportRoutines(prefix, errprefix=None, traceback=False):
596596
from . import imports
597597
readerlist = []
598598
# configure readers that have already been imported
599-
for mod_name in [i for i in sys.modules.keys() if
600-
i.startswith(f'GSASII.imports.G2{prefix}')]:
601-
mod = sys.modules[mod_name]
599+
for mod_name in (_ for _ in dir(imports) if _.startswith(f'G2{prefix}')):
600+
mod = getattr(imports, mod_name)
602601
for member_name in dir(mod):
603602
if member_name.startswith('_'):
604603
continue
@@ -655,9 +654,8 @@ def LoadExportRoutines(parent, usetraceback=False):
655654
exporterlist = []
656655

657656
# configure exporters that have already been imported
658-
for mod_name in [i for i in sys.modules.keys() if
659-
i.startswith('GSASII.exports.G2export')]:
660-
mod = sys.modules[mod_name]
657+
for mod_name in (_ for _ in dir(exports) if _.startswith('G2export')):
658+
mod = getattr(exports, mod_name)
661659
for member_name in dir(mod):
662660
if member_name.startswith('_'):
663661
continue

GSASII/exports/__init__.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
1-
import glob
2-
import os
3-
import importlib.util
4-
import sys
1+
from . import G2export_Bracket
2+
from . import G2export_CIF
3+
from . import G2export_FIT2D
4+
from . import G2export_JSON
5+
from . import G2export_PDB
6+
from . import G2export_csv
7+
from . import G2export_examples
8+
from . import G2export_image
9+
from . import G2export_map
10+
from . import G2export_pwdr
11+
from . import G2export_shelx
512

6-
__all__ = []
7-
for f in sorted(glob.glob(os.path.join(os.path.dirname(__file__),'G2export*.py'))):
8-
nam = os.path.splitext(os.path.split(f)[1])[0]
9-
try:
10-
modspec = importlib.util.spec_from_file_location(nam, f)
11-
module = importlib.util.module_from_spec(modspec)
12-
module.__package__ = "GSASII.exports"
13-
modspec.loader.exec_module(module)
14-
sys.modules[f"GSASII.exports.{nam}"] = module
15-
__all__.append(nam)
16-
except ImportError as msg:
17-
print(f'Failed to import exporter {nam} with error\n{msg}')
13+
__all__ = [
14+
"G2export_Bracket",
15+
"G2export_CIF",
16+
"G2export_FIT2D",
17+
"G2export_JSON",
18+
"G2export_PDB",
19+
"G2export_csv",
20+
"G2export_examples",
21+
"G2export_image",
22+
"G2export_map",
23+
"G2export_pwdr",
24+
"G2export_shelx",
25+
]

GSASII/imports/__init__.py

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,77 @@
1-
import glob
2-
import os
3-
import importlib.util
4-
import sys
1+
from . import G2img_1TIF
2+
from . import G2img_ADSC
3+
from . import G2img_CBF
4+
from . import G2img_CheMin
5+
from . import G2img_EDF
6+
from . import G2img_GE
7+
from . import G2img_HDF5
8+
from . import G2img_MAR
9+
from . import G2img_PILTIF
10+
from . import G2img_Rigaku
11+
from . import G2img_SFRM
12+
from . import G2img_SumG2
13+
from . import G2img_pixirad_1ID_16bit
14+
from . import G2pdf_gr
15+
from . import G2phase
16+
from . import G2phase_CIF
17+
from . import G2phase_GPX
18+
from . import G2phase_INS
19+
from . import G2phase_rmc6f
20+
from . import G2phase_xyz
21+
from . import G2pwd_BrukerBRML
22+
from . import G2pwd_BrukerRAW
23+
from . import G2pwd_CIF
24+
from . import G2pwd_FP
25+
from . import G2pwd_GPX
26+
from . import G2pwd_MIDAS
27+
from . import G2pwd_Panalytical
28+
from . import G2pwd_csv
29+
from . import G2pwd_fxye
30+
from . import G2pwd_rigaku
31+
from . import G2pwd_xye
32+
from . import G2rfd_Panalytical
33+
from . import G2rfd_rigaku
34+
from . import G2rfd_xye
35+
from . import G2sad_xye
36+
from . import G2sfact
37+
from . import G2sfact_CIF
538

6-
__all__ = []
7-
for f in sorted(glob.glob(os.path.join(os.path.dirname(__file__),'G2*.py'))):
8-
nam = os.path.splitext(os.path.split(f)[1])[0]
9-
try:
10-
modspec = importlib.util.spec_from_file_location(nam, f)
11-
module = importlib.util.module_from_spec(modspec)
12-
module.__package__ = "GSASII.imports"
13-
modspec.loader.exec_module(module)
14-
sys.modules[f"GSASII.imports.{nam}"] = module
15-
__all__.append(nam)
16-
except ImportError as msg:
17-
print(f'Failed to import importer {nam} with error\n{msg}')
39+
__all__ = [
40+
"G2img_1TIF",
41+
"G2img_ADSC",
42+
"G2img_CBF",
43+
"G2img_CheMin",
44+
"G2img_EDF",
45+
"G2img_GE",
46+
"G2img_HDF5",
47+
"G2img_MAR",
48+
"G2img_PILTIF",
49+
"G2img_Rigaku",
50+
"G2img_SFRM",
51+
"G2img_SumG2",
52+
"G2img_pixirad_1ID_16bit",
53+
"G2pdf_gr",
54+
"G2phase",
55+
"G2phase_CIF",
56+
"G2phase_GPX",
57+
"G2phase_INS",
58+
"G2phase_rmc6f",
59+
"G2phase_xyz",
60+
"G2pwd_BrukerBRML",
61+
"G2pwd_BrukerRAW",
62+
"G2pwd_CIF",
63+
"G2pwd_FP",
64+
"G2pwd_GPX",
65+
"G2pwd_MIDAS",
66+
"G2pwd_Panalytical",
67+
"G2pwd_csv",
68+
"G2pwd_fxye",
69+
"G2pwd_rigaku",
70+
"G2pwd_xye",
71+
"G2rfd_Panalytical",
72+
"G2rfd_rigaku",
73+
"G2rfd_xye",
74+
"G2sad_xye",
75+
"G2sfact",
76+
"G2sfact_CIF",
77+
]

docs/source/exports.rst

Lines changed: 127 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,137 @@
11
*GSAS-II Export Modules*
22
====================================
33

4+
Many of the data files written by GSAS-II for use by other software is
5+
written using a layer of routines called exporters. Exporters usually require quite
6+
simple code, so they can be written quickly to allow GSAS-II to
7+
provide output in new data formats.
8+
The interface to the exporters
9+
is self-configuring, so all supplied exporters are available once the
10+
exporter is added to the code base. This allows GSAS-II to be quite
11+
flexible in adapting to use many data formats without need for
12+
extensive coding.
13+
414
Exports are implemented by deriving a class from
515
:class:`~GSASII.GSASIIfiles.ExportBaseclass` in module
6-
:mod:`~GSASII.GSASIIfiles`. Initialization of
7-
``self.exporttype`` determines the type of export that will be performed
8-
('project', 'phase', 'single', 'powder', 'image', 'map' or (someday)
9-
'pdf') and of ``self.multiple``
16+
:mod:`~GSASII.GSASIIfiles`.
17+
Export routines commonly access the GUI to determine information on
18+
the contents of the file(s) to be written, but for powder diffraction
19+
and phase data export, a routine named ``Writer()`` may be defined. If this is
20+
present, the exporter can be used from: mod:`~GSASII.GSASIIscriptable`
21+
without GUI access. Note that the arguments for the``Writer()`` method
22+
include a histogram tree name as well as a file name to
23+
be written.
24+
25+
A file containing one or more export routine can be placed
26+
either in the ``GSASII/exports`` directory (which requires
27+
modification of the ``__init__.py`` file or the file can be placed in
28+
the ``~/.GSASII/exports`` directory.
29+
The next time GSAS-II is started,
30+
the file will loaded when the GSAS-II files are read by the Python and
31+
the new data format will appear in the appropriate exporter menu.
32+
33+
.. _export_routines:
34+
35+
======================================
36+
Writing an Exporter Routine
37+
======================================
38+
39+
When writing a exporter routine, one should create a new class derived
40+
from class `~GSASII.GSASIIfiles.ExportBaseclass`.
41+
The name of the class is arbitrary, but if more than one class is
42+
placed in file, each class must have a different name. The same name
43+
can be repeated if it is in different files.
44+
As described below, this class will implement
45+
an ``__init__()`` and an ``Exporter()`` method, and many will supply a
46+
``Writer()`` method, too. The purpose of each of these
47+
routines is described below. The easiest way to craft a new exporter
48+
will be to use the other exporters of the same data type as a model
49+
for where to find the data values that will be written, but the documentation
50+
for the parent class (`~GSASII.GSASIIfiles.ExportBaseclass`) provides
51+
useful information on support routines that pull information from the
52+
GSAS-II data structures into the exporter.
53+
54+
__init__()
55+
--------------
56+
57+
The ``__init__`` method will follow standard boilerplate largely independent
58+
of the data type:
59+
60+
.. code-block:: python
61+
62+
def __init__(self):
63+
super(self.__class__,self).__init__( # fancy way to self-reference
64+
G2frame=G2frame,
65+
formatName = 'Format name for menu',
66+
extension='.extn',
67+
longFormatName = 'Longer more detailed format name for status line'
68+
)
69+
70+
The first line in the ``__init__`` method calls the parent class
71+
``__init__`` method with the following parameters:
72+
73+
* ``G2frame``: a reference to the main GSAS-II GUI window or None
74+
when run scripted.
75+
* ``formatName``: a string to be used in the menu. Should be short.
76+
* ``extension``: a string to be used in the file name. All files
77+
produced by the exporter will have this extension.
78+
* ``longFormatName``: a longer string to be used to describe the
79+
format in help.
80+
81+
In addition, one instance variables must be defined:
82+
83+
.. code-block:: python
84+
85+
self.exporttype = ['phase']
86+
87+
The value for ``self.exporttype`` determines the type of export that will be performed
88+
('project', 'phase', 'single', 'powder', 'image', 'map', 'sasd', 'refd' or (someday)
89+
'pdf') and the menu where the exporter will be placed. Note that
90+
'project' exports are those that include all data from a
91+
.gpx file (all phases, histograms, etc.)
92+
93+
Another item is optional.
94+
95+
.. code-block:: python
96+
97+
self.multiple = True
98+
99+
The value specified for ``self.multiple``
10100
determines if only a single phase, data set, etc. can be exported at a
11-
time (when False) or more than one can be selected.
101+
time (when False) or when True, a file can be produced with multiple
102+
histograms, phases, etc.
103+
104+
Exporter()
105+
--------------
106+
107+
The class must supply a ``Exporter`` method that will write a
108+
file. Depending on the settings for ``self.exporttype`` and
109+
``self.multiple`` and the contents of the Data Tree, will dictate
110+
what dialogs will be presented to the user to select what will be
111+
written.
112+
113+
Writer()
114+
--------------
115+
116+
For powder and phase exports, if the class supplies a ``Writer()``
117+
module, then the export format
118+
will be available for scripted output (with
119+
:mod:`GSASIIscriptable`). These modules are supplied a histogram name
120+
or a phase name and should not attempt to access the GUI. It is not
121+
required that that this method be supplied, but usually it is not hard to do,
122+
unless information from the user is required.
123+
124+
Note that for phase exports the ``Writer()`` should be declared as follows:
125+
126+
.. code-block:: python
127+
128+
def Writer(self,hist,phasenam,mode='w'):
129+
130+
while for histogram exports the ``Writer()`` should be declared as follows:
131+
132+
.. code-block:: python
12133
13-
Powder export routines may optionally define a ``Writer()``
14-
method that accepts the histogram tree name as well as a file name to
15-
be written. This allows :mod:`~GSASII.GSASIIscriptable` to use the exporters
16-
independent of the GUI.
134+
def Writer(self,hist,filename=None,mode='w'):
17135
18136
-------------------------------------------
19137
*Module G2export_examples: Examples*

0 commit comments

Comments
 (0)