Skip to content
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
7 changes: 4 additions & 3 deletions docs/docs/tutorials/tutorial1_brownian.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@
"metadata": {},
"outputs": [],
"source": [
"diffusion_experiment.plot_data(slicer=True)"
"diffusion_experiment.plot_data(slicer=True, ymax=4)"
]
},
{
Expand Down Expand Up @@ -366,7 +366,7 @@
"id": "927b8fb5",
"metadata": {},
"source": [
"We also create a new instrument_model and attach it to our analysis, giving it the resolution model determined in the vanadium analysis. "
"We also create a new instrument_model and attach it to our analysis, giving it the resolution model determined in the vanadium analysis. We further fix all parameters in the resolution model and normalize it."
]
},
{
Expand All @@ -381,6 +381,7 @@
" resolution_model=vanadium_analysis.instrument_model.resolution_model,\n",
")\n",
"instrument_model.resolution_model.fix_all_parameters()\n",
"instrument_model.normalize_resolution()\n",
"\n",
"diffusion_analysis = Analysis(\n",
" display_name='Diffusion Analysis',\n",
Expand Down Expand Up @@ -565,7 +566,7 @@
"outputs": [],
"source": [
"diffusion_model_analysis.fit(fit_method='simultaneous')\n",
"diffusion_model_analysis.plot_data_and_model()"
"diffusion_model_analysis.plot_data_and_model(ymax=2)"
]
},
{
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/tutorials/tutorial2_nanoparticles.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@
" resolution_model=res_analysis.instrument_model.resolution_model,\n",
")\n",
"instrument_model.resolution_model.fix_all_parameters()\n",
"instrument_model.normalize_resolution()\n",
"\n",
"\n",
"analysis = Analysis(\n",
Expand Down Expand Up @@ -417,6 +418,7 @@
" resolution_model=res_analysis.instrument_model.resolution_model,\n",
")\n",
"instrument_model.resolution_model.fix_all_parameters()\n",
"instrument_model.normalize_resolution()\n",
"\n",
"# Create the analysis object\n",
"mag_analysis = Analysis(\n",
Expand Down
9 changes: 9 additions & 0 deletions src/easydynamics/analysis/analysis_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,15 @@ def extra_parameters(self, value: Parameter | list[Parameter]) -> None:
# Other methods
#############

def normalize_resolution(self) -> None:
"""Normalize the resolution in the InstrumentModel to ensure
that it integrates to 1.

This is important for accurate fitting and interpretation of the
results.
"""
self.instrument_model.normalize_resolution()

#############
# Private methods
#############
Expand Down
4 changes: 4 additions & 0 deletions src/easydynamics/sample_model/instrument_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ def free_resolution_parameters(self) -> None:
"""Free all parameters in the resolution model."""
self.resolution_model.free_all_parameters()

def normalize_resolution(self) -> None:
"""Normalize the resolution model to have area 1."""
self.resolution_model.normalize_area()

def get_energy_offset_at_Q(self, Q_index: int) -> Parameter:
"""Get the energy offset Parameter at a specific Q index.

Expand Down
5 changes: 5 additions & 0 deletions src/easydynamics/sample_model/model_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ def get_component_collection(self, Q_index: int) -> ComponentCollection:
)
return self._component_collections[Q_index]

def normalize_area(self) -> None:
"""Normalize the area of the model across all Q values."""
for collection in self._component_collections:
collection.normalize_area()

# ------------------------------------------------------------------
# Private methods
# ------------------------------------------------------------------
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/easydynamics/analysis/test_analysis_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,21 @@ def test_extra_parameters_setter_invalid_type(self, analysis_base, invalid_extra
):
analysis_base.extra_parameters = invalid_extra_parameters

#############
# Other methods
#############

def test_normalize_resolution_calls_instrument_model(self, analysis_base):
with patch.object(
analysis_base.instrument_model, 'normalize_resolution'
) as mock_normalize_resolution:
analysis_base.normalize_resolution()
mock_normalize_resolution.assert_called_once()

#############
# Private methods
#############

def test_on_experiment_changed_updates_Q(self, analysis_base):
# WHEN
fake_Q = [1, 2, 3]
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/easydynamics/sample_model/test_instrument_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,16 @@ def test_get_all_variables_with_nonint_Q_index_raises(self, instrument_model):
):
instrument_model.get_all_variables(Q_index='invalid_index')

def test_normalize_resolution(self, instrument_model):
# WHEN
instrument_model.resolution_model.normalize_area = MagicMock()

# THEN
instrument_model.normalize_resolution()

# EXPECT
instrument_model.resolution_model.normalize_area.assert_called_once()

def test_generate_energy_offsets_Q_none(self, instrument_model):
# WHEN
instrument_model._Q = None
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/easydynamics/sample_model/test_model_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,17 @@ def test_clear_Q_raises_without_confirm(self, model_base):
with pytest.raises(ValueError, match='Clearing Q values requires confirmation'):
model_base.clear_Q()

def test_normalize_area(self, model_base):
# WHEN

# THEN
model_base.normalize_area()

# EXPECT
for collection in model_base._component_collections:
total_area = sum(component.area.value for component in collection.components)
assert total_area == pytest.approx(1.0)

def test_repr(self, model_base):
# WHEN
repr_str = repr(model_base)
Expand Down
Loading