Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Two backgrounds option #19

Merged
merged 18 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 3 additions & 21 deletions .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,24 @@ on:

jobs:
tests:
runs-on: self-hosted
runs-on: ubuntu-22.04
defaults:
run:
shell: bash -l {0}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Miniconda
uses: conda-incubator/setup-miniconda@v2
with:
channels: conda-forge,defaults,mantid
auto-update-conda: true
miniforge-version: latest
python-version: "3.8"
environment-file: environment.yml
activate-environment: liquid-ref
- name: Restore cached conda environment
id: cache-load
uses: actions/cache/restore@v3
with:
path: /usr/share/miniconda/envs/liquid-ref
key: ${{ runner.os }}-conda-${{ hashFiles('environment.yml') }}
- name: Load Environment
if: steps.cache-load.outputs.cache-hit != 'true'
run: |
mamba env update --file environment.yml --prune
- name: Start xvfb daemon
run: |
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
- name: Test with pytest
working-directory: ./reduction
run: |
echo datasearch.directories=/home/cloud/_work/LiquidsReflectometer/LiquidsReflectometer/reduction/tests/data/liquidsreflectometer-data/nexus/ >> ~/.mantid/Mantid.user.properties
cat ~/.mantid/Mantid.user.properties
git submodule add --force https://code.ornl.gov/sns-hfir-scse/infrastructure/test-data/liquidsreflectometer-data.git tests/data/liquidsreflectometer-data
git submodule update --init
python -m pytest --cov=. --cov-report=xml --cov-report=term test
python -m pytest -vv --cov=. --cov-report=xml --cov-report=term test
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
Expand Down
5 changes: 2 additions & 3 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
name: liquid-ref
channels:
- mantid/label/main
- conda-forge
- default
- mantid
- defaults
dependencies:
- pre-commit
- pytest
- pytest-cov
- numpy
- lmfit
- python=3.8
- mantidworkbench>=6.7.0
- codecov
- conda-build
Expand Down
8 changes: 8 additions & 0 deletions reduction/data/template_fbck.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<to_peak_pixels>147</to_peak_pixels>
<peak_discrete_selection>N/A</peak_discrete_selection>
<background_flag>True</background_flag>
<two_backgrounds_flag>True</two_backgrounds_flag>
<back_roi1_from>133</back_roi1_from>
<back_roi1_to>150</back_roi1_to>
<back_roi2_from>0</back_roi2_from>
Expand Down Expand Up @@ -61,6 +62,7 @@
<to_peak_pixels>147</to_peak_pixels>
<peak_discrete_selection>N/A</peak_discrete_selection>
<background_flag>True</background_flag>
<two_backgrounds_flag>True</two_backgrounds_flag>
<back_roi1_from>133</back_roi1_from>
<back_roi1_to>150</back_roi1_to>
<back_roi2_from>0</back_roi2_from>
Expand Down Expand Up @@ -108,6 +110,7 @@
<to_peak_pixels>147</to_peak_pixels>
<peak_discrete_selection>N/A</peak_discrete_selection>
<background_flag>True</background_flag>
<two_backgrounds_flag>True</two_backgrounds_flag>
<back_roi1_from>133</back_roi1_from>
<back_roi1_to>150</back_roi1_to>
<back_roi2_from>0</back_roi2_from>
Expand Down Expand Up @@ -155,6 +158,7 @@
<to_peak_pixels>147</to_peak_pixels>
<peak_discrete_selection>N/A</peak_discrete_selection>
<background_flag>True</background_flag>
<two_backgrounds_flag>True</two_backgrounds_flag>
<back_roi1_from>133</back_roi1_from>
<back_roi1_to>150</back_roi1_to>
<back_roi2_from>0</back_roi2_from>
Expand Down Expand Up @@ -202,6 +206,7 @@
<to_peak_pixels>147</to_peak_pixels>
<peak_discrete_selection>N/A</peak_discrete_selection>
<background_flag>True</background_flag>
<two_backgrounds_flag>True</two_backgrounds_flag>
<back_roi1_from>133</back_roi1_from>
<back_roi1_to>150</back_roi1_to>
<back_roi2_from>0</back_roi2_from>
Expand Down Expand Up @@ -249,6 +254,7 @@
<to_peak_pixels>147</to_peak_pixels>
<peak_discrete_selection>N/A</peak_discrete_selection>
<background_flag>True</background_flag>
<two_backgrounds_flag>True</two_backgrounds_flag>
<back_roi1_from>126</back_roi1_from>
<back_roi1_to>131</back_roi1_to>
<back_roi2_from>153</back_roi2_from>
Expand Down Expand Up @@ -296,6 +302,7 @@
<to_peak_pixels>148</to_peak_pixels>
<peak_discrete_selection>N/A</peak_discrete_selection>
<background_flag>True</background_flag>
<two_backgrounds_flag>True</two_backgrounds_flag>
<back_roi1_from>131</back_roi1_from>
<back_roi1_to>151</back_roi1_to>
<back_roi2_from>0</back_roi2_from>
Expand Down Expand Up @@ -343,6 +350,7 @@
<to_peak_pixels>148</to_peak_pixels>
<peak_discrete_selection>N/A</peak_discrete_selection>
<background_flag>True</background_flag>
<two_backgrounds_flag>True</two_backgrounds_flag>
<back_roi1_from>131</back_roi1_from>
<back_roi1_to>151</back_roi1_to>
<back_roi2_from>0</back_roi2_from>
Expand Down
27 changes: 24 additions & 3 deletions reduction/lr_reduction/reduction_template_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def __init__(self):
# Signal selection
self.data_peak_range = [140, 150]
self.subtract_background = True
self.two_backgrounds: bool = False
self.background_roi = [137, 153, 0, 0]
self.tof_range = [9600., 21600.]
self.select_tof_range = True
Expand Down Expand Up @@ -65,6 +66,20 @@ def __init__(self):
self.incident_medium_index_selected = 0

