PhotonAct turns measured or simulated optical-device response curves into differentiable, hysteresis-aware PyTorch activation functions.
中文说明 · Curve format · Hysteresis semantics · Hardware effects · Roadmap
| Inspect a curve | Explore hysteresis | Use it in a model |
|---|---|---|
| Validate units, provenance, ranges, branches, and thresholds. | Drag the input or run a full scan in a local browser page. | Wrap a branch or explicit-state loop as a differentiable torch.nn.Module. |
git clone https://github.com/SoftBread1217/PhotonAct.git
cd PhotonAct
python -m pip install -e .
photonact inspect examples/curves/sample_phh.csv
photonact demo sample_phhThe last command opens a self-contained local page. Try one full scan, then switch the displayed
quantity or replace sample_phh with your own documented CSV/JSON curve.
import torch
from photonact import CurveActivation
layer = CurveActivation.from_file("examples/curves/sample_phh.csv", branch="up")
x = torch.tensor([0.25, 0.75, 1.25], requires_grad=True)
layer(x).sum().backward()
print(x.grad)Current release: v0.3.0. The core and installed wheel are tested on Python 3.10-3.12. The
bundled sample_phh curve is synthetic demonstration data, not experimental data and not digitized
from a paper.
Run photonact report sample_phh for a descriptive, provenance-aware Markdown curve report.
Run photonact benchmark --dataset synthetic --output-dir local_data/benchmark-demo for an
offline software smoke test that writes summary.md, learning_curves.svg, per-epoch
metrics.csv, and config.json with seeds, versions, architecture, curve hashes, and limitations.
Run python examples/memory_demo.py to
see different outputs at the same final input after different histories. Synthetic benchmark
scores are not evidence of hardware performance or paper reproduction.
The published v0.3.0 benchmark record contains raw, three-seed MNIST and Fashion-MNIST subset results. In this deliberately small setup PhotonAct was comparable on MNIST and lower on Fashion-MNIST; the result is useful evidence about the software workflow, not a claim of activation or hardware superiority.
For reproducible MNIST/Fashion-MNIST runs, install .[benchmark] and use
photonact benchmark --dataset mnist --download --output-dir local_data/mnist-run.
Downloads are opt-in. All candidates share a sigmoid mapping into the curve input range;
the ReLU/GELU comparisons are therefore not conventional unbounded baselines. Static-image
benchmarks use one fixed branch and do not test hysteresis memory. Keep private curves and
their reports inside local_data/ until their data rights are settled.
Researchers often have discrete input/output power points but no simple way to use them inside a PyTorch model. PhotonAct provides the smallest useful bridge:
documented CSV, XLSX, or JSON -> validated branches -> torch.nn.Module -> autograd
It does not include an electromagnetic simulator and does not invent unavailable device data.
PhotonAct focuses on the boundary between an optical response curve and a machine-learning model:
- validate documented measured, simulated, digitized, or synthetic curve data;
- expose the curve as a small, differentiable
torch.nn.Module; - make branch selection, hysteresis state, extrapolation, normalization, and optional hardware effects explicit; and
- provide reproducible benchmarks whose configurations and raw results can be audited.
PhotonAct is not an electromagnetic solver, a substitute for device characterization, or evidence that a model matches physical hardware without documented provenance. It does not claim to reproduce the motivating paper; that paper's underlying curve data are not included in the public package.
PhotonAct targets Python 3.10-3.12.
python -m venv .venv
# Windows: .venv\Scripts\activate
# macOS/Linux: source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .Development tools are optional:
python -m pip install -e ".[dev]"
pytest
ruff check .
mypy photonactGenerate a self-contained HTML page and open it in your browser:
photonact demo sample_phhThe explorer lets you drag the input power, run a complete up/down scan, see the active branch and
state, and compare output power with an optional transmittance column. For a private local curve:
photonact demo local_data/phh_1535nm/phh_1535nm.csv --output local_data/phh_1535nm/phh_1535nm_demo.htmlThe generated HTML embeds a copy of every plotted point. Keep it private when the source curve is
private, and share it only under the data license declared in the metadata. Use --no-open in CI or
other non-interactive environments.
Use photonact prepare to convert an external CSV or XLSX table into canonical curve and metadata
files, with an audit report containing the source SHA-256 and chosen conversion settings. Column
mapping and provenance are explicit; the source file remains unchanged. For example, prepare the
bundled synthetic CSV into the Git-ignored local_data/ directory:
photonact prepare examples/curves/sample_phh.csv --output-dir local_data/roundtrip \
--name roundtrip --input-column input_power --output-column output_power \
--branch-column branch --input-unit normalized_power --output-unit normalized_power \
--source-description "Bundled synthetic demonstration" --data-kind synthetic \
--license CC0-1.0 --lower-threshold 0.6 --upper-threshold 1.4For XLSX input, install .[data] and specify the sheet plus either a branch column or separate
up/down column pairs. See the preparation specification for the mapping
options, explicit transmittance conversion, and validation rules.
CSV files use input_power, output_power, and an optional branch column:
input_power,output_power,branch
0.0,0.00,up
0.4,0.04,up
0.0,0.00,down
0.4,0.08,downWithin each branch, input values must be strictly increasing. For device.csv, optional metadata is
stored in device.meta.json:
{
"name": "my_device",
"input_unit": "mW",
"output_unit": "mW",
"source": "Measured in Example Lab on 2026-01-01",
"valid_min": 0.0,
"valid_max": 2.0,
"normalized": false,
"license": "CC-BY-4.0",
"citation": "DOI or lab record"
}JSON may contain {"metadata": {...}, "points": [...]} or just a list of points. See
docs/curve_data.md.
HysteresisActivation switches between the increasing-scan (up) and decreasing-scan (down)
curves with explicit state. The module never hides trajectory state inside a global or persistent
attribute: each step receives the previous state and returns the next one.
import torch
from photonact import HysteresisActivation
layer = HysteresisActivation.from_file("examples/curves/sample_phh.csv")
x = torch.tensor([0.2, 1.0, 1.8, 1.0, 0.2], requires_grad=True)
y, state_history = layer.forward_sequence(x, initial_state=False)
y.sum().backward()At or above upper_threshold, the state switches high and selects the down branch. At or below
lower_threshold, it switches low and selects the up branch. Between those thresholds it retains
the supplied state. See docs/hysteresis.md for batched inputs, reset behavior,
and gradient semantics.
Wrap an existing curve or hysteresis activation with HardwareAwareActivation and explicitly
configured HardwareEffects. The supported effects are input drift, output-side insertion loss,
finite output range, quantization, and seeded Gaussian readout noise. All effects are off by default.
from photonact import CurveActivation, HardwareAwareActivation, HardwareEffects
base = CurveActivation.from_file("examples/curves/sample_phh.csv", branch="up")
layer = HardwareAwareActivation(
base,
HardwareEffects(quantization_step=0.1, quantization_gradient="straight_through"),
)Run python examples/hardware_effects.py for a reproducible synthetic comparison. Effect order,
units, random-generator usage, and gradient conventions are specified in
docs/hardware_effects.md. Example parameters are not device
calibrations.
CurveActivation uses differentiable piecewise-linear interpolation. This is easier to inspect and
test than a high-order spline and is the deliberate v0.0.1 choice. Multi-branch curves require an
explicit branch. Out-of-range behavior can be clamp, linear, or error. Input and output can be
normalized independently.
PyTorch automatically moves registered curve points when you call .to("cuda"); CPU works by
default. See examples/minimal.py and the
introductory notebook.
The research motivation includes Optical Bistability in Photonic Topological Hypercrystals and Its Applications in Photonic Neural Network (Nanomaterials 2026, 16, 561). The repository does not ship that paper's underlying data and does not claim to reproduce its accuracy results.
sample_phh is a hand-authored synthetic example with separated up/down branches. Replace it with
appropriately licensed measured, simulated, or digitized data and record its provenance.
Authors who have legitimate access to the Figure 4(b) source workbook can prepare a private local curve without modifying the workbook:
python -m pip install -e ".[data]"
python scripts/prepare_phh_1535nm.py path/to/shuangwentiai.xlsx
python examples/hysteresis.py --curve local_data/phh_1535nm/phh_1535nm.csvThe converter records the source SHA-256, provenance, wavelength, polarization, transition
intervals, and output-power calculation. Its default destination, local_data/, is Git-ignored.
Do not publish the generated files until every relevant author or rights holder has approved the
data license.
See the milestone definitions and evidence requirements in docs/roadmap.md.
See CONTRIBUTING.md, SECURITY.md, and CHANGELOG.md. Cite PhotonAct with CITATION.cff and cite device data separately. Code is released under the MIT License; data may declare a different license in metadata.