PythTB 2.0.0 Release Notes#

PythTB 2.0.0 is a major redesign of the package, focused on long-term maintainability, performance, and a modern API. It introduces:

  • A modular package architecture

  • API cleanup and unification

  • Performance improvements via vectorization with significant speedups for large calculations

  • New Lattice, Mesh, and Wannier classes

  • Expanded functionality: maximally localized and disentangled Wannier functions, Quantum geometric tensor, quantum metric, local Chern marker, axion angle, and more

  • Wannier90 + Quantum ESPRESSO I/O utilities

  • Type hints and improved error handling

  • Improved testing and documentation

  • New readthedocs-based documentation site

This document summarizes the design philosophy, API changes, and migration guidance.

Why PythTB 2.0.0?#

The original package had a single-file (pythtb.py) design that served early use cases well. However, as the codebase expanded, this structure became unwieldy. Version 2.0.0 reorganizes the project into a modular structure with a more intuitive API and consistent naming, following PEP-8 and scientific Python community best practices.

The goals:

  • Improve readability and maintainability by breaking the code into smaller, focused modules.

  • Enhance performance through vectorized operations, enabling efficient computations on larger systems.

  • Provide a cleaner, more consistent API that is easier to learn and use.

  • Enable community contributions by establishing clear project structure and guidelines.

  • Establish a stable surface for future development

Major Changes#

Version Support#

What Changed:

  • Dropped support for Python <3.12 and NumPy <2.0

Rationale:

  • Allows use of latest syntax and features (match-case, improved typing, etc.).

  • Many scientific libraries have dropped support for older versions.

  • Follows SPEC-0: Scientific Python minimum standards.

Modular Package Structure#

Before: everything in a single pythtb.py file.

Now: split into multiple modules under the pythtb/ package:

Module

Purpose

tbmodel.py

Tight-binding model class - TBModel

wfarray.py

Wavefunction array - WFArray

mesh.py

k-point and adiabatic parameter mesh construction and related routines

w90.py

W90 class for Wannier90 interfacing

lattice.py

Lattice geometry and related routines

hoptable.py

Hopping terms storage and manipulation

utils.py

General-purpose helpers

visualization/

Plotting utilities, not part of public API

models/

Canonical tight-binding model library (graphene, Haldane, SSH, etc.)

io/wannier90.py

Wannier90 file readers

io/qe.py

Quantum ESPRESSO file readers

Rationale:

New Core Classes#

Lattice#

Encapsulates lattice geometry, orbital positions, and nearest-neighbour shells. Every model and wavefunction array references the same lattice instance to ensure consistent coordinates. A Lattice can be shared across multiple models and wavefunction arrays. The Lattice class also provides methods for visualizing the lattice in real and reciprocal space.

To create a Lattice:

from pythtb import Lattice
a1 = [1.0, 0.0]
a2 = [0.0, 1.0]
tau_1 = [0.0, 0.0]
tau_2 = [0.5, 0.5]

lat = Lattice([a1, a2], [tau_1, tau_2], periodic_dirs=...)  # '...' sets all directions as periodic
lat = Lattice([a1, a2], [tau_1, tau_2])  # not specifying periodic_dirs defaults to a finite system 
lat = Lattice([a1, a2], [tau_1, tau_2], periodic_dirs=[0])  # We may set a subset of directions as periodic (as before)

Mesh#

Describes k-space grids, paths, and parameter sweeps. Encodes topology (loops, endpoints, adiabatic cycles) so WFArray can apply appropriate gauge conditions downstream.

To create a Mesh:

from pythtb import Mesh

mesh = Mesh(dim_k=2, axis_types=['k', 'k'])
mesh.build_grid([10, 10], gamma_centered=True)  # builds a 10x10 k-point grid centered at Gamma

mesh = Mesh(dim_k=1, axis_types=['k'])
mesh.build_path([[0, 0], [0.5, 0], [0.5, 0.5]], [50, 50])  # builds a k-point path

mesh = Mesh(dim_k=1, dim_param=1, axis_types=['k', 'param'])  # k-point + parameter sweep
mesh.build_grid([100, 20])  # builds a grid with 100 k-points and 20 parameter values

# makes the parameter axis a loop (adiabatic cycle) looping the second (index 1) 
# component of the mesh vector back to itself along the second axis (index 1)
mesh.loop(1, 1) 

# Manual point specification
mesh = Mesh(dim_k=1, axis_types=['k'])
k_pts = np.linspace(0, 1, 100, endpoint=True)  # endpoint=True includes the last point
mesh.build_custom(k_pts)
# winds kx around the BZ and makes the path closed
mesh.loop(0, 0, winds_bz=True, closed=True)  

Wannier#

