Device analysis

Now we will run an IV analysis on the device data we uploaded in the previous notebook.

As before, make sure you have the following environment variables set or added to a .env file:

GDSFACTORY_HUB_API_URL="https://{org}.gdsfactoryhub.com"
GDSFACTORY_HUB_QUERY_URL="https://query.{org}.gdsfactoryhub.com"
GDSFACTORY_HUB_KEY="<your-gdsfactoryplus-api-key>"
import getpass

from tqdm.auto import tqdm

import gdsfactoryhub as gfh
project_id = f"resistance-{getpass.getuser()}"
client = gfh.create_client_from_env(project_id=project_id)
api = client.api()
query = client.query()
utils = client.utils()

Device Analysis

We have a bunch of pre-defined analysis functions in the dodata SDK. An analysis function is actually a stand-alone python module with a single run function inside (more helper functions in the file are allowed, but run will be executed). Let's have a look at the iv_resistance analysis.

from gdsfactoryhub.functions.device_data import linear_fit

linear_fit.run?

Let's run this one locally, to see what it gives:

device_data_pkey = query.device_data().execute().data[0]["pk"]
linear_fit.run(
    device_data_pkey=device_data_pkey,
    xname="i",
    yname="v",
    slopename="resistance",
    xlabel="Current (A)",
    ylabel="Voltage (V)",
)
{'output': {'resistance': 4.1555410510312895e-08},
 'summary_plot': <Figure size 640x480 with 1 Axes>,
 'device_data_pkey': '3c4950a3-3d61-4c28-84cb-c1abf10dccd9'}

png

This analysis function clearly fits a straight line to an IV curve to obtain the resistance. The function ran locally, but it's always good to check if it runs on the server too:

# don't error out when function already exists in DoData.
with gfh.suppress_api_error():
    result = api.upload_function(
        function_id="linear_fit",
        target_model="device_data",
        file=gfh.get_module_path(linear_fit),
        test_target_model_pk=device_data_pkey,
        test_kwargs={
            "xname": "i",
            "yname": "v",
            "slopename": "resistance",
            "xlabel": "Current (A)",
            "ylabel": "Voltage (V)",
        },
    )
Duplicate function

Note

If this would have failed to upload to the server but succeeded locally, you probably have to update the 'uv-comment' at the top of the file with updated dependencies. Such a uv-comment ensures that the script can be run by uv and all necessary dependencies will be installed. It usually looks as follows:

# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "gdsfactoryhub-sdk",
#     "matplotlib",
#     "numpy",
# ]
# ///

We can now trigger an analysis for the uploaded function:

result = api.start_analysis(
    analysis_id=f"device_iv_resistance_{device_data_pkey}",
    function_id="linear_fit",
    target_model="device_data",
    target_model_pk=device_data_pkey,
    kwargs={
        "xname": "i",
        "yname": "v",
        "slopename": "resistance",
        "xlabel": "Current (A)",
        "ylabel": "Voltage (V)",
    },
)
utils.analyses().wait_for_completion(pks=[result["pk"]])
analysis = query.analyses().eq("pk", result["pk"]).limit(1).execute().data[0]
img = api.download_plot(analysis["summary_plot"]["path"])
img.resize((530, 400))
Waiting for analyses:   0%|          | 0/1 [00:00<?, ?it/s]

png

Now, let's run the analysis for all devices:

results = []
dd_pks = [d["pk"] for d in query.device_data().execute().data]
for dd_pk in tqdm(dd_pks):
    with gfh.suppress_api_error():
        result = api.start_analysis(
            analysis_id=f"device_iv_resistance_{dd_pk}",
            function_id="linear_fit",
            target_model="device_data",
            target_model_pk=dd_pk,
            kwargs={
                "xname": "i",
                "yname": "v",
                "slopename": "resistance",
                "xlabel": "Current (A)",
                "ylabel": "Voltage (V)",
            },
        )
        results.append(result)
  0%|          | 0/189 [00:00<?, ?it/s]

Let's have a look at the last analysis:

analysis_pks = [r["pk"] for r in results]
utils.analyses().wait_for_completion(pks=analysis_pks)
analyses = query.analyses().in_("pk", analysis_pks).execute().data
succesful_analyses = [a for a in analyses if a["status"] == "COMPLETED"]
analysis = succesful_analyses[-1]
img = api.download_plot(analysis["summary_plot"]["path"])
img.resize((530, 400))
Waiting for analyses:   0%|          | 0/189 [00:00<?, ?it/s]

png

On This Page