def from_dict(self, data_dict):
r"""
Update object's attributes with a dictionary with entries of the type attribute_name: attribute_value.

Raises
------
ValueError
if one entry of the dictionary is not an attribute of this object
"""

# check all keys are data_dict are attributes of object `self`
attribute_names = list(vars(self))
if not all(key in attribute_names for key in data_dict):
raise ValueError("data_dir contains invalid entries")
# update attribute values
for k, v in data_dict.items():
setattr(self, k, v)

Expand All @@ -78,6 +93,7 @@ def to_xml(self):
_xml += "<to_peak_pixels>%s</to_peak_pixels>\n" % str(self.data_peak_range[1])
_xml += "<peak_discrete_selection>N/A</peak_discrete_selection>\n"
_xml += "<background_flag>%s</background_flag>\n" % str(self.subtract_background)
_xml += "<two_backgrounds_flag>%s</two_backgrounds_flag>\n" % str(self.two_backgrounds)
_xml += "<back_roi1_from>%s</back_roi1_from>\n" % str(self.background_roi[0])
_xml += "<back_roi1_to>%s</back_roi1_to>\n" % str(self.background_roi[1])
_xml += "<back_roi2_from>%s</back_roi2_from>\n" % str(self.background_roi[2])
Expand Down Expand Up @@ -162,11 +178,15 @@ def from_xml_element(self, instrument_dom):
self.norm_x_range = [getIntElement(instrument_dom, "norm_x_min"),
getIntElement(instrument_dom, "norm_x_max")]

#background flag
# background flag
self.subtract_background = getBoolElement(instrument_dom, "background_flag",
default=self.subtract_background)

#background from/to pixels
# use two backgrounds flag
self.two_backgrounds = getBoolElement(instrument_dom, "two_backgrounds_flag",
default=self.two_backgrounds)

