Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: James-Durant/experimental-design
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: jfkcooper/HOGBEN
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
Loading
Showing with 12,446 additions and 16,103 deletions.
  1. +47 −0 .circleci/config.yml
  2. +46 −0 .github/workflows/automated-testing.yml
  3. +32 −0 .github/workflows/publish.yml
  4. +7 −7 .gitignore
  5. +4 −3 README.md
  6. 0 {src → }/hogben/README.md
  7. +3 −0 hogben/__init__.py
  8. +28 −30 {src → }/hogben/angles.py
  9. +56 −43 {src → }/hogben/contrasts.py
  10. 0 {src → }/hogben/data/DMPC_bilayer/Si-D2O.dat
  11. 0 {src → }/hogben/data/DMPC_bilayer/Si-DMPC-D2O.dat
  12. 0 {src → }/hogben/data/DMPC_bilayer/Si-DMPC-H2O.dat
  13. 0 {src → }/hogben/data/DPPC_RaLPS_bilayer/dDPPC-RaLPS-D2O.dat
  14. 0 {src → }/hogben/data/DPPC_RaLPS_bilayer/dDPPC-RaLPS-H2O.dat
  15. 0 {src → }/hogben/data/DPPC_RaLPS_bilayer/dDPPC-RaLPS-SMW.dat
  16. 0 {src → }/hogben/data/DPPG_monolayer/dDPPG-NRW.dat
  17. 0 {src → }/hogben/data/DPPG_monolayer/hDPPG-D2O.dat
  18. 0 {src → }/hogben/data/DPPG_monolayer/hDPPG-NRW.dat
  19. 0 {src → }/hogben/data/YIG_sample/YIG_down.dat
  20. 0 {src → }/hogben/data/YIG_sample/YIG_up.dat
  21. +1 −0 hogben/data/__init__.py
  22. 0 {src → }/hogben/data/directbeams/INTER_non_polarised.dat
  23. 0 {src → }/hogben/data/directbeams/OFFSPEC_Polarised.dat
  24. 0 {src → }/hogben/data/directbeams/OFFSPEC_non_polarised.dat
  25. +2,044 −0 hogben/data/directbeams/OFFSPEC_non_polarised_old.dat
  26. +2,044 −0 hogben/data/directbeams/OFFSPEC_polarised_old.dat
  27. 0 {src → }/hogben/data/directbeams/POLREF_non_polarised.dat
  28. +2,843 −0 hogben/data/directbeams/POLREF_polarised.dat
  29. 0 {src → }/hogben/data/directbeams/SURF_non_polarised.dat
  30. +1 −0 hogben/data/directbeams/__init__.py
  31. +220 −0 hogben/data/directbeams/make_beam_spectra.py
  32. +26 −22 {src → }/hogben/kinetics.py
  33. +54 −45 {src → }/hogben/magnetism.py
  34. 0 {src → }/hogben/models/README.md
  35. +1 −0 hogben/models/__init__.py
  36. +548 −0 hogben/models/base.py
  37. +420 −206 {src → }/hogben/models/bilayers.py
  38. +108 −59 {src → }/hogben/models/magnetic.py
  39. +122 −73 {src → }/hogben/models/monolayers.py
  40. +5 −2 {src → }/hogben/models/parsing.py
  41. +557 −0 hogben/models/samples.py
  42. +458 −0 hogben/optimise.py
  43. +181 −0 hogben/simulate.py
  44. +1 −0 hogben/tests/__init__.py
  45. +305 −0 hogben/tests/test_fisher.py
  46. +228 −0 hogben/tests/test_optimise.py
  47. +381 −0 hogben/tests/test_samples.py
  48. +155 −0 hogben/tests/test_simulation.py
  49. +53 −0 hogben/tests/test_visualise.py
  50. +28 −17 {src → }/hogben/underlayers.py
  51. +331 −0 hogben/utils.py
  52. +147 −55 {src → }/hogben/visualise.py
  53. +2 −2 notebooks/README.md
  54. +23 −8,941 notebooks/angle.ipynb
  55. +37 −265 notebooks/bilayers.ipynb
  56. +21 −121 notebooks/contrast.ipynb
  57. +12 −92 notebooks/kinetics.ipynb
  58. +239 −238 notebooks/magnetism.ipynb
  59. +542 −0 notebooks/optimization.ipynb
  60. +25 −155 notebooks/simulation.ipynb
  61. +14 −0 requirements-with-tests.txt
  62. +12 −0 requirements.txt
  63. +10 −0 results/DPPG_monolayer/optimised.txt
  64. +23 −12 setup.cfg
  65. +1 −1 setup.py
  66. 0 src/__init__.py
  67. +0 −2,045 src/hogben/data/directbeams/OFFSPEC_non_polarised_old.dat
  68. +0 −2,045 src/hogben/data/directbeams/OFFSPEC_polarised_old.dat
  69. +0 −86 src/hogben/data/directbeams/make_beam_spectra.py
  70. +0 −273 src/hogben/models/base.py
  71. +0 −367 src/hogben/models/samples.py
  72. +0 −235 src/hogben/optimise.py
  73. +0 −24 src/hogben/results/DMPC_bilayer/optimised_angles.txt
  74. +0 −24 src/hogben/results/DMPC_bilayer/optimised_contrasts.txt
  75. +0 −32 src/hogben/results/DMPC_bilayer/optimised_underlayers.txt
  76. +0 −313 src/hogben/simulate.py
  77. +0 −220 src/hogben/utils.py
  78. 0 tests/__init__.py
  79. +0 −50 tests/test_simulation.py
