Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simulators: add runs resource #2099

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions cognite/client/_api/simulators/runs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from __future__ import annotations

# from typing import TYPE_CHECKING, Any

# from cognite.client._api_client import APIClient
# from cognite.client._constants import DEFAULT_LIMIT_READ
# from cognite.client.data_classes.simulators.filters import SimulationRunsFilter
# from cognite.client.data_classes.simulators.simulators import SimulationRun, SimulationRunCall, SimulationRunsList
# from cognite.client.utils._experimental import FeaturePreviewWarning
# from cognite.client.utils._identifier import IdentifierSequence

# if TYPE_CHECKING:
# from cognite.client import ClientConfig, CogniteClient


# class SimulatorRunsAPI(APIClient):
# _RESOURCE_PATH = "/simulators/runs"
# _RESOURCE_PATH_RUN = "/simulators/run"

# def __init__(self, config: ClientConfig, api_version: str | None, cognite_client: CogniteClient) -> None:
# super().__init__(config, api_version, cognite_client)
# self._warning = FeaturePreviewWarning(
# api_maturity="General Availability", sdk_maturity="alpha", feature_name="Simulators"
# )

# def list(
# self, limit: int = DEFAULT_LIMIT_READ, filter: SimulationRunsFilter | dict[str, Any] | None = None
# ) -> SimulationRunsList:
# """`Filter simulation runs <https://developer.cognite.com/api#tag/Simulation-Runs/operation/filter_simulation_runs_simulators_runs_list_post>`_

# List simulation runs

# Args:
# limit (int): The maximum number of simulation runs to return. Defaults to 100.
# filter (SimulationRunsFilter | dict[str, Any] | None): The filter that helps narrow down the list of simulation runs.

# Returns:
# SimulationRunsList: List of simulation runs

# Examples:

# List simulation runs:

# >>> from cognite.client import CogniteClient
# >>> client = CogniteClient()
# >>> res = client.simulators.runs.list()

# """
# self._warning.warn()
# return self._list(
# method="POST",
# limit=limit,
# url_path="/simulators/runs/list",
# resource_cls=SimulationRun,
# list_cls=SimulationRunsList,
# filter=filter.dump()
# if isinstance(filter, SimulationRunsFilter)
# else filter
# if isinstance(filter, dict)
# else None,
# )

# def retrieve(self, id: int | None = None) -> SimulationRun | None:
# """` Retrieve a simulation run

# Args:
# id (int | None): ID

# Returns:
# SimulationRun | None: The simulation run

# Examples:

# """
# identifier = IdentifierSequence.load(ids=id).as_singleton()
# return self._retrieve_multiple(list_cls=SimulationRunsList, resource_cls=SimulationRun, identifiers=identifier)

# def run(
# self,
# run_call: SimulationRunCall | None = None,
# wait: bool = False,
# ) -> SimulationRun:
# """`Run a simulation.

# Args:
# run_call (SimulationRunCall | None): No description.
# wait (bool): No description.

# Returns:
# SimulationRun: A simulation run object.

# """
# url = self._RESOURCE_PATH_RUN
# try:
# res = self._post(url, json={"items": [run_call]})
# response = res.json()
# run_response = response["items"][0]
# except (KeyError, IndexError, ValueError) as e:
# raise RuntimeError("Failed to parse simulation run response") from e
# run = SimulationRun._load(run_response, cognite_client=self._cognite_client)
# if wait:
# run.wait()
# return run
15 changes: 15 additions & 0 deletions cognite/client/data_classes/simulators/filters.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

from typing import Any

from cognite.client.data_classes._base import CogniteFilter
from cognite.client.utils.useful_types import SequenceNotStr

Expand All @@ -12,3 +14,16 @@ def __init__(
) -> None:
self.simulator_external_ids = simulator_external_ids
self.active = active


class SimulationRunsFilter(CogniteFilter):
def __init__(
self,
model_external_ids: SequenceNotStr[str] | None = None,
all_versions: bool | None = None,
) -> None:
self.model_external_ids = model_external_ids
self.all_versions = all_versions

def dump(self, camel_case: bool = True) -> dict[str, Any]:
return super().dump(camel_case=camel_case)
98 changes: 98 additions & 0 deletions cognite/client/data_classes/simulators/runs.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,101 @@ def dump(self, camel_case: bool = True) -> dict[str, Any]:
output["unit"] = self.unit.dump(camel_case=camel_case)

return output


# class SimulationRun(CogniteResource):
# """
# Every time a simulation routine executes, a simulation run object is created.
# This object ensures that each execution of a routine is documented and traceable.
# Each run has an associated simulation data resource, which stores the inputs and outputs of a
# simulation run, capturing the values set into and read from the simulator model to ensure
# the traceability and integrity of the simulation data.

# Simulation runs provide a historical record of the simulations performed, allowing users to analyze
# and compare different runs, track changes over time, and make informed decisions based on the simulation results.

# This is the read/response format of a simulation run.

# Args:
# cognite_client (CogniteClient | None): An instance of the Cognite client.
# simulator_external_id (str | None): External id of the associated simulator
# simulator_integration_external_id (str | None): External id of the associated simulator integration
# model_external_id (str | None): External id of the associated simulator model
# model_revision_external_id (str | None): External id of the associated simulator model revision
# routine_external_id (str | None): External id of the associated simulator routine
# routine_revision_external_id (str | None): External id of the associated simulator routine revision
# run_time (int | None): Run time in milliseconds. Reference timestamp used for data pre-processing and data sampling.
# simulation_time (int | None): Simulation time in milliseconds. Timestamp when the input data was sampled. Used for indexing input and output time series.
# status (str | None): The status of the simulation run
# status_message (str | None): The status message of the simulation run
# data_set_id (int | None): The id of the dataset associated with the simulation run
# run_type (str | None): The type of the simulation run
# user_id (str | None): The id of the user who executed the simulation run
# log_id (int | None): The id of the log associated with the simulation run
# id (int | None): A unique id of a simulation run
# created_time (int | None): The number of milliseconds since epoch
# last_updated_time (int | None): The number of milliseconds since epoch

