Metadata-Version: 2.4
Name: inspy-conv
Version: 0.3.3
Summary: Toolkit for inelastic neutron scattering resolution calculation and resolution convolution data fitting
Author-email: Guochu Deng <gc.deng.ansto@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/gcdengansto/inspy
Project-URL: Repository, https://github.com/gcdengansto/inspy
Keywords: neutron,scattering,resolution,spectrometer,triple-axis,time-of-flight
Classifier: Programming Language :: Python :: 3
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.20
Requires-Dist: matplotlib>=3.5
Requires-Dist: scipy>=1.7
Requires-Dist: pandas>=1.3
Requires-Dist: lmfit>=1.0
Requires-Dist: h5py>=3.0
Requires-Dist: plotly>=5.0
Requires-Dist: QtPy
Requires-Dist: PySide6
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Dynamic: license-file

# inspy-conv

**inspy-conv** (import name: `inspy`) is a Python toolkit for inelastic neutron scattering data analysis. It provides instrument resolution calculation (Cooper-Nathans / Popovici methods), resolution-convolution fitting, crystal lattice and space group tools, and interactive GUIs.

> Install name: `inspy-conv`  
> Import name: `inspy`

---

## Installation

```bash
pip install inspy-conv
```

For editable development:

```bash
git clone https://github.com/gcdengansto/inspy-conv
cd inspy-conv
pip install -e .
```

Dependencies: `numpy`, `scipy`, `matplotlib`, `pandas`, `lmfit`, `h5py`, `plotly`, `QtPy`, `PySide6`.

---

## Quick Start

```python
import inspy

# Create a neutron beam with energy 14.7 meV
en = inspy.Energy(energy=14.7)
print(en.wavelength)    # Angstrom
print(en.wavevector)    # 1/Angstrom

# Define a crystal sample
sample = inspy.Sample(a=5.0, b=5.0, c=5.0,
                      alpha=90, beta=90, gamma=90,
                      u=[1, 0, 0], v=[0, 1, 0],
                      mosaic=30, vmosaic=30)

# Set up a triple-axis spectrometer (Ef = 14.7 meV)
tas = inspy.TripleAxisSpectr(efixed=14.7, method=1)  # 1 = Popovici
tas.sample = sample

# Calculate the resolution matrix at a given (H, K, L, E)
R0, RM = tas.CalcResMatHKL([1, 0, 0, 0])
```

---

## Package Structure

```
inspy/
├── constants.py          # Physical constants + database loaders
├── energy.py             # Energy / wavelength / wavevector conversion
├── crystal/              # Crystal, lattice, sample, symmetry tools
│   ├── lattice.py        # Lattice with metric tensors, d-spacing
│   ├── sample.py         # Sample with UB orientation matrix
│   ├── atom.py           # Atom / MagneticAtom with scattering lengths
│   ├── symmetry.py       # SpaceGroup with symmetry operations
│   ├── structure_factors.py  # Nuclear / magnetic structure factors
│   └── material.py       # Material = Sample + structure factors
├── instrument/           # Instrument models
│   ├── mono.py           # Monochromator component
│   ├── ana.py            # Analyzer component
│   ├── components.py     # Chopper, Detector, Guide (ToF)
│   ├── tools.py          # Resolution projection utilities
│   └── tas_spectr.py     # TripleAxisSpectr — core resolution engine
├── insfit/               # Resolution-convolution fitting
│   ├── fitconv.py         # FitConv — Levenberg-Marquardt fitting
│   └── uffitconv.py       # UltraFastFitConv — optimised fitting
├── gui/                  # Qt-based graphical interfaces
│   ├── main_gui.py       # Resolution calculator GUI
│   ├── gui_convfit_qscan_uf.py  # Q-scan convolution fit GUI
│   ├── gui_convfit_escan_uf.py  # E-scan convolution fit GUI
│   └── ui/               # Qt Designer .ui files
└── database/             # JSON data files
    ├── magnetic_form_factors.json
    ├── periodic_table.json
    ├── scattering_lengths.json
    └── symmetry.json
```

