Metadata-Version: 2.1
Name: pyccapt
Version: 0.2.0
Summary: A Python package for atom probe control and data calibration.
Home-page: https://github.com/mmonajem/pyccapt
Author: Mehrpad Monajem
Author-email: mehrpad.monajem@fau.de
License: GPL-3.0-or-later
Keywords: atom probe,apt,calibration,instrument control
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: deepdiff
Requires-Dist: h5py
Requires-Dist: matplotlib
Requires-Dist: numba
Requires-Dist: numpy
Requires-Dist: pandas
Requires-Dist: requests
Requires-Dist: scipy
Requires-Dist: tables
Requires-Dist: wget
Provides-Extra: calibration
Requires-Dist: adjustText; extra == "calibration"
Requires-Dist: ase; extra == "calibration"
Requires-Dist: faker; extra == "calibration"
Requires-Dist: fast-histogram; extra == "calibration"
Requires-Dist: imageio; extra == "calibration"
Requires-Dist: ipympl; extra == "calibration"
Requires-Dist: ipywidgets; extra == "calibration"
Requires-Dist: jupyterlab; extra == "calibration"
Requires-Dist: kaleido; extra == "calibration"
Requires-Dist: nglview; extra == "calibration"
Requires-Dist: plotly; extra == "calibration"
Requires-Dist: pybaselines; extra == "calibration"
Requires-Dist: pymatgen; extra == "calibration"
Requires-Dist: pyvista; extra == "calibration"
Requires-Dist: scikit-learn; extra == "calibration"
Requires-Dist: tqdm; extra == "calibration"
Requires-Dist: vispy; extra == "calibration"
Provides-Extra: control
Requires-Dist: mcculw; platform_system == "Windows" and extra == "control"
Requires-Dist: networkx; extra == "control"
Requires-Dist: nidaqmx; platform_system == "Windows" and extra == "control"
Requires-Dist: opencv-python; extra == "control"
Requires-Dist: PyQt6; extra == "control"
Requires-Dist: pyqtgraph; extra == "control"
Requires-Dist: pypylon; platform_system == "Windows" and extra == "control"
Requires-Dist: pyserial; extra == "control"
Requires-Dist: pyvisa; extra == "control"
Requires-Dist: simple-pid; extra == "control"
Provides-Extra: full
Requires-Dist: adjustText; extra == "full"
Requires-Dist: ase; extra == "full"
Requires-Dist: faker; extra == "full"
Requires-Dist: fast-histogram; extra == "full"
Requires-Dist: imageio; extra == "full"
Requires-Dist: ipympl; extra == "full"
Requires-Dist: ipywidgets; extra == "full"
Requires-Dist: jupyterlab; extra == "full"
Requires-Dist: kaleido; extra == "full"
Requires-Dist: nglview; extra == "full"
Requires-Dist: plotly; extra == "full"
Requires-Dist: pybaselines; extra == "full"
Requires-Dist: pymatgen; extra == "full"
Requires-Dist: pyvista; extra == "full"
Requires-Dist: scikit-learn; extra == "full"
Requires-Dist: tqdm; extra == "full"
Requires-Dist: vispy; extra == "full"
Requires-Dist: mcculw; platform_system == "Windows" and extra == "full"
Requires-Dist: networkx; extra == "full"
Requires-Dist: nidaqmx; platform_system == "Windows" and extra == "full"
Requires-Dist: opencv-python; extra == "full"
Requires-Dist: PyQt6; extra == "full"
Requires-Dist: pyqtgraph; extra == "full"
Requires-Dist: pypylon; platform_system == "Windows" and extra == "full"
Requires-Dist: pyserial; extra == "full"
Requires-Dist: pyvisa; extra == "full"
Requires-Dist: simple-pid; extra == "full"
Provides-Extra: all
Requires-Dist: adjustText; extra == "all"
Requires-Dist: ase; extra == "all"
Requires-Dist: faker; extra == "all"
Requires-Dist: fast-histogram; extra == "all"
Requires-Dist: imageio; extra == "all"
Requires-Dist: ipympl; extra == "all"
Requires-Dist: ipywidgets; extra == "all"
Requires-Dist: jupyterlab; extra == "all"
Requires-Dist: kaleido; extra == "all"
Requires-Dist: nglview; extra == "all"
Requires-Dist: plotly; extra == "all"
Requires-Dist: pybaselines; extra == "all"
Requires-Dist: pymatgen; extra == "all"
Requires-Dist: pyvista; extra == "all"
Requires-Dist: scikit-learn; extra == "all"
Requires-Dist: tqdm; extra == "all"
Requires-Dist: vispy; extra == "all"
Requires-Dist: mcculw; platform_system == "Windows" and extra == "all"
Requires-Dist: networkx; extra == "all"
Requires-Dist: nidaqmx; platform_system == "Windows" and extra == "all"
Requires-Dist: opencv-python; extra == "all"
Requires-Dist: PyQt6; extra == "all"
Requires-Dist: pyqtgraph; extra == "all"
Requires-Dist: pypylon; platform_system == "Windows" and extra == "all"
Requires-Dist: pyserial; extra == "all"
Requires-Dist: pyvisa; extra == "all"
Requires-Dist: simple-pid; extra == "all"
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-mock; extra == "dev"
Requires-Dist: twine; extra == "dev"

