Metadata-Version: 2.2
Name: mgtoolbox-kernel
Version: 0.2.0
Summary: MGToolBox Materials Genome Toolbox core library for crystal structure analysis
Home-page: https://gitee.com/shuhebing/mgtoolbox_kernel
Author: Bing He
Author-email: Bing He <shhebing@qq.com>
Project-URL: Homepage, https://gitee.com/shuhebing/mgtoolbox_kernel
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Chemistry
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pycifrw
Requires-Dist: numpy>=1.20
Requires-Dist: scipy>=1.7
Requires-Dist: pandas>=1.3
Requires-Dist: spglib>=2.0
Dynamic: author
Dynamic: home-page
Dynamic: requires-python

# mgtoolbox-kernel

MGToolBox Materials Genome Toolbox core library for crystal structure analysis, CIF file processing, and computational materials science research.

## Installation

### Method 1: pip install

```bash
pip install mgtoolbox-kernel
```

### Method 2: Install from source

```bash
git clone https://gitee.com/shuhebing/mgtoolbox_kernel.git
cd mgtoolbox_kernel
pip install -e .
```

### Requirements

- Python >= 3.8
- numpy
- scipy
- pandas
- pycifrw
- spglib

## Usage

### 1. Reading from String Data

```python
from mgtoolbox_kernel.kernel import Structure, SymmetryStructure

cif_data = """
data_test
_cell_length_a    3.0
_cell_length_b    3.0
_cell_length_c    3.0
_cell_angle_alpha 90.0
_cell_angle_beta 90.0
_cell_angle_gamma 90.0
_symmetry_space_group_name_H-M 'P 1'
_symmetry_Int_Tables_number 1
loop_
_symmetry_equiv_pos_site_id
_symmetry_equiv_pos_as_xyz
1 'x, y, z'
loop_
_atom_site_label
_atom_site_type_symbol
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
_atom_site_occupancy
Li1 Li 0.0 0.0 0.0 1.0
"""

structures = Structure.from_data(cif_data)
structure = structures[0]
print(f"Number of sites: {len(structure.sites)}")

sym_structures = SymmetryStructure.from_data(cif_data)
sym_structure = sym_structures[0]
print(f"SymmetryStructure sites: {len(sym_structure.sites)}")
print(f"Space group: {sym_structure.space_group_info['space_group_name']}")
```

**Output:**
```
Number of sites: 1
SymmetryStructure sites: 1
Space group: Pm-3m
```

### 2. Reading from Files

Supports CIF and VASP POSCAR formats:

```python
from mgtoolbox_kernel.kernel import Structure, SymmetryStructure

# Read CIF file
structures = Structure.from_file("example.cif")
structure = structures[0]
print(f"Number of sites: {len(structure.sites)}")

# Read with symmetry detection
sym_structures = SymmetryStructure.from_file("example.cif")
sym_structure = sym_structures[0]
print(f"Inequivalent sites: {len(sym_structure.sites)}")
```

### 3. Creating Cells and Sites

```python
from mgtoolbox_kernel.kernel import Structure, Cell, Site, Atom

# Create cell (a, b, c, alpha, beta, gamma)
cell = Cell.from_lattice_parameters(3.0, 3.0, 3.0, 90.0, 90.0, 90.0)

# Create sites
atom1 = Atom("Li", 1.0)
atom2 = Atom("O", -2.0)
site1 = Site([0.0, 0.0, 0.0], {atom1: 1.0}, label="Li1")
site2 = Site([0.5, 0.5, 0.5], {atom2: 1.0}, label="O1")

# Create structure
structure = Structure([site1, site2], cell)
print(f"Number of sites: {len(structure.sites)}")
print(f"Cell volume: {structure.cell.volume:.3f}")
```

**Output:**
```
Number of sites: 2
Cell volume: 27.000
```

### 4. Accessing Cell Information