---

## Modules

### `inspy.Energy`

Convert between neutron energy (meV), wavelength (Angstrom), wavevector (1/Angstrom), velocity (m/s), temperature (K), and frequency (THz).

```python
e = inspy.Energy(wavelength=2.5)
print(e.energy)        # 13.06 meV
print(e.wavevector)    # 2.513 1/A
```

### `inspy.crystal`

#### `Lattice`

Crystal lattice defined by six parameters (a, b, c, alpha, beta, gamma). Provides metric tensors (G, Gstar), reciprocal lattice vectors, d-spacing, and volume.

```python
lat = inspy.Lattice(5.0, 5.0, 5.0, 90, 90, 90)
print(lat.volume)          # 125.0
print(lat.get_d_spacing([1, 0, 0]))  # 5.0
```

#### `Sample`

Extends `Lattice` with orientation vectors (u, v), mosaic spread, and sample shape. Exposes the UB orientation matrix.

```python
s = inspy.Sample(5.0, 5.0, 5.0, 90, 90, 90,
                 u=[1, 0, 0], v=[0, 1, 0], mosaic=30)
print(s.UBmatrix)
```

#### `Atom` / `MagneticAtom`

Defines atoms with position, occupancy, thermal parameters (Uiso, Uaniso). Automatically looks up coherent scattering length (b), cross-sections, and mass from internal databases.

```python
from inspy.crystal import Atom
atom = Atom('Mn', pos=[0, 0, 0], occupancy=1.0, Uiso=0.005)
print(atom.b)   # coherent scattering length
```

#### `Material`

Combines sample lattice, composition, and structure factor calculations (nuclear and magnetic). Accepts a dictionary-based configuration.

```python
crystal_dict = {
    'name': 'MnO',
    'lattice': [4.445, 4.445, 4.445, 90, 90, 90],
    'space_group': 'Fm-3m',
    'composition': [
        {'ion': 'Mn', 'pos': [0, 0, 0], 'occupancy': 1.0},
        {'ion': 'O',  'pos': [0.5, 0.5, 0.5], 'occupancy': 1.0},
    ],
}
mat = inspy.Material(crystal_dict)
```

#### `SpaceGroup`

Represents a crystallographic space group from the 230 possibilities. Generates symmetry-equivalent positions.

```python
sg = inspy.SpaceGroup('Fm-3m')
equiv_pos = sg.symmetrize_position([0, 0, 0])
```

#### Structure Factors

- `NuclearStructureFactor.calc_nuc_str_fac(hkl)` — Nuclear structure factor with Debye-Waller factor.
- `MagneticFormFactor(ion)` — Magnetic form factor coefficients from database.
- `MagneticStructureFactor` — Magnetic structure factor (partially implemented).

### `inspy.instrument`

#### `TripleAxisSpectr`

The core resolution engine. Implements both the **Cooper-Nathans** (method=0) and **Popovici** (method=1) resolution formalisms for triple-axis spectrometers.

**Key configuration:**
- `efixed` — Fixed energy (meV)
- `method` — 0 = Cooper-Nathans, 1 = Popovici (default)
- `infin` — -1 for fixed-kf, +1 for fixed-ki
- `hcol` / `vcol` — Horizontal / vertical collimation (arcmin)
- `arms` — Distances [L0, L1, L2, L3, L1mon]
- `mono` / `ana` — Monochromator and analyzer (`Mono` / `Ana` objects)
- `sample` — `Sample` object

**Key methods:**

| Method | Description |
|--------|-------------|
| `CalcResMatHKL([H, K, L, E])` | Resolution matrix in HKL-E coordinates |
| `ResConv(sqw, pref, ...)` | Full 4D resolution convolution of a cross-section model |
| `get_angles_and_Q([H, K, L, E])` | Spectrometer angles from HKL-E |
| `get_hkl_and_Q(M2, S1, S2, A2)` | HKL-E from motor angles |
| `ResolutionPlot([H, K, L, E])` | 4-panel matplotlib resolution plot |
| `ResolutionPlotProj(ax, qslice, ...)` | Single-panel projection |
| `ResolutionPlot3D(...)` | 3D resolution ellipsoid with dispersion |

