AtomKit is a modern Python framework for atomic structure calculations and spectroscopic data analysis. It acts as a universal translator and a unified analysis platform, allowing you to define your physics calculations once and run them across multiple atomic physics codes.
AtomKit's design philosophy is "Physics First, Code Second." It abstracts the underlying code implementation, letting you focus on the physics.
- Define Calculations Physically: Structure your problem using high-level physical terms (e.g., coupling schemes, transition types, configurations) instead of code-specific syntax.
- Agnostic Workflow: Automatically translate your physics definitions into the specific input formats for various supported codes (e.g., AUTOSTRUCTURE, FAC, GRASP).
- Interchangeable Codes: Seamlessly switch between different atomic codes without needing to rewrite your entire workflow.
- Agnostic Parsing: Ingest and parse the outputs from different codes into a single, consistent, and easy-to-use data structure.
- Comparative Analysis: Directly compare results (e.g., energy levels, transition probabilities) from multiple codes in one environment.
- Data Visualization: Generate a wide range of analysis plots and publication-ready tables directly from the unified data objects.
- Modular Design: Built with a modular structure, making it straightforward to extend with new atomic codes, analysis routines, or export formats.
- Easy Integration: Designed for interoperability, allowing components to be easily imported and used within other scientific programs and research workflows.
- Standardized Output: Export your processed and analyzed data into common formats.
- Cross-Platform Integration: Create outputs ready for use in other scientific platforms, including radiative transfer codes, plasma modeling suites, and spectroscopic databases.
Define your atomic physics calculation once in physical terms:
from atomkit.core import AtomicCalculation
from atomkit import Configuration
# Define calculation in physics terms - no code-specific syntax!
calc = AtomicCalculation(
element="Fe",
charge=16, # Fe XVII
calculation_type="radiative", # What physics to compute
coupling="IC", # Intermediate coupling
relativistic="Breit", # Include Breit interaction
radiation_types=["E1", "M1"], # Electric & magnetic dipole
configurations=[
Configuration.from_string("1s2 2s2 2p6"),
Configuration.from_string("1s2 2s2 2p5 3s1"),
],
code="autostructure" # ← Only code-specific choice!
)
# Generate input file
input_file = calc.write_input()
# Switch codes by changing ONE parameter:
calc.code = "fac"
fac_input = calc.write_input() # Same physics, different code!Supported Codes:
- ✅ AUTOSTRUCTURE (Badnell 2011) - all namelists and options
- ✅ FAC (Flexible Atomic Code, Gu 2008) - via SFAC wrapper
- 🚧 GRASP (coming soon)
- 🚧 MCDF (planned)
Parse and analyze outputs from any code consistently:
from atomkit.readers import read_autostructure_levels, read_fac_levels
# Read data from different codes
as_levels = read_autostructure_levels("output.j")
fac_levels = read_fac_levels("output.lev.asc")
# Both return pandas DataFrames with standardized columns:
# - energy, configuration, term, J, parity, g-factor, ...
# Compare results directly!Generate tables and plots ready for papers, databases, and radiative transfer codes:
from atomkit.physics.plotting import plot_grotrian_diagram, plot_cross_section
from atomkit.export import to_chianti_format, to_adas_format, to_latex_table
# Create publication-quality visualizations
plot_grotrian_diagram(levels_df, transitions_df, save="grotrian.pdf")
plot_cross_section(energy, cross_section, save="cross_section.png")
# Export for other platforms
to_chianti_format(levels, transitions, "fe_17.elvlc") # For CHIANTI database
to_adas_format(transitions, "fe_17.dat") # For ADAS
to_latex_table(levels, "levels.tex") # For publicationsPowerful configuration management that speaks physics:
- Configuration Generation: Ground states, excitations, ionization states
- Electronic Structure: Holes, core-valence splitting, configuration interaction
- Quantum Numbers: Full support for LS, IC, jj, LSJ coupling schemes
- Validation: Automatic checks for occupancy, quantum number rules, parity
- Notation: Parse and convert between different spectroscopic notations
Everything you need for atomic physics analysis:
- Energy Conversion: eV ↔ Rydberg ↔ cm⁻¹ ↔ wavelength ↔ temperature
- Cross Sections: Photoionization, electron impact, autoionization rates
- Collision Strengths: Resonance calculations, effective collision strengths
- Atomic Potentials: Thomas-Fermi, Hartree-Fock, screening potentials
- Statistical Equilibrium: Population analysis, ionization balance
Define physics in AUTOSTRUCTURE syntax
↓
Run AUTOSTRUCTURE
↓
Parse AUTOSTRUCTURE output (custom script)
↓
Want to compare with FAC? → Start over with completely different syntax!
Define physics ONCE in AtomKit (code-agnostic)
↓
├→ Generate AUTOSTRUCTURE input → Run → Parse results ──┐
├→ Generate FAC input → Run → Parse results ────────────┤
└→ Generate GRASP input → Run → Parse results ──────────┤
↓
Unified DataFrame for analysis
↓
├─ Compare codes ─ Publication plots ─┤
├─ Export to CHIANTI/ADAS ────────────┤
└─ Generate LaTeX tables ─────────────┘
Key Benefits:
- 🎯 Reproducibility: Same physics definition across all codes
- ⚡ Efficiency: Switch codes by changing one parameter
- 📊 Consistency: All outputs in same format for direct comparison
- 🔬 Validation: Easily benchmark codes against each other
- 🚀 Productivity: Focus on physics, not code syntax
AtomKit requires Python 3.10 or higher. We recommend using conda to create a dedicated environment:
# Clone the repository
git clone https://github.com/rfsilva13/atomkit.git
cd atomkit
# Create and activate the atomkit environment
conda create -n atomkit python=3.13
conda activate atomkit
# Install dependencies
pip install -e .
## Using atomkit from external scripts
You can keep this repository as a clean, minimal package and write your own analysis scripts in a different folder (even one level up).
1. Activate your environment and install atomkit in editable mode:
```fish
micromamba activate atomkit
python -m pip install -e /home/rfsilva/Programs/atomkit- In your own folder, import and use the package:
from atomkit.analysis import load_fac_data, process_fac_diagram_intensities
# ... your analysis code ...Outputs and ad-hoc analysis files should live outside this repo. If you place scripts inside this repo, prefer tools/ and work/ which are git-ignored.
pip install -e ".[all]" # Includes plotting and enhanced logging
### Using Poetry
If you prefer using Poetry for dependency management:
```bash
# Clone the repository
git clone https://github.com/rfsilva13/atomkit.git
cd atomkit
# Install with Poetry (automatically creates virtual environment)
poetry install
# Install with all optional features
poetry install --extras "all"
# Activate the Poetry shell
poetry shell
# Create environment from environment.yml
conda env create -f environment.yml
conda activate atomkit- Calculate atomic data for stellar atmosphere models (TLUSTY, PHOENIX, MARCS)
- Generate opacity tables for radiative transfer
- Compare codes to quantify systematic uncertainties
- Export line lists for spectral synthesis
- Electron collision cross sections for plasma diagnostics
- Ionization balance and level populations
- Spectral line emission for tokamak modeling
- ADAS-format output for plasma codes
- Generate data for CHIANTI, NIST, VAMDC
- Validate and compare database entries
- Create custom atomic datasets
- Quality control and consistency checks
- Identify spectral lines from experimental data
- Predict transition wavelengths and intensities
- Analyze fine structure and isotope shifts
- Generate synthetic spectra for comparison
- Explore atomic structure interactively
- Compare theoretical predictions with experiment
- Benchmark different computational methods
- Teach atomic physics concepts with real calculations
from atomkit.core import AtomicCalculation
from atomkit import Configuration
# Physics problem: Fe XVII radiative transitions
calc = AtomicCalculation(
element="Fe",
charge=16,
calculation_type="radiative",
coupling="IC", # Intermediate coupling
relativistic="Breit", # Breit-Pauli Hamiltonian
radiation_types=["E1"], # Electric dipole transitions
configurations=[
Configuration.from_string("1s2 2s2 2p6"), # Ground: 2p⁶
Configuration.from_string("1s2 2s2 2p5 3s1"), # Excited: 2p⁵3s
],
code="autostructure"
)
# Generate input - physics is translated automatically!
input_file = calc.write_input()from atomkit.readers import read_levels, read_transitions
from atomkit.physics.plotting import plot_energy_levels
# Read output (works for AUTOSTRUCTURE, FAC, etc.)
levels = read_levels("output.lev")
transitions = read_transitions("output.tr")
# Analyze
print(f"Found {len(levels)} levels")
print(f"Found {len(transitions)} transitions")
# Find strongest lines
strongest = transitions.nlargest(10, 'gf')
print(strongest[['wavelength_nm', 'gf', 'transition']])
# Visualize
plot_energy_levels(levels, save="energy_diagram.pdf")from atomkit.export import (
to_chianti_format, # For CHIANTI database
to_adas_format, # For plasma modeling
to_latex_table, # For publications
to_radtrans_format # For radiative transfer
)
# Export for CHIANTI atomic database
to_chianti_format(levels, transitions, "fe_17.elvlc", "fe_17.wgfa")
# Generate LaTeX table for paper
to_latex_table(
strongest,
"table1.tex",
caption="Strongest transitions in Fe XVII",
columns=['wavelength_nm', 'gf', 'A_value']
)from atomkit import Configuration
from atomkit.converters import configurations_to_autostructure
# Step 1: Generate configurations (PHYSICS - code-agnostic)
ground = Configuration.from_string('1s2 2s2 2p6 3s2 3p6 3d6 4s2')
excited = ground.generate_excitations(
target_shells=['4p', '5s', '4d'], # Where to excite TO
excitation_level=1, # Single excitations
source_shells=['3d', '4s'] # Excite FROM valence
)
# Step 1.5: Filter/modify (physics is done, now manipulate!)
filtered = [c for c in excited if '5s' in c.to_string()]
# Step 2: Format for AUTOSTRUCTURE (I/O - only now code-specific)
result = configurations_to_autostructure(
[ground] + filtered,
last_core_orbital='3p',
output_file='fe_configs.txt'
)
print(f"Generated {result['mxconf']} configurations")
# Same configs could be formatted for FAC, GRASP, or any other code!from atomkit.readers import read_fac_levels, read_fac_transitions
# Read energy levels
levels_df = read_fac_levels("my_data.lev.asc", energy_unit="eV")
print(levels_df.head())
# Read transitions
transitions_df = read_fac_transitions("my_data.tr.asc", wavelength_unit="nm")
print(transitions_df[["wavelength_nm", "gf", "config_initial", "config_final"]])from atomkit import get_element_info, parse_ion_notation
# Get element information
info = get_element_info('Fe')
print(f"Iron: Z={info['Z']}, name={info['name']}")
info = get_element_info(26) # Also accepts atomic number
print(f"Element {info['symbol']}")
# Parse spectroscopic ion notation
element, charge, electrons = parse_ion_notation('Fe I') # Neutral
element, charge, electrons = parse_ion_notation('Fe II') # Singly ionized
print(f"Fe II: charge=+{charge}, {electrons} electrons")from atomkit.physics import energy_converter
# Convert between units
energy_ry = energy_converter.ev_to_rydberg(13.6)
energy_cm = energy_converter.convert(100, from_unit="eV", to_unit="cm-1")
temp_k = energy_converter.ev_to_kelvin(1.0)
print(f"13.6 eV = {energy_ry:.2f} Ry")
print(f"100 eV = {energy_cm:.2e} cm⁻¹")
print(f"1 eV = {temp_k:.2e} K")from atomkit.physics.plotting import quick_plot_cross_section
import numpy as np
# Generate sample data
energies = np.linspace(10, 200, 100)
cross_sections = 1e-18 / energies # Simple 1/E behavior
# Create publication-quality plot
fig, ax = quick_plot_cross_section(
energies,
cross_sections,
title="Electron Impact Cross Section",
save_path="cross_section.png"
)Atom kit provides a Python wrapper for generating FAC input files without requiring pfac compilation:
from atomkit.fac import SFACWriter
from atomkit import Configuration
# Option 1: Generate FAC input from atomkit configurations
ground = Configuration.from_element("Fe", 23) # Fe XXIV
excited = ground.generate_excitations(["2s", "2p", "3s"], 1)
with SFACWriter("fe_calculation.sf") as fac:
fac.SetAtom("Fe")
fac.SetBreit(-1) # Enable Breit interaction
fac.SetSE(-1) # Enable QED corrections
# Add configurations from atomkit
fac.config_from_atomkit(ground, "ground")
for i, state in enumerate(excited):
fac.config_from_atomkit(state, f"excited{i}")
# Perform calculation
fac.OptimizeRadial(["ground"])
fac.Structure("output.lev.b", ["ground"] + [f"excited{i}" for i in range(len(excited))])
fac.PrintTable("output.lev.b", "output.lev", 1)
# Execute the generated file
# $ sfac fe_calculation.sf
# $ mpirun -n 24 sfac fe_calculation.sf # parallel
# Option 2: Direct SFAC syntax (like FAC manual examples)
with SFACWriter("ne_like_fe.sf") as fac:
fac.SetAtom("Fe")
fac.Closed("1s")
fac.Config("2*8", group="n2") # n=2 complex
fac.Config("2*7 3*1", group="n3") # n=2 -> n=3 excitation
fac.ConfigEnergy(0)
fac.OptimizeRadial(["n2"])
fac.ConfigEnergy(1)
fac.Structure("ne.lev.b", ["n2", "n3"])
fac.TransitionTable("ne.tr.b", ["n2"], ["n3"])The FAC wrapper:
- ✅ No pfac dependency - pure Python
- ✅ Generates readable .sf files
- ✅ Full integration with atomkit configurations
- ✅ All major FAC functions supported
- ✅ MPI parallel calculation support
See examples/fac_wrapper_demo.py for comprehensive examples and src/atomkit/fac/README.md for complete documentation.
For detailed API documentation, see:
- API Reference - Complete function and class documentation
- FAC Integration Guide - FAC wrapper documentation
- Configuration Guide - Detailed guide for configuration manipulation
- Examples Directory - Working examples demonstrating key features
# Create conda environment
conda create -n atomkit python=3.13
conda activate atomkit
# Install in development mode with all dependencies
pip install -e ".[all]"
# Install development dependencies
pip install pytest pytest-cov black ruff mypy
# Or using Poetry
poetry install --extras "all" --with dev# Run all tests
pytest tests/ -v
# Run with coverage report
pytest tests/ --cov=src/atomkit --cov-report=html
# Run specific test file
pytest tests/test_configuration.py -v# Format code with black
black src/ tests/
# Lint with ruff
ruff check src/ tests/
# Type checking with mypy
mypy src/- Python ≥ 3.10
- NumPy ≥ 1.24
- Pandas ≥ 2.2
- SciPy ≥ 1.10
- Mendeleev ≥ 0.9
- Matplotlib ≥ 3.7 (for plotting)
- Seaborn ≥ 0.12 (enhanced plotting)
- Colorlog ≥ 6.7 (colored logging)
atomkit/
├── src/atomkit/ # Main package
│ ├── configuration.py # Configuration class
│ ├── shell.py # Shell representation
│ ├── utils.py # Element info & ion notation parsing
│ ├── definitions.py # Constants and mappings
│ ├── converters/ # Format converters
│ │ ├── as_generator.py # AUTOSTRUCTURE
│ │ ├── fac_to_as.py # FAC to AS
│ │ └── ls_to_icr.py # LS to ICR
│ ├── readers/ # Data file parsers
│ │ ├── levels.py # FAC levels
│ │ ├── transitions.py # FAC transitions
│ │ ├── autostructure.py # AS parser
│ │ └── autoionization.py # Autoionization
│ └── physics/ # Physics utilities
│ ├── units.py # Energy conversion
│ ├── cross_sections.py # Collision strengths
│ ├── potentials.py # Atomic potentials
│ └── plotting.py # Visualization
├── tests/ # Test suite (226 tests)
├── examples/ # Usage examples
└── docs/ # Additional documentation
- AUTOSTRUCTURE - Complete support (all namelists, validated with official test suite)
- FAC - Full support via SFAC wrapper
- GRASP - Reader implemented, writer in progress
- MCDF - Planned
- R-Matrix codes - Under consideration
- Energy level diagrams
- Cross section plotting
- Grotrian diagrams (in progress)
- Interactive spectral line identification
- Atomic structure visualization (orbitals, densities)
- Collisional-radiative modeling integration
- AUTOSTRUCTURE format
- FAC format
- CHIANTI database format (in progress)
- ADAS format (in progress)
- NIST ASD format
- VAMDC format
- Kurucz/VALD line lists
- Opacity Project format
- Energy unit conversions
- Configuration generation and manipulation
- LS/IC/jj coupling schemes
- Mixing coefficient analysis
- JJ2LSJ transformation
- Boltzmann and Saha equation solvers
- Collisional-radiative equilibrium
- Autoionization rate calculations
- NIST ASD integration for validation
- Comparison tools for benchmarking codes
- Experimental data integration
- Systematic uncertainty quantification
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
If you use AtomKit in your research, please cite:
@software{atomkit,
author = {Silva, Ricardo Ferreira da},
title = {AtomKit: A Python Toolkit for Atomic Physics},
year = {2025},
url = {https://github.com/rfsilva13/atomkit}
}Ricardo Ferreira da Silva - [email protected]
Project Link: https://github.com/rfsilva13/atomkit