Metadata-Version: 2.4
Name: midas-fit-grain
Version: 0.1.0
Summary: PyTorch single/multi-grain refiner (drop-in replacement for FitPosOrStrainsOMP / FitPosOrStrainsGPU)
Author-email: Hemant Sharma <hsharma@anl.gov>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/marinerhemant/MIDAS
Project-URL: Documentation, https://github.com/marinerhemant/MIDAS/tree/master/packages/midas_fit_grain
Project-URL: Issues, https://github.com/marinerhemant/MIDAS/issues
Keywords: MIDAS,HEDM,grain-refinement,PyTorch,far-field,diffraction,crystallography,polycrystal
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.22
Requires-Dist: torch>=2.0
Requires-Dist: scipy>=1.10
Requires-Dist: midas-diffract>=0.1.0
Requires-Dist: midas-params>=0.3.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"

# midas-fit-grain

PyTorch single- and multi-grain refiner. Drop-in replacement for the C executables
`FitPosOrStrainsOMP` / `FitPosOrStrainsGPU` in MIDAS FF-HEDM.

Status: pre-alpha (under development). The C path remains the ff_MIDAS default;
this package is opt-in via `--refine-backend python`.

## What it does

For each grain in `SpotsToIndex.csv`:

- Reads matched spots from `ExtraInfo.bin` and the seed orientation from
  `BestPos_*.csv` (the indexer's per-spot output).
- Refines 12 parameters: position (3) + Bunge Euler (3) + lattice (6).
- Writes byte-identical `OrientPosFit.bin` / `FitBest.bin` / `Key.bin`
  consumed by the existing `ff_MIDAS.py` merge stage.

## Solvers

`--solver {lbfgs,adam,lm,nelder_mead}` — default `lbfgs`.

## Loss functions

`--loss {pixel,angular,internal_angle}` — default `pixel`.

| Loss | Residual | Equivalent C function |
|------|----------|------------------------|
| `pixel` | `(y, z)` pixel positions on detector | `FitErrorsPosT` (`FitPosOrStrainsOMP`) |
| `angular` | `(2θ, η, ω)` in radians | `optimize_single_grain` (midas-diffract) |
| `internal_angle` | angle between `ĝ_pred` and `ĝ_obs` (rad) | `CalcInternalAngle` (`FitOrientationOMP`) |

## Fit modes

`--mode {iterative,all_at_once}` — default `iterative`.

- `iterative`: position → re-match → orientation → re-match → strain → re-match
  → joint polish (matches `FitPosOrStrainsOMP` default behavior).
- `all_at_once`: 12 params jointly, association computed once at entry, no
  mid-fit re-match.

## Backends

`MIDAS_FIT_GRAIN_DEVICE` and `MIDAS_FIT_GRAIN_DTYPE` follow the same precedence
contract as `midas-index` (`cuda > mps > cpu` auto-detect; `f64` on CPU,
`f32` on accelerators). Per-grain refinement is batched into a single forward
call across the block, so scaling depends on `B × S` (grains × spots/grain),
not per-grain Python overhead.

## CLI

```
midas-fit-grain paramstest.txt <blockNr> <numBlocks> <numLines> <numProcs> \
                [--solver lbfgs] [--loss pixel] [--mode iterative]
```

Argv shape mirrors the C binary so the ff_MIDAS subprocess line is one-for-one.