47 changes: 47 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1

# Orbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects.
# See: https://circleci.com/docs/2.0/orb-intro/
orbs:
# The python orb contains a set of prepackaged CircleCI configuration you can use repeatedly in your configuration files
# Orb commands and jobs help you with common scripting around a language/tool
# so you dont have to copy and paste it everywhere.
# See the orb documentation here: https://circleci.com/developer/orbs/orb/circleci/python
python: circleci/python@1.5.0

# Define a job to be invoked later in a workflow.
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
jobs:
build-and-test: # This is the name of the job, feel free to change it to better match what you're trying to do!
# These next lines defines a Docker executors: https://circleci.com/docs/2.0/executor-types/
# You can specify an image from Dockerhub or use one of the convenience images from CircleCI's Developer Hub
# A list of available CircleCI Docker convenience images are available here: https://circleci.com/developer/images/image/cimg/python
# The executor is the environment in which the steps below will be executed - below will use a python 3.10.2 container
# Change the version below to your required version of python
docker:
- image: cimg/python:3.10.2
# Checkout the code as the first step. This is a dedicated CircleCI step.
# The python orb's install-packages step will install the dependencies from a Pipfile via Pipenv by default.
# Here we're making sure we use just use the system-wide pip. By default it uses the project root's requirements.txt.
# Then run your tests!
# CircleCI will report the results back to your VCS provider.
steps:
- checkout
- python/install-packages:
pkg-manager: pip
# app-dir: ~/project/package-directory/ # If you're requirements.txt isn't in the root directory.
pip-dependency-file: requirements-with-tests.txt
- run:
name: Run tests
# This assumes pytest is installed via the install-package step above
command: pytest

# Invoke jobs via workflows
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
workflows:
sample: # This is the name of the workflow, feel free to change it to better match your workflow.
# Inside the workflow, you define the jobs you want to run.
jobs:
- build-and-test
46 changes: 46 additions & 0 deletions .github/workflows/automated-testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
on:
push:
branches:
- main
pull_request:
branches:
- main
- jfkcooper:main
workflow_dispatch:

name: CI
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest
python -m pip install .
- name: Test with pytest
run: |
python -m pytest
flake8-lint:
name: flake8
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python environment
uses: actions/setup-python@v4
with:
python-version: "3.10"
# Install flake8 extensions (this step is not required. Default is "None").
- name: Set up flake8
run: pip install flake8-quotes flake8-docstrings
- name: flake8 Lint
uses: reviewdog/action-flake8@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
fail_on_error: true
32 changes: 32 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Publish ${package_name} to PyPI / GitHub

on:
push:
tags:
- "v*"
workflow_dispatch:

jobs:
build-n-publish:
name: Build and publish to PyPI
runs-on: ubuntu-latest

steps:
- name: Checkout source
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.x"

