Skip to content

Python sample

The SIDRA API is a .NET 8 assembly. From Python the supported path is Python.NET (pythonnet), which loads the assembly straight into the CLR and exposes its types as Python objects. This is not COM: there is no pywin32, no win32com.client.Dispatch, and no COM registration involved.

This sample opens a SIDRA project, processes every site, and prints its level of service and degree of saturation.

Note

Complete the Getting started prerequisites first (SIDRA Intersection installed, .NET 8). You also need a SIDRA project (.sipx) file to open. Save one from SIDRA Intersection, or point the sample at any existing project. Replace C:\Samples\Demo.sipx below with its path. If anything fails, see Troubleshooting.

1. Install Python.NET

pip install pythonnet

Important

Use 64-bit Python. The SIDRA API is net8.0-windows x64-only and will fail to load into a 32-bit interpreter.

Note

The API targets .NET 8, so Python.NET must host the CoreCLR runtime, not .NET Framework. Select it before the first import clr (see Selecting the runtime).

2. Write the program

first_program.py:

import os
import winreg
from pythonnet import set_runtime
from clr_loader import get_coreclr


def sidra_install_path():
    """Read the SIDRA Intersection install folder from the registry."""
    key = r"SOFTWARE\SIDRA SOLUTIONS\SIDRA INTERSECTION 11"
    with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key) as k:
        return winreg.QueryValueEx(k, "InstallLocation")[0]


sidra = sidra_install_path()

# Host the API's own .NET 8 runtime (via its runtimeconfig), then load the DLL.
# This must happen before the first `import clr`.
set_runtime(get_coreclr(
    runtime_config=os.path.join(sidra, "SIDRASolutions.SI.API.runtimeconfig.json")))

import clr
clr.AddReference(os.path.join(sidra, "SIDRASolutions.SI.API.dll"))

from SIDRASolutions.SI.API import SIAPI

api = SIAPI()
try:
    if not api.OpenProject(r"C:\Samples\Demo.sipx"):
        raise RuntimeError(f"Could not open project: {api.LastErrorMessage}")

    project = api.Project
    print(f"Project: {project.Name}")

    # Project -> SiteFolders -> Sites. In SIDRA a "site" is an intersection.
    # .NET indexers map to Python subscripting, so use [] (not COM-style ()).
    folders = project.SiteFolders
    for f in range(folders.Count):
        sites = folders[f].Sites
        for s in range(sites.Count):
            site = sites[s]

            site.Process()                      # run the analysis for this site

            # Site-level vehicle results live under Outputset.OutputSiteVehicle.
            result = site.Outputset.OutputSiteVehicle
            print(f"  {site.Name}: LOS {result.Level_of_service}, "
                  f"degree of saturation {result.Deg_satn:.3f}")
finally:
    api.Close()                                 # shuts down the SIDRA runtime

3. Run it

python first_program.py

Expected output (values depend on your project):

Project: Demo
  North Rd / Main St: LOS B, degree of saturation 0.742
  East Ave / Main St: LOS C, degree of saturation 0.871

Selecting the runtime

Python.NET 3.x can host either .NET Framework or .NET (CoreCLR), and on Windows it may default to .NET Framework. The SIDRA API is .NET 8, so you must host CoreCLR. Passing the API's own SIDRASolutions.SI.API.runtimeconfig.json to get_coreclr(...) and calling set_runtime(...) before the first import clr (as above) selects the correct .NET 8 runtime and the dependencies the API was built against.

Python.NET also needs a .NET 8 runtime present on the machine. The SIDRA Intersection installer satisfies this; otherwise install the .NET 8 Desktop Runtime.

Locating the assembly

The install folder holds SIDRASolutions.SI.API.dll alongside its SIDRASolutions.SI.API.runtimeconfig.json. The sample reads that folder from the registry value HKLM\SOFTWARE\SIDRA SOLUTIONS\SIDRA INTERSECTION 11\InstallLocation, which avoids hard-coding a path. You can also pass the folder explicitly, then load the assembly by full path with clr.AddReference(os.path.join(folder, "SIDRASolutions.SI.API.dll")).

Working with .NET types

Because Python.NET binds the managed types directly, you get the real SIDRASolutions.SI.API classes rather than a late-bound COM wrapper. Interfaces such as ISIAPIProject and their members surface as ordinary Python attributes, collection indexers are accessed with [], and .NET enums import from the same namespace.