Files
altium-scripts/README.md
2026-02-11 12:36:14 +13:00

6.6 KiB
Raw Blame History

Altium Scripts

Convention: All Python scripts use .env for input/output paths (and optional settings); you can override any value via CLI. All scripts write JSON output to the outputs/ folder by default. Copy .env.example to .env and edit.


Capacitors by net pair

Script: CapacitorsByNetPair.pas

Finds all two-pad components on the PCB that share the same two nets (e.g. decoupling capacitors between VCC and GND). Outputs a JSON file with:

  • Key: net pair (e.g. "GND|VCC"), sorted so the same pair is always grouped
  • Value: for each net pair:
    • List of capacitors: designator, value string, package (footprint), and capacitance in farads
    • Total capacitance for that net pair (sum of all caps between those two nets)

How to run

  1. Open your PcbDoc in Altium Designer.
  2. DXP → Run Script… (or File → Run Script… depending on version).
  3. Browse to CapacitorsByNetPair.pas and run it.
  4. Choose a save location for the JSON file when prompted.

JSON output format

{
  "GND|VCC": {
    "total_capacitance_F": 2.2e-05,
    "total_capacitance_str": "22uF",
    "capacitors": [
      {
        "designator": "C1",
        "value": "10uF",
        "package": "0805",
        "capacitance_F": 1e-05
      },
      {
        "designator": "C2",
        "value": "12uF",
        "package": "0805",
        "capacitance_F": 1.2e-05
      }
    ]
  },
  "GND|VDD": {
    "total_capacitance_F": 1e-06,
    "total_capacitance_str": "1uF",
    "capacitors": [
      {
        "designator": "C10",
        "value": "1uF",
        "package": "0603",
        "capacitance_F": 1e-06
      }
    ]
  }
}

Protel PCB 2.8 ASCII — easier (Python, no Altium)

Yes — Protel PCB 2.8 ASCII is easier. Its plain text, so you can parse it with Python and no OLE/binary handling. You dont need Altium running.

  1. Export from Altium: Open your PcbDoc → File → Save As (or Export) → choose PCB 2.8 ASCII or Protel PCB ASCII if your version offers it. Some versions use File → Save Copy As with format “PCB Binary/ASCII” or similar.

  2. Run the Python script on the exported .pcb / .PcbDoc (ASCII) file:

    python3 capacitors_by_net_pair.py board.PcbDoc
    python3 capacitors_by_net_pair.py board.PcbDoc -o out.json
    

    Input/output from .env: Copy .env.example to .env and set INPUT_FILE and OUTPUT_FILE. The script reads these when the optional python-dotenv package is installed; CLI arguments override them. Without .env, you can still pass the input file and -o on the command line. By default the JSON is written to outputs/capacitors_by_net_pair.json (the outputs/ directory is created if needed).

See capacitors_by_net_pair.py for the script. It parses COMP/PATTERN/VALUE and NET/PIN data from the ASCII file and produces the same JSON shape as the DelphiScript.

Test file: tests/sample_protel_ascii.pcb is a minimal Protel PCB 2.8 ASCII sample. Run:

python3 capacitors_by_net_pair.py tests/sample_protel_ascii.pcb -o tests/out.json

Compare component locations (two Protel files)

Script: compare_protel_locations.py

Loads two Protel PCB 2.8 ASCII files and reports which components have moved between them. Component position is the centroid of pin coordinates. Output is written to outputs/compare_locations.json by default.

  • Moved: designators with different (x, y) in file2, with old position, new position, and distance.
  • Only in file1 / only in file2: components that appear in just one file.

Usage:

python3 compare_protel_locations.py board_v1.pcb board_v2.pcb
python3 compare_protel_locations.py board_v1.pcb board_v2.pcb -o outputs/compare_locations.json

Use .env (optional): set FILE1, FILE2, and COMPARE_OUTPUT; CLI arguments override them. Use --threshold N to set the minimum position change to count as moved (default 1.0).

Test: tests/sample_protel_ascii.pcb and tests/sample_protel_ascii_rev2.pcb (C1 and C2 moved in rev2):

python3 compare_protel_locations.py tests/sample_protel_ascii.pcb tests/sample_protel_ascii_rev2.pcb

Spreadsheet diff by designator

Script: diff_spreadsheets.py

Compares two spreadsheets (.xlsx or .csv) on a designator column. Data is read from row 10 by default (first 9 rows skipped). Outputs which designators are only in file1, only in file2, or in both.

Usage:

pip install pandas openpyxl
python3 diff_spreadsheets.py sheet1.xlsx sheet2.xlsx -o outputs/spreadsheet_diff.json

Options: --designator-col 0 (0-based column index), --start-row 9 (0-based; 9 = row 10). Env: SHEET1, SHEET2, DIFF_OUTPUT.

Test: tests/sheet1.csv and tests/sheet2.csv (designators from row 10):

python3 diff_spreadsheets.py tests/sheet1.csv tests/sheet2.csv --start-row 9

Find bottom termination parts (QFN, DFN, BGA) by description

Script: find_bottom_termination_parts.py

Reads the same spreadsheet format (designator column, data from row 10) plus description and optionally package columns. Finds components whose description or package indicates bottom termination, including:

  • Package types: QFN, DFN, BGA, LGA, SON, MLF, MLP, WDFN, WQFN, VQFN, etc.
  • Generic: “bottom termination” (e.g. with 0201 or 0402)

Outputs matching designators, description, package, and the matched pattern to outputs/bottom_termination_parts.json.

Usage:

python3 find_bottom_termination_parts.py sheet.xlsx --description-col 1
python3 find_bottom_termination_parts.py sheet.xlsx --description-col 3

Env: SHEET, BOTTOM_TERM_OUTPUT, DESCRIPTION_COL (default 1), START_ROW (default 9). No package column; only description is searched.

Test: tests/sheet_with_descriptions.csv (description col 3):

python3 find_bottom_termination_parts.py tests/sheet_with_descriptions.csv --description-col 3 --start-row 9

Notes

  • Only components with exactly two pads (each on a net) and designator starting with C are included (treated as capacitors). To include all two-pad parts, edit the script and remove the And (UpperCase(Copy(Component.Name.Text, 1, 1)) = 'C') condition.
  • Capacitance is parsed from the component Value parameter (e.g. 10uF, 100nF, 22pF) and totalled in farads. Supported suffixes: F, mF, uF/µF, nF, pF.
  • Package is taken from the components Pattern (footprint) name.
  • If your Altium version uses different parameter or footprint property names, you may need to adjust the script (e.g. DM_ComponentParameterName / DM_ComponentParameterValue, or Pattern vs Footprint).