```python
from mgtoolbox_kernel.kernel import Cell

cell = Cell(4.61, 4.61, 4.61, 90.0, 90.0, 90.0)

# Lattice parameters
print(f"a, b, c: {cell.abc}")
print(f"alpha, beta, gamma: {cell.angles}")

# Cell volume
print(f"Volume: {cell.volume:.4f}")

# Coordinate conversion
frac = [0.5, 0.5, 0.5]
cart = cell.get_cartesian_coords(frac)
print(f"Fractional {frac} -> Cartesian {cart}")

back = cell.get_fractional_coordinates(cart)
print(f"Cartesian -> Fractional {back}")
```

**Output:**
```
a, b, c: [4.61 4.61 4.61]
alpha, beta, gamma: [90. 90. 90.]
Volume: 97.9722
Fractional [0.5, 0.5, 0.5] -> Cartesian [2.305 2.305 2.305]
Cartesian -> Fractional [0.5 0.5 0.5]
```

### 5. Accessing Site Information

```python
from mgtoolbox_kernel.kernel import Structure, Cell, Site, Atom

cell = Cell(4.0, 4.0, 4.0, 90.0, 90.0, 90.0)
atom1 = Atom("Li", 1.0)
atom2 = Atom("O", -2.0)
site1 = Site([0.0, 0.0, 0.0], {atom1: 1.0}, label="Li1")
site2 = Site([0.5, 0.5, 0.5], {atom2: 1.0}, label="O1")
structure = Structure([site1, site2], cell)

# Iterate over all sites
for site in structure.sites:
    print(f"Site: {site.label}")
    print(f"  Coordinate: ({site.x:.4f}, {site.y:.4f}, {site.z:.4f})")
    print(f"  Atoms: {site.atom_symbols}")
    print(f"  Occupancy: {site.atom_occupancies}")
    print(f"  Ordered: {site.is_ordered}")

print(f"Structure is ordered: {structure.is_ordered}")
```

**Output:**
```
Site: Li1
  Coordinate: (0.0000, 0.0000, 0.0000)
  Atoms: ['Li']
  Occupancy: [1.0]
  Ordered: True
Site: O1
  Coordinate: (0.5000, 0.5000, 0.5000)
  Atoms: ['O']
  Occupancy: [1.0]
  Ordered: True
Structure is ordered: True
```

### 6. Manipulating Sites

```python
from mgtoolbox_kernel.kernel import Structure, Cell, Site, Atom

cell = Cell(5.0, 5.0, 5.0, 90.0, 90.0, 90.0)
atom = Atom("Li", 1.0)
site = Site([0.0, 0.0, 0.0], {atom: 1.0}, label="Li1")
structure = Structure([site], cell)

# Add a site
new_atom = Atom("Fe", 3.0)
new_site = Site([0.25, 0.25, 0.25], {new_atom: 1.0}, label="Fe1")
structure.add_site(new_site)
print(f"After add: {len(structure.sites)} sites")

# Add multiple sites
atom_o = Atom("O", -2.0)
site_o = Site([0.5, 0.5, 0.5], {atom_o: 1.0}, label="O1")
structure.add_sites([site_o])
print(f"After batch add: {len(structure.sites)} sites")

# Remove a site
structure.remove_sites([new_site])
print(f"After remove: {len(structure.sites)} sites")

# Update cell
new_cell = Cell(6.0, 6.0, 6.0, 90.0, 90.0, 90.0)
structure.set_cell(new_cell)
print(f"Updated cell: {structure.cell.abc}")
```

**Output:**
```
After add: 2 sites
After batch add: 3 sites
After remove: 2 sites
Updated cell: [6. 6. 6.]
```

### 7. Calculating Interatomic Distances

```python
import numpy as np
from mgtoolbox_kernel.kernel import Cell

cell = Cell(4.61, 4.61, 4.61, 90.0, 90.0, 90.0)

# Minimum image distance between two Cartesian coordinates
vector, length = cell.distance([0.0, 0.0, 0.0], [2.305, 2.305, 2.305])
print(f"Distance vector: {vector}")
print(f"Distance: {length:.4f}")
```