Build Wannier gauges directly inside PythTB from a WFArray, perform projections, disentanglement and maximal localization, and analyze spreads and centers.

from pythtb import Wannier

wannier = Wannier(wf_array)

# Define trial functions as list of (orbital index, weight) tuples
tf_list = [[(orb, weight)] for orb, weight in zip(orbital_indices, weights)]

# project onto occupied bands
wannier.project(tf_list, band_idxs=list(range(n_occ)))  

# disentanglement procedure
frozen_window = [E_min, E_max]  # define frozen window energies
outer_window = [E_min_outer, E_max_outer]  # define outer window energies
wannier.disentangle(
  n_wfs=2, 
  frozen_window=frozen_window,
  outer_window=outer_window,
  max_iter=1000,
  tol=1e-6
  )

wannier.project(use_tilde=True)  # re-project using disentangled states

# maximal localization
wannier.maxloc(
  alpha=1/2, 
  max_iter=1000, 
  tol=1e-10, 
  grad_min=1e-10, 
  verbose=True)  

API Cleanup & Naming Consistency#

Renaming Classes#

Renamed classes using PascalCase per PEP 8 conventions

< v2.0

v2.0

tb_model

TBModel

wf_array

WFArray

w90

W90

Dropped redundant object base class (i.e., class TBModel(object): is now class TBModel:). All classes are new-style in Python 3.

Rationale:

  • Follows community conventions.

  • Improves distinguishability of classes and functions.

Initialization Patterns#

The Lattice and Mesh classes were introduced to encapsulate lattice geometry and k-point/parameter mesh construction, respectively. This separates concerns and improves code organization. These classes can also be used as standalone utilities and shared across multiple models.

< v2.0

2.0

Purpose

tb_model(dim_r, dim_k, lat, orb, per, nspin)

TBModel(Lattice, spinful)

Lattice geometry and orbital positions are encapsulated in a Lattice instance.

wf_array(model, mesh_arr, nsta_arr)

WFArray(Lattice, Mesh, nstates)

Decouples wavefunction storage from model definition. Mesh encodes k-point and parameter grids.

Rationale:

  • Separation of concerns -> easier maintenance and testing.

  • Reusable components for advanced workflows.

  • Aligns with object-oriented design principles.

Method Renaming & Unification#

Many methods were renamed for clarity and consistency. Some methods were merged to reduce redundancy.

Examples:

< v2.0

v2.0

Notes

tb_model.solve_one & tb_model.solve_all

TBModel.solve_ham

Unified method for solving Hamiltonian at single/multiple k-points

wf_array.berry_phase parameter dir

Renamed to axis_idx to avoid conflict with Python keyword dir

Prevents syntax issues and improves clarity

w90.w90_bands_consistency

Renamed to W90.bands_w90

Brevity and clarity

Rationale:

Vectorization and Performance#

What Changed:

  • Performance bottlenecks were addressed via NumPy vectorization.

    • For example, the tb_model._gen_ham and tb_model._sol_ham functions for generating and diagonalizing the Hamiltonian were a major bottleneck. It has been restructured to utilize NumPy vectorization, eliminating explicit for loops over the k-points.

  • TensorFlow optional acceleration added for large-scale problems. TensorFlow accelerates linear algebra operations on GPUs. This is an optional dependency that can be enabled for users with compatible hardware.

Rationale:

Type Hints and Error Handling#

What Changed:

  • Added type annotations throughout codebase (PEP 484 – Type Hints

  • Replaced generic raise Error with specific exceptions, e.g., TypeError or ValueError

Rationale:

Logging vs. Print Statements#

What Changed:

  • Replaced print-based messaging with Python’s logging module.

Rationale:

Packaging and Distribution#

What Changed:
Transitioned from setup.py to pyproject.toml, added standard files (LICENSE, CHANGELOG, CONTRIBUTING).

  • LICENSE: GPL-3 license (copied over from the .txt file).

  • CHANGELOG: This file for tracking changes between versions.

  • pyproject.toml: Now the recommended way to package Python projects.

  • CONTRIBUTING: Outlines expectations and guidelines for contributors.

Rationale:

Testing and Continuous Integration#

What Changed:

  • Added a tests/test_examples directory with pytest-based regression tests for all examples

  • Each test runs the example scripts and compares outputs to reference data from v1.8.

  • Added a tests/test_examples/make_test_example.py to automatically generate a skeleton for new tests to be made in the future.

  • Added a tests/report_test_status.py to print a summary of which tests are passing and the date/time of last pass/fail.

  • See tests/test_examples/README.md for more information.

Rationale:

  • Ensures backward compatibility and prevents regressions during refactors or feature additions

  • Encourages contributors to include tests alongside new code

If you have questions or want to propose a change, please open an issue or start a discussion.