Skip to content
Merged
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
8 changes: 6 additions & 2 deletions api/data_loader_pg.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,11 @@ def _shape_run_record(row) -> Dict[str, Any]:
rec = dict(row)
for ts_field in ("run_date", "created_at"):
if rec.get(ts_field):
rec[ts_field] = rec[ts_field].isoformat()
rec[ts_field] = (
rec[ts_field].isoformat()
if hasattr(rec[ts_field], "isoformat")
else str(rec[ts_field])
)
rec["features"] = {
"Etch_AvgO2Flow": rec.pop("etch_avgo2flow", None),
"Etch_Avg_Rf1_Pow": rec.pop("etch_avg_rf1_pow", None),
Expand Down Expand Up @@ -518,7 +522,7 @@ def get_projects_list_pg(nanohub_user_id: Optional[str] = None, is_admin: bool =
records = []
for row in rows:
rec = dict(row)
if rec.get('created'):
if rec.get('created') and hasattr(rec['created'], "isoformat"):
rec['created'] = rec['created'].isoformat()
records.append(rec)

Expand Down
8 changes: 7 additions & 1 deletion api/db_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ def execute(self, query: str, params: Optional[Any] = None):
logger.info(f"[DB-MOCK] Executing query: {query[:100]}...")

# Extremely simple query router for the simulation
if "from projects" in query:
if "from equipment_metadata" in query:
self.results = self.data.get("equipment_metadata", [])
elif "from experiment_types" in query:
self.results = self.data.get("experiment_types", [])
elif "from process_definitions" in query:
self.results = self.data.get("process_definitions", [])
elif "from projects" in query:
self.results = self.data.get("projects", [])
elif "from project_members" in query:
self.results = self.data.get("project_members", [])
Expand Down
112 changes: 111 additions & 1 deletion api/local_data/mock_pg_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,119 @@
"role": "pi"
}
],
"equipment_metadata": [
{
"domain_id": "etcher",
"equipment_name": "PlasmaTherm ICP Etcher",
"equipment_type": "Etching",
"manufacturer": "PlasmaTherm",
"model": "ICP",
"location": "Birck Nanotechnology Center",
"serial_number": "DEMO-ETCHER",
"description": "Mock ICP etcher record for local Digital Twin testing.",
"source_type": "postgresql",
"connection_host": "localhost",
"connection_port": "5432",
"connection_database": "digital_twin",
"dt_mode": "full",
"outlier_method": "zscore",
"outlier_threshold": 3.0,
"owner_id": "ngholiza",
"owner_org": "Birck Nanotechnology Center",
"status": "approved",
"registered_at": "2026-04-18T20:00:00Z",
"updated_at": "2026-04-18T20:00:00Z",
"parameters_json": [
{"id": "etch_avg_rf1_pow", "name": "RF1 Power", "unit": "W"},
{"id": "etch_avgpres", "name": "Pressure", "unit": "mTorr"}
],
"columns_json": [],
"features_json": [],
"primary_target_json": {"id": "avg_etch_rate", "name": "Average Etch Rate", "unit": "nm/min"},
"secondary_target_json": {"id": "range_nm", "name": "Range", "unit": "nm"},
"config_json": {
"outputs": [
{"id": "avg_etch_rate", "name": "Average Etch Rate", "unit": "nm/min"},
{"id": "range_nm", "name": "Range", "unit": "nm"}
],
"operational_metadata": {"status": "available"}
}
}
],
"experiment_types": [
{
"id": "unit_icp_etch_demo",
"name": "ICP Etch Unit Experiment",
"description": "Mock unit experiment for ICP etching.",
"scientific_objective": "Tune etch rate while controlling range.",
"equipment_id": "etcher",
"type_parameters_json": [
{"id": "etch_avg_rf1_pow", "name": "RF1 Power", "unit": "W"},
{"id": "etch_avgpres", "name": "Pressure", "unit": "mTorr"}
],
"outputs_json": [
{"id": "avg_etch_rate", "name": "Average Etch Rate", "unit": "nm/min"},
{"id": "range_nm", "name": "Range", "unit": "nm"}
],
"additional_inputs_json": [],
"visibility": "shared",
"version": 1,
"pid": "DT-ET-DEMO",
"parent_id": "",
"forked_from": "",
"author_name": "N. Gholiza",
"author_email": "ngholiza@purdue.edu",
"primary_target": "avg_etch_rate",
"primary_objective": "maximize",
"secondary_target": "range_nm",
"secondary_objective": "minimize",
"owner_id": "ngholiza",
"owner_org": "Birck Nanotechnology Center",
"created_at": "2026-04-18T20:00:00Z",
"updated_at": "2026-04-18T20:00:00Z"
}
],
"process_definitions": [
{
"id": "process_icp_etch_demo",
"name": "ICP Etch Demo Process",
"description": "Mock reusable process for ICP etch optimization.",
"visibility": "shared",
"status": "active",
"version": 1,
"pid": "DT-PROC-DEMO",
"owner_id": "ngholiza",
"owner_org": "Birck Nanotechnology Center",
"created_at": "2026-04-18T20:00:00Z",
"updated_at": "2026-04-18T20:00:00Z",
"step_summary": [
{
"id": "step_icp_etch_demo",
"process_id": "process_icp_etch_demo",
"type_id": "unit_icp_etch_demo",
"sequence_index": 1,
"upstream_type_id": "",
"handoff_type": "manual",
"handoff_description": "Run ICP etch and inspect output metrics.",
"output_mapping": {},
"unit_experiment_name": "ICP Etch Unit Experiment",
"equipment_id": "etcher"
}
]
}
],
"etcher_runs": [
{
"idruns": 999999,
"run_id": 999999,
"project_id": "project_demo",
"lotname": "etch04/18/2026_SIM_01",
"lot_name": "etch04/18/2026_SIM_01",
"run_date": "2026-04-19T00:45:57Z",
"created_at": "2026-04-19T00:45:57Z",
"is_outlier": true,
"is_calibration_recipe": false,
"is_calibration": false,
"outlier_type": "simulation_mock",
"avg_etch_rate": 195.5,
"range_etch_rate": 3.0,
Expand All @@ -44,7 +149,12 @@
"etch_avg_rf1_pow": 400.0,
"etch_avg_rf2_pow": 50.0,
"etch_avgpres": 25.0,
"etch_avgcf4flow": 50.0
"etch_avgcf4flow": 50.0,
"project_name": "Simulation Demo Project",
"equipment_id": "etcher",
"equipment_name": "PlasmaTherm ICP Etcher",
"pi_name": "N. Gholiza",
"project_access": "open"
}
]
}
15 changes: 12 additions & 3 deletions geddes/k8s/04-ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@ spec:
port:
number: 3000

# 2. Next longest match: /api/dt goes to Next.js server-side proxy
# 2. Next longest match: /api/mcp goes to Next.js MCP endpoint
- path: /api/mcp
pathType: Prefix
backend:
service:
name: dt-web
port:
number: 3000

# 3. Next longest match: /api/dt goes to Next.js server-side proxy
- path: /api/dt
pathType: Prefix
backend:
Expand All @@ -29,7 +38,7 @@ spec:
port:
number: 3000

# 3. Next longest match: /api goes to FastAPI
# 4. Next longest match: /api goes to FastAPI
# FastAPI is natively configured to handle /api routes so no rewrite is needed!
- path: /api
pathType: Prefix
Expand All @@ -39,7 +48,7 @@ spec:
port:
number: 8000

# 4. Default match: / goes to Next.js Web App
# 5. Default match: / goes to Next.js Web App
- path: /
pathType: Prefix
backend:
Expand Down
Loading