# background from/to pixels
self.background_roi = [getIntElement(instrument_dom, "back_roi1_from"),
getIntElement(instrument_dom, "back_roi1_to"),
getIntElement(instrument_dom, "back_roi2_from"),
Expand All @@ -191,6 +211,7 @@ def from_xml_element(self, instrument_dom):
# Background subtraction option
self.subtract_norm_background = getBoolElement(instrument_dom, "norm_background_flag",
default=self.subtract_norm_background)

self.norm_background_roi = [getIntElement(instrument_dom, "norm_from_back_pixels"),
getIntElement(instrument_dom, "norm_to_back_pixels")]

Expand Down Expand Up @@ -312,7 +333,7 @@ def from_xml(xml_str):
data_set.from_xml_element(item)
data_sets.append(data_set)

if len(data_sets)==0:
if len(data_sets) == 0:
data_sets = [ReductionParameters()]

return data_sets
4 changes: 3 additions & 1 deletion reduction/lr_reduction/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ def process_from_template_ws(ws_sc, template_data, q_summing=False,
peak = template_data.data_peak_range
if template_data.subtract_background:
peak_bck = template_data.background_roi
if template_data.two_backgrounds is False:
peak_bck = peak_bck[0: 2] # retain only the first background
else:
peak_bck = None

Expand All @@ -202,7 +204,7 @@ def process_from_template_ws(ws_sc, template_data, q_summing=False,
else:
norm_low_res = None

# We are not subtrating background for the direct beam
# We are not subtracting background for the direct beam
if template_data.subtract_norm_background:
norm_bck = template_data.norm_background_roi
else:
Expand Down
68 changes: 68 additions & 0 deletions reduction/lr_reduction/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# standard imports
from contextlib import contextmanager
from copy import deepcopy
from pathlib import Path
from typing import Union

# third-party libraries
from mantid.kernel import ConfigService


@contextmanager
def amend_config(
new_config: dict = None, data_dir: Union[str, list] = None, data_dir_insert_mode: str = "prepend"
) -> None:
r"""
Context manager to safely modify Mantid Configuration Service while
the function is executed.

Parameters
----------
new_config
(key, value) pairs to substitute in the configuration service
data_dir
prepend one (when passing a string) or more (when passing a list)
directories to the list of data search directories. Alternatively, replace instead of prepend.
data_dir_insert_mode
How to insert the data directories. Options are: "prepend" (default) and "replace".
"""
modified_keys = list()
backup = dict()
config = ConfigService.Instance()
if new_config is not None:
SEARCH_ARCHIVE = "datasearch.searcharchive"
if SEARCH_ARCHIVE not in new_config:
new_config[SEARCH_ARCHIVE] = "hfir, sns"
DEFAULT_FACILITY = "default.facility"
if DEFAULT_FACILITY not in new_config:
new_config[DEFAULT_FACILITY] = "SNS"
for key, val in new_config.items():
backup[key] = config[key]
config[key] = val # config does not have an 'update' method
modified_keys.append(key)
if data_dir is not None:
data_dirs = (
[
data_dir,
]
if isinstance(data_dir, str)
else data_dir
)
# make sure the data_dirs exists and are directories
for path in data_dirs:
if Path(path).is_dir() is False:
raise ValueError(f"Data directory: {path} does not exist or is not a directory")
key = "datasearch.directories"
backup[key] = deepcopy(config[key])
# prepend or replace our custom data directories to the list of data search directories
if data_dir_insert_mode == "prepend":
config.setDataSearchDirs(data_dirs + list(config.getDataSearchDirs()))
elif data_dir_insert_mode == "replace":
config.setDataSearchDirs(data_dirs)
else:
raise ValueError(f"Invalid data_dir_insert_mode: {data_dir_insert_mode}")
try:
yield
finally:
for key in modified_keys:
config[key] = backup[key]
17 changes: 17 additions & 0 deletions reduction/test/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# standard imports
from pathlib import Path

# third-party imports
import pytest


@pytest.fixture(scope="session")
def nexus_dir() -> str:
r"""Absolute path to the event nexus files"""
return str(Path(__file__).parent.parent / "tests/data/liquidsreflectometer-data/nexus")


@pytest.fixture(scope="session")
def template_dir() -> str:
r"""Absolute path to reduction/data/ directory"""
return str(Path(__file__).parent.parent / "data")
Loading
Loading