mirror of
https://github.com/deepmodeling/Uni-Lab-OS
synced 2026-05-23 02:19:58 +00:00
Compare commits
2 Commits
633c8b3d2c
...
a1c0b83490
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1c0b83490 | ||
|
|
570d6763c0 |
@@ -424,14 +424,9 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
|
|
||||||
@action(
|
@action(
|
||||||
always_free=True,
|
always_free=True,
|
||||||
node_type=NodeType.MANUAL_CONFIRM,
|
|
||||||
placeholder_keys={"assignee_user_ids": "unilabos_manual_confirm"},
|
|
||||||
goal_default={
|
goal_default={
|
||||||
"reset_operations": ["scheduler_reset", "reset_order_status", "reset_location"],
|
"reset_operations": ["scheduler_reset", "reset_order_status", "reset_location"],
|
||||||
"timeout_seconds": 3600,
|
|
||||||
"assignee_user_ids": [],
|
|
||||||
},
|
},
|
||||||
feedback_interval=300,
|
|
||||||
description="复位小核酸实验前状态",
|
description="复位小核酸实验前状态",
|
||||||
)
|
)
|
||||||
def reset(
|
def reset(
|
||||||
@@ -439,8 +434,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
reset_operations: Optional[
|
reset_operations: Optional[
|
||||||
List[Literal["scheduler_reset", "reset_order_status", "reset_location"]]
|
List[Literal["scheduler_reset", "reset_order_status", "reset_location"]]
|
||||||
] = None,
|
] = None,
|
||||||
timeout_seconds: int = 3600,
|
|
||||||
assignee_user_ids: Optional[List[str]] = None,
|
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""复位调度器、订单状态和库位,并按清理读回结果决定是否 take-out。"""
|
"""复位调度器、订单状态和库位,并按清理读回结果决定是否 take-out。"""
|
||||||
@@ -451,7 +444,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
api_host = self._kwarg_text(kwargs, "api_host")
|
api_host = self._kwarg_text(kwargs, "api_host")
|
||||||
api_key = self._kwarg_text(kwargs, "api_key")
|
api_key = self._kwarg_text(kwargs, "api_key")
|
||||||
ready_signal = self._kwarg_text(kwargs, "ready_signal") or DEFAULT_READY_SIGNAL
|
ready_signal = self._kwarg_text(kwargs, "ready_signal") or DEFAULT_READY_SIGNAL
|
||||||
del timeout_seconds, assignee_user_ids
|
|
||||||
self._update_runtime_api_config(api_host=api_host, api_key=api_key)
|
self._update_runtime_api_config(api_host=api_host, api_key=api_key)
|
||||||
self._require_ready_signal(ready_signal)
|
self._require_ready_signal(ready_signal)
|
||||||
rpc = self._require_hardware_interface_for_reset()
|
rpc = self._require_hardware_interface_for_reset()
|
||||||
@@ -616,14 +608,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
|
|
||||||
@action(
|
@action(
|
||||||
always_free=True,
|
always_free=True,
|
||||||
node_type=NodeType.MANUAL_CONFIRM,
|
|
||||||
placeholder_keys={"assignee_user_ids": "unilabos_manual_confirm"},
|
|
||||||
goal_default={
|
|
||||||
"optional_params": {"auto_register_materials": True},
|
|
||||||
"timeout_seconds": 3600,
|
|
||||||
"assignee_user_ids": [],
|
|
||||||
},
|
|
||||||
feedback_interval=300,
|
|
||||||
description="提交小核酸实验1(报告基因检测)",
|
description="提交小核酸实验1(报告基因检测)",
|
||||||
handles=[
|
handles=[
|
||||||
ActionOutputHandle(
|
ActionOutputHandle(
|
||||||
@@ -671,14 +655,20 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
data_key="mount_resource",
|
data_key="mount_resource",
|
||||||
data_source=DataSource.EXECUTOR,
|
data_source=DataSource.EXECUTOR,
|
||||||
),
|
),
|
||||||
|
ActionOutputHandle(
|
||||||
|
key="resultTable",
|
||||||
|
data_type="object",
|
||||||
|
label="物料装载结果表",
|
||||||
|
data_key="resultTable",
|
||||||
|
data_source=DataSource.EXECUTOR,
|
||||||
|
io_type="target",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def submit_experiment_1(
|
def submit_experiment_1(
|
||||||
self,
|
self,
|
||||||
required_params: Experiment1RequiredParams,
|
required_params: Experiment1RequiredParams,
|
||||||
optional_params: Optional[Experiment1OptionalParams] = None,
|
optional_params: Optional[Experiment1OptionalParams] = None,
|
||||||
timeout_seconds: int = 3600,
|
|
||||||
assignee_user_ids: Optional[List[str]] = None,
|
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""提交小核酸实验1(报告基因检测)到 Bioyond LIMS。
|
"""提交小核酸实验1(报告基因检测)到 Bioyond LIMS。
|
||||||
@@ -722,8 +712,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
order_name=str(optional_params.get("order_name", "") or ""),
|
order_name=str(optional_params.get("order_name", "") or ""),
|
||||||
parameter_overrides=optional_params.get("parameter_overrides", ""),
|
parameter_overrides=optional_params.get("parameter_overrides", ""),
|
||||||
auto_register_materials=bool(optional_params.get("auto_register_materials", True)),
|
auto_register_materials=bool(optional_params.get("auto_register_materials", True)),
|
||||||
timeout_seconds=timeout_seconds,
|
|
||||||
assignee_user_ids=assignee_user_ids,
|
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -765,14 +753,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
|
|
||||||
@action(
|
@action(
|
||||||
always_free=True,
|
always_free=True,
|
||||||
node_type=NodeType.MANUAL_CONFIRM,
|
|
||||||
placeholder_keys={"assignee_user_ids": "unilabos_manual_confirm"},
|
|
||||||
goal_default={
|
|
||||||
"optional_params": {"auto_register_materials": True},
|
|
||||||
"timeout_seconds": 3600,
|
|
||||||
"assignee_user_ids": [],
|
|
||||||
},
|
|
||||||
feedback_interval=300,
|
|
||||||
description="提交小核酸实验2(基因表达检测)",
|
description="提交小核酸实验2(基因表达检测)",
|
||||||
handles=[
|
handles=[
|
||||||
ActionOutputHandle(
|
ActionOutputHandle(
|
||||||
@@ -815,14 +795,20 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
data_key="mount_resource",
|
data_key="mount_resource",
|
||||||
data_source=DataSource.EXECUTOR,
|
data_source=DataSource.EXECUTOR,
|
||||||
),
|
),
|
||||||
|
ActionOutputHandle(
|
||||||
|
key="resultTable",
|
||||||
|
data_type="object",
|
||||||
|
label="物料装载结果表",
|
||||||
|
data_key="resultTable",
|
||||||
|
data_source=DataSource.EXECUTOR,
|
||||||
|
io_type="target",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def submit_experiment_2(
|
def submit_experiment_2(
|
||||||
self,
|
self,
|
||||||
required_params: Experiment2RequiredParams,
|
required_params: Experiment2RequiredParams,
|
||||||
optional_params: Optional[Experiment2OptionalParams] = None,
|
optional_params: Optional[Experiment2OptionalParams] = None,
|
||||||
timeout_seconds: int = 3600,
|
|
||||||
assignee_user_ids: Optional[List[str]] = None,
|
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""提交小核酸实验2(基因表达检测)到 Bioyond LIMS。"""
|
"""提交小核酸实验2(基因表达检测)到 Bioyond LIMS。"""
|
||||||
@@ -841,8 +827,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
order_name=str(optional_params.get("order_name", "") or ""),
|
order_name=str(optional_params.get("order_name", "") or ""),
|
||||||
parameter_overrides=optional_params.get("parameter_overrides", ""),
|
parameter_overrides=optional_params.get("parameter_overrides", ""),
|
||||||
auto_register_materials=bool(optional_params.get("auto_register_materials", True)),
|
auto_register_materials=bool(optional_params.get("auto_register_materials", True)),
|
||||||
timeout_seconds=timeout_seconds,
|
|
||||||
assignee_user_ids=assignee_user_ids,
|
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -857,8 +841,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
order_name: str,
|
order_name: str,
|
||||||
parameter_overrides: Any,
|
parameter_overrides: Any,
|
||||||
auto_register_materials: bool,
|
auto_register_materials: bool,
|
||||||
timeout_seconds: int = 3600,
|
|
||||||
assignee_user_ids: Optional[List[str]] = None,
|
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
with self._debug_call_session(action_name):
|
with self._debug_call_session(action_name):
|
||||||
@@ -882,7 +864,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
bool(parameter_overrides),
|
bool(parameter_overrides),
|
||||||
)
|
)
|
||||||
|
|
||||||
del timeout_seconds, assignee_user_ids, kwargs
|
|
||||||
rpc = self._require_hardware_interface("create_order")
|
rpc = self._require_hardware_interface("create_order")
|
||||||
workflow = self._resolve_experiment_workflow(
|
workflow = self._resolve_experiment_workflow(
|
||||||
rpc,
|
rpc,
|
||||||
@@ -1004,6 +985,10 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
"manual_load_tables": self._build_manual_load_tables(
|
"manual_load_tables": self._build_manual_load_tables(
|
||||||
confirmation_data.get("materials_by_type", {})
|
confirmation_data.get("materials_by_type", {})
|
||||||
),
|
),
|
||||||
|
"resultTable": self._build_result_table(
|
||||||
|
confirmation_data.get("materials_by_type", {}),
|
||||||
|
table_name="物料放置指引",
|
||||||
|
),
|
||||||
"manual_load_probe": self._build_manual_load_probe(
|
"manual_load_probe": self._build_manual_load_probe(
|
||||||
confirmation_data.get("materials_by_type", {})
|
confirmation_data.get("materials_by_type", {})
|
||||||
),
|
),
|
||||||
@@ -1069,6 +1054,7 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
"target_device": "unilabos_devices",
|
"target_device": "unilabos_devices",
|
||||||
"resource": "unilabos_resources",
|
"resource": "unilabos_resources",
|
||||||
"mount_resource": "unilabos_resources",
|
"mount_resource": "unilabos_resources",
|
||||||
|
"resultTable": "unilabos_manual_confirm",
|
||||||
"assignee_user_ids": "unilabos_manual_confirm",
|
"assignee_user_ids": "unilabos_manual_confirm",
|
||||||
},
|
},
|
||||||
goal_default={
|
goal_default={
|
||||||
@@ -1115,6 +1101,14 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
data_source=DataSource.HANDLE,
|
data_source=DataSource.HANDLE,
|
||||||
io_type="source",
|
io_type="source",
|
||||||
),
|
),
|
||||||
|
ActionInputHandle(
|
||||||
|
key="resultTable",
|
||||||
|
data_type="object",
|
||||||
|
label="物料装载结果表",
|
||||||
|
data_key="resultTable",
|
||||||
|
data_source=DataSource.HANDLE,
|
||||||
|
io_type="source",
|
||||||
|
),
|
||||||
# Order metadata for scheduler start.
|
# Order metadata for scheduler start.
|
||||||
ActionInputHandle(
|
ActionInputHandle(
|
||||||
key="order_id", data_type="bioyond_order_id",
|
key="order_id", data_type="bioyond_order_id",
|
||||||
@@ -1139,6 +1133,7 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
resource: Optional[List[ResourceSlot]] = None,
|
resource: Optional[List[ResourceSlot]] = None,
|
||||||
coin_cell_code: Optional[List[str]] = None,
|
coin_cell_code: Optional[List[str]] = None,
|
||||||
mount_resource: Optional[List[ResourceSlot]] = None,
|
mount_resource: Optional[List[ResourceSlot]] = None,
|
||||||
|
resultTable: Optional[Dict[str, Any]] = None,
|
||||||
order_id: str = "",
|
order_id: str = "",
|
||||||
materials_loaded: bool = False,
|
materials_loaded: bool = False,
|
||||||
timeout_seconds: int = 3600,
|
timeout_seconds: int = 3600,
|
||||||
@@ -1152,6 +1147,7 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
resource: 上游句柄提供的待装载物料显示值。
|
resource: 上游句柄提供的待装载物料显示值。
|
||||||
coin_cell_code: 上游句柄提供的临时物料名称列。
|
coin_cell_code: 上游句柄提供的临时物料名称列。
|
||||||
mount_resource: 上游句柄提供的临时库位列。
|
mount_resource: 上游句柄提供的临时库位列。
|
||||||
|
resultTable: 上游句柄提供的新格式结果表(data/columns/tableName)。
|
||||||
order_id: 上游 ``submit_experiment_1`` 创建的订单 ID(可选;若上游连接则自动传入)。
|
order_id: 上游 ``submit_experiment_1`` 创建的订单 ID(可选;若上游连接则自动传入)。
|
||||||
materials_loaded: 操作员勾选确认物料已装载。未勾选且存在物料显示则阻断启动。
|
materials_loaded: 操作员勾选确认物料已装载。未勾选且存在物料显示则阻断启动。
|
||||||
timeout_seconds: 超时时间(秒,框架参数)。
|
timeout_seconds: 超时时间(秒,框架参数)。
|
||||||
@@ -3259,6 +3255,75 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
}
|
}
|
||||||
return tables
|
return tables
|
||||||
|
|
||||||
|
def _build_result_table(
|
||||||
|
self,
|
||||||
|
materials_by_type: Dict[str, List[Dict[str, Any]]],
|
||||||
|
table_name: str = "resultTable",
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""构建新的前端结果表格 schema(data/columns/tableName 结构)。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
materials_by_type: 按模式分组的物料(Sample/Consumables/Reagent)
|
||||||
|
table_name: 前端表格标识符
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
包含以下键的字典: data(行对象列表)、columns(列规格列表)、tableName
|
||||||
|
"""
|
||||||
|
# 展平所有类型的物料
|
||||||
|
all_materials = []
|
||||||
|
for mode in ("Sample", "Consumables", "Reagent"):
|
||||||
|
all_materials.extend(materials_by_type.get(mode, []))
|
||||||
|
|
||||||
|
# 为每个物料解析仓库名称
|
||||||
|
warehouse_inventory_cache: Dict[str, List[Dict[str, Any]]] = {}
|
||||||
|
material_info_cache: Dict[str, Dict[str, Any]] = {}
|
||||||
|
|
||||||
|
data_rows = []
|
||||||
|
for mat in all_materials:
|
||||||
|
# 从 materialId 解析仓库名称
|
||||||
|
try:
|
||||||
|
resolved = self._resolve_material_record_to_warehouse(
|
||||||
|
mat,
|
||||||
|
warehouse_inventory_cache=warehouse_inventory_cache,
|
||||||
|
material_info_cache=material_info_cache,
|
||||||
|
)
|
||||||
|
wh_name = resolved.get("warehouse_name", "")
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning(
|
||||||
|
"无法解析仓库名称: materialId=%s, error=%s",
|
||||||
|
mat.get("materialId"),
|
||||||
|
exc,
|
||||||
|
)
|
||||||
|
wh_name = ""
|
||||||
|
|
||||||
|
data_rows.append({
|
||||||
|
"whName": wh_name,
|
||||||
|
"locationCode": str(mat.get("locationShowName") or mat.get("locationCode") or ""),
|
||||||
|
"materialName": str(mat.get("materialName") or ""),
|
||||||
|
"quantity": str(mat.get("quantity") or ""),
|
||||||
|
})
|
||||||
|
|
||||||
|
# 定义列 schema
|
||||||
|
columns = [
|
||||||
|
{"name": "设备", "key": "whName"},
|
||||||
|
{"name": "位置", "key": "locationCode"},
|
||||||
|
{"name": "物料名称", "key": "materialName"},
|
||||||
|
{"name": "数量", "key": "quantity"},
|
||||||
|
]
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
"构建结果表格: tableName=%s, columns=%s, dataRows=%s",
|
||||||
|
table_name,
|
||||||
|
columns,
|
||||||
|
data_rows,
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"data": data_rows,
|
||||||
|
"columns": columns,
|
||||||
|
"tableName": table_name,
|
||||||
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _manual_load_resource_stub(
|
def _manual_load_resource_stub(
|
||||||
row: Dict[str, Any],
|
row: Dict[str, Any],
|
||||||
|
|||||||
Reference in New Issue
Block a user