# PyCCAPT

[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.10210507.svg)](https://doi.org/10.5281/zenodo.10210507)
[![Documentation Status](https://readthedocs.org/projects/pyccapt/badge/?version=latest)](https://pyccapt.readthedocs.io/en/latest/?badge=latest)

PyCCAPT is a modular, FAIR-oriented Python package for atom probe tomography (APT) instrument control, data calibration, and reconstruction workflows.

It provides:

- experiment control and acquisition for APT hardware
- calibration workflows such as `t0` and flight-path estimation, ROI selection, voltage and bowl correction, and ranging
- reconstruction and visualization tooling
- interoperable data export for HDF5-based workflows and common APT exchange formats

<img align="right" src="https://github.com/mmonajem/pyccapt/blob/main/pyccapt/files/logo2.png?raw=True" alt="PyCCAPT logo" width="220" height="220">

## Project Scope

PyCCAPT was developed and validated on the OXCART atom probe platform and is designed to be adaptable to other APT systems through device-specific modules. Current integrations include detector backends such as Surface Concept and RoentDek, together with modular support for common laboratory hardware.

![OXCART atom probe](pyccapt/files/readme_images/oxcart.jpg)

## Installation

PyCCAPT requires Python `>=3.9`.

### Recommended Quick Start (Conda)

For most users, this is the best way to install PyCCAPT:

```bash
conda create -n pyccapt python=3.11
conda activate pyccapt
python -m pip install --upgrade pip
pip install "pyccapt[full]"
```

If you want to work from this repository instead of PyPI:

```bash
git clone https://github.com/mmonajem/pyccapt.git
cd pyccapt
conda activate pyccapt
pip install -e ".[full]"
```

Predefined conda environment files are also included in the repo:

```bash
conda env create -f environment.yml
conda env create -f environment.full.yml
```

### Other Installation Options

1. Install from PyPI:

```bash
pip install pyccapt
```

Optional dependency groups:

```bash
pip install "pyccapt[calibration]"
pip install "pyccapt[control]"
pip install "pyccapt[full]"
```

Module-specific editable installs:

```bash
pip install -e ".[control]"
pip install -e ".[calibration]"
```

## Running PyCCAPT

Start the control application:

```bash
pyccapt
```

Fallback entrypoint:

```bash
python -m pyccapt.control
```

Run tests:

```bash
pytest -q --run-calibration
pytest -q --run-control
pytest -q
```

Run calibration tutorials:

```bash
jupyter lab
```

Then open notebooks under `pyccapt/calibration/tutorials`.

## Configuration

Control runtime configuration is stored in `pyccapt/config.toml`.

Control GUI electrode labels are stored in `pyccapt/control/electrode.toml`:

```toml
[electrodes]
names = [
  "NiC1", # Nickel electrode
  "CuC1", # Copper electrode
]
```

For device toggles, prefer `enabled` and `disabled`. Legacy `on` and `off` values still work.

## Control Highlights

![Main GUI](pyccapt/files/readme_images/main_gui.png)

The control stack includes the main acquisition GUI together with dedicated windows for gates, pumps and vacuum, cameras, laser, stage control, visualization, and baking. Startup reports unavailable configured ports clearly, GUI error boxes wrap long messages, and `Access Override` now asks for confirmation before allowing a run to proceed with missing enabled devices.

Vacuum logs are written under `pyccapt/files/logs/vacuum`, and baking logs are written under `pyccapt/files/logs/baking/<timestamp>`.

## Calibration Highlights

![Calibration visualization](pyccapt/files/readme_images/visualization_gif.gif)

PyCCAPT calibration workflows cover detector hit maps, FDM views, mass-spectrum calibration, bowl and voltage correction, reconstruction, and downstream visualization.

![Mass spectrum](pyccapt/files/readme_images/hist.png)

<p align="center">
  <img width="36%" src="pyccapt/files/readme_images/fdm.png" alt="FDM">
  <img width="32%" src="pyccapt/files/readme_images/detector.gif" alt="Detector GIF">
</p>

<p align="center">
  <img width="30%" src="pyccapt/files/readme_images/vol_corr.png" alt="Voltage correction">
  <img width="30%" src="pyccapt/files/readme_images/bowl_corr.png" alt="Bowl correction">
</p>

<p align="center">
  <img width="30%" src="pyccapt/files/readme_images/tof_V_corr.png" alt="TOF versus voltage">
  <img width="30%" src="pyccapt/files/readme_images/tof_bowl_corr_y_det.png" alt="TOF bowl correction">
</p>

![Ranged mass spectrum](pyccapt/files/readme_images/mc.png)

Processed calibration datasets can be exported as `HDF5`, `EPOS`, `POS`, and `ATO`.

The visualization helpers also include optional two-segment precipitate clustering with a Min-Max algorithm so a selected precipitate population can be segmented directly in the 3D and iso-surface views.

For control part of the package you can follow the steps
on [documentation](https://pyccapt.readthedocs.io/).

<p align="center">
  <img width="40%" src="pyccapt/files/readme_images/roto.gif" alt="3D rotation">
  <img width="40%" src="pyccapt/files/readme_images/iso.gif" alt="3D isosurface">
</p>

## Documentation

- Full documentation: [Read the Docs](https://pyccapt.readthedocs.io/)
- Control guide: [docs/configuration](https://pyccapt.readthedocs.io/en/latest/configuration.html)
- Calibration tutorials: [docs/tutorials](https://pyccapt.readthedocs.io/en/latest/tutorials.html)

Google Colab notebooks:

- [Data processing](https://colab.research.google.com/github/mmonajem/pyccapt/blob/main/pyccapt/calibration/tutorials/colab/data_processing.ipynb)
- [Visualization](https://colab.research.google.com/github/mmonajem/pyccapt/blob/main/pyccapt/calibration/tutorials/colab/visualization.ipynb)
- [`t0` and flight path estimation](https://colab.research.google.com/github/mmonajem/pyccapt/blob/main/pyccapt/calibration/tutorials/colab/L_and_t0_determination.ipynb)

## Data Structures

- Control data model: [pyccapt/control/DATA_STRUCTURE.md](pyccapt/control/DATA_STRUCTURE.md)
- Calibration data model: [pyccapt/calibration/DATA_STRUCTURE.md](pyccapt/calibration/DATA_STRUCTURE.md)

## Tutorial Dataset

Calibration tutorial data (pure aluminum), including raw and processed outputs, is available on Zenodo:

[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.14673955.svg)](https://doi.org/10.5281/zenodo.14673955)

## Citation

If you use PyCCAPT in your work, please cite:

```bibtex
@article{monajem2025pyccapt,
  title={PyCCAPT: A Python Package for Open-Source Atom Probe Instrument Control and Data Calibration},
  author={Monajem, Mehrpad and Ott, Benedict and Heimerl, Jonas and Meier, Stefan and Hommelhoff, Peter and Felfer, Peter},
  journal={Microscopy Research and Technique},
  volume={88},
  number={12},
  pages={3199--3210},
  year={2025},
  publisher={Wiley Online Library}
}
```

Citation metadata is also available in [CITATION.cff](CITATION.cff).

## Contributing

Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for development workflow and pull-request guidance.

## Support

- Issues and bug reports: [GitHub Issues](https://github.com/mmonajem/pyccapt/issues)
- Contact: Mehrpad Monajem (`mehrpad.monajem@fau.de`)

## License

PyCCAPT is licensed under the GNU General Public License v3.0. See [LICENSE](LICENSE).