**Output:**
```
Distance vector: [ 2.305  2.305 -2.305]
Distance: 3.9924
```

### 8. Coordinate Transformation

```python
from mgtoolbox_kernel.kernel import Cell

cell = Cell(4.61, 4.61, 4.61, 90.0, 90.0, 90.0)

# Fractional to Cartesian
frac_coords = [0.5, 0.5, 0.5]
cart_coords = cell.get_cartesian_coords(frac_coords)
print(f"Fractional {frac_coords}")
print(f"Cartesian {cart_coords}")

# Cartesian to fractional
back = cell.get_fractional_coordinates([2.305, 2.305, 2.305])
print(f"Cartesian [2.305, 2.305, 2.305]")
print(f"Fractional {back}")
```

**Output:**
```
Fractional [0.5, 0.5, 0.5]
Cartesian [2.305 2.305 2.305]
Cartesian [2.305, 2.305, 2.305]
Fractional [0.5 0.5 0.5]
```

### 9. Cell Reduction

```python
from mgtoolbox_kernel.kernel import Cell

cell = Cell(4.61, 4.61, 4.61, 90.0, 90.0, 90.0)
print(f"Original parameters: {cell.abc}")

reduced_cell = cell.get_reduced_cell(algorithm='niggli')
print(f"Niggli reduced parameters: {reduced_cell.abc}")
```

**Output:**
```
Original parameters: [4.61 4.61 4.61]
Niggli reduced parameters: [4.61 4.61 4.61]
```

### 10. Writing Structure Files

```python
from mgtoolbox_kernel.kernel import Structure, Cell, Site, Atom

cell = Cell(5.0, 5.0, 5.0, 90.0, 90.0, 90.0)
atom = Atom("Li", 1.0)
site = Site([0.0, 0.0, 0.0], {atom: 1.0}, label="Li1")
structure = Structure([site], cell)

# Write CIF file (P1 symmetry)
structure.write_to_cif("output.cif")
print("Written output.cif")

# Write VASP POSCAR file (ordered structures only)
structure.write_to_poscar("POSCAR", scale=1.0)
print("Written POSCAR")
```

**Output:**
```
Written output.cif
Written POSCAR
```

### 11. Getting Symmetry Information

```python
from mgtoolbox_kernel.kernel import SymmetryStructure

cif_data = """
data_test
_cell_length_a    3.0
_cell_length_b    3.0
_cell_length_c    3.0
_cell_angle_alpha 90.0
_cell_angle_beta 90.0
_cell_angle_gamma 90.0
_symmetry_space_group_name_H-M 'P 1'
_symmetry_Int_Tables_number 1
loop_
_symmetry_equiv_pos_site_id
_symmetry_equiv_pos_as_xyz
1 'x, y, z'
loop_
_atom_site_label
_atom_site_type_symbol
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
_atom_site_occupancy
Li1 Li 0.0 0.0 0.0 1.0
"""

structures = SymmetryStructure.from_data(cif_data)
sym_structure = structures[0]

space_group = sym_structure.space_group_info
print(f"Space group number: {space_group['space_group_number']}")
print(f"Space group name: {space_group['space_group_name']}")
print(f"Hall number: {space_group['space_group_hall_number']}")
print(f"Equivalent atoms: {space_group['equivalent_atoms']}")
```

**Output:**
```
Space group number: 221
Space group name: Pm-3m
Hall number: 517
Equivalent atoms: [0]
```

## Running Tests

```bash
pip install pytest
pytest tests/
```

## Module Structure

| Module | Description |
|--------|-------------|
| `mgtoolbox_kernel.io` | File I/O (CIF, VASP POSCAR) |
| `mgtoolbox_kernel.kernel` | Core data models (Structure, SymmetryStructure, Cell, Site, Atom) |
| `mgtoolbox_kernel.util` | Utility functions (symmetry parsing, lattice vector conversion) |
| `mgtoolbox_kernel.crystal_tools` | Crystal symmetry analysis tools (based on spglib) |