# """

# def __init__(
# self,
# id: int,
# created_time: int,
# last_updated_time: int,
# cognite_client: CogniteClient | None = None,
# simulator_external_id: str | None = None,
# simulator_integration_external_id: str | None = None,
# model_external_id: str | None = None,
# model_revision_external_id: str | None = None,
# routine_external_id: str | None = None,
# routine_revision_external_id: str | None = None,
# run_time: int | None = None,
# simulation_time: int | None = None,
# status: str | None = None,
# status_message: str | None = None,
# data_set_id: int | None = None,
# run_type: str | None = None,
# user_id: str | None = None,
# log_id: int | None = None,
# ) -> None:
# self.id = id
# self.created_time = created_time
# self.last_updated_time = last_updated_time
# self.simulator_external_id = simulator_external_id
# self.simulator_integration_external_id = simulator_integration_external_id
# self.model_external_id = model_external_id
# self.model_revision_external_id = model_revision_external_id
# self.routine_external_id = routine_external_id
# self.routine_revision_external_id = routine_revision_external_id
# self.run_time = run_time
# self.simulation_time = simulation_time
# self.status = status
# self.status_message = status_message
# self.data_set_id = data_set_id
# self.run_type = run_type
# self.user_id = user_id
# self.log_id = log_id
# if cognite_client is not None:
# self._cognite_client = cognite_client

# @classmethod
# def _load(cls, resource: dict, cognite_client: CogniteClient | None = None) -> SimulationRun:
# return super()._load(resource, cognite_client)

# def dump(self, camel_case: bool = True) -> dict[str, Any]:
# return super().dump(camel_case=camel_case)

# def __hash__(self) -> int:
# return hash(self.id)

# def update(self) -> None:
# latest = self._cognite_client.simulators.runs.retrieve(id=self.id)
# if latest is None:
# raise RuntimeError("Unable to update the simulation run object (it was not found)")
# self.status = latest.status

# def wait(self) -> None:
# while self.status is not None and self.status.lower() == "ready":
# self.update()
# time.sleep(1.0)
24 changes: 24 additions & 0 deletions cognite/client/data_classes/simulators/simulators.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,27 @@ def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None =

class SimulatorIntegrationList(CogniteResourceList[SimulatorIntegration], IdTransformerMixin):
_RESOURCE = SimulatorIntegration


# class SimulationRunsList(CogniteResourceList[SimulationRun], IdTransformerMixin):
# _RESOURCE = SimulationRun


# class SimulationRunCall(CogniteResource):
# """A representation of a Simulation Run call.

# Args:
# routine_external_id (str | None): No description.
# routine_revision_external_id (str | None): No description.
# """

# def __init__(
# self,
# routine_external_id: str | None = None,
# routine_revision_external_id: str | None = None,
# ) -> None:
# self.routine_external_id = routine_external_id
# self.routine_revision_external_id = routine_revision_external_id

# def dump(self, camel_case: bool = True) -> dict[str, Any]:
# return super().dump(camel_case=camel_case)
50 changes: 50 additions & 0 deletions tests/tests_integration/test_api/test_simulators/test_runs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# import time
# import pytest

# from typing import TYPE_CHECKING
# from cognite.client._cognite_client import CogniteClient
# from cognite.client.data_classes.simulators.filters import SimulationRunsFilter
# from cognite.client.data_classes.simulators.simulators import SimulationRunCall

# if TYPE_CHECKING:
# from cognite.client import CogniteClient

# class TestSimulationRuns:
# def test_list_runs(self, cognite_client: CogniteClient) -> None:
# routines = cognite_client.simulators.runs.list(limit=5)

# @pytest.mark.usefixtures("seed_simulator_routine_revisions", "delete_simulator", "seed_resource_names")
# def test_create_runs(self, cognite_client: CogniteClient, seed_resource_names) -> None:
# integrations = cognite_client.simulators.integrations.list()
# assert len(integrations) > 0
# # Check if the seeded simulator integration is alive
# integration_to_check = seed_resource_names["simulator_integration_external_id"]
# integration = next((x for x in integrations if x.external_id == integration_to_check), None)
# assert integration is not None
# assert integration.heartbeat >= time.time() - 60

# run_to_create = SimulationRunCall(
# routine_external_id=seed_resource_names["simulator_routine_external_id"],
# )

# run = cognite_client.simulators.runs.run(run_to_create)
# assert run is not None
# assert run.status == "ready"

# @pytest.mark.usefixtures("seed_resource_names")
# def test_list_runs(self, cognite_client: CogniteClient, seed_resource_names) -> None:
# model_external_id = seed_resource_names["simulator_model_external_id"]
# routines = cognite_client.simulators.runs.list(
# limit=5, filter=SimulationRunsFilter(model_external_ids=[model_external_id])
# )
# assert len(routines) > 0

# @pytest.mark.usefixtures("seed_resource_names")
# async def test_run_async(self, cognite_client: CogniteClient, seed_resource_names) -> None:
# run_to_create = SimulationRunCall(
# routine_external_id=seed_resource_names["simulator_routine_external_id"],
# )

# run = cognite_client.simulators.runs.run(run_to_create)

# assert run is not None
Loading