Skip to content

Commit 8d8df50

Browse files
ajjacksonpeterfpeterson
authored andcommitted
Abins cleanup for 37350 (mantidproject#39343)
Some small bits of refactoring pulled out of mantidproject#37350
1 parent b668962 commit 8d8df50

File tree

4 files changed

+87
-72
lines changed

4 files changed

+87
-72
lines changed

Framework/PythonInterface/test/python/plugins/algorithms/Abins2BasicTest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ def test_non_unique_elements(self):
178178
Atoms="C,C,H",
179179
OutputWorkspace=self._workspace_name,
180180
CacheDirectory=self._cache_directory,
181+
QuantumOrderEventsNumber=self._quantum_order_events_number,
181182
)
182183

183184
def test_non_unique_atoms(self):
@@ -193,6 +194,7 @@ def test_non_unique_atoms(self):
193194
Atoms="atom_1,atom_2,atom1",
194195
OutputWorkspace=self._workspace_name,
195196
CacheDirectory=self._cache_directory,
197+
QuantumOrderEventsNumber=self._quantum_order_events_number,
196198
)
197199

198200
def test_non_existing_atoms(self):
@@ -209,6 +211,7 @@ def test_non_existing_atoms(self):
209211
Atoms="N",
210212
OutputWorkspace=self._workspace_name,
211213
CacheDirectory=self._cache_directory,
214+
QuantumOrderEventsNumber=self._quantum_order_events_number,
212215
)
213216

214217
def test_atom_index_limits(self):

scripts/abins/abinsalgorithm.py

Lines changed: 67 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -328,84 +328,82 @@ def get_atom_selection(*, atoms_data: abins.AtomsData, selection: list) -> Tuple
328328
all_atms_smbls = list(set([atoms_data[atom_index]["symbol"] for atom_index in range(num_atoms)]))
329329
all_atms_smbls.sort()
330330