- name: Build source and wheel distributions
run: |
python -m pip install --upgrade build twine
python -m build
twine check --strict dist/*
- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
14 changes: 7 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
**__pycache__
.*
/.spyproject
/src/notebooks/results
/src/notebooks/.ipynb_checkpoints
/src/hogben/__pycache__
/src/hogben/models/__pycache__
/src/hogben/results/
/dist
/src/hogben/HOGBEN.egg-info
/examples/results
/hogben/results/
/hogben/HOGBEN.egg-info
/notebooks/results
/notebooks/.ipynb_checkpoints
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![DOI](https://zenodo.org/badge/366323997.svg)](https://zenodo.org/badge/latestdoi/366323997)

# HOGBEN
**H**olistic **O**ptimization for **G**enerating **B**etter **E**xperimental **N**eutrons
**H**olistic **O**ptimization for **G**aining **B**etter **E**vidence from **N**eutrons

## About the Project
**For the original repositories that this work is based on, see [fisher-information](https://github.com/James-Durant/fisher-information) and [experimental-design](https://github.com/James-Durant/experimental-design)**.
@@ -30,9 +30,10 @@ Or with BibTeX as:
```

## Contact
Jos Cooper - jos.cooper@stfc.ac.uk \
Jos Cooper - jos.cooper@ess.eu \
Sjoerd Stendahl - sjoerd.stendahl@physics.uu.se \
James Durant - james.durant@warwick.ac.uk \
Lucas Wilkins - lucas@lucaswilkins.com
Lucas Wilkins - lucas.wilkins@stfc.ac.uk

## Acknowledgements
We thank Luke Clifton for his assistance and expertise in fitting the lipid monolayer and lipid bilayer data sets.
File renamed without changes.
3 changes: 3 additions & 0 deletions hogben/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Top-level package for HOGBEN."""

__version__ = '3.1.1'
58 changes: 28 additions & 30 deletions src/hogben/angles.py → hogben/angles.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
"""
Functions for visualizing and optimizing angle choice for a given sample.
"""
import os
import time

import numpy as np
import os, sys, time
# Add the current directory to the system path to avoid issues with threading.
# Add the models directory to the system path to access example samples.
sys.path.append(os.path.join(os.path.dirname(__file__)))
sys.path.append(os.path.join(os.path.dirname(__file__), 'models'))

from optimise import Optimiser
from visualise import angle_choice, angle_choice_with_time
from hogben.optimise import Optimiser
from models.samples import simple_sample
from hogben.visualise import angle_choice, angle_choice_with_time


def _angle_results_visualise(save_path):
"""Visualises the initial angle choice for a sample and how the choice of
next angle changes as the counting time of the initial angle increases.
Args:
save_path (str): path to directory to save results to.
"""
from samples import similar_sld_sample_1, similar_sld_sample_2
from samples import thin_layer_sample_1, thin_layer_sample_2
from samples import simple_sample, many_param_sample
from bilayers import BilayerDMPC, BilayerDPPC
from magnetic import SampleYIG

# Choose sample here.
sample = simple_sample()

# Choose contrasts here (only bilayers should use this).
contrasts = []
#contrasts = [-0.56, 6.36]
# contrasts = [-0.56, 6.36]

# Number of points and counting time for the initial angle choice.
points = 100
@@ -37,43 +35,37 @@ def _angle_results_visualise(save_path):
angle_range = np.linspace(0.2, 4, 500)
initial_angle = angle_choice(sample, [], angle_range, points, time,
save_path, 'initial', contrasts)

# Plot how the choice of angle changes with initial angle counting time.
angle_range = np.linspace(0.2, 4, 50)
time_range = np.linspace(0, time*8, 50)
time_range = np.linspace(0, time * 8, 50)
angle_choice_with_time(sample, initial_angle, angle_range, time_range,
points, time, save_path, contrasts)


def _angle_results_optimise(save_path):
"""Optimises the choice measurement angles and counting times for a sample.
Args:
save_path (str): path to directory to save results to.
"""
from samples import similar_sld_sample_1, similar_sld_sample_2
from samples import thin_layer_sample_1, thin_layer_sample_2
from samples import simple_sample, many_param_sample
from bilayers import BilayerDMPC, BilayerDPPC
from magnetic import SampleYIG

# Choose sample here.
sample = simple_sample()

# Choose contrasts here (only bilayers should use this).
contrasts = []
#contrasts = [-0.56, 6.36]
# contrasts = [-0.56, 6.36]

# Total time budget.
total_time = 1000 # A large time improves DE convergence.
total_time = 1000 # A large time improves DE convergence.

# Interval containing angles to consider.
angle_bounds = (0.2, 4.0)

# Create a new .txt file for the results.
save_path = os.path.join(save_path, sample.name)
with open(os.path.join(save_path, 'optimised_angles.txt'), 'w') as file:
optimiser = Optimiser(sample) # Optimiser for the experiment.
optimiser = Optimiser(sample) # Optimiser for the experiment.

# Optimise the experiment using 1-4 angles.
for i, num_angles in enumerate([1, 2, 3, 4]):
@@ -89,18 +81,24 @@ def _angle_results_optimise(save_path):

# Convert to percentages.
angles, splits, val = results
splits = np.array(splits)*100
splits = np.array(splits) * 100

# Round the optimisation function value to 4 significant figures.
val = np.format_float_positional(val, precision=4, unique=False,
fractional=False, trim='k')
val = np.format_float_positional(
val, precision=4, unique=False, fractional=False, trim='k'
)

# Save the conditions, objective value and computation time.
file.write('----------- {} Angles -----------\n'.format(num_angles))
file.write(
'----------- {} Angles -----------\n'.format(num_angles)
)
file.write('Angles: {}\n'.format(list(np.round(angles, 2))))
file.write('Splits (%): {}\n'.format(list(np.round(splits, 1))))
file.write('Objective value: {}\n'.format(val))
file.write('Computation time: {}\n\n'.format(round(end-start, 1)))
file.write(
'Computation time: {}\n\n'.format(round(end - start, 1))
)


if __name__ == '__main__':
save_path = './results'
Loading