Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
_commit: 8bdcedc
_src_path: gh:/EasyScience/EasyProjectTemplate
description: A reflectometry python package built on the EasyScience framework.
max_python: '3.12'
max_python: '3.13'
min_python: '3.9'
orgname: EasyScience
packagename: easyreflectometry
Expand Down
181 changes: 181 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# GitHub Copilot Instructions for EasyReflectometryLib

## Project Overview

EasyReflectometryLib is a reflectometry Python package built on the EasyScience framework. It provides tools for reflectometry analysis and modeling.

## Development Environment

- **Python Versions**: 3.11, 3.12
- **Supported Platforms**: Linux (ubuntu-latest), macOS (macos-latest), Windows (windows-latest)
- **Package Manager**: pip
- **Build System**: hatchling with setuptools-git-versioning

## Code Style and Formatting

### Ruff Configuration
- Use **Ruff** for linting and formatting (configured in `pyproject.toml`)
- Maximum line length: 127 characters
- Quote style: single quotes for strings
- Import style: force single-line imports
- To fix issues automatically: `python -m ruff . --fix`

### Code Quality Standards
- Follow PEP 8 guidelines
- Use type hints where appropriate
- Write clear, self-documenting code with meaningful variable names
- Maintain consistency with existing code patterns in the repository

### Linting Rules
The project uses Ruff with the following rule sets:
- `E9`, `F63`, `F7`, `F82`: Critical flake8 rules
- `E`: pycodestyle errors
- `F`: Pyflakes
- `I`: isort (import sorting)
- `S`: flake8-bandit (security checks)

Special notes:
- Asserts are allowed in test files (`*test_*.py`)
- Init module imports are ignored
- Exclude `docs` directory from linting

## Testing

### Test Framework
- Use **pytest** for all tests
- Test coverage should be tracked with **pytest-cov**
- Aim for comprehensive test coverage
- Tests are located in the `tests/` directory

### Running Tests
```bash
# Install dev dependencies
pip install -e '.[dev]'

# Run tests with coverage
pytest --cov --cov-report=xml

# Run tests using tox (for multiple Python versions)
pip install tox tox-gh-actions
tox
```

### Test Guidelines
- Write unit tests for all new functionality
- Include tests when fixing bugs to prevent regression
- Test files should match the pattern `test_*.py`
- Use descriptive test function names that explain what is being tested
- Follow the existing test structure and patterns in the repository

## Security

- Follow flake8-bandit security guidelines (enabled via Ruff `S` rules)
- Be cautious with user input and file operations
- Do not commit secrets or sensitive information
- Review security implications of all changes

## Documentation

### Docstring Style
- Include docstrings for all public modules, classes, and functions
- Use **Sphinx/reStructuredText style** docstrings (`:param`, `:type`, `:return`, `:rtype`)
- Use clear, concise descriptions
- Document parameters, return values, and exceptions
- Example format:
```python
"""
Brief description of the function.

:param param_name: description of parameter
:type param_name: type
:return: description of return value
:rtype: return_type
"""
```

### Documentation Build
- Documentation is built using Sphinx (version 8.1.3)
- Source files are in the `docs/` directory
- Use `myst_parser` (MyST parser) for Markdown support
- Include code examples in documentation where appropriate

## Dependencies

### Core Dependencies
- easyscience (EasyScience framework)
- scipp (Scientific computing)
- refnx, refl1d (Reflectometry calculations)
- orsopy (Data format support)
- bumps (Optimization)

### Adding New Dependencies
- Only add dependencies when absolutely necessary
- Add to appropriate section in `pyproject.toml`:
- `dependencies` for core runtime dependencies
- `dev` for development tools
- `docs` for documentation building
- Document why the dependency is needed

## Git and Version Control

### Commit Messages
- Write clear, descriptive commit messages
- Use present tense ("Add feature" not "Added feature")
- Reference issue numbers when applicable

### Branch Workflow
- Create feature branches from the main branch
- Use descriptive branch names (e.g., `feature/add-new-calculator`, `bugfix/fix-reflection-calculation`)
- Keep changes focused and atomic

## Pull Request Guidelines

1. Include tests for new functionality
2. Update documentation if adding or changing features
3. Ensure all CI checks pass:
- Code consistency (Ruff)
- Code testing (pytest on all supported platforms/versions)
- Package building
4. Code should work on Python 3.11, 3.12 and all supported platforms
5. Write a clear PR description explaining the changes

## Project Structure

```
src/easyreflectometry/ # Main package source code
├── calculators/ # Calculator implementations (refnx, refl1d)
│ └── bornagain/ # BornAgain calculator (not yet functional)
├── model/ # Reflectometry models
├── sample/ # Sample structures and materials
├── special/ # Special calculations and parsing
├── summary/ # Summary generation
└── project.py # Main project interface

tests/ # Test suite
docs/ # Documentation source
```

## Best Practices

1. **Minimal Changes**: Make the smallest possible changes to accomplish the task
2. **Don't Break Existing Code**: Maintain backward compatibility unless explicitly required
3. **Test Before Committing**: Always run tests and linting before pushing
4. **Follow Existing Patterns**: Look at similar code in the repository for guidance
5. **Ask When Uncertain**: If unsure about an approach, ask for clarification

## CI/CD Pipeline

The project uses GitHub Actions for continuous integration:
- **Code Consistency**: Runs Ruff linting on all pushes and PRs
- **Code Testing**: Runs pytest across multiple Python versions and platforms
- **Package Testing**: Validates package building and installation
- **Coverage**: Uploads test coverage to Codecov

All CI checks must pass before merging PRs.

