ChessAnalysisPipeline 0.0.14__py3-none-any.whl → 0.0.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ChessAnalysisPipeline might be problematic. Click here for more details.
- CHAP/__init__.py +1 -1
- CHAP/common/__init__.py +13 -0
- CHAP/common/models/integration.py +29 -26
- CHAP/common/models/map.py +395 -224
- CHAP/common/processor.py +1725 -93
- CHAP/common/reader.py +265 -28
- CHAP/common/writer.py +191 -18
- CHAP/edd/__init__.py +9 -2
- CHAP/edd/models.py +886 -665
- CHAP/edd/processor.py +2592 -936
- CHAP/edd/reader.py +889 -0
- CHAP/edd/utils.py +846 -292
- CHAP/foxden/__init__.py +6 -0
- CHAP/foxden/processor.py +42 -0
- CHAP/foxden/writer.py +65 -0
- CHAP/giwaxs/__init__.py +8 -0
- CHAP/giwaxs/models.py +100 -0
- CHAP/giwaxs/processor.py +520 -0
- CHAP/giwaxs/reader.py +5 -0
- CHAP/giwaxs/writer.py +5 -0
- CHAP/pipeline.py +48 -10
- CHAP/runner.py +161 -72
- CHAP/tomo/models.py +31 -29
- CHAP/tomo/processor.py +169 -118
- CHAP/utils/__init__.py +1 -0
- CHAP/utils/fit.py +1292 -1315
- CHAP/utils/general.py +411 -53
- CHAP/utils/models.py +594 -0
- CHAP/utils/parfile.py +10 -2
- ChessAnalysisPipeline-0.0.16.dist-info/LICENSE +60 -0
- {ChessAnalysisPipeline-0.0.14.dist-info → ChessAnalysisPipeline-0.0.16.dist-info}/METADATA +1 -1
- ChessAnalysisPipeline-0.0.16.dist-info/RECORD +62 -0
- {ChessAnalysisPipeline-0.0.14.dist-info → ChessAnalysisPipeline-0.0.16.dist-info}/WHEEL +1 -1
- CHAP/utils/scanparsers.py +0 -1431
- ChessAnalysisPipeline-0.0.14.dist-info/LICENSE +0 -21
- ChessAnalysisPipeline-0.0.14.dist-info/RECORD +0 -54
- {ChessAnalysisPipeline-0.0.14.dist-info → ChessAnalysisPipeline-0.0.16.dist-info}/entry_points.txt +0 -0
- {ChessAnalysisPipeline-0.0.14.dist-info → ChessAnalysisPipeline-0.0.16.dist-info}/top_level.txt +0 -0
CHAP/runner.py
CHANGED
|
@@ -21,25 +21,35 @@ class RunConfig():
|
|
|
21
21
|
'outputdir': '.',
|
|
22
22
|
'interactive': False,
|
|
23
23
|
'log_level': 'INFO',
|
|
24
|
-
'profile': False
|
|
24
|
+
'profile': False,
|
|
25
|
+
'spawn': 0}
|
|
25
26
|
|
|
26
|
-
def __init__(self, config={}):
|
|
27
|
-
"""RunConfig constructor
|
|
27
|
+
def __init__(self, config={}, comm=None):
|
|
28
|
+
"""RunConfig constructor.
|
|
28
29
|
|
|
29
|
-
:param config: Pipeline configuration options
|
|
30
|
-
|
|
30
|
+
:param config: Pipeline configuration options,
|
|
31
|
+
defaults to `{}`.
|
|
32
|
+
:type config: dict, optional
|
|
33
|
+
:param comm: MPI communicator, defaults to `None`.
|
|
34
|
+
:type comm: mpi4py.MPI.Comm, optional
|
|
31
35
|
"""
|
|
32
36
|
# System modules
|
|
33
37
|
from tempfile import NamedTemporaryFile
|
|
34
38
|
|
|
39
|
+
# Make sure os.makedirs is only called from the root node
|
|
40
|
+
if comm is None:
|
|
41
|
+
rank = 0
|
|
42
|
+
else:
|
|
43
|
+
rank = comm.Get_rank()
|
|
35
44
|
for opt in self.opts:
|
|
36
45
|
setattr(self, opt, config.get(opt, self.opts[opt]))
|
|
37
46
|
|
|
38
47
|
# Check if root exists (create it if not) and is readable
|
|
39
|
-
if not
|
|
40
|
-
os.
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
if not rank:
|
|
49
|
+
if not os.path.isdir(self.root):
|
|
50
|
+
os.makedirs(self.root)
|
|
51
|
+
if not os.access(self.root, os.R_OK):
|
|
52
|
+
raise OSError('root directory is not accessible for reading '
|
|
43
53
|
f'({self.root})')
|
|
44
54
|
|
|
45
55
|
# Check if inputdir exists and is readable
|
|
@@ -56,16 +66,21 @@ class RunConfig():
|
|
|
56
66
|
if not os.path.isabs(self.outputdir):
|
|
57
67
|
self.outputdir = os.path.realpath(
|
|
58
68
|
os.path.join(self.root, self.outputdir))
|
|
59
|
-
if not
|
|
60
|
-
os.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
if not rank:
|
|
70
|
+
if not os.path.isdir(self.outputdir):
|
|
71
|
+
os.makedirs(self.outputdir)
|
|
72
|
+
try:
|
|
73
|
+
tmpfile = NamedTemporaryFile(dir=self.outputdir)
|
|
74
|
+
except:
|
|
75
|
+
raise OSError('output directory is not accessible for writing '
|
|
76
|
+
f'({self.outputdir})')
|
|
66
77
|
|
|
67
78
|
self.log_level = self.log_level.upper()
|
|
68
79
|
|
|
80
|
+
# Make sure os.makedirs completes before continuing all nodes
|
|
81
|
+
if comm is not None:
|
|
82
|
+
comm.barrier()
|
|
83
|
+
|
|
69
84
|
def parser():
|
|
70
85
|
"""Return an argument parser for the `CHAP` CLI. This parser has
|
|
71
86
|
one argument: the input CHAP configuration file.
|
|
@@ -77,78 +92,145 @@ def parser():
|
|
|
77
92
|
return parser
|
|
78
93
|
|
|
79
94
|
def main():
|
|
80
|
-
"""Main function"""
|
|
95
|
+
"""Main function."""
|
|
96
|
+
# Third party modules
|
|
97
|
+
try:
|
|
98
|
+
from mpi4py import MPI
|
|
99
|
+
have_mpi = True
|
|
100
|
+
comm = MPI.COMM_WORLD
|
|
101
|
+
except:
|
|
102
|
+
have_mpi = False
|
|
103
|
+
comm = None
|
|
104
|
+
|
|
81
105
|
args = parser().parse_args()
|
|
82
106
|
|
|
83
|
-
#
|
|
107
|
+
# Read the input config file
|
|
84
108
|
configfile = args.config
|
|
85
109
|
with open(configfile) as file:
|
|
86
110
|
config = safe_load(file)
|
|
87
|
-
|
|
111
|
+
|
|
112
|
+
# Check if run was a worker spawned by another Processor
|
|
113
|
+
run_config = RunConfig(config.get('config', {}), comm)
|
|
114
|
+
if have_mpi and run_config.spawn:
|
|
115
|
+
sub_comm = MPI.Comm.Get_parent()
|
|
116
|
+
common_comm = sub_comm.Merge(True)
|
|
117
|
+
# Read worker specific input config file
|
|
118
|
+
if run_config.spawn > 0:
|
|
119
|
+
with open(f'{configfile}_{common_comm.Get_rank()}') as file:
|
|
120
|
+
config = safe_load(file)
|
|
121
|
+
run_config = RunConfig(config.get('config', {}), common_comm)
|
|
122
|
+
else:
|
|
123
|
+
with open(f'{configfile}_{sub_comm.Get_rank()}') as file:
|
|
124
|
+
config = safe_load(file)
|
|
125
|
+
run_config = RunConfig(config.get('config', {}), comm)
|
|
126
|
+
else:
|
|
127
|
+
common_comm = comm
|
|
128
|
+
|
|
129
|
+
# Get the pipeline configurations
|
|
88
130
|
pipeline_config = config.get('pipeline', [])
|
|
89
131
|
|
|
90
|
-
#
|
|
132
|
+
# Profiling setup
|
|
91
133
|
if run_config.profile:
|
|
92
134
|
from cProfile import runctx # python profiler
|
|
93
135
|
from pstats import Stats # profiler statistics
|
|
94
|
-
cmd = 'runner(run_config, pipeline_config)'
|
|
136
|
+
cmd = 'runner(run_config, pipeline_config, common_comm)'
|
|
95
137
|
runctx(cmd, globals(), locals(), 'profile.dat')
|
|
96
138
|
info = Stats('profile.dat')
|
|
97
139
|
info.sort_stats('cumulative')
|
|
98
140
|
info.print_stats()
|
|
99
141
|
else:
|
|
100
|
-
runner(run_config, pipeline_config)
|
|
142
|
+
runner(run_config, pipeline_config, common_comm)
|
|
143
|
+
|
|
144
|
+
# Disconnect the spawned worker
|
|
145
|
+
if have_mpi and run_config.spawn:
|
|
146
|
+
common_comm.barrier()
|
|
147
|
+
sub_comm.Disconnect()
|
|
101
148
|
|
|
102
|
-
def runner(run_config, pipeline_config):
|
|
103
|
-
"""Main runner funtion
|
|
149
|
+
def runner(run_config, pipeline_config, comm=None):
|
|
150
|
+
"""Main runner funtion.
|
|
104
151
|
|
|
105
|
-
:param run_config: CHAP run configuration
|
|
106
|
-
:type run_config: RunConfig
|
|
107
|
-
:param pipeline_config: CHAP Pipeline configuration
|
|
152
|
+
:param run_config: CHAP run configuration.
|
|
153
|
+
:type run_config: CHAP.runner.RunConfig
|
|
154
|
+
:param pipeline_config: CHAP Pipeline configuration.
|
|
108
155
|
:type pipeline_config: dict
|
|
156
|
+
:param comm: MPI communicator, defaults to `None`.
|
|
157
|
+
:type comm: mpi4py.MPI.Comm, optional
|
|
158
|
+
:return: The pipeline's returned data field.
|
|
109
159
|
"""
|
|
160
|
+
# System modules
|
|
161
|
+
from time import time
|
|
162
|
+
|
|
110
163
|
# logging setup
|
|
111
164
|
logger, log_handler = setLogger(run_config.log_level)
|
|
112
165
|
logger.info(f'Input pipeline configuration: {pipeline_config}\n')
|
|
113
166
|
|
|
114
|
-
#
|
|
115
|
-
|
|
167
|
+
# Run the pipeline
|
|
168
|
+
t0 = time()
|
|
169
|
+
data = run(pipeline_config,
|
|
116
170
|
run_config.inputdir, run_config.outputdir, run_config.interactive,
|
|
117
|
-
logger, run_config.log_level, log_handler)
|
|
171
|
+
logger, run_config.log_level, log_handler, comm)
|
|
172
|
+
logger.info(f'Executed "run" in {time()-t0:.3f} seconds')
|
|
173
|
+
return data
|
|
118
174
|
|
|
119
|
-
def setLogger(log_level=
|
|
120
|
-
"""
|
|
121
|
-
Helper function to set CHAP logger
|
|
175
|
+
def setLogger(log_level='INFO'):
|
|
176
|
+
"""Helper function to set CHAP logger.
|
|
122
177
|
|
|
123
|
-
:param log_level:
|
|
178
|
+
:param log_level: Logger level, defaults to `"INFO"`.
|
|
179
|
+
:type log_level: str
|
|
180
|
+
:return: The CHAP logger and logging handler.
|
|
181
|
+
:rtype: logging.Logger, logging.StreamHandler
|
|
124
182
|
"""
|
|
125
183
|
logger = logging.getLogger(__name__)
|
|
126
184
|
log_level = getattr(logging, log_level.upper())
|
|
127
185
|
logger.setLevel(log_level)
|
|
128
186
|
log_handler = logging.StreamHandler()
|
|
129
187
|
log_handler.setFormatter(logging.Formatter(
|
|
130
|
-
'{name:20}: {message}', style='{'))
|
|
188
|
+
'{name:20}: {levelname}: {message}', style='{'))
|
|
131
189
|
logger.addHandler(log_handler)
|
|
132
190
|
return logger, log_handler
|
|
133
191
|
|
|
134
192
|
def run(
|
|
135
193
|
pipeline_config, inputdir=None, outputdir=None, interactive=False,
|
|
136
|
-
logger=None, log_level=None, log_handler=None):
|
|
137
|
-
"""
|
|
138
|
-
Run given pipeline_config
|
|
194
|
+
logger=None, log_level=None, log_handler=None, comm=None):
|
|
195
|
+
"""Run a given pipeline_config.
|
|
139
196
|
|
|
140
|
-
:param pipeline_config: CHAP
|
|
197
|
+
:param pipeline_config: CHAP Pipeline configuration.
|
|
198
|
+
:type pipeline_config: dict
|
|
199
|
+
:param inputdir: Input directory, defaults to `None'`.
|
|
200
|
+
:type inputdir: str, optional
|
|
201
|
+
:param outputdir: Output directory, defaults to `None'`.
|
|
202
|
+
:type outputdir: str, optional
|
|
203
|
+
:param interactive: Allows for user interactions,
|
|
204
|
+
defaults to `False`.
|
|
205
|
+
:type interactive: bool, optional
|
|
206
|
+
:param logger: CHAP logger, defaults to `None`.
|
|
207
|
+
:type logger: logging.Logger, optional
|
|
208
|
+
:param log_level: Logger level, defaults to `None`.
|
|
209
|
+
:type log_level: str, optional
|
|
210
|
+
:param log_handler: logging handler, defaults to `None`.
|
|
211
|
+
:type log_handler: logging.StreamHandler, optional
|
|
212
|
+
:param comm: MPI communicator, defaults to `None`.
|
|
213
|
+
:type comm: mpi4py.MPI.Comm, optional
|
|
214
|
+
:return: The `data` field of the first item in the returned
|
|
215
|
+
list of pipeline items.
|
|
141
216
|
"""
|
|
142
217
|
# System modules
|
|
143
218
|
from tempfile import NamedTemporaryFile
|
|
144
219
|
|
|
220
|
+
# Make sure os.makedirs is only called from the root node
|
|
221
|
+
if comm is None:
|
|
222
|
+
rank = 0
|
|
223
|
+
else:
|
|
224
|
+
rank = comm.Get_rank()
|
|
225
|
+
|
|
145
226
|
objects = []
|
|
146
227
|
kwds = []
|
|
147
228
|
for item in pipeline_config:
|
|
148
|
-
#
|
|
229
|
+
# Load individual object with given name from its module
|
|
149
230
|
kwargs = {'inputdir': inputdir,
|
|
150
231
|
'outputdir': outputdir,
|
|
151
|
-
'interactive': interactive
|
|
232
|
+
'interactive': interactive,
|
|
233
|
+
'comm': comm}
|
|
152
234
|
if isinstance(item, dict):
|
|
153
235
|
name = list(item.keys())[0]
|
|
154
236
|
item_args = item[name]
|
|
@@ -156,39 +238,41 @@ def run(
|
|
|
156
238
|
# "outputdir" and "interactive" with the item's arguments
|
|
157
239
|
# joining "inputdir" and "outputdir" and giving precedence
|
|
158
240
|
# for "interactive" in the latter
|
|
159
|
-
if
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
241
|
+
if item_args is not None:
|
|
242
|
+
if 'inputdir' in item_args:
|
|
243
|
+
newinputdir = os.path.normpath(os.path.join(
|
|
244
|
+
kwargs['inputdir'], item_args.pop('inputdir')))
|
|
245
|
+
if not os.path.isdir(newinputdir):
|
|
246
|
+
raise OSError(
|
|
247
|
+
f'input directory does not exist ({newinputdir})')
|
|
248
|
+
if not os.access(newinputdir, os.R_OK):
|
|
249
|
+
raise OSError('input directory is not accessible for '
|
|
250
|
+
f'reading ({newinputdir})')
|
|
251
|
+
kwargs['inputdir'] = newinputdir
|
|
252
|
+
if 'outputdir' in item_args:
|
|
253
|
+
newoutputdir = os.path.normpath(os.path.join(
|
|
254
|
+
kwargs['outputdir'], item_args.pop('outputdir')))
|
|
255
|
+
if not rank:
|
|
256
|
+
if not os.path.isdir(newoutputdir):
|
|
257
|
+
os.makedirs(newoutputdir)
|
|
258
|
+
try:
|
|
259
|
+
tmpfile = NamedTemporaryFile(dir=newoutputdir)
|
|
260
|
+
except:
|
|
261
|
+
raise OSError('output directory is not accessible '
|
|
262
|
+
f'for writing ({newoutputdir})')
|
|
263
|
+
kwargs['outputdir'] = newoutputdir
|
|
264
|
+
kwargs = {**kwargs, **item_args}
|
|
181
265
|
else:
|
|
182
266
|
name = item
|
|
183
267
|
if "users" in name:
|
|
184
|
-
#
|
|
268
|
+
# Load users module. This is required in CHAPaaS which can
|
|
185
269
|
# have common area for users module. Otherwise, we will be
|
|
186
270
|
# required to have invidual user's PYTHONPATHs to load user
|
|
187
271
|
# processors.
|
|
188
272
|
try:
|
|
189
273
|
import users
|
|
190
274
|
except ImportError:
|
|
191
|
-
if logger:
|
|
275
|
+
if logger is not None:
|
|
192
276
|
logger.error(f'Unable to load {name}')
|
|
193
277
|
continue
|
|
194
278
|
clsName = name.split('.')[-1]
|
|
@@ -199,23 +283,28 @@ def run(
|
|
|
199
283
|
modName, clsName = name.split('.')
|
|
200
284
|
module = __import__(f'CHAP.{modName}', fromlist=[clsName])
|
|
201
285
|
obj = getattr(module, clsName)()
|
|
202
|
-
if log_level:
|
|
286
|
+
if log_level is not None:
|
|
203
287
|
obj.logger.setLevel(log_level)
|
|
204
|
-
if log_handler:
|
|
288
|
+
if log_handler is not None:
|
|
205
289
|
obj.logger.addHandler(log_handler)
|
|
206
|
-
if logger:
|
|
290
|
+
if logger is not None:
|
|
207
291
|
logger.info(f'Loaded {obj}')
|
|
208
292
|
objects.append(obj)
|
|
209
293
|
kwds.append(kwargs)
|
|
210
294
|
pipeline = Pipeline(objects, kwds)
|
|
211
|
-
if log_level:
|
|
295
|
+
if log_level is not None:
|
|
212
296
|
pipeline.logger.setLevel(log_level)
|
|
213
|
-
if log_handler:
|
|
297
|
+
if log_handler is not None:
|
|
214
298
|
pipeline.logger.addHandler(log_handler)
|
|
215
|
-
if logger:
|
|
299
|
+
if logger is not None:
|
|
216
300
|
logger.info(f'Loaded {pipeline} with {len(objects)} items\n')
|
|
217
301
|
logger.info(f'Calling "execute" on {pipeline}')
|
|
218
|
-
|
|
302
|
+
|
|
303
|
+
# Make sure os.makedirs completes before continuing all nodes
|
|
304
|
+
if comm is not None:
|
|
305
|
+
comm.barrier()
|
|
306
|
+
|
|
307
|
+
return pipeline.execute()[0]['data']
|
|
219
308
|
|
|
220
309
|
|
|
221
310
|
if __name__ == '__main__':
|
CHAP/tomo/models.py
CHANGED
|
@@ -7,7 +7,6 @@ from typing import (
|
|
|
7
7
|
)
|
|
8
8
|
from pydantic import (
|
|
9
9
|
BaseModel,
|
|
10
|
-
StrictBool,
|
|
11
10
|
conint,
|
|
12
11
|
conlist,
|
|
13
12
|
confloat,
|
|
@@ -37,7 +36,7 @@ class Detector(BaseModel):
|
|
|
37
36
|
columns: conint(gt=0)
|
|
38
37
|
pixel_size: conlist(
|
|
39
38
|
item_type=confloat(gt=0, allow_inf_nan=False),
|
|
40
|
-
|
|
39
|
+
min_length=1, max_length=2)
|
|
41
40
|
lens_magnification: confloat(gt=0, allow_inf_nan=False) = 1.0
|
|
42
41
|
|
|
43
42
|
|
|
@@ -54,8 +53,8 @@ class TomoReduceConfig(BaseModel):
|
|
|
54
53
|
:type delta_theta: float, optional
|
|
55
54
|
"""
|
|
56
55
|
img_row_bounds: Optional[
|
|
57
|
-
conlist(item_type=conint(ge=-1),
|
|
58
|
-
delta_theta: Optional[confloat(gt=0, allow_inf_nan=False)]
|
|
56
|
+
conlist(item_type=conint(ge=-1), min_length=2, max_length=2)] = None
|
|
57
|
+
delta_theta: Optional[confloat(gt=0, allow_inf_nan=False)] = None
|
|
59
58
|
|
|
60
59
|
|
|
61
60
|
class TomoFindCenterConfig(BaseModel):
|
|
@@ -85,19 +84,19 @@ class TomoFindCenterConfig(BaseModel):
|
|
|
85
84
|
reconstruction in pixels, defaults to no filtering performed.
|
|
86
85
|
:type ring_width: float, optional
|
|
87
86
|
"""
|
|
88
|
-
center_stack_index: Optional[conint(ge=0)]
|
|
87
|
+
center_stack_index: Optional[conint(ge=0)] = None
|
|
89
88
|
center_rows: Optional[conlist(
|
|
90
|
-
item_type=conint(ge=0),
|
|
89
|
+
item_type=conint(ge=0), min_length=2, max_length=2)] = None
|
|
91
90
|
center_offsets: Optional[conlist(
|
|
92
91
|
item_type=confloat(allow_inf_nan=False),
|
|
93
|
-
|
|
94
|
-
center_offset_min: Optional[confloat(allow_inf_nan=False)]
|
|
95
|
-
center_offset_max: Optional[confloat(allow_inf_nan=False)]
|
|
92
|
+
min_length=2, max_length=2)] = None
|
|
93
|
+
center_offset_min: Optional[confloat(allow_inf_nan=False)] = None
|
|
94
|
+
center_offset_max: Optional[confloat(allow_inf_nan=False)] = None
|
|
96
95
|
center_search_range: Optional[conlist(
|
|
97
96
|
item_type=confloat(allow_inf_nan=False),
|
|
98
|
-
|
|
99
|
-
gaussian_sigma: Optional[confloat(ge=0, allow_inf_nan=False)]
|
|
100
|
-
ring_width: Optional[confloat(ge=0, allow_inf_nan=False)]
|
|
97
|
+
min_length=1, max_length=3)] = None
|
|
98
|
+
gaussian_sigma: Optional[confloat(ge=0, allow_inf_nan=False)] = None
|
|
99
|
+
ring_width: Optional[confloat(ge=0, allow_inf_nan=False)] = None
|
|
101
100
|
|
|
102
101
|
|
|
103
102
|
class TomoReconstructConfig(BaseModel):
|
|
@@ -127,15 +126,15 @@ class TomoReconstructConfig(BaseModel):
|
|
|
127
126
|
:type ring_width: float, optional
|
|
128
127
|
"""
|
|
129
128
|
x_bounds: Optional[
|
|
130
|
-
conlist(item_type=conint(ge=-1),
|
|
129
|
+
conlist(item_type=conint(ge=-1), min_length=2, max_length=2)] = None
|
|
131
130
|
y_bounds: Optional[
|
|
132
|
-
conlist(item_type=conint(ge=-1),
|
|
131
|
+
conlist(item_type=conint(ge=-1), min_length=2, max_length=2)] = None
|
|
133
132
|
z_bounds: Optional[
|
|
134
|
-
conlist(item_type=conint(ge=-1),
|
|
133
|
+
conlist(item_type=conint(ge=-1), min_length=2, max_length=2)] = None
|
|
135
134
|
secondary_iters: conint(ge=0) = 0
|
|
136
|
-
gaussian_sigma: Optional[confloat(ge=0, allow_inf_nan=False)]
|
|
137
|
-
remove_stripe_sigma: Optional[confloat(ge=0, allow_inf_nan=False)]
|
|
138
|
-
ring_width: Optional[confloat(ge=0, allow_inf_nan=False)]
|
|
135
|
+
gaussian_sigma: Optional[confloat(ge=0, allow_inf_nan=False)] = None
|
|
136
|
+
remove_stripe_sigma: Optional[confloat(ge=0, allow_inf_nan=False)] = None
|
|
137
|
+
ring_width: Optional[confloat(ge=0, allow_inf_nan=False)] = None
|
|
139
138
|
|
|
140
139
|
|
|
141
140
|
class TomoCombineConfig(BaseModel):
|
|
@@ -151,11 +150,11 @@ class TomoCombineConfig(BaseModel):
|
|
|
151
150
|
:type z_bounds: list[int], optional
|
|
152
151
|
"""
|
|
153
152
|
x_bounds: Optional[
|
|
154
|
-
conlist(item_type=conint(ge=-1),
|
|
153
|
+
conlist(item_type=conint(ge=-1), min_length=2, max_length=2)] = None
|
|
155
154
|
y_bounds: Optional[
|
|
156
|
-
conlist(item_type=conint(ge=-1),
|
|
155
|
+
conlist(item_type=conint(ge=-1), min_length=2, max_length=2)] = None
|
|
157
156
|
z_bounds: Optional[
|
|
158
|
-
conlist(item_type=conint(ge=-1),
|
|
157
|
+
conlist(item_type=conint(ge=-1), min_length=2, max_length=2)] = None
|
|
159
158
|
|
|
160
159
|
|
|
161
160
|
class TomoSimConfig(BaseModel):
|
|
@@ -168,9 +167,11 @@ class TomoSimConfig(BaseModel):
|
|
|
168
167
|
:type detector: Detector
|
|
169
168
|
:ivar sample_type: Sample type for the tomography simulator.
|
|
170
169
|
:type sample_type: Literal['square_rod', 'square_pipe',
|
|
171
|
-
'hollow_cube', 'hollow_brick']
|
|
170
|
+
'hollow_cube', 'hollow_brick', 'hollow_pyramid']
|
|
172
171
|
:ivar sample_size: Size of each sample dimension in mm (internally
|
|
173
|
-
converted to an integer number of pixels).
|
|
172
|
+
converted to an integer number of pixels). Enter three values
|
|
173
|
+
for sample_type == `'hollow_pyramid'`, the height and the side
|
|
174
|
+
at the respective bottom and the top of the pyramid.
|
|
174
175
|
:type sample_size: list[float]
|
|
175
176
|
:ivar wall_thickness: Wall thickness for pipe, cube, and brick in
|
|
176
177
|
mm (internally converted to an integer number of pixels).
|
|
@@ -185,18 +186,19 @@ class TomoSimConfig(BaseModel):
|
|
|
185
186
|
:type beam_intensity: float, optional
|
|
186
187
|
:ivar background_intensity: Background intensity in counts,
|
|
187
188
|
defaults to 20.
|
|
188
|
-
:type background_intensity
|
|
189
|
+
:type background_intensity: float, optional
|
|
189
190
|
:ivar slit_size: Vertical beam height in mm, defaults to 1.0.
|
|
190
|
-
:type slit_size
|
|
191
|
+
:type slit_size: float, optional
|
|
191
192
|
"""
|
|
192
193
|
station: Literal['id1a3', 'id3a', 'id3b']
|
|
193
|
-
detector: Detector.
|
|
194
|
+
detector: Detector.model_construct()
|
|
194
195
|
sample_type: Literal[
|
|
195
|
-
'square_rod', 'square_pipe', 'hollow_cube', 'hollow_brick'
|
|
196
|
+
'square_rod', 'square_pipe', 'hollow_cube', 'hollow_brick',
|
|
197
|
+
'hollow_pyramid']
|
|
196
198
|
sample_size: conlist(
|
|
197
199
|
item_type=confloat(gt=0, allow_inf_nan=False),
|
|
198
|
-
|
|
199
|
-
wall_thickness: Optional[confloat(ge=0, allow_inf_nan=False)]
|
|
200
|
+
min_length=1, max_length=3)
|
|
201
|
+
wall_thickness: Optional[confloat(ge=0, allow_inf_nan=False)] = None
|
|
200
202
|
mu: Optional[confloat(gt=0, allow_inf_nan=False)] = 0.05
|
|
201
203
|
theta_step: confloat(gt=0, allow_inf_nan=False)
|
|
202
204
|
beam_intensity: Optional[confloat(gt=0, allow_inf_nan=False)] = 1.e9
|