diff --git a/.github/workflows/documentation-build.yml b/.github/workflows/documentation-build.yml index 30f49425..d628da20 100644 --- a/.github/workflows/documentation-build.yml +++ b/.github/workflows/documentation-build.yml @@ -34,7 +34,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: 3.11 - name: Install Pandoc, repo and dependencies run: | sudo apt install pandoc diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 1eed04bb..837ad854 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -30,7 +30,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.9', '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} @@ -74,7 +74,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: 3.11 - name: Install dependencies and build run: | diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 9b42c1de..e2fc15df 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.9', '3.10', '3.11'] + python-version: ['3.10', '3.11','3.12'] if: "!contains(github.event.head_commit.message, '[ci skip]')" steps: diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 0da371b7..bc12d4e9 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: 3.10 - name: Install dependencies and build run: | diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index d7f8646e..13df4c78 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -102,7 +102,7 @@ Before you submit a pull request, check that it meets these guidelines: 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.md. -3. The pull request should work for Python 3.9, 3.10, and 3.11, and for PyPy. Check +3. The pull request should work for Python, 3.10, 3.11 and 3.12, and for PyPy. Check https://travis-ci.com/easyScience/EasyReflectometryLib/pull_requests and make sure that the tests pass for all supported Python versions. diff --git a/docs/src/calculators.rst b/docs/src/calculators.rst deleted file mode 100644 index 6b0c8c28..00000000 --- a/docs/src/calculators.rst +++ /dev/null @@ -1,15 +0,0 @@ -Calculators & Optimisation -========================== - -:py:mod:`easyreflectometry` is built on the :py:mod:`easyscience` framework which facilities the use of a range of different reflectometry calculation engines and optimiser solutions. -Currently, :py:mod:`easyreflectometry` can offer two different calculation engines, namely: - -* `refnx`_ -* `Refl1D`_ - -And we are working to add more, in particular `bornagain`_ and `GenX`_. - -.. _`refnx`: https://refnx.readthedocs.io/ -.. _`Refl1D`: https://refl1d.readthedocs.io/en/latest/ -.. _`BornAgain`: https://www.bornagainproject.org -.. _`GenX`: https://aglavic.github.io/genx/doc/ \ No newline at end of file diff --git a/docs/src/dictionay.rst b/docs/src/dictionay.rst deleted file mode 100644 index e213d43d..00000000 --- a/docs/src/dictionay.rst +++ /dev/null @@ -1,20 +0,0 @@ -Dictionary -========== -The following serves to clarify what we mean by the terms we use in this project. - -Sample ------- -A sample is an ideal representation of a the full physical setup. -This includes the layer(s) under investigation, the surrounding superphase, and the subphase. - -Calculator ----------- -A calculator is the physics engine which calculates the reflectivity curve from our inputted sample parameters. -We rely on third party software to provide the necessary calculators. -Different calculators might have different capabilities and limitations. - -Model ------ -A model combines a sample and calculator. -The model is also responsible for including instrumental effects such as background, scale, and resolution. - diff --git a/docs/src/index.rst b/docs/src/index.rst index e83be6d5..e2c8dc09 100644 --- a/docs/src/index.rst +++ b/docs/src/index.rst @@ -7,11 +7,7 @@ installation usage - sample/sample - calculators - model/model tutorials/tutorials - dictionary contributing authors api/api diff --git a/docs/src/tutorials/advancedfitting/multi_contrast.ipynb b/docs/src/tutorials/advancedfitting/multi_contrast.ipynb new file mode 100644 index 00000000..1dd68e76 --- /dev/null +++ b/docs/src/tutorials/advancedfitting/multi_contrast.ipynb @@ -0,0 +1,662 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7e1a1f25-dc5c-4768-8d0e-7a7aa9bb98fc", + "metadata": {}, + "source": [ + "# Analysis of multiple isotopic contrasts\n", + "\n", + "In the use of neutron reflectometry, it is common to use multiple isotopic contrasts of experimental data to analyse a system in a constrained fashion. \n", + "That is to say, that we have data from multiple different species (where isotopic substitution has been used to produce data with different scattering length density) that share the same structure. \n", + "In this tutorial we will look at how `easyreflectometry` can be used to fit multiple contrasts of data from a [surfactant monolayer](./monolayer.rst) system, if you haven't looked at the tutorial for a single contrast of surfactant monolayer data it is suggested that you as this tutorial will build on it." + ] + }, + { + "cell_type": "markdown", + "id": "9e2929d2", + "metadata": {}, + "source": [ + "First configure matplotlib to place figures in notebook and import needed modules. Note that the plot function needs installation of `plopp` seperately or installation of `easyreflectometry[dev]`" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e7055fbd-2a72-40ce-aca5-6e35f723f8ec", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "easyreflectometry: 1.3.0\n", + "refnx: 0.1.51\n" + ] + } + ], + "source": [ + "%matplotlib inline\n", + "\n", + "import refnx\n", + "import pooch\n", + "\n", + "import easyreflectometry\n", + "\n", + "from easyreflectometry.data import load\n", + "from easyreflectometry.plot import plot\n", + "from easyreflectometry.sample import Material\n", + "from easyreflectometry.sample import SurfactantLayer\n", + "from easyreflectometry.sample import Layer\n", + "from easyreflectometry.sample import Multilayer\n", + "from easyreflectometry.sample import LayerAreaPerMolecule\n", + "from easyreflectometry.sample import Sample\n", + "from easyreflectometry.model import Model\n", + "from easyreflectometry.model import PercentageFwhm\n", + "from easyreflectometry.calculators import CalculatorFactory\n", + "from easyreflectometry.fitting import MultiFitter\n", + "from easyscience.fitting import AvailableMinimizers\n", + "\n", + "print(f'easyreflectometry: {easyreflectometry.__version__}')\n", + "print(f'refnx: {refnx.__version__}')" + ] + }, + { + "cell_type": "markdown", + "id": "9c15bac0-c762-4235-ab57-aaa99471e2f1", + "metadata": {}, + "source": [ + "## Reading in the experimental data\n", + "\n", + "We load in three different isotopic contrast that are stored in a single `.ort` file. \n", + "This `.ort` file uses the [mutliple data set syntax](https://github.com/reflectivity/file_format/blob/master/specification.md#multiple-data-sets) to indicate that different measurements are present in a single file.\n", + "We use `pooch` to fetch the file from the repository." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "694b4e5e-2d1a-402e-aa3f-a26cc82f7774", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Downloading data from 'https://raw.githubusercontent.com/EasyScience/EasyReflectometryLib/master/docs/src/tutorials/sample/multiple.ort' to file 'C:\\Users\\mads-\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\\LocalCache\\Local\\pooch\\pooch\\Cache\\14e53c019def90deab6565306d5c3891-multiple.ort'.\n" + ] + } + ], + "source": [ + "file_path = pooch.retrieve(\n", + " # URL to one of Pooch's test files\n", + " url=\"https://raw.githubusercontent.com/EasyScience/EasyReflectometryLib/master/docs/src/tutorials/sample/multiple.ort\",\n", + " known_hash=\"241bcb819cdae47fbbb310a99c2456c7332312719496b936a153dc7dee83e62c\",\n", + ")\n", + "data = load(file_path)" + ] + }, + { + "cell_type": "markdown", + "id": "0f30bd22-3c91-4b4e-819a-3fd9e555528e", + "metadata": {}, + "source": [ + "We can plot the data and return the dimensions of the data to see the contrasts that are present. " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "82c89248-9852-4196-859c-6beb8232599b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "()" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data.dims" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "095696d6-cb54-4c6c-b0d8-45b1c7ad103f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot(data)" + ] + }, + { + "cell_type": "markdown", + "id": "0fa55bb4-f20c-4008-b49b-109229bea64b", + "metadata": {}, + "source": [ + "## Building our models\n", + "\n", + "It can be seen above that there are three isotopic contrasts present in the `'multiple.ort'` file, namely:\n", + "- `'d13DSPC-D2O'`\n", + "- `'d70DSPC-D2O'`\n", + "- `'d83DSPC-ACMW'`\n", + "\n", + "where, `'d13'` indicates that it is the head layer that is deuterated, `'d70'` indicates that the tail is deuterated and `'d83'` indicates the whole molecule is deuterated. \n", + "We describe these different deuterations as chemical formulae below. " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "7834b80e-1dc9-47b8-923a-dec58e3494be", + "metadata": {}, + "outputs": [], + "source": [ + "dspc = {'d-head': 'C10D18NO8P', 'd-tail': 'C34D70',\n", + " 'h-head': 'C10H18NO8P', 'h-tail': 'C34H70'}" + ] + }, + { + "cell_type": "markdown", + "id": "60bb92d4-62dc-4bd4-9a2a-e0cc09cb167b", + "metadata": {}, + "source": [ + "The solvent contrast is indicated as either D2O or ACMW (air-contrast matched water). " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "58855c68-c95b-40de-9fee-a662771c247b", + "metadata": {}, + "outputs": [], + "source": [ + "d2o = Material(sld=6.36, isld=0, name='D2O')\n", + "acmw = Material(sld=0, isld=0, name='ACMW')" + ] + }, + { + "cell_type": "markdown", + "id": "f249860e-10a7-4ca6-82d5-44f275949dee", + "metadata": {}, + "source": [ + "All of the contrasts are at the air/water interface, so we also need an `air` material." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "08112c21-2027-47ba-845b-a3135439d862", + "metadata": {}, + "outputs": [], + "source": [ + "air = Material(sld=0, isld=0, name='Air')" + ] + }, + { + "cell_type": "markdown", + "id": "b0fb931b-fa81-42ab-a907-fe5d384d003e", + "metadata": {}, + "source": [ + "Then we can create all of the traditional layers that we will need. " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e7caedc2-8305-4f3b-bad2-c042bacb363b", + "metadata": {}, + "outputs": [], + "source": [ + "d2o_layer = Layer(material=d2o, thickness=0, roughness=3, name='D2O Subphase')\n", + "acmw_layer = Layer(material=acmw, thickness=0, roughness=3, name='D2O Subphase')\n", + "air_layer = Layer(material=air, thickness=0, roughness=0, name='Air Superphase')" + ] + }, + { + "cell_type": "markdown", + "id": "bb3c7fa9-162a-43b3-b70b-4d2813db2d29", + "metadata": {}, + "source": [ + "The different isotopic contrasts of `SurfactantLayer` objects can also be created (all with the same structural parameters)." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "74e19578-03d4-4295-b6e2-a65fb2508c78", + "metadata": {}, + "outputs": [], + "source": [ + "head_thickness = 12\n", + "tail_thickness = 20\n", + "head_solvent_fraction = 0.5\n", + "tail_solvent_fraction = 0.0\n", + "area_per_molecule = 45\n", + "roughness = 3" + ] + }, + { + "cell_type": "markdown", + "id": "e50a2ffd", + "metadata": {}, + "source": [ + "The `'d13DSPC-D2O'` surfactant layer " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "c4aa6c00", + "metadata": {}, + "outputs": [], + "source": [ + "tail_layer_d13d2o = LayerAreaPerMolecule(\n", + " molecular_formula=dspc['h-tail'],\n", + " thickness=tail_thickness,\n", + " solvent=air,\n", + " solvent_fraction=tail_solvent_fraction,\n", + " area_per_molecule=area_per_molecule,\n", + " roughness=roughness\n", + ")\n", + "head_layer_d13d2o = LayerAreaPerMolecule(\n", + " molecular_formula=dspc['d-head'],\n", + " thickness=head_thickness,\n", + " solvent=d2o,\n", + " solvent_fraction=head_solvent_fraction,\n", + " area_per_molecule=area_per_molecule,\n", + " roughness=roughness\n", + ")\n", + "d13d2o = SurfactantLayer(\n", + " tail_layer=tail_layer_d13d2o,\n", + " head_layer=head_layer_d13d2o\n", + ")\n", + "d13d2o.constrain_area_per_molecule = True\n", + "d13d2o.conformal_roughness = True\n", + "d13d2o.constrain_solvent_roughness(d2o_layer)" + ] + }, + { + "cell_type": "markdown", + "id": "55fe44f5", + "metadata": {}, + "source": [ + "The `'d70DSPC-D2O'` surfactant layer " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "16a970d8", + "metadata": {}, + "outputs": [], + "source": [ + "tail_layer_d70d2o = LayerAreaPerMolecule(\n", + " molecular_formula=dspc['d-tail'],\n", + " thickness=tail_thickness,\n", + " solvent=air,\n", + " solvent_fraction=tail_solvent_fraction,\n", + " area_per_molecule=area_per_molecule,\n", + " roughness=roughness\n", + ")\n", + "head_layer_d70d2o = LayerAreaPerMolecule(\n", + " molecular_formula=dspc['h-head'],\n", + " thickness=head_thickness,\n", + " solvent=d2o,\n", + " solvent_fraction=head_solvent_fraction,\n", + " area_per_molecule=area_per_molecule,\n", + " roughness=roughness\n", + ")\n", + "d70d2o = SurfactantLayer(\n", + " tail_layer=tail_layer_d70d2o,\n", + " head_layer=head_layer_d70d2o\n", + ")\n", + "d70d2o.constrain_area_per_molecule = True\n", + "d70d2o.conformal_roughness = True\n", + "d70d2o.constrain_solvent_roughness(d2o_layer)" + ] + }, + { + "cell_type": "markdown", + "id": "6f57d61d", + "metadata": {}, + "source": [ + "The `'d83DSPC-ACMW'` surfactant layer " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "021272e0-7abb-4703-a4cd-92daed10ae50", + "metadata": {}, + "outputs": [], + "source": [ + "tail_layer_d83acmw = LayerAreaPerMolecule(\n", + " molecular_formula=dspc['d-tail'],\n", + " thickness=tail_thickness,\n", + " solvent=air,\n", + " solvent_fraction=tail_solvent_fraction,\n", + " area_per_molecule=area_per_molecule,\n", + " roughness=roughness\n", + ")\n", + "head_layer_d83acmw = LayerAreaPerMolecule(\n", + " molecular_formula=dspc['d-head'],\n", + " thickness=head_thickness,\n", + " solvent=acmw,\n", + " solvent_fraction=head_solvent_fraction,\n", + " area_per_molecule=area_per_molecule,\n", + " roughness=roughness\n", + ")\n", + "d83acmw = SurfactantLayer(\n", + " tail_layer=tail_layer_d83acmw,\n", + " head_layer=head_layer_d83acmw\n", + ")\n", + "d83acmw.constrain_area_per_molecule = True\n", + "d83acmw.conformal_roughness = True\n", + "d83acmw.constrain_solvent_roughness(acmw_layer)" + ] + }, + { + "cell_type": "markdown", + "id": "58dad79b-6145-4159-966e-9eb0f15558e5", + "metadata": {}, + "source": [ + "## Introducing constraints\n", + "\n", + "Then to ensure that the structure (thicknesss, area per molecule, etc.) is kept the same between the different contrasts we constain these (`layer2` is the head layer and `layer1`, which the neutron are incident on first are the tail layer). \n", + "The `constrain_multiple_contrast` method allows this, not that is it important that a chain of constraints is produced, one constraining the next. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "24808923-ba02-4a7d-9be3-8d717b08aa8e", + "metadata": {}, + "outputs": [], + "source": [ + "# These four lines should be removed in future\n", + "d70d2o.head_layer.area_per_molecule_parameter.enabled = True\n", + "d70d2o.tail_layer.area_per_molecule_parameter.enabled = True\n", + "d83acmw.head_layer.area_per_molecule_parameter.enabled = True\n", + "d83acmw.tail_layer.area_per_molecule_parameter.enabled = True\n", + "\n", + "d70d2o.constain_multiple_contrast(d13d2o)\n", + "d83acmw.constain_multiple_contrast(d70d2o)" + ] + }, + { + "cell_type": "markdown", + "id": "bfad7f64-7c81-41e0-8f7c-d99b535bade3", + "metadata": {}, + "source": [ + "We can check this constraint as worked as follows." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f21a92b7-f2b0-4315-a92b-950aa1e80b63", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(12.0, 12.0, 12.0)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d13d2o.head_layer.thickness.value, d70d2o.head_layer.thickness.value, d83acmw.head_layer.thickness.value" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "e31a4807-c6f4-4bfd-986e-749955aa7e49", + "metadata": {}, + "outputs": [], + "source": [ + "d13d2o.head_layer.thickness.value = 10" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "df2dbb56-6dc1-4388-97b7-1aef9da1769e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(10.0, 10.0, 10.0)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d13d2o.head_layer.thickness.value, d70d2o.head_layer.thickness.value, d83acmw.head_layer.thickness.value" + ] + }, + { + "cell_type": "markdown", + "id": "01abb1a2-1c77-4c59-b8ae-58fc29c00857", + "metadata": {}, + "source": [ + "Even through only as single value (that for the d13-DSPC head thickness) was changed, all three values changed. \n", + "\n", + "Having constructed each of the surfactant layer object and implemented the constraints, we can now build Samples and models. " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "6e92498a-581b-445d-94cd-dda6474f1984", + "metadata": {}, + "outputs": [], + "source": [ + "resolution_function = PercentageFwhm(5)\n", + "\n", + "d13d2o_sample = Sample(Multilayer(air_layer), d13d2o, Multilayer(d2o_layer))\n", + "d70d2o_sample = Sample(Multilayer(air_layer), d70d2o, Multilayer(d2o_layer))\n", + "d83acmw_sample = Sample(Multilayer(air_layer), d83acmw, Multilayer(acmw_layer))\n", + "d13d2o_model = Model(\n", + " sample=d13d2o_sample,\n", + " scale=0.1,\n", + " background=data['data']['R_d13DSPC-D2O'].values.min(),\n", + " resolution_function=resolution_function\n", + ")\n", + "d70d2o_model = Model(\n", + " sample=d70d2o_sample,\n", + " scale=0.1,\n", + " background=data['data']['R_d70DSPC-D2O'].values.min(),\n", + " resolution_function=resolution_function\n", + ")\n", + "d83acmw_model = Model(\n", + " sample=d83acmw_sample,\n", + " scale=0.1,\n", + " background=data['data']['R_d83DSPC-ACMW'].values.min(),\n", + " resolution_function=resolution_function\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "f40ff64a-2777-4d9a-b7ff-ad0ac66f7916", + "metadata": {}, + "source": [ + "## Setting varying parameters\n", + "\n", + "For this analysis, we want the scale and background for each model to vary and then some of the structural parameters. \n", + "Since the structural parameters are constrained, we only need to define the bounds once. \n", + "In the case on the `d13d2o` object, as this is the basis for the constraints. " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "cf35ee97-2d64-4a0f-9212-7cca8bb2dcfc", + "metadata": {}, + "outputs": [], + "source": [ + "d13d2o_model.scale.bounds = (0.05, 1.5)\n", + "d13d2o_model.background.bounds = (4e-8, 1e-5)\n", + "d70d2o_model.scale.bounds = (0.05, 1.5)\n", + "d70d2o_model.background.bounds = (4e-8, 1e-5)\n", + "d83acmw_model.scale.bounds = (0.05, 1.5)\n", + "d83acmw_model.background.bounds = (4e-8, 1e-5)\n", + "\n", + "d13d2o.tail_layer.area_per_molecule_parameter.bounds = (40, 50)\n", + "d13d2o.head_layer.solvent_fraction_parameter.bounds = (0.2, 0.6)\n", + "d13d2o.tail_layer.thickness.bounds = (18, 24)\n", + "d13d2o.head_layer.thickness.bounds = (8, 12)" + ] + }, + { + "cell_type": "markdown", + "id": "de0f41e9-785a-4591-8dfe-d694ef0d52b3", + "metadata": {}, + "source": [ + "## Creating interfaces and performing the fitting\n", + "\n", + "The model has been created and the parameters defined, so the fitting process can begin. \n", + "First, we should create a unique interface for each of the models. " + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "dc8e7f8f-6b4b-45ce-a38c-274dea683df4", + "metadata": {}, + "outputs": [], + "source": [ + "d13d2o_model.interface = CalculatorFactory()\n", + "d70d2o_model.interface = CalculatorFactory()\n", + "d83acmw_model.interface = CalculatorFactory()" + ] + }, + { + "cell_type": "markdown", + "id": "0570619e-2768-409d-ab9d-2c2c584dd711", + "metadata": {}, + "source": [ + "The models and the interface fit functions are then passed to the `MultiFitter` object, which is capable of performed the multiple dataset fitting process." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "ce890544-f3cf-4a74-b927-d19dc292e12c", + "metadata": {}, + "outputs": [], + "source": [ + "fitter = MultiFitter(d13d2o_model, d70d2o_model, d83acmw_model)\n", + "fitter.switch_minimizer(AvailableMinimizers.LMFit_scipy_least_squares)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "0cb9d7b4-aa04-4c73-a700-4ff5af7e6f47", + "metadata": {}, + "outputs": [], + "source": [ + "analysed = fitter.fit(data)" + ] + }, + { + "cell_type": "markdown", + "id": "47526f09-c8b9-40bf-ba31-8873dc64e11e", + "metadata": {}, + "source": [ + "Once the fitting is complete, we can probe a given value to check that the constraints have been respected or plot the results." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "28f5d3e2-0e2f-4ef0-bc70-0f508b7fbc52", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(44.43261084507265, 44.43261084507265, 44.43261084507265)" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d13d2o.head_layer.area_per_molecule, d70d2o.head_layer.area_per_molecule, d83acmw.head_layer.area_per_molecule" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "faf00d17-55ea-45c3-be9e-772bf5cea70f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot(analysed)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv2", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/src/tutorials/sample/multiple.ort b/docs/src/tutorials/advancedfitting/multiple.ort similarity index 100% rename from docs/src/tutorials/sample/multiple.ort rename to docs/src/tutorials/advancedfitting/multiple.ort diff --git a/docs/src/sample/assemblies_library.rst b/docs/src/tutorials/basic/assemblies_library.rst similarity index 93% rename from docs/src/sample/assemblies_library.rst rename to docs/src/tutorials/basic/assemblies_library.rst index 8becbbaf..1f7d8ab5 100644 --- a/docs/src/sample/assemblies_library.rst +++ b/docs/src/tutorials/basic/assemblies_library.rst @@ -1,15 +1,16 @@ -Assemblies +Creating multilayers and surfactant layers ========== -:py:mod:`easyreflectometry` is designed to be used with a broad range of different assemblies. -These assemblies offer flexibility for the user and enable more powerful analysis by making chemical and pysical constraints available with limited code. +:py:mod:`easyreflectometry` is designed to be used with a broad range of different assemblies. +Assemblies are collective layers behaving as a single object, for example, a multilayer or a surfactant layer. +These assemblies offer flexibility for the user and enable more powerful analysis by making chemical and physical constraints available with limited code. In this page, we will document the assemblies that are available with simple examples of the constructors that exist. Full API documentation is also available for the :py:mod:`easyreflectometry.sample.assemblies` module. :py:class:`Multilayer` ---------------------- -This assembly should be used for a series of layers that, for whatever reason, should be thought of as a single object. +This assembly should be used for a series of layers that should be thought of as a single object. For example, in the `simple fitting tutorial`_ this assembly type is used to combine the silicon and silicon dioxide layer that as formed into a single object. All of the separate layers in these objects will be fitted individually, i.e. there is no constraints present, however, there is some cognative benefit to grouping layers together. diff --git a/docs/src/sample/layer_library.rst b/docs/src/tutorials/basic/layer_library.rst similarity index 99% rename from docs/src/sample/layer_library.rst rename to docs/src/tutorials/basic/layer_library.rst index 48411385..28d5e438 100644 --- a/docs/src/sample/layer_library.rst +++ b/docs/src/tutorials/basic/layer_library.rst @@ -1,4 +1,4 @@ -Layers +Defining Layers ====== Similar to a range of different `materials`_, there are a few different ways that a layer can be defined in :py:mod:`easyreflectometry`. diff --git a/docs/src/sample/material_library.rst b/docs/src/tutorials/basic/material_library.rst similarity index 96% rename from docs/src/sample/material_library.rst rename to docs/src/tutorials/basic/material_library.rst index 7007675d..2224aefc 100644 --- a/docs/src/sample/material_library.rst +++ b/docs/src/tutorials/basic/material_library.rst @@ -1,9 +1,9 @@ -Materials +Defining materials ========= In order to support a wide range of applications (and to build complex `assemblies`_) there are a few different types of material that can be utilised in :py:mod:`easyreflectometry`. -These can include constraints or enabel the user to define the material based on chemical or physical properties. -Full API documentation for the :py:mod:`easyreflectometry.sample.elements.material` mdoule is also available, but here we will give some simple uses for them. +These can include constraints or enable the user to define the material based on chemical or physical properties. +Full API documentation for the :py:mod:`easyreflectometry.sample.elements.material` module is also available, but here we will give some simple uses for them. :py:class:`Material` -------------------- diff --git a/docs/src/model/model.rst b/docs/src/tutorials/basic/model.rst similarity index 99% rename from docs/src/model/model.rst rename to docs/src/tutorials/basic/model.rst index 77a6741e..597ce52f 100644 --- a/docs/src/model/model.rst +++ b/docs/src/tutorials/basic/model.rst @@ -1,4 +1,4 @@ -Model +Creating a model ===== The main component of an experiment in :py:mod:`easyreflectometry` is the :py:class:`Model`. diff --git a/docs/src/sample/sample.rst b/docs/src/tutorials/basic/sample.rst similarity index 97% rename from docs/src/sample/sample.rst rename to docs/src/tutorials/basic/sample.rst index ab227b69..1ba61061 100644 --- a/docs/src/sample/sample.rst +++ b/docs/src/tutorials/basic/sample.rst @@ -1,4 +1,4 @@ -Sample +Basic ====== The :py:mod:`easyreflectometry` package is focused on making easy to use functionality for specific modelling approaches. diff --git a/docs/src/tutorials/sample/dspc.png b/docs/src/tutorials/fitting/dspc.png similarity index 100% rename from docs/src/tutorials/sample/dspc.png rename to docs/src/tutorials/fitting/dspc.png diff --git a/docs/src/tutorials/sample/material_solvated.ipynb b/docs/src/tutorials/fitting/material_solvated.ipynb similarity index 98% rename from docs/src/tutorials/sample/material_solvated.ipynb rename to docs/src/tutorials/fitting/material_solvated.ipynb index cfaca5b5..213c9bab 100644 --- a/docs/src/tutorials/sample/material_solvated.ipynb +++ b/docs/src/tutorials/fitting/material_solvated.ipynb @@ -20,7 +20,7 @@ "id": "f404875e", "metadata": {}, "source": [ - "First configure matplotlib to place figures in notebook and import needed modules" + "First configure matplotlib to place figures in notebook and import needed modules. Note that the plot function needs installation of `plopp` seperately or installation of `easyreflectometry[dev]`" ] }, { @@ -354,7 +354,7 @@ ], "metadata": { "kernelspec": { - "display_name": "erl_d", + "display_name": ".venv2", "language": "python", "name": "python3" }, @@ -368,7 +368,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.5" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-0.0.ort b/docs/src/tutorials/fitting/mod_pointwise_two_layer_sample_dq-0.0.ort similarity index 100% rename from docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-0.0.ort rename to docs/src/tutorials/fitting/mod_pointwise_two_layer_sample_dq-0.0.ort diff --git a/docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-1.0.ort b/docs/src/tutorials/fitting/mod_pointwise_two_layer_sample_dq-1.0.ort similarity index 100% rename from docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-1.0.ort rename to docs/src/tutorials/fitting/mod_pointwise_two_layer_sample_dq-1.0.ort diff --git a/docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-10.0.ort b/docs/src/tutorials/fitting/mod_pointwise_two_layer_sample_dq-10.0.ort similarity index 100% rename from docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-10.0.ort rename to docs/src/tutorials/fitting/mod_pointwise_two_layer_sample_dq-10.0.ort diff --git a/docs/src/tutorials/sample/monolayer.ipynb b/docs/src/tutorials/fitting/monolayer.ipynb similarity index 98% rename from docs/src/tutorials/sample/monolayer.ipynb rename to docs/src/tutorials/fitting/monolayer.ipynb index 42b20958..6ec2e726 100644 --- a/docs/src/tutorials/sample/monolayer.ipynb +++ b/docs/src/tutorials/fitting/monolayer.ipynb @@ -17,7 +17,7 @@ "id": "e46c0e41", "metadata": {}, "source": [ - "First configure matplotlib to place figures in notebook and import needed modules" + "First configure matplotlib to place figures in notebook and import needed modules. Note that the plot function needs installation of `plopp` seperately or installation of `easyreflectometry[dev]`" ] }, { @@ -151,7 +151,7 @@ "Now we can create the `SurfactantLayer` object, this takes a large number of parameters, that we will introduce gradually. \n", "\n", "
\n", - " The chemical structure for the DSPC molecule.\n", + " The chemical structure for the DSPC molecule.\n", "
\n", "
\n", " The chemical structure for the DSPC molecule. By Graeme Bartlett - Self Drawn, CC0\n", @@ -474,7 +474,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": ".venv2", "language": "python", "name": "python3" }, @@ -488,7 +488,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.10" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/docs/src/tutorials/sample/monolayer.png b/docs/src/tutorials/fitting/monolayer.png similarity index 100% rename from docs/src/tutorials/sample/monolayer.png rename to docs/src/tutorials/fitting/monolayer.png diff --git a/docs/src/tutorials/sample/monolayer.svg b/docs/src/tutorials/fitting/monolayer.svg similarity index 100% rename from docs/src/tutorials/sample/monolayer.svg rename to docs/src/tutorials/fitting/monolayer.svg diff --git a/docs/src/tutorials/fitting/repeating.ipynb b/docs/src/tutorials/fitting/repeating.ipynb index 7da35fb7..75335c98 100644 --- a/docs/src/tutorials/fitting/repeating.ipynb +++ b/docs/src/tutorials/fitting/repeating.ipynb @@ -21,7 +21,7 @@ "id": "f5d0bd58", "metadata": {}, "source": [ - "First configure matplotlib to place figures in notebook and import needed modules" + "First configure matplotlib to place figures in notebook and import needed modules. Note that the plot function needs installation of `plopp` seperately or installation of `easyreflectometry[dev]`" ] }, { @@ -327,7 +327,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": ".venv2", "language": "python", "name": "python3" }, @@ -341,7 +341,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.10" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/docs/src/tutorials/fitting/simple_fitting.ipynb b/docs/src/tutorials/fitting/simple_fitting.ipynb index c17e03e2..8e61f0f2 100644 --- a/docs/src/tutorials/fitting/simple_fitting.ipynb +++ b/docs/src/tutorials/fitting/simple_fitting.ipynb @@ -17,7 +17,8 @@ "id": "d0fea80b", "metadata": {}, "source": [ - "First configure matplotlib to place figures in notebook and import needed modules" + "First configure matplotlib to place figures in notebook and import needed modules.\n", + "Note that the plot function needs installation of `plopp` seperately or installation of `easyreflectometry[dev]`" ] }, { @@ -523,7 +524,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": ".test", "language": "python", "name": "python3" }, @@ -537,7 +538,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.10" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/docs/src/tutorials/project.ipynb b/docs/src/tutorials/project.ipynb index 4687a175..1200f995 100644 --- a/docs/src/tutorials/project.ipynb +++ b/docs/src/tutorials/project.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -32,7 +32,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -50,52 +50,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "EasyModels:\n", - "- EasyModel:\n", - " scale: 1.0\n", - " background: 1.0e-08\n", - " resolution: 5.0 %\n", - " color: black\n", - " sample:\n", - " EasySample:\n", - " - Superphase:\n", - " Vacuum Layer:\n", - " - Vacuum Layer:\n", - " material:\n", - " Air:\n", - " sld: 0.000e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - " thickness: 0.000 Å\n", - " roughness: 0.000 Å\n", - " - D2O:\n", - " D2O Layer:\n", - " - D2O Layer:\n", - " material:\n", - " D2O:\n", - " sld: 6.335e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - " thickness: 100.000 Å\n", - " roughness: 3.000 Å\n", - " - Subphase:\n", - " Si Layer:\n", - " - Si Layer:\n", - " material:\n", - " Si:\n", - " sld: 2.074e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - " thickness: 0.000 Å\n", - " roughness: 1.200 Å\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "project.default_model()\n", "print(project.models)" @@ -110,27 +67,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "EasyMaterials:\n", - "- Air:\n", - " sld: 0.000e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - "- D2O:\n", - " sld: 6.335e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - "- Si:\n", - " sld: 2.074e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "print(project._materials)" ] @@ -144,7 +83,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -162,18 +101,7 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "WindowsPath('MyNewProject/summary.pdf')" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "summary = Summary(project)\n", "summary.save_pdf_summary(str(project.path / 'summary.pdf'))\n", @@ -196,20 +124,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "EasyModels: []\n", - "\n", - "EasyMaterials: []\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "project.reset()\n", "print(project.models)\n", @@ -225,63 +142,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "EasyModels:\n", - "- EasyModel:\n", - " scale: 1.0\n", - " background: 1.0e-08\n", - " resolution: 5.0 %\n", - " color: black\n", - " sample:\n", - " EasySample:\n", - " - Superphase:\n", - " EasyLayerCollection:\n", - " - Vacuum Layer:\n", - " material:\n", - " Air:\n", - " sld: 0.000e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - " thickness: 0.000 Å\n", - " roughness: 0.000 Å\n", - " - D2O:\n", - " EasyLayerCollection:\n", - " - D2O Layer:\n", - " material:\n", - " D2O:\n", - " sld: 6.335e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - " thickness: 100.000 Å\n", - " roughness: 3.000 Å\n", - " - Subphase:\n", - " EasyLayerCollection:\n", - " - Si Layer:\n", - " material:\n", - " Si:\n", - " sld: 2.074e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - " thickness: 0.000 Å\n", - " roughness: 1.200 Å\n", - "\n", - "EasyMaterials:\n", - "- Air:\n", - " sld: 0.000e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - "- D2O:\n", - " sld: 6.335e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - "- Si:\n", - " sld: 2.074e-6 1/Å^2\n", - " isld: 0.000e-6 1/Å^2\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "project.set_path_project_parent('.')\n", "project._info['name'] = 'MyNewProject'\n", diff --git a/docs/src/tutorials/sample/d70d2o.ort b/docs/src/tutorials/sample/d70d2o.ort deleted file mode 100644 index f155bdc0..00000000 --- a/docs/src/tutorials/sample/d70d2o.ort +++ /dev/null @@ -1,91 +0,0 @@ -# # ORSO reflectivity data file | 0.1 standard | YAML encoding | https://www.reflectometry.org/ -# data_source: -# owner: -# name: Andrew McCluskey -# affiliation: European Spallation Source -# contact: andrew.mccluskey@ess.eu -# experiment: -# facility: ISIS -# start_date: 2015-05-20 -# title: A single contrast of DSPC -# instrument: surf -# probe: neutron -# sample: -# name: DSPC monolayer -# category: air / liquid -# composition: air / d70DSPC / D2O -# measurement: -# instrument_settings: -# wavelength: -# magnitude: 12 -# unit: angstrom -# incident_angle: -# magnitude: 0.2 -# unit: deg -# data_files: -# - Unknown.nxs -# scheme: angle-dispersive -# reduction: -# software: mantid -# timestamp: 2015-08-27T15:33:59+01:00 -# corrections: -# - footprint -# - incident intensity -# - detector efficiency -# columns: -# - {name: Qz, unit: 1/angstrom, dimension: WW transfer} -# - {name: R, dimension: reflectivity} -# - {name: sR, dimension: error-reflectivity} -# - {name: sQz, unit: 1/angstrom, dimension: resolution-WW transfer} -## Qz RQz sR sQz -5.1792999999999999e-02 1.4254000000000000e-04 2.9187999999999999e-06 2.5896500000000002e-03 -5.4383000000000001e-02 1.1424000000000000e-04 2.3277000000000002e-06 2.7191500000000000e-03 -5.7102000000000000e-02 9.5197000000000004e-05 1.9168000000000000e-06 2.8551000000000002e-03 -5.9957000000000003e-02 7.4925000000000005e-05 1.5375000000000001e-06 2.9978500000000003e-03 -6.2954999999999997e-02 6.1081999999999996e-05 1.2839999999999999e-06 3.1477499999999999e-03 -6.6102999999999995e-02 5.2451000000000003e-05 1.0896999999999999e-06 3.3051499999999998e-03 -6.9407999999999997e-02 4.3195000000000002e-05 9.3939000000000000e-07 3.4704000000000002e-03 -7.2877999999999998e-02 3.5877999999999998e-05 8.0683999999999999e-07 3.6439000000000003e-03 -7.6522000000000007e-02 2.8937000000000001e-05 6.8090000000000002e-07 3.8261000000000007e-03 -8.0348000000000003e-02 2.7223999999999999e-05 6.3740000000000003e-07 4.0174000000000000e-03 -8.4364999999999996e-02 2.3142999999999998e-05 5.5753000000000004e-07 4.2182499999999998e-03 -8.8583999999999996e-02 1.9910000000000001e-05 4.8592000000000000e-07 4.4292000000000003e-03 -9.3012999999999998e-02 1.7467000000000001e-05 4.3365000000000002e-07 4.6506500000000001e-03 -9.7664000000000001e-02 1.5252000000000001e-05 3.8785999999999998e-07 4.8832000000000007e-03 -1.0255000000000000e-01 1.4654999999999999e-05 3.6547000000000000e-07 5.1275000000000001e-03 -1.0767000000000000e-01 1.3203000000000000e-05 3.3522000000000001e-07 5.3835000000000003e-03 -1.1305999999999999e-01 1.2407000000000000e-05 3.1808000000000000e-07 5.6530000000000000e-03 -1.1871000000000000e-01 1.1365999999999999e-05 3.0100000000000001e-07 5.9354999999999998e-03 -1.2465000000000000e-01 1.0529000000000000e-05 2.7911000000000002e-07 6.2325000000000002e-03 -1.3088000000000000e-01 9.5791999999999997e-06 2.6436000000000002e-07 6.5440000000000003e-03 -1.3741999999999999e-01 8.5473000000000003e-06 2.5890999999999998e-07 6.8709999999999995e-03 -1.4429000000000000e-01 8.2166000000000002e-06 2.5923000000000003e-07 7.2145000000000004e-03 -1.5151000000000001e-01 7.1802000000000003e-06 2.5376999999999998e-07 7.5755000000000006e-03 -1.5908000000000000e-01 6.9426000000000002e-06 2.6561000000000001e-07 7.9540000000000010e-03 -1.6703999999999999e-01 5.5822999999999999e-06 7.3669999999999997e-07 8.3520000000000000e-03 -1.7538999999999999e-01 5.1837000000000000e-06 4.6409999999999998e-07 8.7694999999999995e-03 -1.8415999999999999e-01 3.9739000000000002e-06 3.0730000000000001e-07 9.2079999999999992e-03 -1.9336999999999999e-01 4.1088999999999997e-06 9.5290000000000002e-07 9.6685000000000000e-03 -2.0304000000000000e-01 3.0409000000000000e-06 2.3160000000000001e-07 1.0152000000000001e-02 -2.1318999999999999e-01 2.7470999999999999e-06 4.2269999999999999e-07 1.0659500000000001e-02 -2.2384999999999999e-01 2.3638000000000001e-06 1.4970000000000000e-07 1.1192500000000001e-02 -2.3504000000000000e-01 2.3843000000000002e-06 8.1460000000000000e-07 1.1752000000000000e-02 -2.4679000000000001e-01 1.5583000000000000e-06 1.0840000000000000e-07 1.2339500000000002e-02 -2.5913000000000003e-01 1.2864000000000001e-06 4.7440000000000001e-07 1.2956500000000003e-02 -2.7209000000000000e-01 1.1920000000000000e-06 1.8839999999999999e-07 1.3604500000000000e-02 -2.8569000000000000e-01 1.2465000000000001e-06 3.9385000000000000e-07 1.4284500000000000e-02 -2.9998000000000002e-01 9.1670000000000005e-07 2.3955000000000000e-07 1.4999000000000002e-02 -3.1497000000000003e-01 8.8736999999999998e-07 3.5324000000000001e-07 1.5748500000000002e-02 -3.3072000000000001e-01 8.5180000000000004e-07 5.0846000000000004e-07 1.6536000000000002e-02 -3.4726000000000001e-01 8.7400000000000002e-07 2.2312000000000000e-07 1.7363000000000000e-02 -3.6462000000000000e-01 1.0644999999999999e-06 4.2865999999999998e-07 1.8231000000000001e-02 -3.8285000000000002e-01 8.5601999999999996e-07 2.9493000000000001e-07 1.9142500000000003e-02 -4.0200000000000002e-01 7.8897999999999996e-07 2.3347000000000001e-07 2.0100000000000003e-02 -4.2209999999999998e-01 7.1536999999999998e-07 3.3494000000000001e-07 2.1104999999999999e-02 -4.4319999999999998e-01 1.0234000000000000e-06 2.3370999999999999e-07 2.2159999999999999e-02 -4.6536000000000000e-01 8.3895000000000003e-07 3.2623999999999999e-07 2.3268000000000000e-02 -4.8863000000000001e-01 8.2964000000000001e-07 6.0419000000000001e-07 2.4431500000000002e-02 -5.1305999999999996e-01 5.2732000000000004e-07 3.4821999999999998e-07 2.5652999999999999e-02 -5.3871000000000002e-01 5.1435999999999996e-07 4.3279000000000000e-07 2.6935500000000001e-02 -5.6564999999999999e-01 4.6185999999999998e-07 1.8862999999999999e-07 2.8282500000000002e-02 -5.8877000000000002e-01 5.6128999999999997e-07 4.3959999999999999e-07 2.9438500000000003e-02 diff --git a/docs/src/tutorials/sample/multi_contrast.ipynb b/docs/src/tutorials/sample/multi_contrast.ipynb deleted file mode 100644 index b3ba549e..00000000 --- a/docs/src/tutorials/sample/multi_contrast.ipynb +++ /dev/null @@ -1,579 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "7e1a1f25-dc5c-4768-8d0e-7a7aa9bb98fc", - "metadata": {}, - "source": [ - "# Analysis of multiple isotopic contrasts\n", - "\n", - "In the use of neutron reflectometry, it is common to use multiple isotopic contrasts of experimental data to analyse a system in a constrained fashion. \n", - "That is to say, that we have data from multiple different species (where isotopic substitution has been used to produce data with different scattering length density) that share the same structure. \n", - "In this tutorial we will look at how `easyreflectometry` can be used to fit multiple contrasts of data from a [surfactant monolayer](./monolayer.rst) system, if you haven't looked at the tutorial for a single contrast of surfactant monolayer data it is suggested that you as this tutorial will build on it." - ] - }, - { - "cell_type": "markdown", - "id": "9e2929d2", - "metadata": {}, - "source": [ - "First configure matplotlib to place figures in notebook and import needed modules" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e7055fbd-2a72-40ce-aca5-6e35f723f8ec", - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "\n", - "import refnx\n", - "import pooch\n", - "\n", - "import easyreflectometry\n", - "\n", - "from easyreflectometry.data import load\n", - "from easyreflectometry.plot import plot\n", - "from easyreflectometry.sample import Material\n", - "from easyreflectometry.sample import SurfactantLayer\n", - "from easyreflectometry.sample import Layer\n", - "from easyreflectometry.sample import Multilayer\n", - "from easyreflectometry.sample import LayerAreaPerMolecule\n", - "from easyreflectometry.sample import Sample\n", - "from easyreflectometry.model import Model\n", - "from easyreflectometry.model import PercentageFwhm\n", - "from easyreflectometry.calculators import CalculatorFactory\n", - "from easyreflectometry.fitting import MultiFitter\n", - "from easyscience.fitting import AvailableMinimizers\n", - "\n", - "print(f'easyreflectometry: {easyreflectometry.__version__}')\n", - "print(f'refnx: {refnx.__version__}')" - ] - }, - { - "cell_type": "markdown", - "id": "9c15bac0-c762-4235-ab57-aaa99471e2f1", - "metadata": {}, - "source": [ - "## Reading in the experimental data\n", - "\n", - "We load in three different isotopic contrast that are stored in a single `.ort` file. \n", - "This `.ort` file uses the [mutliple data set syntax](https://github.com/reflectivity/file_format/blob/master/specification.md#multiple-data-sets) to indicate that different measurements are present in a single file.\n", - "We use `pooch` to fetch the file from the repository." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "694b4e5e-2d1a-402e-aa3f-a26cc82f7774", - "metadata": {}, - "outputs": [], - "source": [ - "file_path = pooch.retrieve(\n", - " # URL to one of Pooch's test files\n", - " url=\"https://raw.githubusercontent.com/EasyScience/EasyReflectometryLib/master/docs/src/tutorials/sample/multiple.ort\",\n", - " known_hash=\"241bcb819cdae47fbbb310a99c2456c7332312719496b936a153dc7dee83e62c\",\n", - ")\n", - "data = load(file_path)" - ] - }, - { - "cell_type": "markdown", - "id": "0f30bd22-3c91-4b4e-819a-3fd9e555528e", - "metadata": {}, - "source": [ - "We can plot the data and return the dimensions of the data to see the contrasts that are present. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "82c89248-9852-4196-859c-6beb8232599b", - "metadata": {}, - "outputs": [], - "source": [ - "data.dims" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "095696d6-cb54-4c6c-b0d8-45b1c7ad103f", - "metadata": {}, - "outputs": [], - "source": [ - "plot(data)" - ] - }, - { - "cell_type": "markdown", - "id": "0fa55bb4-f20c-4008-b49b-109229bea64b", - "metadata": {}, - "source": [ - "## Building our models\n", - "\n", - "It can be seen above that there are three isotopic contrasts present in the `'multiple.ort'` file, namely:\n", - "- `'d13DSPC-D2O'`\n", - "- `'d70DSPC-D2O'`\n", - "- `'d83DSPC-ACMW'`\n", - "\n", - "where, `'d13'` indicates that it is the head layer that is deuterated, `'d70'` indicates that the tail is deuterated and `'d83'` indicates the whole molecule is deuterated. \n", - "We describe these different deuterations as chemical formulae below. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7834b80e-1dc9-47b8-923a-dec58e3494be", - "metadata": {}, - "outputs": [], - "source": [ - "dspc = {'d-head': 'C10D18NO8P', 'd-tail': 'C34D70',\n", - " 'h-head': 'C10H18NO8P', 'h-tail': 'C34H70'}" - ] - }, - { - "cell_type": "markdown", - "id": "60bb92d4-62dc-4bd4-9a2a-e0cc09cb167b", - "metadata": {}, - "source": [ - "The solvent contrast is indicated as either D2O or ACMW (air-contrast matched water). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "58855c68-c95b-40de-9fee-a662771c247b", - "metadata": {}, - "outputs": [], - "source": [ - "d2o = Material(sld=6.36, isld=0, name='D2O')\n", - "acmw = Material(sld=0, isld=0, name='ACMW')" - ] - }, - { - "cell_type": "markdown", - "id": "f249860e-10a7-4ca6-82d5-44f275949dee", - "metadata": {}, - "source": [ - "All of the contrasts are at the air/water interface, so we also need an `air` material." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "08112c21-2027-47ba-845b-a3135439d862", - "metadata": {}, - "outputs": [], - "source": [ - "air = Material(sld=0, isld=0, name='Air')" - ] - }, - { - "cell_type": "markdown", - "id": "b0fb931b-fa81-42ab-a907-fe5d384d003e", - "metadata": {}, - "source": [ - "Then we can create all of the traditional layers that we will need. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e7caedc2-8305-4f3b-bad2-c042bacb363b", - "metadata": {}, - "outputs": [], - "source": [ - "d2o_layer = Layer(material=d2o, thickness=0, roughness=3, name='D2O Subphase')\n", - "acmw_layer = Layer(material=acmw, thickness=0, roughness=3, name='D2O Subphase')\n", - "air_layer = Layer(material=air, thickness=0, roughness=0, name='Air Superphase')" - ] - }, - { - "cell_type": "markdown", - "id": "bb3c7fa9-162a-43b3-b70b-4d2813db2d29", - "metadata": {}, - "source": [ - "The different isotopic contrasts of `SurfactantLayer` objects can also be created (all with the same structural parameters)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "74e19578-03d4-4295-b6e2-a65fb2508c78", - "metadata": {}, - "outputs": [], - "source": [ - "head_thickness = 12\n", - "tail_thickness = 20\n", - "head_solvent_fraction = 0.5\n", - "tail_solvent_fraction = 0.0\n", - "area_per_molecule = 45\n", - "roughness = 3" - ] - }, - { - "cell_type": "markdown", - "id": "e50a2ffd", - "metadata": {}, - "source": [ - "The `'d13DSPC-D2O'` surfactant layer " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c4aa6c00", - "metadata": {}, - "outputs": [], - "source": [ - "tail_layer_d13d2o = LayerAreaPerMolecule(\n", - " molecular_formula=dspc['h-tail'],\n", - " thickness=tail_thickness,\n", - " solvent=air,\n", - " solvent_fraction=tail_solvent_fraction,\n", - " area_per_molecule=area_per_molecule,\n", - " roughness=roughness\n", - ")\n", - "head_layer_d13d2o = LayerAreaPerMolecule(\n", - " molecular_formula=dspc['d-head'],\n", - " thickness=head_thickness,\n", - " solvent=d2o,\n", - " solvent_fraction=head_solvent_fraction,\n", - " area_per_molecule=area_per_molecule,\n", - " roughness=roughness\n", - ")\n", - "d13d2o = SurfactantLayer(\n", - " tail_layer=tail_layer_d13d2o,\n", - " head_layer=head_layer_d13d2o\n", - ")\n", - "d13d2o.constrain_area_per_molecule = True\n", - "d13d2o.conformal_roughness = True\n", - "d13d2o.constrain_solvent_roughness(d2o_layer)" - ] - }, - { - "cell_type": "markdown", - "id": "55fe44f5", - "metadata": {}, - "source": [ - "The `'d70DSPC-D2O'` surfactant layer " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "16a970d8", - "metadata": {}, - "outputs": [], - "source": [ - "tail_layer_d70d2o = LayerAreaPerMolecule(\n", - " molecular_formula=dspc['d-tail'],\n", - " thickness=tail_thickness,\n", - " solvent=air,\n", - " solvent_fraction=tail_solvent_fraction,\n", - " area_per_molecule=area_per_molecule,\n", - " roughness=roughness\n", - ")\n", - "head_layer_d70d2o = LayerAreaPerMolecule(\n", - " molecular_formula=dspc['h-head'],\n", - " thickness=head_thickness,\n", - " solvent=d2o,\n", - " solvent_fraction=head_solvent_fraction,\n", - " area_per_molecule=area_per_molecule,\n", - " roughness=roughness\n", - ")\n", - "d70d2o = SurfactantLayer(\n", - " tail_layer=tail_layer_d70d2o,\n", - " head_layer=head_layer_d70d2o\n", - ")\n", - "d70d2o.constrain_area_per_molecule = True\n", - "d70d2o.conformal_roughness = True\n", - "d70d2o.constrain_solvent_roughness(d2o_layer)" - ] - }, - { - "cell_type": "markdown", - "id": "6f57d61d", - "metadata": {}, - "source": [ - "The `'d83DSPC-ACMW'` surfactant layer " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "021272e0-7abb-4703-a4cd-92daed10ae50", - "metadata": {}, - "outputs": [], - "source": [ - "tail_layer_d83acmw = LayerAreaPerMolecule(\n", - " molecular_formula=dspc['d-tail'],\n", - " thickness=tail_thickness,\n", - " solvent=air,\n", - " solvent_fraction=tail_solvent_fraction,\n", - " area_per_molecule=area_per_molecule,\n", - " roughness=roughness\n", - ")\n", - "head_layer_d83acmw = LayerAreaPerMolecule(\n", - " molecular_formula=dspc['d-head'],\n", - " thickness=head_thickness,\n", - " solvent=acmw,\n", - " solvent_fraction=head_solvent_fraction,\n", - " area_per_molecule=area_per_molecule,\n", - " roughness=roughness\n", - ")\n", - "d83acmw = SurfactantLayer(\n", - " tail_layer=tail_layer_d83acmw,\n", - " head_layer=head_layer_d83acmw\n", - ")\n", - "d83acmw.constrain_area_per_molecule = True\n", - "d83acmw.conformal_roughness = True\n", - "d83acmw.constrain_solvent_roughness(acmw_layer)" - ] - }, - { - "cell_type": "markdown", - "id": "58dad79b-6145-4159-966e-9eb0f15558e5", - "metadata": {}, - "source": [ - "## Introducing constraints\n", - "\n", - "Then to ensure that the structure (thicknesss, area per molecule, etc.) is kept the same between the different contrasts we constain these (`layer2` is the head layer and `layer1`, which the neutron are incident on first are the tail layer). \n", - "The `constrain_multiple_contrast` method allows this, not that is it important that a chain of constraints is produced, one constraining the next. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "24808923-ba02-4a7d-9be3-8d717b08aa8e", - "metadata": {}, - "outputs": [], - "source": [ - "# These four lines should be removed in future\n", - "d70d2o.head_layer.area_per_molecule_parameter.enabled = True\n", - "d70d2o.tail_layer.area_per_molecule_parameter.enabled = True\n", - "d83acmw.head_layer.area_per_molecule_parameter.enabled = True\n", - "d83acmw.tail_layer.area_per_molecule_parameter.enabled = True\n", - "\n", - "d70d2o.constain_multiple_contrast(d13d2o)\n", - "d83acmw.constain_multiple_contrast(d70d2o)" - ] - }, - { - "cell_type": "markdown", - "id": "bfad7f64-7c81-41e0-8f7c-d99b535bade3", - "metadata": {}, - "source": [ - "We can check this constraint as worked as follows." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f21a92b7-f2b0-4315-a92b-950aa1e80b63", - "metadata": {}, - "outputs": [], - "source": [ - "d13d2o.head_layer.thickness.value, d70d2o.head_layer.thickness.value, d83acmw.head_layer.thickness.value" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e31a4807-c6f4-4bfd-986e-749955aa7e49", - "metadata": {}, - "outputs": [], - "source": [ - "d13d2o.head_layer.thickness.value = 10" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "df2dbb56-6dc1-4388-97b7-1aef9da1769e", - "metadata": {}, - "outputs": [], - "source": [ - "d13d2o.head_layer.thickness.value, d70d2o.head_layer.thickness.value, d83acmw.head_layer.thickness.value" - ] - }, - { - "cell_type": "markdown", - "id": "01abb1a2-1c77-4c59-b8ae-58fc29c00857", - "metadata": {}, - "source": [ - "Even through only as single value (that for the d13-DSPC head thickness) was changed, all three values changed. \n", - "\n", - "Having constructed each of the surfactant layer object and implemented the constraints, we can now build Samples and models. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6e92498a-581b-445d-94cd-dda6474f1984", - "metadata": {}, - "outputs": [], - "source": [ - "resolution_function = PercentageFwhm(5)\n", - "\n", - "d13d2o_sample = Sample(Multilayer(air_layer), d13d2o, Multilayer(d2o_layer))\n", - "d70d2o_sample = Sample(Multilayer(air_layer), d70d2o, Multilayer(d2o_layer))\n", - "d83acmw_sample = Sample(Multilayer(air_layer), d83acmw, Multilayer(acmw_layer))\n", - "d13d2o_model = Model(\n", - " sample=d13d2o_sample,\n", - " scale=0.1,\n", - " background=data['data']['R_d13DSPC-D2O'].values.min(),\n", - " resolution_function=resolution_function\n", - ")\n", - "d70d2o_model = Model(\n", - " sample=d70d2o_sample,\n", - " scale=0.1,\n", - " background=data['data']['R_d70DSPC-D2O'].values.min(),\n", - " resolution_function=resolution_function\n", - ")\n", - "d83acmw_model = Model(\n", - " sample=d83acmw_sample,\n", - " scale=0.1,\n", - " background=data['data']['R_d83DSPC-ACMW'].values.min(),\n", - " resolution_function=resolution_function\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "f40ff64a-2777-4d9a-b7ff-ad0ac66f7916", - "metadata": {}, - "source": [ - "## Setting varying parameters\n", - "\n", - "For this analysis, we want the scale and background for each model to vary and then some of the structural parameters. \n", - "Since the structural parameters are constrained, we only need to define the bounds once. \n", - "In the case on the `d13d2o` object, as this is the basis for the constraints. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cf35ee97-2d64-4a0f-9212-7cca8bb2dcfc", - "metadata": {}, - "outputs": [], - "source": [ - "d13d2o_model.scale.bounds = (0.05, 1.5)\n", - "d13d2o_model.background.bounds = (4e-8, 1e-5)\n", - "d70d2o_model.scale.bounds = (0.05, 1.5)\n", - "d70d2o_model.background.bounds = (4e-8, 1e-5)\n", - "d83acmw_model.scale.bounds = (0.05, 1.5)\n", - "d83acmw_model.background.bounds = (4e-8, 1e-5)\n", - "\n", - "d13d2o.tail_layer.area_per_molecule_parameter.bounds = (40, 50)\n", - "d13d2o.head_layer.solvent_fraction_parameter.bounds = (0.2, 0.6)\n", - "d13d2o.tail_layer.thickness.bounds = (18, 24)\n", - "d13d2o.head_layer.thickness.bounds = (8, 12)" - ] - }, - { - "cell_type": "markdown", - "id": "de0f41e9-785a-4591-8dfe-d694ef0d52b3", - "metadata": {}, - "source": [ - "## Creating interfaces and performing the fitting\n", - "\n", - "The model has been created and the parameters defined, so the fitting process can begin. \n", - "First, we should create a unique interface for each of the models. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dc8e7f8f-6b4b-45ce-a38c-274dea683df4", - "metadata": {}, - "outputs": [], - "source": [ - "d13d2o_model.interface = CalculatorFactory()\n", - "d70d2o_model.interface = CalculatorFactory()\n", - "d83acmw_model.interface = CalculatorFactory()" - ] - }, - { - "cell_type": "markdown", - "id": "0570619e-2768-409d-ab9d-2c2c584dd711", - "metadata": {}, - "source": [ - "The models and the interface fit functions are then passed to the `MultiFitter` object, which is capable of performed the multiple dataset fitting process." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ce890544-f3cf-4a74-b927-d19dc292e12c", - "metadata": {}, - "outputs": [], - "source": [ - "fitter = MultiFitter(d13d2o_model, d70d2o_model, d83acmw_model)\n", - "fitter.switch_minimizer(AvailableMinimizers.LMFit_scipy_least_squares)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0cb9d7b4-aa04-4c73-a700-4ff5af7e6f47", - "metadata": {}, - "outputs": [], - "source": [ - "analysed = fitter.fit(data)" - ] - }, - { - "cell_type": "markdown", - "id": "47526f09-c8b9-40bf-ba31-8873dc64e11e", - "metadata": {}, - "source": [ - "Once the fitting is complete, we can probe a given value to check that the constraints have been respected or plot the results." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "28f5d3e2-0e2f-4ef0-bc70-0f508b7fbc52", - "metadata": {}, - "outputs": [], - "source": [ - "d13d2o.head_layer.area_per_molecule, d70d2o.head_layer.area_per_molecule, d83acmw.head_layer.area_per_molecule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "faf00d17-55ea-45c3-be9e-772bf5cea70f", - "metadata": {}, - "outputs": [], - "source": [ - "plot(analysed)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.10" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/src/tutorials/magnetism.ipynb b/docs/src/tutorials/simulation/magnetism.ipynb similarity index 99% rename from docs/src/tutorials/magnetism.ipynb rename to docs/src/tutorials/simulation/magnetism.ipynb index 237c67bf..a72fe39f 100644 --- a/docs/src/tutorials/magnetism.ipynb +++ b/docs/src/tutorials/simulation/magnetism.ipynb @@ -80,7 +80,7 @@ "We show the model that will be used graphically below. \n", "\n", "
\n", - " A slab model description of the two_layers system.\n", + " A slab model description of the two_layers system.\n", "
\n", "
\n", " A slab model description of the two layer.\n", @@ -555,7 +555,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": ".venv2", "language": "python", "name": "python3" }, @@ -569,7 +569,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.10" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/docs/src/tutorials/simulation/resolution_functions copy.ipynb b/docs/src/tutorials/simulation/resolution_functions copy.ipynb new file mode 100644 index 00000000..dabafc8b --- /dev/null +++ b/docs/src/tutorials/simulation/resolution_functions copy.ipynb @@ -0,0 +1,402 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a60117e3-d089-4375-ac7c-12a52ed47271", + "metadata": {}, + "source": [ + "# Resolution functions\n", + "The purpose of the resolution function is to enable the `easyreflectometry` model to quantify the experimental uncertainties in wavelength and incident angle.\n", + "When determining reflectivity the resolution function defines the smearing to apply. For a given Q-point such smearing is applied by determining an average of the neighboring Q-point weigthed by a normal distribution, which has a Q-point dependent Full Width at the Half Maximum (FWHM) that again is defined by the resolution function.\n", + "\n", + "Often we rely on a resolution function that has a simple functional dependecy of the Q-point. By this is understood that the applied smearing in an Q point-has a FWHM that is given as a percentage of the value of the Q-point.\n", + "\n", + "Alternatively the FWHM value might be determined and declared directly for each measured Q-point.\n", + "When this is the case the provided Q-points and the corresponding FWHM values can be used to declare a linear spline function and thereby enable a determination of the reflectivity at an arbitrary point within the provided range of discrete Q-points." + ] + }, + { + "cell_type": "markdown", + "id": "f5d0bd58", + "metadata": {}, + "source": [ + "## Setup\n", + "First configure matplotlib to place figures in notebook and import needed modules. Note that the plot function needs installation of `plopp` seperately or installation of `easyreflectometry[dev]`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29d5d62d-af4a-416d-bbe2-1338d32b30f5", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import scipp as sc\n", + "import refnx\n", + "import pooch\n", + "\n", + "import easyreflectometry\n", + "\n", + "from easyreflectometry.calculators import CalculatorFactory\n", + "from easyreflectometry.data import load\n", + "from easyreflectometry.model import Model\n", + "from easyreflectometry.model import LinearSpline\n", + "from easyreflectometry.model import PercentageFwhm\n", + "from easyreflectometry.sample import Layer\n", + "from easyreflectometry.sample import Material\n", + "from easyreflectometry.sample import Multilayer\n", + "from easyreflectometry.sample import Sample\n", + "from easyreflectometry.plot import plot" + ] + }, + { + "cell_type": "markdown", + "id": "8fd3e8f7-84ac-41c4-a89d-922ed82a001e", + "metadata": {}, + "source": [ + "For reference we fetch the version of the software packages we are using. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "549734c1-bbd9-41f3-8a20-d7a8ded37802", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'numpy: {np.__version__}')\n", + "print(f'scipp: {sc.__version__}')\n", + "print(f'easyreflectometry: {easyreflectometry.__version__}')\n", + "print(f'refnx: {refnx.__version__}')" + ] + }, + { + "cell_type": "markdown", + "id": "687719c7-d5a2-4d60-953f-c854c5ca1c4a", + "metadata": {}, + "source": [ + "## Reading in measured data\n", + "\n", + "The data that we will investigate in this tutorial was generated with `Refnx` and are stored in `.ort` [format file](https://github.com/reflectivity/file_format/blob/master/specification.md) files. In this tutorial we are investigation how we can include resolution effects when simulating and reproducing data measured in an experiment. For an `.ort` file the resoultion data for reflectivity is stored in the fourth column.\n", + "\n", + "IMPORTANT when using `easyreflectometry` functionality for loading an `.ort` file we store the resolution data as a variance (squared value). As a consequence one needs to take the squareroot of the loaded data to recover the raw values (fourth column).\n", + "We use `pooch` to fetch the file from the repository." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "609174e5-1371-412d-a29f-cb05bfe36df0", + "metadata": {}, + "outputs": [], + "source": [ + "file_path_0 = pooch.retrieve(\n", + " # URL to one of Pooch's test files\n", + " url=\"https://raw.githubusercontent.com/EasyScience/EasyReflectometryLib/master/docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-0.0.ort\",\n", + " known_hash=\"f8a3e7007b83f0de4e2c761134e7d1c55027f0099528bd56f746b50349369f50\",\n", + ")\n", + "file_path_1 = pooch.retrieve(\n", + " # URL to one of Pooch's test files\n", + " url=\"https://raw.githubusercontent.com/EasyScience/EasyReflectometryLib/master/docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-1.0.ort\",\n", + " known_hash=\"9d81a512cbe45f923806ad307e476b27535614b2e08a2bf0f4559ab608a34f7a\",\n", + ")\n", + "file_path_10 = pooch.retrieve(\n", + " # URL to one of Pooch's test files\n", + " url=\"https://raw.githubusercontent.com/EasyScience/EasyReflectometryLib/master/docs/src/tutorials/sample/mod_pointwise_two_layer_sample_dq-10.0.ort\",\n", + " known_hash=\"991395c0b6a91bf60c12d234c645143dcac1cab929944fc4e452020d44b787ad\",\n", + ")\n", + "dict_reference = {}\n", + "dict_reference['0'] = load(file_path_0)\n", + "dict_reference['1'] = load(file_path_1)\n", + "dict_reference['10'] = load(file_path_10)" + ] + }, + { + "cell_type": "markdown", + "id": "1ab3a164-62c8-4bd3-b0d8-e6f22c83dc74", + "metadata": {}, + "source": [ + "As an example we can plot the reference data without any resolution effects." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31ab44d3-826a-4270-9046-ad667dcb66ba", + "metadata": {}, + "outputs": [], + "source": [ + "plot(dict_reference['0'])" + ] + }, + { + "cell_type": "markdown", + "id": "dad78ccc-1e6f-47cd-8557-c4fa6c736f4b", + "metadata": {}, + "source": [ + "## Building our model\n", + "\n", + "The system that was used to produce the data shown above is based on a silicon subphase with two layers upon it. \n", + "These two layers are charachterized by having a scattering length density (SLD) of respectively 4 and 8.\n", + "Both layers have a rougness of 2 but their thicknesses are 100 and 150 angstrom respectively.\n", + "We show the model that will be used graphically below. \n", + "\n", + "
\n", + " A slab model description of the two_layers system.\n", + "
\n", + "
\n", + " A slab model description of the two layer.\n", + "
\n", + "\n", + "To construct such a layer structure, first we create each of the materials, the associated layers, and the sub and super phases. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f95d620-35b7-4b47-a3b4-9e33d5525b50", + "metadata": {}, + "outputs": [], + "source": [ + "sld_4 = Material(sld=4.0, isld=0, name='Sld 4')\n", + "sld_8 = Material(sld=8.0, isld=0, name='Sld 8')\n", + "vacuum = Material(sld=0, isld=0, name='Vacuum')\n", + "si = Material(sld=2.047, isld=0, name='Si')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a0b37ed-8714-4614-b49f-1e86ac232ac1", + "metadata": {}, + "outputs": [], + "source": [ + "sld_4_layer = Layer(material=sld_4, thickness=100, roughness=2, name='SLD 4 Layer')\n", + "sld_8_layer = Layer(material=sld_8, thickness=150, roughness=2, name='SLD 8 Layer')\n", + "superphase = Layer(material=vacuum, thickness=0, roughness=0, name='Vacuum Superphase')\n", + "subphase = Layer(material=si, thickness=0, roughness=2, name='Si Subphase')" + ] + }, + { + "cell_type": "markdown", + "id": "f63ec440-089f-46cf-8ff5-be5012ad8dc8", + "metadata": {}, + "source": [ + "Then, to produce the two layered structure, we use the `Multilayer` [assembly type](../../sample/assemblies_library.rst#Multilayer)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "311b25a1-6d5d-4e91-a72e-394ad8dcf464", + "metadata": {}, + "outputs": [], + "source": [ + "two_layers = Multilayer([sld_4_layer, sld_8_layer], name='SLD 4/8 Layer')\n", + "two_layers" + ] + }, + { + "cell_type": "markdown", + "id": "1c32d8ad-9baf-41bf-9fd8-419b92be36c4", + "metadata": {}, + "source": [ + "From this, we can construct our structure and combine this with a scaling and background." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2af8c30b", + "metadata": {}, + "outputs": [], + "source": [ + "sample = Sample(Multilayer(superphase), two_layers, Multilayer(subphase), name='Two Layer Sample')\n", + "model = Model(\n", + " sample=sample,\n", + " scale=1,\n", + " background=0,\n", + " name='Two Layer Model',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "8f0581b9-7690-4b17-9a4f-766ed92aaba2", + "metadata": {}, + "source": [ + "## Set the calculation engine\n", + "\n", + "We will use the default [Refnx](https://refnx.readthedocs.io/) calculator for our analysis. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f1500603-d85d-4e16-b697-e1bf16502991", + "metadata": {}, + "outputs": [], + "source": [ + "interface = CalculatorFactory()\n", + "model.interface = interface\n", + "print(interface.current_interface.name)" + ] + }, + { + "cell_type": "markdown", + "id": "defd6dd5-c618-4af6-a5c7-17532207f0a0", + "metadata": {}, + "source": [ + "## Resolution functions\n", + "\n", + "We now define the different resoultion functions. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "880d10d7-b655-4ef1-b376-21b2e4394160", + "metadata": {}, + "outputs": [], + "source": [ + "resolution_function_dict = {}\n", + "resolution_function_dict['0'] = LinearSpline(\n", + " q_data_points=dict_reference['0']['coords']['Qz_0'].values,\n", + " fwhm_values=np.sqrt(dict_reference['0']['coords']['Qz_0'].variances),\n", + ")\n", + "\n", + "resolution_function_dict['1'] = LinearSpline(\n", + " q_data_points=dict_reference['1']['coords']['Qz_0'].values,\n", + " fwhm_values=np.sqrt(dict_reference['1']['coords']['Qz_0'].variances),\n", + ")\n", + "\n", + "resolution_function_dict['10'] = LinearSpline(\n", + " q_data_points=dict_reference['10']['coords']['Qz_0'].values,\n", + " fwhm_values=np.sqrt(dict_reference['10']['coords']['Qz_0'].variances),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "0481604e-3973-4e5d-a0ee-2f5915461d71", + "metadata": {}, + "source": [ + "## Simulations\n", + "The next step is to visualise how the resolution functions affect the model. \n", + "Furthermore, we compare the here determined reflectivities (Resolution) and the ones that were determined in `Refnx` (Reference)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e59d3153-f0da-4fce-a4f0-a424010acbec", + "metadata": {}, + "outputs": [], + "source": [ + "for key in resolution_function_dict.keys():\n", + " reference_coords = dict_reference[key]['coords']['Qz_0'].values\n", + " reference_data = dict_reference[key]['data']['R_0'].values\n", + " model_coords = np.linspace(\n", + " start=min(reference_coords),\n", + " stop=max(reference_coords),\n", + " num=1000,\n", + " )\n", + " model.resolution_function = resolution_function_dict[key]\n", + " model_data = model.interface().reflectity_profile(\n", + " model_coords,\n", + " model.unique_name,\n", + " )\n", + " plt.plot(model_coords, model_data, 'k-', label=f'Resolution: {key}%')\n", + " plt.plot(reference_coords, reference_data, 'rx', label=f'Reference')\n", + " ax = plt.gca()\n", + " ax.set_xlim([-0.01, 0.45])\n", + " ax.set_ylim([1e-10, 2.5])\n", + " plt.legend()\n", + " plt.yscale('log')\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "60d1896d-06ca-4bd2-b44c-d3788304220c", + "metadata": {}, + "source": [ + "From the plots it is apparent that an increasing resolution flattens the reflectivity profile." + ] + }, + { + "cell_type": "markdown", + "id": "e3c97d1b", + "metadata": {}, + "source": [ + "## Afterthoughts\n", + "As a last task we will compare the reflectivity determined using a percentage resolution function and a point-wise function.\n", + "We should recall that the \"experimental\" data was generated using `Refnx`.\n", + "By comparing the reflectivities determined using a resolution function with a FWHM of 1.0% and the point-wise FHWN constructed from data in a `.ort` file it is apparent that this reference data also was constructed using a resolution function of 1.0%." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ca0932f6", + "metadata": {}, + "outputs": [], + "source": [ + "key = '1'\n", + "reference_coords = dict_reference[key]['coords']['Qz_0'].values\n", + "reference_data = dict_reference[key]['data']['R_0'].values\n", + "model_coords = np.linspace(\n", + " start=min(reference_coords),\n", + " stop=max(reference_coords),\n", + " num=1000,\n", + ")\n", + "\n", + "model.resolution_function = resolution_function_dict[key]\n", + "model_data = model.interface().reflectity_profile(\n", + " model_coords,\n", + " model.unique_name,\n", + ")\n", + "plt.plot(model_coords, model_data, 'k-', label=f'Variable', linewidth=5)\n", + "\n", + "model.resolution_function = PercentageFwhm(1.0)\n", + "model_data = model.interface().reflectity_profile(\n", + " model_coords,\n", + " model.unique_name,\n", + ")\n", + "plt.plot(model_coords, model_data, 'r-', label=f'Percentage')\n", + "\n", + "ax = plt.gca()\n", + "ax.set_xlim([-0.01, 0.45])\n", + "ax.set_ylim([1e-10, 2.5])\n", + "plt.legend()\n", + "plt.yscale('log')\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv2", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/src/tutorials/sample/resolution_functions.ipynb b/docs/src/tutorials/simulation/resolution_functions.ipynb similarity index 98% rename from docs/src/tutorials/sample/resolution_functions.ipynb rename to docs/src/tutorials/simulation/resolution_functions.ipynb index 04d21f27..dabafc8b 100644 --- a/docs/src/tutorials/sample/resolution_functions.ipynb +++ b/docs/src/tutorials/simulation/resolution_functions.ipynb @@ -21,7 +21,7 @@ "metadata": {}, "source": [ "## Setup\n", - "First configure matplotlib to place figures in notebook and import needed modules" + "First configure matplotlib to place figures in notebook and import needed modules. Note that the plot function needs installation of `plopp` seperately or installation of `easyreflectometry[dev]`" ] }, { @@ -380,7 +380,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": ".venv2", "language": "python", "name": "python3" }, @@ -394,7 +394,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.10" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/docs/src/tutorials/sample/two_layers.png b/docs/src/tutorials/simulation/two_layers.png similarity index 100% rename from docs/src/tutorials/sample/two_layers.png rename to docs/src/tutorials/simulation/two_layers.png diff --git a/docs/src/tutorials/sample/two_layers.svg b/docs/src/tutorials/simulation/two_layers.svg similarity index 100% rename from docs/src/tutorials/sample/two_layers.svg rename to docs/src/tutorials/simulation/two_layers.svg diff --git a/docs/src/tutorials/tutorials.rst b/docs/src/tutorials/tutorials.rst index bf0b40e2..ea6868d7 100644 --- a/docs/src/tutorials/tutorials.rst +++ b/docs/src/tutorials/tutorials.rst @@ -1,15 +1,49 @@ -Tutorials -========= +================ +**How to use** +================ -The tutorials associated with using :py:mod:`easyreflectometry` are collected here. +Dictionary +========== +The following serves to clarify what we mean by the terms we use in this project. + +Sample +------ +A sample is an ideal representation of a the full physical setup. +This includes the layer(s) under investigation, the surrounding superphase, and the subphase. + +Calculator +---------- +A calculator is the physics engine which calculates the reflectivity curve from our inputted sample parameters. +We rely on third party software to provide the necessary calculators. +Different calculators might have different capabilities and limitations. + +Model +----- +A model combines a sample and calculator. +The model is also responsible for including instrumental effects such as background, scale, and resolution. + + +Calculators & Optimisation +========================== + +:py:mod:`easyreflectometry` is built on the :py:mod:`easyscience` framework which facilities the use of a range of different reflectometry calculation engines and optimiser solutions. +Currently, :py:mod:`easyreflectometry` can offer two different calculation engines, namely: + +* `refnx`_ +* `Refl1D`_ + +And we are working to add more, in particular `bornagain`_ and `GenX`_. + +.. _`refnx`: https://refnx.readthedocs.io/ +.. _`Refl1D`: https://refl1d.readthedocs.io/en/latest/ +.. _`BornAgain`: https://www.bornagainproject.org +.. _`GenX`: https://aglavic.github.io/genx/doc/ .. toctree:: :maxdepth: 1 - fitting/simple_fitting - fitting/repeating - sample/material_solvated - sample/monolayer - sample/multi_contrast - sample/resolution_functions - magnetism + tutorials/basic + tutorials/simulation + tutorials/fitting + tutorials/advancedfitting + tutorials/extra diff --git a/docs/src/usage.rst b/docs/src/usage.rst index 567adfa0..c20cc720 100644 --- a/docs/src/usage.rst +++ b/docs/src/usage.rst @@ -1,10 +1,41 @@ ===== -Usage +Getting started ===== To use :py:mod:`easyreflectometry` in a project:: import easyreflectometry + from easyreflectometry.sample import Material, Layer + from easyreflectometry.model import Model + from easyreflectometry.fitting import MultiFitter + from easyreflectometry.plot import plot + + # Define your Material + material = Material(...) + + # Create a Layer + layer = Layer(material=material, ...) + + # Make a Sample out of the Layer + sample = Sample(layer, ...) + + # Define a Model of the experiment + model = Model( + sample=sample, + scale=1, + background=1e-6, + ... + ) + + # Set parameter bounds for fit + ... + + # Perform the fit and plot + fitter = MultiFitter(model) + analysed = fitter.fit(data) + + plot(analysed) + Details of specific usage of :py:mod:`easyreflectometry` can be found in the `tutorials`_. diff --git a/pyproject.toml b/pyproject.toml index 4c95bda3..34732349 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,48 +21,49 @@ classifiers = [ "Topic :: Scientific/Engineering", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Development Status :: 3 - Alpha" ] -requires-python = ">=3.9,<3.13" + +requires-python = ">=3.10,<3.13" + dependencies = [ - "easyscience>=1.2.0", - "scipp>=23.12.0", - "refnx>=0.1.15", - "refl1d>=0.8.14", - "orsopy>=0.0.4", - "pint==0.23", # Only to ensure that unit is reported as dimensionless rather than empty string - "xhtml2pdf>=0.2.16" + "easyscience==1.3.0", + "scipp==25.2.0", + "refnx==0.1.52", + "refl1d[webview]==1.0.0a12", + "orsopy==1.2.1", + "xhtml2pdf==0.2.17", ] [project.optional-dependencies] dev = [ - "build", - "codecov>=2.1.11", - "coverage", - "coveralls", - "flake8>=6.0.0", - "ipykernel", - "jupyter>=1.0.0", - "jupyterlab", - "plopp", - "pooch", - "pytest>=5.2", - "pytest-cov>=3.0.0", - "ruff", - "toml>=0.10", - "yapf>=0.31.0", + "build==1.2.2.post1", + "codecov==2.1.13", + "coverage==7.7.0", + "coveralls==4.0.1", + "flake8==7.1.2", + "ipykernel==6.29.5", + "jupyter==1.1.1", + "jupyterlab==4.3.6", + "plopp==25.3.0", + "pooch==1.8.2", + "pytest==8.3.5", + "pytest-cov==6.0.0", + "ruff==0.11.0", + "toml==0.10.2", + "yapf==0.43.0", ] + docs = [ - "myst_parser", - "nbsphinx", - "sphinx_autodoc_typehints", - "sphinx_book_theme", - "sphinx-copybutton", - "toml" + "myst_parser==4.0.1", + "nbsphinx==0.9.7", + "sphinx_autodoc_typehints==3.0.1", + "sphinx_book_theme==1.1.4", + "sphinx-copybutton==0.5.2", + "toml==0.10.2", ] [project.urls] @@ -131,10 +132,9 @@ force-single-line = true legacy_tox_ini = """ [tox] isolated_build = True -envlist = py{3.9,3.10,3.11,3.12} +envlist = py{3.10,3.11,3.12} [gh-actions] python = - 3.9: py39 3.10: py310 3.11: py311 3.12: py312 diff --git a/src/easyreflectometry/calculators/refl1d/wrapper.py b/src/easyreflectometry/calculators/refl1d/wrapper.py index d3a2a809..b211d1d4 100644 --- a/src/easyreflectometry/calculators/refl1d/wrapper.py +++ b/src/easyreflectometry/calculators/refl1d/wrapper.py @@ -3,8 +3,8 @@ from typing import Tuple import numpy as np -from refl1d import model from refl1d import names +from refl1d.sample.layers import Repeat from easyreflectometry.model import PercentageFwhm @@ -34,7 +34,7 @@ def create_layer(self, name: str): magnetism = names.Magnetism(rhoM=0.0, thetaM=0.0) else: magnetism = None - self.storage['layer'][name] = model.Slab(name=str(name), magnetism=magnetism) + self.storage['layer'][name] = names.Slab(name=str(name), magnetism=magnetism) def create_item(self, name: str): """ @@ -42,8 +42,8 @@ def create_item(self, name: str): :param name: The name of the item """ - self.storage['item'][name] = model.Repeat( - model.Stack(model.Slab(names.SLD(), thickness=0, interface=0)), name=str(name) + self.storage['item'][name] = Repeat( + names.Stack(names.Slab(names.SLD(), thickness=0, interface=0)), name=str(name) ) del self.storage['item'][name].stack[0] @@ -66,7 +66,7 @@ def get_layer_value(self, name: str, key: str) -> float: :param key: The given value keys """ if key in ['magnetism_rhoM', 'magnetism_thetaM']: - return getattr(self.storage['layer'][name].magnetism, key.split('_')[-1]) + return getattr(self.storage['layer'][name].magnetism, key.split('_')[-1]).value #TODO: check if we want to return the raw value or the full Parameter # noqa: E501 return super().get_layer_value(name, key) def create_model(self, name: str): @@ -267,8 +267,8 @@ def _get_polarized_probe( return names.PolarizedQProbe(xs=four_probes, name='polarized') -def _build_sample(storage: dict, model_name: str) -> model.Stack: - sample = model.Stack() +def _build_sample(storage: dict, model_name: str) -> names.Stack: + sample = names.Stack() # -1 to reverse the order for i in storage['model'][model_name]['items'][::-1]: if i.repeat.value == 1: @@ -276,9 +276,9 @@ def _build_sample(storage: dict, model_name: str) -> model.Stack: for j in range(len(i.stack))[::-1]: sample |= i.stack[j] else: - stack = model.Stack() + stack = names.Stack() # -1 to reverse the order for j in range(len(i.stack))[::-1]: stack |= i.stack[j] - sample |= model.Repeat(stack, repeat=i.repeat.value) + sample |= Repeat(stack, repeat=i.repeat.value) return sample diff --git a/src/easyreflectometry/model/model.py b/src/easyreflectometry/model/model.py index c990e117..969c955a 100644 --- a/src/easyreflectometry/model/model.py +++ b/src/easyreflectometry/model/model.py @@ -9,8 +9,8 @@ import numpy as np from easyscience import global_object -from easyscience.Objects.new_variable import Parameter from easyscience.Objects.ObjectClasses import BaseObj +from easyscience.Objects.variable import Parameter from easyreflectometry.sample import BaseAssembly from easyreflectometry.sample import Sample @@ -26,7 +26,7 @@ 'url': 'https://github.com/reflectivity/edu_outreach/blob/master/refl_maths/paper.tex', 'value': 1.0, 'min': 0, - 'max': np.Inf, + 'max': np.inf, 'fixed': True, }, 'background': { @@ -34,7 +34,7 @@ 'url': 'https://github.com/reflectivity/edu_outreach/blob/master/refl_maths/paper.tex', 'value': 1e-8, 'min': 0.0, - 'max': np.Inf, + 'max': np.inf, 'fixed': True, }, 'resolution': { diff --git a/src/easyreflectometry/project.py b/src/easyreflectometry/project.py index 1270e617..de769ab8 100644 --- a/src/easyreflectometry/project.py +++ b/src/easyreflectometry/project.py @@ -11,7 +11,7 @@ from easyscience import global_object from easyscience.fitting import AvailableMinimizers from easyscience.fitting.fitter import DEFAULT_MINIMIZER -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from scipp import DataGroup from easyreflectometry.calculators import CalculatorFactory diff --git a/src/easyreflectometry/sample/assemblies/repeating_multilayer.py b/src/easyreflectometry/sample/assemblies/repeating_multilayer.py index e904c34c..f022d960 100644 --- a/src/easyreflectometry/sample/assemblies/repeating_multilayer.py +++ b/src/easyreflectometry/sample/assemblies/repeating_multilayer.py @@ -2,7 +2,7 @@ from typing import Union from easyscience import global_object -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from easyreflectometry.utils import get_as_parameter diff --git a/src/easyreflectometry/sample/assemblies/surfactant_layer.py b/src/easyreflectometry/sample/assemblies/surfactant_layer.py index b104d1e4..a7dbe1e3 100644 --- a/src/easyreflectometry/sample/assemblies/surfactant_layer.py +++ b/src/easyreflectometry/sample/assemblies/surfactant_layer.py @@ -4,7 +4,7 @@ from easyscience import global_object from easyscience.Constraints import ObjConstraint -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from ..collections.layer_collection import LayerCollection from ..elements.layers.layer_area_per_molecule import LayerAreaPerMolecule diff --git a/src/easyreflectometry/sample/elements/layers/layer.py b/src/easyreflectometry/sample/elements/layers/layer.py index 00d6672b..49d858a2 100644 --- a/src/easyreflectometry/sample/elements/layers/layer.py +++ b/src/easyreflectometry/sample/elements/layers/layer.py @@ -4,7 +4,7 @@ import numpy as np from easyscience import global_object -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from easyreflectometry.utils import get_as_parameter @@ -18,7 +18,7 @@ 'value': 10.0, 'unit': 'angstrom', 'min': 0.0, - 'max': np.Inf, + 'max': np.inf, 'fixed': True, }, 'roughness': { @@ -27,7 +27,7 @@ 'value': 3.3, 'unit': 'angstrom', 'min': 0.0, - 'max': np.Inf, + 'max': np.inf, 'fixed': True, }, } diff --git a/src/easyreflectometry/sample/elements/layers/layer_area_per_molecule.py b/src/easyreflectometry/sample/elements/layers/layer_area_per_molecule.py index fea67833..dd010ec0 100644 --- a/src/easyreflectometry/sample/elements/layers/layer_area_per_molecule.py +++ b/src/easyreflectometry/sample/elements/layers/layer_area_per_molecule.py @@ -4,7 +4,7 @@ import numpy as np from easyscience import global_object from easyscience.Constraints import FunctionalConstraint -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from easyreflectometry.special.calculations import area_per_molecule_to_scattering_length_density from easyreflectometry.special.calculations import neutron_scattering_length @@ -31,8 +31,8 @@ 'url': 'https://www.ncnr.nist.gov/resources/activation/', 'value': 4.186, 'unit': 'angstrom', - 'min': -np.Inf, - 'max': np.Inf, + 'min': -np.inf, + 'max': np.inf, 'fixed': True, }, 'isl': { @@ -40,8 +40,8 @@ 'url': 'https://www.ncnr.nist.gov/resources/activation/', 'value': 0.0, 'unit': 'angstrom', - 'min': -np.Inf, - 'max': np.Inf, + 'min': -np.inf, + 'max': np.inf, 'fixed': True, }, } diff --git a/src/easyreflectometry/sample/elements/materials/material.py b/src/easyreflectometry/sample/elements/materials/material.py index 1973426c..9c9220e4 100644 --- a/src/easyreflectometry/sample/elements/materials/material.py +++ b/src/easyreflectometry/sample/elements/materials/material.py @@ -5,7 +5,7 @@ import numpy as np from easyscience import global_object -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from easyreflectometry.utils import get_as_parameter @@ -17,8 +17,8 @@ 'url': 'https://www.ncnr.nist.gov/resources/activation/', 'value': 4.186, 'unit': '1 / angstrom^2', - 'min': -np.Inf, - 'max': np.Inf, + 'min': -np.inf, + 'max': np.inf, 'fixed': True, }, 'isld': { @@ -26,8 +26,8 @@ 'url': 'https://www.ncnr.nist.gov/resources/activation/', 'value': 0.0, 'unit': '1 / angstrom^2', - 'min': -np.Inf, - 'max': np.Inf, + 'min': -np.inf, + 'max': np.inf, 'fixed': True, }, } diff --git a/src/easyreflectometry/sample/elements/materials/material_density.py b/src/easyreflectometry/sample/elements/materials/material_density.py index 388f6e84..1f7890b7 100644 --- a/src/easyreflectometry/sample/elements/materials/material_density.py +++ b/src/easyreflectometry/sample/elements/materials/material_density.py @@ -4,7 +4,7 @@ import numpy as np from easyscience import global_object from easyscience.Constraints import FunctionalConstraint -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from easyreflectometry.special.calculations import density_to_sld from easyreflectometry.special.calculations import molecular_weight @@ -22,7 +22,7 @@ 'value': 2.33, 'unit': 'gram / centimeter ** 3', 'min': 0, - 'max': np.Inf, + 'max': np.inf, 'fixed': True, }, 'molecular_weight': { @@ -30,8 +30,8 @@ 'url': 'https://en.wikipedia.org/wiki/Molecular_mass', 'value': 28.02, 'unit': 'g / mole', - 'min': -np.Inf, - 'max': np.Inf, + 'min': -np.inf, + 'max': np.inf, 'fixed': True, }, } diff --git a/src/easyreflectometry/sample/elements/materials/material_mixture.py b/src/easyreflectometry/sample/elements/materials/material_mixture.py index f3f558d9..cee47a9f 100644 --- a/src/easyreflectometry/sample/elements/materials/material_mixture.py +++ b/src/easyreflectometry/sample/elements/materials/material_mixture.py @@ -3,7 +3,7 @@ from easyscience import global_object from easyscience.Constraints import FunctionalConstraint -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from easyreflectometry.special.calculations import weighted_average from easyreflectometry.utils import get_as_parameter diff --git a/src/easyreflectometry/sample/elements/materials/material_solvated.py b/src/easyreflectometry/sample/elements/materials/material_solvated.py index db68a0f9..74f6ab31 100644 --- a/src/easyreflectometry/sample/elements/materials/material_solvated.py +++ b/src/easyreflectometry/sample/elements/materials/material_solvated.py @@ -2,7 +2,7 @@ from typing import Union from easyscience import global_object -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from easyreflectometry.utils import get_as_parameter diff --git a/src/easyreflectometry/utils.py b/src/easyreflectometry/utils.py index 00138804..176afe6e 100644 --- a/src/easyreflectometry/utils.py +++ b/src/easyreflectometry/utils.py @@ -5,7 +5,7 @@ import yaml from easyscience import global_object -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter def get_as_parameter( diff --git a/tests/calculators/refl1d/test_refl1d_wrapper.py b/tests/calculators/refl1d/test_refl1d_wrapper.py index 6753a439..a78d61b1 100644 --- a/tests/calculators/refl1d/test_refl1d_wrapper.py +++ b/tests/calculators/refl1d/test_refl1d_wrapper.py @@ -425,8 +425,8 @@ def test_get_polarized_probe_polarization(): assert len(probe.xs[3].calc_Qo) == len(q) -@patch('easyreflectometry.calculators.refl1d.wrapper.model.Stack') -@patch('easyreflectometry.calculators.refl1d.wrapper.model.Repeat') +@patch('easyreflectometry.calculators.refl1d.wrapper.names.Stack') +@patch('easyreflectometry.calculators.refl1d.wrapper.Repeat') def test_build_sample(mock_repeat, mock_stack): # When mock_item_1 = MagicMock() diff --git a/tests/model/test_model.py b/tests/model/test_model.py index 0524a30e..45755e25 100644 --- a/tests/model/test_model.py +++ b/tests/model/test_model.py @@ -37,13 +37,13 @@ def test_default(self): assert_equal(str(p.scale.unit), 'dimensionless') assert_equal(p.scale.value, 1.0) assert_equal(p.scale.min, 0.0) - assert_equal(p.scale.max, np.Inf) + assert_equal(p.scale.max, np.inf) assert_equal(p.scale.fixed, True) assert_equal(p.background.display_name, 'background') assert_equal(str(p.background.unit), 'dimensionless') assert_equal(p.background.value, 1.0e-8) assert_equal(p.background.min, 0.0) - assert_equal(p.background.max, np.Inf) + assert_equal(p.background.max, np.inf) assert_equal(p.background.fixed, True) assert p._resolution_function.smearing([1]) == 5.0 assert p._resolution_function.smearing([100]) == 5.0 @@ -73,13 +73,13 @@ def test_from_pars(self): assert_equal(str(mod.scale.unit), 'dimensionless') assert_equal(mod.scale.value, 2.0) assert_equal(mod.scale.min, 0.0) - assert_equal(mod.scale.max, np.Inf) + assert_equal(mod.scale.max, np.inf) assert_equal(mod.scale.fixed, True) assert_equal(mod.background.display_name, 'background') assert_equal(str(mod.background.unit), 'dimensionless') assert_equal(mod.background.value, 1.0e-5) assert_equal(mod.background.min, 0.0) - assert_equal(mod.background.max, np.Inf) + assert_equal(mod.background.max, np.inf) assert_equal(mod.background.fixed, True) assert mod._resolution_function.smearing([1]) == 2.0 assert mod._resolution_function.smearing([100]) == 2.0 diff --git a/tests/sample/assemblies/test_surfactant_layer.py b/tests/sample/assemblies/test_surfactant_layer.py index 85672708..b6b25243 100644 --- a/tests/sample/assemblies/test_surfactant_layer.py +++ b/tests/sample/assemblies/test_surfactant_layer.py @@ -101,6 +101,7 @@ def test_constain_solvent_roughness(self): def test_dict_repr(self): p = SurfactantLayer() + assert p._dict_repr == { 'EasySurfactantLayer': { 'head_layer': { @@ -125,9 +126,9 @@ def test_dict_repr(self): 'material': { 'C32D64 in Air': { 'solvent_fraction': '0.000 dimensionless', - 'sld': '8.297e-6 1/Å^2', + 'sld': '8.292e-6 1/Å^2', 'isld': '0.000e-6 1/Å^2', - 'material': {'C32D64': {'sld': '8.297e-6 1/Å^2', 'isld': '0.000e-6 1/Å^2'}}, + 'material': {'C32D64': {'sld': '8.292e-6 1/Å^2', 'isld': '0.000e-6 1/Å^2'}}, 'solvent': {'Air': {'sld': '0.000e-6 1/Å^2', 'isld': '0.000e-6 1/Å^2'}}, } }, diff --git a/tests/sample/elements/layers/test_layer.py b/tests/sample/elements/layers/test_layer.py index 7d6cb6bd..1d66c19d 100644 --- a/tests/sample/elements/layers/test_layer.py +++ b/tests/sample/elements/layers/test_layer.py @@ -29,13 +29,13 @@ def test_no_arguments(self): assert_equal(str(p.thickness.unit), 'Å') assert_equal(p.thickness.value, 10.0) assert_equal(p.thickness.min, 0.0) - assert_equal(p.thickness.max, np.Inf) + assert_equal(p.thickness.max, np.inf) assert_equal(p.thickness.fixed, True) assert_equal(p.roughness.display_name, 'roughness') assert_equal(str(p.roughness.unit), 'Å') assert_equal(p.roughness.value, 3.3) assert_equal(p.roughness.min, 0.0) - assert_equal(p.roughness.max, np.Inf) + assert_equal(p.roughness.max, np.inf) assert_equal(p.roughness.fixed, True) def test_shuffled_arguments(self): @@ -48,13 +48,13 @@ def test_shuffled_arguments(self): assert_equal(str(p.thickness.unit), 'Å') assert_equal(p.thickness.value, 5.0) assert_equal(p.thickness.min, 0.0) - assert_equal(p.thickness.max, np.Inf) + assert_equal(p.thickness.max, np.inf) assert_equal(p.thickness.fixed, True) assert_equal(p.roughness.display_name, 'roughness') assert_equal(str(p.roughness.unit), 'Å') assert_equal(p.roughness.value, 2.0) assert_equal(p.roughness.min, 0.0) - assert_equal(p.roughness.max, np.Inf) + assert_equal(p.roughness.max, np.inf) assert_equal(p.roughness.fixed, True) def test_only_roughness_key(self): @@ -63,7 +63,7 @@ def test_only_roughness_key(self): assert_equal(str(p.roughness.unit), 'Å') assert_equal(p.roughness.value, 10.0) assert_equal(p.roughness.min, 0.0) - assert_equal(p.roughness.max, np.Inf) + assert_equal(p.roughness.max, np.inf) assert_equal(p.roughness.fixed, True) def test_only_roughness_key_paramter(self): @@ -79,7 +79,7 @@ def test_only_thickness_key(self): assert_equal(str(p.thickness.unit), 'Å') assert_equal(p.thickness.value, 10.0) assert_equal(p.thickness.min, 0.0) - assert_equal(p.thickness.max, np.Inf) + assert_equal(p.thickness.max, np.inf) assert_equal(p.thickness.fixed, True) def test_only_thickness_key_paramter(self): diff --git a/tests/sample/elements/layers/test_layer_area_per_molecule.py b/tests/sample/elements/layers/test_layer_area_per_molecule.py index acfabd9f..97011261 100644 --- a/tests/sample/elements/layers/test_layer_area_per_molecule.py +++ b/tests/sample/elements/layers/test_layer_area_per_molecule.py @@ -24,7 +24,7 @@ def test_default(self): assert p.roughness.value == 3.3 assert str(p.roughness.unit) == 'Å' assert p.roughness.fixed is True - assert_almost_equal(p.material.sld, 2.2691419) + assert_almost_equal(p.material.sld, 2.268770124481328) assert_almost_equal(p.material.isld, 0) assert p.material.name == 'C10H18NO8P in D2O' assert p.solvent.sld.value == 6.36 @@ -66,7 +66,7 @@ def test_from_pars_constraint(self): ) assert p.molecular_formula == 'C8O10H12P' assert p.area_per_molecule == 50 - assert_almost_equal(p.material.sld, 0.31513666667) + assert_almost_equal(p.material.sld, 0.31494833333333333) assert p.thickness.value == 12 assert p.roughness.value == 2 assert p.solvent.sld.value == -0.561 @@ -74,10 +74,10 @@ def test_from_pars_constraint(self): assert p.solvent_fraction == 0.5 p.area_per_molecule = 30 assert p.area_per_molecule == 30 - assert_almost_equal(p.material.sld, 0.712227778) + assert_almost_equal(p.material.sld, 0.7119138888888887) p.thickness.value = 10 assert p.thickness.value == 10 - assert_almost_equal(p.material.sld, 0.910773333) + assert_almost_equal(p.material.sld, 0.9103966666666665) def test_solvent_change(self): h2o = Material(-0.561, 0, 'H2O') @@ -93,7 +93,7 @@ def test_solvent_change(self): assert p.molecular_formula == 'C8O10H12P' assert p.area_per_molecule == 50 print(p.material) - assert_almost_equal(p.material.sld, 0.31513666667) + assert_almost_equal(p.material.sld, 0.31494833333333333) assert p.thickness.value == 12 assert p.roughness.value == 2 assert p.solvent.sld.value == -0.561 @@ -103,7 +103,7 @@ def test_solvent_change(self): p.solvent = d2o assert p.molecular_formula == 'C8O10H12P' assert p.area_per_molecule == 50 - assert_almost_equal(p.material.sld, 3.7631366667) + assert_almost_equal(p.material.sld, 3.762948333333333) assert p.thickness.value == 12 assert p.roughness.value == 2 assert p.solvent.sld.value == 6.335 @@ -123,7 +123,7 @@ def test_molecular_formula_change(self): ) assert p.molecular_formula == 'C8O10H12P' assert p.area_per_molecule == 50 - assert_almost_equal(p.material.sld, 0.31513666667) + assert_almost_equal(p.material.sld, 0.31494833333333333) assert p.thickness.value == 12 assert p.roughness.value == 2 @@ -134,7 +134,7 @@ def test_molecular_formula_change(self): p.molecular_formula = 'C8O10D12P' assert p.molecular_formula == 'C8O10D12P' assert p.area_per_molecule == 50 - assert_almost_equal(p.material.sld, 1.3566266666666666) + assert_almost_equal(p.material.sld, 1.3558483333333333) assert p.thickness.value == 12 assert p.roughness.value == 2 assert p.solvent.sld.value == -0.561 diff --git a/tests/sample/elements/materials/test_material.py b/tests/sample/elements/materials/test_material.py index 8ef9b9d0..0885c6a1 100644 --- a/tests/sample/elements/materials/test_material.py +++ b/tests/sample/elements/materials/test_material.py @@ -21,14 +21,14 @@ def test_no_arguments(self): assert p.sld.display_name == 'sld' assert str(p.sld.unit) == '1/Å^2' assert p.sld.value == 4.186 - assert p.sld.min == -np.Inf - assert p.sld.max == np.Inf + assert p.sld.min == -np.inf + assert p.sld.max == np.inf assert p.sld.fixed is True assert p.isld.display_name == 'isld' assert str(p.isld.unit) == '1/Å^2' assert p.isld.value == 0.0 - assert p.isld.min == -np.Inf - assert p.isld.max == np.Inf + assert p.isld.min == -np.inf + assert p.isld.max == np.inf assert p.isld.fixed is True def test_shuffled_arguments(self): @@ -38,14 +38,14 @@ def test_shuffled_arguments(self): assert p.sld.display_name == 'sld' assert str(p.sld.unit) == '1/Å^2' assert p.sld.value == 6.908 - assert p.sld.min == -np.Inf - assert p.sld.max == np.Inf + assert p.sld.min == -np.inf + assert p.sld.max == np.inf assert p.sld.fixed is True assert p.isld.display_name == 'isld' assert str(p.isld.unit) == '1/Å^2' assert p.isld.value == -0.278 - assert p.isld.min == -np.Inf - assert p.isld.max == np.Inf + assert p.isld.min == -np.inf + assert p.isld.max == np.inf assert p.isld.fixed is True def test_only_sld_key(self): @@ -53,8 +53,8 @@ def test_only_sld_key(self): assert p.sld.display_name == 'sld' assert str(p.sld.unit) == '1/Å^2' assert p.sld.value == 10 - assert p.sld.min == -np.Inf - assert p.sld.max == np.Inf + assert p.sld.min == -np.inf + assert p.sld.max == np.inf assert p.sld.fixed is True def test_only_sld_key_parameter(self): @@ -69,8 +69,8 @@ def test_only_isld_key(self): assert p.isld.display_name == 'isld' assert str(p.isld.unit) == '1/Å^2' assert p.isld.value == 10 - assert p.isld.min == -np.Inf - assert p.isld.max == np.Inf + assert p.isld.min == -np.inf + assert p.isld.max == np.inf assert p.isld.fixed is True def test_only_isld_key_parameter(self): diff --git a/tests/sample/elements/materials/test_material_density.py b/tests/sample/elements/materials/test_material_density.py index cde67369..315dab10 100644 --- a/tests/sample/elements/materials/test_material_density.py +++ b/tests/sample/elements/materials/test_material_density.py @@ -16,31 +16,31 @@ def test_default(self): assert str(p.density.unit) == 'kg/L' assert p.density.value == 2.33 assert p.density.min == 0 - assert p.density.max == np.Inf + assert p.density.max == np.inf assert p.density.fixed is True def test_default_constraint(self): p = MaterialDensity() assert p.density.value == 2.33 - assert_almost_equal(p.sld.value, 2.073705382) + assert_almost_equal(p.sld.value, 2.0737423003838087) p.density.value = 2 - assert_almost_equal(p.sld.value, 1.780004619) + assert_almost_equal(p.sld.value, 1.7800363093423253) def test_from_pars(self): p = MaterialDensity('Co', 8.9, 'Cobalt') assert p.density.value == 8.9 - assert_almost_equal(p.sld.value, 2.2645412328256) + assert_almost_equal(p.sld.value,2.264541463379026) assert p.chemical_structure == 'Co' def test_chemical_structure_change(self): p = MaterialDensity('Co', 8.9, 'Cobolt') assert p.density.value == 8.9 - assert_almost_equal(p.sld.value, 2.2645412328256) + assert_almost_equal(p.sld.value, 2.264541463379026) assert_almost_equal(p.isld.value, 0.0) assert p.chemical_structure == 'Co' p.chemical_structure = 'B' assert p.density.value == 8.9 - assert_almost_equal(p.sld.value, 4.820107844970) + assert_almost_equal(p.sld.value, 4.82010833570636) assert_almost_equal(p.isld.value, -0.19098540517806603) assert p.chemical_structure == 'B' diff --git a/tests/sample/elements/materials/test_material_solvated.py b/tests/sample/elements/materials/test_material_solvated.py index 4fe90cd7..abce4c1c 100644 --- a/tests/sample/elements/materials/test_material_solvated.py +++ b/tests/sample/elements/materials/test_material_solvated.py @@ -2,7 +2,7 @@ import pytest from easyscience import global_object -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter import easyreflectometry.sample.elements.materials.material_mixture import easyreflectometry.sample.elements.materials.material_solvated diff --git a/tests/special/test_calculations.py b/tests/special/test_calculations.py index 3e3211a2..e7f1f89f 100644 --- a/tests/special/test_calculations.py +++ b/tests/special/test_calculations.py @@ -27,7 +27,7 @@ def test_neutron_scattering_length_B(self) -> None: def test_molecular_weight(self) -> None: a = molecular_weight('H2O') - assert_almost_equal(a, 18.01528) + assert_almost_equal(a, 18.015) def test_area_per_molecule_to_sld(self) -> None: a = area_per_molecule_to_scattering_length_density(2, 1, 0.5) diff --git a/tests/test_parameter_utils.py b/tests/test_parameter_utils.py index 8438031d..d8d2ce97 100644 --- a/tests/test_parameter_utils.py +++ b/tests/test_parameter_utils.py @@ -10,7 +10,7 @@ 'url': 'https://veryrealwebsite.com', 'value': 1.0, 'min': 0, - 'max': np.Inf, + 'max': np.inf, 'fixed': True, }, 'test_parameter_10': { @@ -36,7 +36,7 @@ def test_get_as_parameter(): assert_equal(str(test_parameter.unit), 'dimensionless') assert_equal(test_parameter.value, 1.0) assert_equal(test_parameter.min, 0.0) - assert_equal(test_parameter.max, np.Inf) + assert_equal(test_parameter.max, np.inf) assert_equal(test_parameter.fixed, True) assert_equal(test_parameter.description, 'Test parameter') @@ -96,7 +96,7 @@ def test_dict_remains_unchanged(): 'url': 'https://veryrealwebsite.com', 'value': 1.0, 'min': 0, - 'max': np.Inf, + 'max': np.inf, 'fixed': True, } } diff --git a/tests/test_project.py b/tests/test_project.py index 66b92041..523138c3 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -6,7 +6,7 @@ import numpy as np from easyscience import global_object from easyscience.fitting import AvailableMinimizers -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import Parameter from numpy.testing import assert_allclose import easyreflectometry