## Special Notes

- The project is part of the EasyScience ecosystem
- Built on top of established reflectometry libraries (refnx, refl1d)
- Focuses on providing a user-friendly interface for reflectometry analysis
- Maintains compatibility with multiple calculator backends
21 changes: 18 additions & 3 deletions .github/workflows/documentation-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ jobs:
# This workflow contains a single job called "build"
build_documentation:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
contents: read # to clone the repository
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source

steps:
- name: Checkout
uses: actions/checkout@master
Expand All @@ -34,16 +44,21 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11
python-version: 3.12
- name: Install Pandoc, repo and dependencies
run: |
sudo apt install pandoc
sudo apt install libcairo2-dev
pip install sphinx==8.1.3
pip install . '.[dev,docs]'

- name: Install Jupyter kernel
run: |
python -m ipykernel install --user --name=python3

- name: Build and Commit
uses: sphinx-notes/pages@master
uses: sphinx-notes/pages@v3
with:
install_requirements: false
sphinx_version: 8.1.3
documentation_path: docs/src
- name: Push changes
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ossar-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
OSSAR-Scan:
# OSSAR runs on windows-latest.
# ubuntu-latest and macos-latest support coming soon
runs-on: windows-latest
runs-on: windows-2022

steps:
# Checkout your code repository to scan
Expand Down
31 changes: 17 additions & 14 deletions .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
# - build the package
# - check the package
#
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: CI using pip

on: [push, pull_request]
Expand All @@ -30,8 +28,8 @@ jobs:
strategy:
max-parallel: 4
matrix:
python-version: ['3.11', '3.12']
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.11', '3.12', '3.13']
os: [ubuntu-latest, macos-latest, windows-2022]

runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, '[ci skip]')"
Expand All @@ -50,19 +48,24 @@ jobs:
- name: Install dependencies
run: pip install -e '.[dev]'

- name: Test with tox
- name: Test with pytest and coverage
run: |
pip install tox tox-gh-actions coverage
tox
pip install pytest pytest-cov
pytest --cov=src/easyreflectometry tests --cov-branch --cov-report=xml:coverage-unit.xml

- name: Upload coverage
uses: codecov/codecov-action@v3
- name: Upload coverage reports to Codecov
# only on ubuntu to avoid multiple uploads
if: runner.os == 'Linux'
uses: codecov/codecov-action@v5
with:
name: Pytest coverage
env_vars: OS,PYTHON,GITHUB_ACTIONS,GITHUB_ACTION,GITHUB_REF,GITHUB_REPOSITORY,GITHUB_HEAD_REF,GITHUB_RUN_ID,GITHUB_SHA,COVERAGE_FILE
env:
OS: ${{ matrix.os }}
PYTHON: ${{ matrix.python-version }}
name: unit-tests-job
flags: unittests
files: ./coverage-unit.xml
fail_ci_if_error: true
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
slug: EasyScience/EasyReflectometryLib


Package_Testing:

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.11','3.12']
python-version: ['3.11','3.12','3.13']
if: "!contains(github.event.head_commit.message, '[ci skip]')"

steps:
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.11 and 3.12, and for PyPy. Check
3. The pull request should work for Python, 3.11, 3.12, and 3.13, and for PyPy. Check
https://travis-ci.com/easyScience/EasyReflectometryLib/pull_requests
and make sure that the tests pass for all supported Python versions.

Expand Down
9 changes: 9 additions & 0 deletions docs/src/api/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ Sample is build from assemblies.

sample

Project
=======
Project provides a higher-level interface for managing models, experiments, and ORSO import.

.. toctree::
:maxdepth: 1

project

Assemblies
==========
Assemblies are collections of layers that are used to represent a specific physical setup.
Expand Down
4 changes: 4 additions & 0 deletions docs/src/api/project.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. automodule:: easyreflectometry.project
:members:
:undoc-members:
:show-inheritance:
18 changes: 6 additions & 12 deletions docs/src/tutorials/advancedfitting/multi_contrast.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@
")\n",
"d13d2o.constrain_area_per_molecule = True\n",
"d13d2o.conformal_roughness = True\n",
"d13d2o.constrain_solvent_roughness(d2o_layer)"
"d13d2o.constrain_solvent_roughness(d2o_layer.roughness)"
]
},
{
Expand Down Expand Up @@ -291,7 +291,7 @@
")\n",
"d70d2o.constrain_area_per_molecule = True\n",
"d70d2o.conformal_roughness = True\n",
"d70d2o.constrain_solvent_roughness(d2o_layer)"
"d70d2o.constrain_solvent_roughness(d2o_layer.roughness)"
]
},
{
Expand Down Expand Up @@ -331,7 +331,7 @@
")\n",
"d83acmw.constrain_area_per_molecule = True\n",
"d83acmw.conformal_roughness = True\n",
"d83acmw.constrain_solvent_roughness(acmw_layer)"
"d83acmw.constrain_solvent_roughness(acmw_layer.roughness)"
]
},
{
Expand All @@ -341,8 +341,8 @@
"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. "
"To ensure that the structure (thicknesss, area per molecule, etc.) is kept the same between the different contrasts we constrain 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, note that it is important that a chain of constraints is produced, one constraining the next. "
]
},
{
Expand All @@ -352,12 +352,6 @@
"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.constrain_multiple_contrast(d13d2o)\n",
"d83acmw.constrain_multiple_contrast(d70d2o)"
]
Expand Down Expand Up @@ -571,7 +565,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.9"
"version": "3.12.11"
}
},
"nbformat": 4,
Expand Down
Loading
Loading