Files
ovf/models/basic.py
2025-09-15 11:41:55 -04:00

149 lines
5.1 KiB
Python

from abc import abstractmethod
from skrf import Network
from schemas.paramer import SimulationRequestUnit, UuidResponseUnit, SimulationResponseUnit
from typing import List, Literal, Union, Dict
import requests
import time
from utils import send_get_request
from pydantic import BaseModel, Field
import itertools
import json
import numpy as np
class ModelBasicParametersUnit(BaseModel):
name: str
type: Literal["number","integer","string","boolean"]
range: List[Union[float,int,str,bool]]
class ModelBasicInfo(BaseModel):
base_url = "http://localhost:8105/api/v1"
nports: int = Field(default=2)
cell_name: str
template_name: str
user_id: int = Field(default=0)
template_version: str = Field(default="")
class ModelBasicDatasetUnit(BaseModel):
nports: int = Field(default=2)
parameters: Dict[str, Union[float, int, str, bool]]
id: int = Field(default=0)
result_dir: str = Field(default="")
@property
def network(self) -> Network:
try:
network = Network(f"{self.result_dir}/{self.id}.s{self.nports}p")
return network
except Exception as e:
raise RuntimeError(f"Error loading network from {self.result_dir}: {e}")
@property
def s_params(self) -> np.ndarray:
return self.network.s
@property
def y_params(self) -> np.ndarray:
return self.network.y
@property
def z_params(self) -> np.ndarray:
return self.network.z
@property
def freqs(self) -> np.ndarray:
return self.network.f
class ModelBasic:
def __init__(self):
self._dataset:List[ModelBasicDatasetUnit] = []
@property
@abstractmethod
def info(self)->ModelBasicInfo:
pass
@property
@abstractmethod
def parameters(self)->List[ModelBasicParametersUnit]:
pass
@property
@abstractmethod
def settings(self)->dict:
pass
def sweep(self):
parameters_list = []
lst = [res.range for res in self.parameters]
parameters_name = [res.name for res in self.parameters]
result = [list(item) for item in itertools.product(*lst)]
for res in result:
parameters_list.append({parameters_name[i]:res[i] for i in range(len(res))})
for res in parameters_list:
request_unit = SimulationRequestUnit(
user_id=self.info.user_id,
template_name=self.info.template_name,
template_version=self.info.template_version,
cell_name=self.info.cell_name,
parameters=res,
settings=self.settings
)
response = self.simulate(request_unit)
self._dataset.append(ModelBasicDatasetUnit(nports=self.info.nports,parameters=res, id=response.id, result_dir=response.result_path))
@property
def results(self)->List[ModelBasicDatasetUnit]:
return self._dataset
def export(self, path:str|None):
if path is None:
path = f"{self.info.cell_name}_dataset.json"
with open(path,"w") as f:
json.dump([dict(item) for item in self.results],f,indent=4)
def load(self, path:str|None):
if path is None:
path = f"{self.info.cell_name}_dataset.json"
with open(path,"r") as f:
data = json.load(f)
self._dataset += [ModelBasicDatasetUnit(**item) for item in data]
def clear(self):
self._dataset = []
def simulate(self,simulation_request:SimulationRequestUnit)->UuidResponseUnit:
def send_simulate_request(url, data:list)->list[dict]:
response = requests.post(url, json = data)
if response.status_code not in [200,201,202]:
raise RuntimeError(f"send_simulate_request: {response.status_code}, {response.text}")
return response.json()
response = send_simulate_request(f"{self.info.base_url}/simulations/create", [dict(simulation_request)])
simulation_response_model:SimulationResponseUnit = SimulationResponseUnit(**(response[0]))
time.sleep(0.01)
response = send_get_request(f"{self.info.base_url}/simulations/input_hash/{simulation_response_model.input_hash}")
assert isinstance(response, dict), "Response is not a dictionary."
uuid_model = UuidResponseUnit(**response)
time.sleep(0.01) # Wait for 2 seconds before checking the status again
status = uuid_model.status
while status != "completed" and status != "failed":
time.sleep(0.01) # Wait for 2 seconds before checking again
response = send_get_request(f"{self.info.base_url}/simulations/input_hash/{simulation_response_model.input_hash}")
assert isinstance(response, dict), "Response is not a dictionary."
uuid_model = UuidResponseUnit(**response)
assert response is not None, "No response received from the server."
status = uuid_model.status
if status == "failed":
raise RuntimeError(f"Simulation failed: {uuid_model.error_message}")
else:
return uuid_model