```python
tas = inspy.TripleAxisSpectr(efixed=14.7)
tas.sample = sample
tas.hcol = [40, 40, 40, 120]   # collimation in arcmin
tas.arms = [200, 100, 100, 200]  # distances in cm

# Calculate resolution at (1, 0, 0, 0)
R0, RM = tas.CalcResMatHKL([1, 0, 0, 0])
```

#### `Mono` / `Ana`

Monochromator and analyzer crystals with tau (d-spacing), mosaic, dimensions, and focusing parameters. Supports standard crystals (PG, Si, Ge, Cu, Be, etc.).

```python
from inspy.instrument import Mono
mono = Mono(tau=1.873, mosaic=30, width=10, height=10)
```

#### `Chopper` / `Detector` / `Guide`

Components for Time-of-Flight spectrometers (partially implemented).

### `inspy.instrument.tools`

Utilities for resolution analysis:

- `get_bragg_widths(RM)` — Bragg FWHM from resolution matrix
- `get_phonon_width(r0, M, C)` — Phonon FWHM projected from resolution
- `project_into_plane(...)` — Out-of-plane Gaussian integration
- `calc_proj_hwhm(MP)` — 2D projection HWHM and rotation
- `_voigt(x, a)` — Voigt function (Faddeeva approximation)

### `inspy.insfit`

Convolution-based fitting: fit parameters of an S(Q,w) model to measured data by numerically convolving with the instrument resolution function.

#### `FitConv`

Standard fitter using `scipy.optimize.least_squares` (Levenberg-Marquardt).

```python
from inspy import FitConv

fitter = FitConv(tas, sqw_func, prefactor, hkle,
                 Iobs, dIobs, params, param_fixed_mask)
result = fitter.fitwithconv(...)
```

#### `UltraFastFitConv`

Optimised fitter with LRU caching, pre-computed data, and adaptive Jacobian step sizes for maximum performance.

```python
from inspy import UltraFastFitConv

uf_fitter = UltraFastFitConv(tas, sqw_func, prefactor,
                              hkle, Iobs, dIobs, cache_size=256)
result = uf_fitter.fit_ultrafast(param_initial, param_fixed_mask)
```

### `inspy.gui`

Qt-based graphical interfaces:

- **Resolution Calculator** (`main_gui.py`) — Interactive 3-panel resolution plot (QxQy, QxE, QyE) with adjustable instrument parameters.
- **Q-scan Convolution Fit** (`gui_convfit_qscan_uf.py`) — GUI for fitting constant-Q scans with resolution convolution.
- **E-scan Convolution Fit** (`gui_convfit_escan_uf.py`) — GUI for fitting constant-E scans with resolution convolution.

Launch via:

```python
import inspy
inspy.main()   # Resolution calculator GUI
```

Or from individual GUI modules (requires Qt):
```python
from inspy.gui import main_gui
main_gui.main()
```

## Database

The package includes four JSON databases loaded automatically:

| File | Contents | Loader |
|------|----------|--------|
| `magnetic_form_factors.json` | j0, j2, j4 coefficients for magnetic ions | `magnetic_ion_j()` |
| `periodic_table.json` | Atomic mass, number, density | `periodic_table()` |
| `scattering_lengths.json` | Coherent/incoherent scattering lengths | `scattering_lengths()` |
| `symmetry.json` | 230 space group definitions | `symmetry()` |

---

## Scope

- Neutron scattering data analysis
- TAS resolution calculation (Cooper-Nathans, Popovici)
- Resolution-convolution fitting of inelastic neutron data
- Crystal lattice, symmetry, and structure factor calculations
- Interactive GUIs for resolution and fitting workflows

## Author

Guochu Deng — gc.deng.ansto@gmail.com

## License

MIT
