Source code for squadds.database.generalized_ncap_dataset

"""Normalize generalized interdigital capacitor sweeps for SQuADDS."""

from __future__ import annotations

import json
from collections.abc import Iterable
from pathlib import Path
from typing import Any

COMPONENT_NAME = "GeneralizedCapNInterdigital"
CONTRIBUTOR = {
    "group": "Levenson-Falk Lab",
    "PI": "Eli Levenson-Falk",
    "institution": "USC",
    "uploader": "Saikat Das",
    "date_created": "2026-07-25",
}
MATRIX_KEYS = (
    "C_G_G",
    "C_G_N",
    "C_G_S",
    "C_N_G",
    "C_N_N",
    "C_N_S",
    "C_S_G",
    "C_S_N",
    "C_S_S",
)


def _pairwise_results(matrix: dict[str, float]) -> dict[str, float | str | dict[str, float]]:
    return {
        "north_to_north": matrix["C_N_N"],
        "north_to_south": abs(matrix["C_N_S"]),
        "north_to_ground": abs(matrix["C_N_G"]),
        "south_to_south": matrix["C_S_S"],
        "south_to_ground": abs(matrix["C_S_G"]),
        "ground_to_ground": matrix["C_G_G"],
        "top_to_top": matrix["C_N_N"],
        "top_to_bottom": abs(matrix["C_N_S"]),
        "top_to_ground": abs(matrix["C_N_G"]),
        "bottom_to_bottom": matrix["C_S_S"],
        "bottom_to_ground": abs(matrix["C_S_G"]),
        "maxwell_matrix": {key: matrix[key] for key in MATRIX_KEYS},
        "units": "fF",
    }


[docs] def validate_source_record(record: dict[str, Any]) -> None: """Validate fields and physical matrix invariants required by the converter.""" required = {"cap_instance_name", "cap_options", "ansys_gds", "cap_matrix"} missing = required.difference(record) if missing: raise ValueError(f"Source record is missing required fields: {sorted(missing)}") matrix = record["cap_matrix"].get("matrix_elements_fF", {}) if set(matrix) != set(MATRIX_KEYS): raise ValueError("Source record must contain the complete 3x3 Maxwell capacitance matrix.") for left, right in (("C_G_N", "C_N_G"), ("C_G_S", "C_S_G"), ("C_N_S", "C_S_N")): if abs(matrix[left] - matrix[right]) > 1e-9: raise ValueError(f"Maxwell matrix is not symmetric at {left}/{right}.") if any(matrix[key] <= 0 for key in ("C_G_G", "C_N_N", "C_S_S")): raise ValueError("Maxwell matrix diagonal entries must be positive.") if any(matrix[key] > 0 for key in ("C_G_N", "C_G_S", "C_N_S")): raise ValueError("Maxwell matrix off-diagonal entries must be non-positive.")
[docs] def convert_source_record(record: dict[str, Any], campaign: str, source_file: str) -> dict[str, Any]: """Convert one raw sweep record to the public SQuADDS row contract.""" validate_source_record(record) q3d = record["ansys_gds"]["q3d_signal"] matrix = record["cap_matrix"]["matrix_elements_fF"] source_id = f"{campaign}/{record['cap_instance_name']}" return { "sim_options": { "sim_type": "cap_matrix", "setup": q3d["setup"], "renderer_options": { "margin_factor_east_west": record["margin_factor_ew"], "margin_factor_north_south": record["margin_factor_ns"], "gds_north_port_length": record["gds_north_port_length"], "gds_north_port_layer": record["gds_north_port_layer"], "gds_south_port_length": record["gds_south_port_length"], "gds_south_port_layer": record["gds_south_port_layer"], "mesh": record["mesh"], "gds_import": q3d, }, "layer_stack": record["layer_stack"], "simulator": "Ansys Q3D", }, "sim_results": _pairwise_results(matrix), "design": { "design_options": record["cap_options"], "design_tool": "qiskit-metal", "coupler_type": COMPONENT_NAME, "component_name": COMPONENT_NAME, "component_module": "squadds.components", "component_class": COMPONENT_NAME, "pin_names": ["north_end", "south_end"], "pin_aliases": {"top": "north_end", "bottom": "south_end"}, }, "notes": { "source_id": source_id, "source_campaign": campaign, "source_instance_name": record["cap_instance_name"], "source_file": source_file, "attribution": "Simulated and contributed by Saikat Das, Levenson-Falk Lab, USC.", }, "contributor": dict(CONTRIBUTOR), }
[docs] def iter_source_files(source_root: Path) -> Iterable[Path]: """Yield source JSON files in deterministic campaign/name order.""" return sorted(source_root.glob("*/*.json"), key=lambda path: (path.parent.name, path.name))
[docs] def convert_dataset(source_root: Path, output_path: Path) -> int: """Convert an export tree to a deterministic Hugging Face JSON artifact.""" rows = [] source_ids = set() for path in iter_source_files(source_root): with path.open(encoding="utf-8") as source: record = json.load(source) relative_path = path.relative_to(source_root).as_posix() row = convert_source_record(record, path.parent.name, relative_path) source_id = row["notes"]["source_id"] if source_id in source_ids: raise ValueError(f"Duplicate source id: {source_id}") source_ids.add(source_id) rows.append(row) if not rows: raise ValueError(f"No JSON files found under {source_root}") output_path.parent.mkdir(parents=True, exist_ok=True) with output_path.open("w", encoding="utf-8") as destination: json.dump(rows, destination, indent=2) destination.write("\n") return len(rows)