331+
# Exit early if nothing was selected: default is to return no numbers, all symbols
331332
if len(selection) == 0: # case: all atoms
332-
atom_symbols = all_atms_smbls
333-
atom_numbers = []
334-
else: # case selected atoms
335-
# Specific atoms are identified with prefix and integer index, e.g 'atom_5'. Other items are element symbols
336-
# A regular expression match is used to make the underscore separator optional and check the index format
337-
338-
# Acceptable formats for index: atom_1 atom1 1
339-
numbered_atom_test = re.compile(
340-
f"""^ # No arbitrary prefixes
341-
({ATOM_PREFIX})? # optional ATOM_PREFIX (i.e. "atom")
342-
_? # optional underscore
343-
(?P<index>[0-9]+) # capture digits as "index"
344-
$ # No suffix
345-
""",
346-
re.VERBOSE,
347-
)
348-
atom_numbers = [int(match.group("index")) for item in selection if (match := numbered_atom_test.match(item))]
349-
350-
# Acceptable formats for range: 1-2
351-
atom_range_test = re.compile(
352-
"""^ # No prefix
353-
(?P<start>\\d+) # Capture starting index
354-
(-|\\.\\.)
355-
# range indicated with "-" or ".."
356-
(?P<end>\\d+) # Capture ending index
357-
$ # No suffix
358-
""",
359-
re.VERBOSE,
360-
)
361-
atom_ranges = [
362-
(int(match.group("start")), int(match.group("end"))) for item in selection if (match := atom_range_test.match(item))
363-
]
364-
365-
# Acceptable formats for symbol: Ca
366-
element_symbol_test = re.compile(
367-
f"""^(?!{ATOM_PREFIX}) # Must not start with ATOM_PREFIX (i.e. "atom")
368-
[a-zA-Z]+$ # Must contain only letters
369-
""",
370-
re.VERBOSE,
333+
return [], all_atms_smbls
334+
335+
# Specific atoms are identified with prefix and integer index, e.g 'atom_5'. Other items are element symbols
336+
# A regular expression match is used to make the underscore separator optional and check the index format
337+
338+
# Acceptable formats for index: atom_1 atom1 1
339+
numbered_atom_test = re.compile(
340+
f"""^ # No arbitrary prefixes
341+
({ATOM_PREFIX})? # optional ATOM_PREFIX (i.e. "atom")
342+
_? # optional underscore
343+
(?P<index>[0-9]+) # capture digits as "index"
344+
$ # No suffix
345+
""",
346+
re.VERBOSE,
347+
)
348+
atom_numbers = [int(match.group("index")) for item in selection if (match := numbered_atom_test.match(item))]
349+
350+
# Acceptable formats for range: 1-2
351+
atom_range_test = re.compile(
352+
"""^ # No prefix
353+
(?P<start>\\d+) # Capture starting index
354+
(-|\\.\\.)
355+
# range indicated with "-" or ".."
356+
(?P<end>\\d+) # Capture ending index
357+
$ # No suffix
358+
""",
359+
re.VERBOSE,
360+
)
361+
atom_ranges = [(int(match.group("start")), int(match.group("end"))) for item in selection if (match := atom_range_test.match(item))]
362+
363+
# Acceptable formats for symbol: Ca
364+
element_symbol_test = re.compile(
365+
f"""^(?!{ATOM_PREFIX}) # Must not start with ATOM_PREFIX (i.e. "atom")
366+
[a-zA-Z]+$ # Must contain only letters
367+
""",
368+
re.VERBOSE,
369+
)
370+
atom_symbols = [item for item in selection if element_symbol_test.match(item)]
371+
372+
if len(atom_numbers) != len(set(atom_numbers)):
373+
raise ValueError(
374+
"User atom selection (by number) contains repeated atom. This is not permitted as Abins"
375+
" cannot create multiple workspaces with the same name."
371376
)
372-
atom_symbols = [item for item in selection if element_symbol_test.match(item)]
373377

374-
if len(atom_numbers) != len(set(atom_numbers)):
378+
for atom_number in atom_numbers:
379+
if atom_number < 1 or atom_number > num_atoms:
375380
raise ValueError(
376-
"User atom selection (by number) contains repeated atom. This is not permitted as Abins"
377-
" cannot create multiple workspaces with the same name."
381+
"Invalid user atom selection (by number) '%s%s': out of range (%s - %s)" % (ATOM_PREFIX, atom_number, 1, num_atoms)
378382
)
379383

380-
for atom_number in atom_numbers:
381-
if atom_number < 1 or atom_number > num_atoms:
382-
raise ValueError(
383-
"Invalid user atom selection (by number) '%s%s': out of range (%s - %s)" % (ATOM_PREFIX, atom_number, 1, num_atoms)
384-
)
384+
for atom_symbol in atom_symbols:
385+
if atom_symbol not in all_atms_smbls:
386+
raise ValueError("User defined atom selection (by element) '%s': not present in the system." % atom_symbol)
385387

386-
for atom_symbol in atom_symbols:
387-
if atom_symbol not in all_atms_smbls:
388-
raise ValueError("User defined atom selection (by element) '%s': not present in the system." % atom_symbol)
389-
390-
if len(atom_symbols) != len(set(atom_symbols)): # only different types
391-
raise ValueError(
392-
"User atom selection (by symbol) contains repeated species. This is not permitted as "
393-
"Abins cannot create multiple workspaces with the same name."
394-
)
388+
if len(atom_symbols) != len(set(atom_symbols)): # only different types
389+
raise ValueError(
390+
"User atom selection (by symbol) contains repeated species. This is not permitted as "
391+
"Abins cannot create multiple workspaces with the same name."
392+
)
395393

396-
# Final sanity check that everything in "atoms" field was understood
397-
if len(atom_symbols) + len(atom_numbers) + len(atom_ranges) < len(selection):
398-
elements_report = " Symbols: " + ", ".join(atom_symbols) if atom_symbols else ""
399-
numbers_report = " Numbers: " + ", ".join(atom_numbers) if atom_numbers else ""
400-
ranges_report = " Ranges: " + ", ".join(f"{start}-{end}" for start, end in atom_ranges) if atom_ranges else ""
401-
raise ValueError(
402-
"Not all user atom selections ('atoms' option) were understood." + elements_report + numbers_report + ranges_report
403-
)
394+
# Final sanity check that everything in "atoms" field was understood
395+
if len(atom_symbols) + len(atom_numbers) + len(atom_ranges) < len(selection):
396+
elements_report = " Symbols: " + ", ".join(atom_symbols) if atom_symbols else ""
397+
numbers_report = " Numbers: " + ", ".join(atom_numbers) if atom_numbers else ""
398+
ranges_report = " Ranges: " + ", ".join(f"{start}-{end}" for start, end in atom_ranges) if atom_ranges else ""
399+
raise ValueError(
400+
"Not all user atom selections ('atoms' option) were understood." + elements_report + numbers_report + ranges_report
401+
)
404402

405-
for start, end in atom_ranges:
406-
if start > end:
407-
start, end = end, start
408-
atom_numbers = atom_numbers + list(range(start, end + 1))
403+
for start, end in atom_ranges:
404+
if start > end:
405+
start, end = end, start
406+
atom_numbers = atom_numbers + list(range(start, end + 1))
409407

410408
return sorted(atom_numbers), atom_symbols
411409

scripts/abins/instruments/instrument.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ def calculate_q_powder(self, *, input_data=None, angle=None):
128128
"""
129129
raise NotImplementedError()
130130

131+
def prepare_resolution(self):
132+
"""Perform preparation steps for resolution calculation
133+
134+
This should be called automatically by convolve_with_resolution_function if appropriate
135+
136+
The purpose of this method is to allow common computation
137+
(e.g. lookup-table generation) to be performed before the instrument is
138+
duplicated in parallel calculations.
139+
140+
"""
141+
pass
142+
131143
def convolve_with_resolution_function(self, frequencies=None, bins=None, s_dft=None, scheme="auto"):
132144
"""
133145
Convolves discrete spectrum with the resolution function for the particular instrument.

scripts/abins/instruments/pychop.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,16 @@ def _check_chopper_frequency(self, chopper_frequency: Union[int, None], logger:
4444
def get_angle_range(self) -> Tuple[float, float]:
4545
return np.min(self._tthlims), np.max(self._tthlims)
4646

47+
def prepare_resolution(self):
48+
if self._e_init not in self._polyfits:
49+
self._polyfit_resolution()
50+
4751
def calculate_sigma(self, frequencies):
4852
"""
4953
Calculates width of Gaussian resolution function.
5054
:return: width of Gaussian resolution function
5155
"""
52-
if self._e_init not in self._polyfits:
53-
self._polyfit_resolution()
54-
56+
self.prepare_resolution()
5557
return np.polyval(self._polyfits[self._e_init], frequencies)
5658

5759
def _polyfit_resolution(self, n_values=40, order=4):

0 commit comments

Comments
 (0)