mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-17 13:01:12 +00:00
modify bioyond/plr converter, bioyond resource registry, and tests
This commit is contained in:
265
test/resources/bioyond_materials_liquidhandling_1.json
Normal file
265
test/resources/bioyond_materials_liquidhandling_1.json
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "3a1c62c4-c3d2-b803-b72d-7f1153ffef3b",
|
||||||
|
"typeName": "试剂瓶",
|
||||||
|
"code": "0004-00050",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "NMP",
|
||||||
|
"quantity": 287.16699029126215,
|
||||||
|
"lockQuantity": 285.16699029126215,
|
||||||
|
"unit": "毫升",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"id": "3a14198c-c2d0-efce-0939-69ca5a7dfd39",
|
||||||
|
"whid": "3a14198c-c2cc-0290-e086-44a428fba248",
|
||||||
|
"whName": "试剂堆栈",
|
||||||
|
"code": "0001-0008",
|
||||||
|
"x": 2,
|
||||||
|
"y": 4,
|
||||||
|
"z": 1,
|
||||||
|
"quantity": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-0e03-1bc1-1296-dae1905c4108",
|
||||||
|
"typeName": "试剂瓶",
|
||||||
|
"code": "0004-00052",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "NMP",
|
||||||
|
"quantity": 386.8990291262136,
|
||||||
|
"lockQuantity": 45.89902912621359,
|
||||||
|
"unit": "毫升",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"id": "3a14198c-c2d0-f3e7-871a-e470d144296f",
|
||||||
|
"whid": "3a14198c-c2cc-0290-e086-44a428fba248",
|
||||||
|
"whName": "试剂堆栈",
|
||||||
|
"code": "0001-0005",
|
||||||
|
"x": 2,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"quantity": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-0e03-68a4-bcb3-02fc6ba72d1b",
|
||||||
|
"typeName": "试剂瓶",
|
||||||
|
"code": "0004-00053",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "NMP",
|
||||||
|
"quantity": 400.0,
|
||||||
|
"lockQuantity": 0.0,
|
||||||
|
"unit": "",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"id": "3a14198c-c2d0-2070-efc8-44e245f10c6f",
|
||||||
|
"whid": "3a14198c-c2cc-0290-e086-44a428fba248",
|
||||||
|
"whName": "试剂堆栈",
|
||||||
|
"code": "0001-0006",
|
||||||
|
"x": 2,
|
||||||
|
"y": 2,
|
||||||
|
"z": 1,
|
||||||
|
"quantity": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-3fa1-cc72-fda6276ae38d",
|
||||||
|
"typeName": "10%分装小瓶",
|
||||||
|
"code": "0005-00513",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "10%分装小瓶",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 1.0,
|
||||||
|
"unit": "个",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-561f-73b6-f8501f814dbb",
|
||||||
|
"typeName": "90%分装小瓶",
|
||||||
|
"code": "0006-00497",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "90%分装小瓶",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 1.0,
|
||||||
|
"unit": "个",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-81cf-7dad-2e51cab9ffd6",
|
||||||
|
"typeName": "90%分装小瓶",
|
||||||
|
"code": "0006-00496",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "90%分装小瓶",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 1.0,
|
||||||
|
"unit": "个",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-94ae-f770-27847e73ad38",
|
||||||
|
"typeName": "90%分装小瓶",
|
||||||
|
"code": "0006-00498",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "90%分装小瓶",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 1.0,
|
||||||
|
"unit": "个",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-c632-c7da-02d385b18628",
|
||||||
|
"typeName": "10%分装小瓶",
|
||||||
|
"code": "0005-00514",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "10%分装小瓶",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 1.0,
|
||||||
|
"unit": "个",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-d850-5439-4499f20f07fe",
|
||||||
|
"typeName": "分装板",
|
||||||
|
"code": "0007-00185",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "1010",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 2.0,
|
||||||
|
"unit": "块",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"id": "3a14198e-6929-46fe-841e-03dd753f1e4a",
|
||||||
|
"whid": "3a14198e-6928-121f-7ca6-88ad3ae7e6a0",
|
||||||
|
"whName": "粉末堆栈",
|
||||||
|
"code": "0002-0009",
|
||||||
|
"x": 3,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"quantity": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-28a4-f5d0-f7e2436c575f",
|
||||||
|
"detailMaterialId": "3a1cdefe-d5e0-94ae-f770-27847e73ad38",
|
||||||
|
"code": null,
|
||||||
|
"name": "90%分装小瓶",
|
||||||
|
"quantity": "1",
|
||||||
|
"lockQuantity": "1",
|
||||||
|
"unit": "个",
|
||||||
|
"x": 2,
|
||||||
|
"y": 3,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-3ed6-3607-133df89baf5b",
|
||||||
|
"detailMaterialId": "3a1cdefe-d5e0-f2fa-66bf-94c565d852fb",
|
||||||
|
"code": null,
|
||||||
|
"name": "10%分装小瓶",
|
||||||
|
"quantity": "1",
|
||||||
|
"lockQuantity": "1",
|
||||||
|
"unit": "个",
|
||||||
|
"x": 1,
|
||||||
|
"y": 3,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-72b6-e015-be7b93cf09eb",
|
||||||
|
"detailMaterialId": "3a1cdefe-d5e0-81cf-7dad-2e51cab9ffd6",
|
||||||
|
"code": null,
|
||||||
|
"name": "90%分装小瓶",
|
||||||
|
"quantity": "1",
|
||||||
|
"lockQuantity": "1",
|
||||||
|
"unit": "个",
|
||||||
|
"x": 2,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-81d3-ad30-48134afc9ce7",
|
||||||
|
"detailMaterialId": "3a1cdefe-d5e0-3fa1-cc72-fda6276ae38d",
|
||||||
|
"code": null,
|
||||||
|
"name": "10%分装小瓶",
|
||||||
|
"quantity": "1",
|
||||||
|
"lockQuantity": "1",
|
||||||
|
"unit": "个",
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-dbdf-d966-9a8926fe1e06",
|
||||||
|
"detailMaterialId": "3a1cdefe-d5e0-c632-c7da-02d385b18628",
|
||||||
|
"code": null,
|
||||||
|
"name": "10%分装小瓶",
|
||||||
|
"quantity": "1",
|
||||||
|
"lockQuantity": "1",
|
||||||
|
"unit": "个",
|
||||||
|
"x": 1,
|
||||||
|
"y": 2,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-f099-b260-e3089a2d08c3",
|
||||||
|
"detailMaterialId": "3a1cdefe-d5e0-561f-73b6-f8501f814dbb",
|
||||||
|
"code": null,
|
||||||
|
"name": "90%分装小瓶",
|
||||||
|
"quantity": "1",
|
||||||
|
"lockQuantity": "1",
|
||||||
|
"unit": "个",
|
||||||
|
"x": 2,
|
||||||
|
"y": 2,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdefe-d5e0-f2fa-66bf-94c565d852fb",
|
||||||
|
"typeName": "10%分装小瓶",
|
||||||
|
"code": "0005-00515",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "10%分装小瓶",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 1.0,
|
||||||
|
"unit": "个",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
}
|
||||||
|
]
|
||||||
216
test/resources/bioyond_materials_liquidhandling_2.json
Normal file
216
test/resources/bioyond_materials_liquidhandling_2.json
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "3a1cde21-a4f4-4f95-6221-eaafc2ae6a8d",
|
||||||
|
"typeName": "样品瓶",
|
||||||
|
"code": "0002-00407",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "ODA",
|
||||||
|
"quantity": 25.0,
|
||||||
|
"lockQuantity": 2.0,
|
||||||
|
"unit": "克",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cde21-a4f4-7887-9258-e8f8ab7c8a7a",
|
||||||
|
"typeName": "样品板",
|
||||||
|
"code": "0008-00160",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "1010sample",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 27.69187,
|
||||||
|
"unit": "块",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"id": "3a14198e-6929-4379-affa-9a2935c17f99",
|
||||||
|
"whid": "3a14198e-6928-121f-7ca6-88ad3ae7e6a0",
|
||||||
|
"whName": "粉末堆栈",
|
||||||
|
"code": "0002-0002",
|
||||||
|
"x": 1,
|
||||||
|
"y": 2,
|
||||||
|
"z": 1,
|
||||||
|
"quantity": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"id": "3a1cde21-a4f4-0339-f2b6-8e680ad7e8c7",
|
||||||
|
"detailMaterialId": "3a1cde21-a4f4-ab37-f7a2-ecc3bc083e7c",
|
||||||
|
"code": null,
|
||||||
|
"name": "MPDA",
|
||||||
|
"quantity": "10.505",
|
||||||
|
"lockQuantity": "-0.0174",
|
||||||
|
"unit": "克",
|
||||||
|
"x": 2,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cde21-a4f4-a21a-23cf-bb7857b41947",
|
||||||
|
"detailMaterialId": "3a1cde21-a4f4-99c7-55e7-c80c7320e300",
|
||||||
|
"code": null,
|
||||||
|
"name": "ODA",
|
||||||
|
"quantity": "1.795",
|
||||||
|
"lockQuantity": "2.0093",
|
||||||
|
"unit": "克",
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cde21-a4f4-af1b-ba0b-2874836800e9",
|
||||||
|
"detailMaterialId": "3a1cde21-a4f4-4f95-6221-eaafc2ae6a8d",
|
||||||
|
"code": null,
|
||||||
|
"name": "ODA",
|
||||||
|
"quantity": "25",
|
||||||
|
"lockQuantity": "2",
|
||||||
|
"unit": "克",
|
||||||
|
"x": 1,
|
||||||
|
"y": 2,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cde21-a4f4-99c7-55e7-c80c7320e300",
|
||||||
|
"typeName": "样品瓶",
|
||||||
|
"code": "0002-00406",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "ODA",
|
||||||
|
"quantity": 1.795,
|
||||||
|
"lockQuantity": 2.00927,
|
||||||
|
"unit": "克",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cde21-a4f4-ab37-f7a2-ecc3bc083e7c",
|
||||||
|
"typeName": "样品瓶",
|
||||||
|
"code": "0002-00408",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "MPDA",
|
||||||
|
"quantity": 10.505,
|
||||||
|
"lockQuantity": -0.0174,
|
||||||
|
"unit": "克",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdeff-c92a-08f6-c822-732ab734154c",
|
||||||
|
"typeName": "样品板",
|
||||||
|
"code": "0008-00161",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "1010sample2",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"lockQuantity": 3.0,
|
||||||
|
"unit": "块",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"id": "3a14198e-6929-31f0-8a22-0f98f72260df",
|
||||||
|
"whid": "3a14198e-6928-121f-7ca6-88ad3ae7e6a0",
|
||||||
|
"whName": "粉末堆栈",
|
||||||
|
"code": "0002-0001",
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"quantity": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"id": "3a1cdeff-c92b-3ace-9623-0bcdef6fa07d",
|
||||||
|
"detailMaterialId": "3a1cdeff-c92b-d084-2a96-5d62746d9321",
|
||||||
|
"code": null,
|
||||||
|
"name": "BTDA1",
|
||||||
|
"quantity": "0.362",
|
||||||
|
"lockQuantity": "14.494",
|
||||||
|
"unit": "克",
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdeff-c92b-856e-f481-792b91b6dbde",
|
||||||
|
"detailMaterialId": "3a1cdeff-c92b-30f2-f907-8f5e2fe0586b",
|
||||||
|
"code": null,
|
||||||
|
"name": "BTDA3",
|
||||||
|
"quantity": "1.935",
|
||||||
|
"lockQuantity": "13.067",
|
||||||
|
"unit": "克",
|
||||||
|
"x": 1,
|
||||||
|
"y": 2,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdeff-c92b-d144-c5e5-ab9d94e21187",
|
||||||
|
"detailMaterialId": "3a1cdeff-c92b-519f-a70f-0bb71af537a7",
|
||||||
|
"code": null,
|
||||||
|
"name": "BTDA2",
|
||||||
|
"quantity": "1.903",
|
||||||
|
"lockQuantity": "13.035",
|
||||||
|
"unit": "克",
|
||||||
|
"x": 2,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1,
|
||||||
|
"associateId": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdeff-c92b-30f2-f907-8f5e2fe0586b",
|
||||||
|
"typeName": "样品瓶",
|
||||||
|
"code": "0002-00411",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "BTDA3",
|
||||||
|
"quantity": 1.935,
|
||||||
|
"lockQuantity": 13.067,
|
||||||
|
"unit": "克",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdeff-c92b-519f-a70f-0bb71af537a7",
|
||||||
|
"typeName": "样品瓶",
|
||||||
|
"code": "0002-00410",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "BTDA2",
|
||||||
|
"quantity": 1.903,
|
||||||
|
"lockQuantity": 13.035,
|
||||||
|
"unit": "克",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a1cdeff-c92b-d084-2a96-5d62746d9321",
|
||||||
|
"typeName": "样品瓶",
|
||||||
|
"code": "0002-00409",
|
||||||
|
"barCode": "",
|
||||||
|
"name": "BTDA1",
|
||||||
|
"quantity": 0.362,
|
||||||
|
"lockQuantity": 14.494,
|
||||||
|
"unit": "克",
|
||||||
|
"status": 1,
|
||||||
|
"isUse": false,
|
||||||
|
"locations": [],
|
||||||
|
"detail": []
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
[
|
||||||
"data": [
|
|
||||||
{
|
{
|
||||||
"id": "3a1c67a9-aed7-b94d-9e24-bfdf10c8baa9",
|
"id": "3a1c67a9-aed7-b94d-9e24-bfdf10c8baa9",
|
||||||
"typeName": "烧杯",
|
"typeName": "烧杯",
|
||||||
@@ -191,8 +190,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"code": 1,
|
|
||||||
"message": "",
|
|
||||||
"timestamp": 1758560573511
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@ import pytest
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from pylabrobot.resources import Resource as ResourcePLR
|
||||||
from unilabos.resources.graphio import resource_bioyond_to_plr
|
from unilabos.resources.graphio import resource_bioyond_to_plr
|
||||||
from unilabos.registry.registry import lab_registry
|
from unilabos.registry.registry import lab_registry
|
||||||
|
|
||||||
@@ -14,22 +15,62 @@ type_mapping = {
|
|||||||
"烧杯": "BIOYOND_PolymerStation_1FlaskCarrier",
|
"烧杯": "BIOYOND_PolymerStation_1FlaskCarrier",
|
||||||
"试剂瓶": "BIOYOND_PolymerStation_1BottleCarrier",
|
"试剂瓶": "BIOYOND_PolymerStation_1BottleCarrier",
|
||||||
"样品板": "BIOYOND_PolymerStation_6VialCarrier",
|
"样品板": "BIOYOND_PolymerStation_6VialCarrier",
|
||||||
|
"分装板": "BIOYOND_PolymerStation_6VialCarrier",
|
||||||
|
"样品瓶": "BIOYOND_PolymerStation_Solid_Stock",
|
||||||
|
"90%分装小瓶": "BIOYOND_PolymerStation_Solid_Vial",
|
||||||
|
"10%分装小瓶": "BIOYOND_PolymerStation_Liquid_Vial",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type_uuid_mapping = {
|
||||||
|
"烧杯": "BIOYOND_PolymerStation_1FlaskCarrier",
|
||||||
|
"试剂瓶": "BIOYOND_PolymerStation_1BottleCarrier",
|
||||||
|
"样品板": "BIOYOND_PolymerStation_6VialCarrier",
|
||||||
|
"分装板": "3a14196e-5dfe-6e21-0c79-fe2036d052c4",
|
||||||
|
"样品瓶": "3a14196a-cf7d-8aea-48d8-b9662c7dba94",
|
||||||
|
"90%分装小瓶": "3a14196c-cdcf-088d-dc7d-5cf38f0ad9ea",
|
||||||
|
"10%分装小瓶": "3a14196c-76be-2279-4e22-7310d69aed68",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def bioyond_materials() -> list[dict]:
|
def bioyond_materials_reaction() -> list[dict]:
|
||||||
print("加载 BioYond 物料数据...")
|
print("加载 BioYond 物料数据...")
|
||||||
print(os.getcwd())
|
print(os.getcwd())
|
||||||
with open("bioyond_materials.json", "r", encoding="utf-8") as f:
|
with open("bioyond_materials_reaction.json", "r", encoding="utf-8") as f:
|
||||||
data = json.load(f)["data"]
|
data = json.load(f)
|
||||||
print(f"加载了 {len(data)} 条物料数据")
|
print(f"加载了 {len(data)} 条物料数据")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def test_bioyond_to_plr(bioyond_materials) -> list[dict]:
|
@pytest.fixture
|
||||||
|
def bioyond_materials_liquidhandling_1() -> list[dict]:
|
||||||
|
print("加载 BioYond 物料数据...")
|
||||||
|
print(os.getcwd())
|
||||||
|
with open("bioyond_materials_liquidhandling_1.json", "r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
print(f"加载了 {len(data)} 条物料数据")
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def bioyond_materials_liquidhandling_2() -> list[dict]:
|
||||||
|
print("加载 BioYond 物料数据...")
|
||||||
|
print(os.getcwd())
|
||||||
|
with open("bioyond_materials_liquidhandling_2.json", "r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
print(f"加载了 {len(data)} 条物料数据")
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("materials_fixture", [
|
||||||
|
"bioyond_materials_reaction",
|
||||||
|
"bioyond_materials_liquidhandling_1",
|
||||||
|
])
|
||||||
|
def test_bioyond_to_plr(materials_fixture, request) -> list[dict]:
|
||||||
|
materials = request.getfixturevalue(materials_fixture)
|
||||||
deck = BIOYOND_PolymerReactionStation_Deck("test_deck")
|
deck = BIOYOND_PolymerReactionStation_Deck("test_deck")
|
||||||
print("将 BioYond 物料数据转换为 PLR 格式...")
|
output = resource_bioyond_to_plr(materials, type_mapping=type_mapping, deck=deck)
|
||||||
output = resource_bioyond_to_plr(bioyond_materials, type_mapping=type_mapping, deck=deck)
|
|
||||||
print(deck.summary())
|
print(deck.summary())
|
||||||
print([resource.serialize() for resource in output])
|
print([resource.serialize() for resource in output])
|
||||||
print([resource.serialize_all_state() for resource in output])
|
print([resource.serialize_all_state() for resource in output])
|
||||||
|
json.dump(deck.serialize(), open("test.json", "w", encoding="utf-8"), indent=4)
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
from pylabrobot.resources import create_homogeneous_resources, Coordinate, ResourceHolder, create_ordered_items_2d
|
from pylabrobot.resources import create_homogeneous_resources, Coordinate, ResourceHolder, create_ordered_items_2d
|
||||||
|
|
||||||
from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
|
from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
|
||||||
from unilabos.resources.bioyond.bottles import BIOYOND_PolymerStation_Solid_Vial, BIOYOND_PolymerStation_Solution_Beaker, BIOYOND_PolymerStation_Reagent_Bottle
|
from unilabos.resources.bioyond.bottles import (
|
||||||
|
BIOYOND_PolymerStation_Solid_Stock,
|
||||||
|
BIOYOND_PolymerStation_Solid_Vial,
|
||||||
|
BIOYOND_PolymerStation_Liquid_Vial,
|
||||||
|
BIOYOND_PolymerStation_Solution_Beaker,
|
||||||
|
BIOYOND_PolymerStation_Reagent_Bottle
|
||||||
|
)
|
||||||
# 命名约定:试剂瓶-Bottle,烧杯-Beaker,烧瓶-Flask,小瓶-Vial
|
# 命名约定:试剂瓶-Bottle,烧杯-Beaker,烧瓶-Flask,小瓶-Vial
|
||||||
|
|
||||||
|
|
||||||
@@ -92,6 +98,57 @@ def BIOYOND_Electrolyte_1BottleCarrier(name: str) -> BottleCarrier:
|
|||||||
return carrier
|
return carrier
|
||||||
|
|
||||||
|
|
||||||
|
def BIOYOND_PolymerStation_6StockCarrier(name: str) -> BottleCarrier:
|
||||||
|
"""6瓶载架 - 2x3布局"""
|
||||||
|
|
||||||
|
# 载架尺寸 (mm)
|
||||||
|
carrier_size_x = 127.8
|
||||||
|
carrier_size_y = 85.5
|
||||||
|
carrier_size_z = 50.0
|
||||||
|
|
||||||
|
# 瓶位尺寸
|
||||||
|
bottle_diameter = 20.0
|
||||||
|
bottle_spacing_x = 42.0 # X方向间距
|
||||||
|
bottle_spacing_y = 35.0 # Y方向间距
|
||||||
|
|
||||||
|
# 计算起始位置 (居中排列)
|
||||||
|
start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||||
|
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
|
||||||
|
|
||||||
|
sites = create_ordered_items_2d(
|
||||||
|
klass=ResourceHolder,
|
||||||
|
num_items_x=3,
|
||||||
|
num_items_y=2,
|
||||||
|
dx=start_x,
|
||||||
|
dy=start_y,
|
||||||
|
dz=5.0,
|
||||||
|
item_dx=bottle_spacing_x,
|
||||||
|
item_dy=bottle_spacing_y,
|
||||||
|
|
||||||
|
size_x=bottle_diameter,
|
||||||
|
size_y=bottle_diameter,
|
||||||
|
size_z=carrier_size_z,
|
||||||
|
)
|
||||||
|
for k, v in sites.items():
|
||||||
|
v.name = f"{name}_{v.name}"
|
||||||
|
|
||||||
|
carrier = BottleCarrier(
|
||||||
|
name=name,
|
||||||
|
size_x=carrier_size_x,
|
||||||
|
size_y=carrier_size_y,
|
||||||
|
size_z=carrier_size_z,
|
||||||
|
sites=sites,
|
||||||
|
model="BIOYOND_PolymerStation_6VialCarrier",
|
||||||
|
)
|
||||||
|
carrier.num_items_x = 3
|
||||||
|
carrier.num_items_y = 2
|
||||||
|
carrier.num_items_z = 1
|
||||||
|
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
|
||||||
|
for i in range(6):
|
||||||
|
carrier[i] = BIOYOND_PolymerStation_Solid_Stock(f"{name}_vial_{ordering[i]}")
|
||||||
|
return carrier
|
||||||
|
|
||||||
|
|
||||||
def BIOYOND_PolymerStation_6VialCarrier(name: str) -> BottleCarrier:
|
def BIOYOND_PolymerStation_6VialCarrier(name: str) -> BottleCarrier:
|
||||||
"""6瓶载架 - 2x3布局"""
|
"""6瓶载架 - 2x3布局"""
|
||||||
|
|
||||||
@@ -138,8 +195,10 @@ def BIOYOND_PolymerStation_6VialCarrier(name: str) -> BottleCarrier:
|
|||||||
carrier.num_items_y = 2
|
carrier.num_items_y = 2
|
||||||
carrier.num_items_z = 1
|
carrier.num_items_z = 1
|
||||||
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
|
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
|
||||||
for i in range(6):
|
for i in range(3):
|
||||||
carrier[i] = BIOYOND_PolymerStation_Solid_Vial(f"{name}_vial_{ordering[i]}")
|
carrier[i] = BIOYOND_PolymerStation_Solid_Vial(f"{name}_solidvial_{ordering[i]}")
|
||||||
|
for i in range(3, 6):
|
||||||
|
carrier[i] = BIOYOND_PolymerStation_Liquid_Vial(f"{name}_liquidvial_{ordering[i]}")
|
||||||
return carrier
|
return carrier
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,30 @@ from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
|
|||||||
# 工厂函数
|
# 工厂函数
|
||||||
|
|
||||||
|
|
||||||
def BIOYOND_PolymerStation_Solid_Vial(
|
def BIOYOND_PolymerStation_Solid_Stock(
|
||||||
name: str,
|
name: str,
|
||||||
diameter: float = 20.0,
|
diameter: float = 20.0,
|
||||||
height: float = 100.0,
|
height: float = 100.0,
|
||||||
max_volume: float = 30000.0, # 30mL
|
max_volume: float = 30000.0, # 30mL
|
||||||
barcode: str = None,
|
barcode: str = None,
|
||||||
|
) -> Bottle:
|
||||||
|
"""创建粉末瓶"""
|
||||||
|
return Bottle(
|
||||||
|
name=name,
|
||||||
|
diameter=diameter,
|
||||||
|
height=height,
|
||||||
|
max_volume=max_volume,
|
||||||
|
barcode=barcode,
|
||||||
|
model="BIOYOND_PolymerStation_Solid_Stock",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def BIOYOND_PolymerStation_Solid_Vial(
|
||||||
|
name: str,
|
||||||
|
diameter: float = 25.0,
|
||||||
|
height: float = 60.0,
|
||||||
|
max_volume: float = 30000.0, # 30mL
|
||||||
|
barcode: str = None,
|
||||||
) -> Bottle:
|
) -> Bottle:
|
||||||
"""创建粉末瓶"""
|
"""创建粉末瓶"""
|
||||||
return Bottle(
|
return Bottle(
|
||||||
@@ -20,6 +38,24 @@ def BIOYOND_PolymerStation_Solid_Vial(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def BIOYOND_PolymerStation_Liquid_Vial(
|
||||||
|
name: str,
|
||||||
|
diameter: float = 25.0,
|
||||||
|
height: float = 60.0,
|
||||||
|
max_volume: float = 30000.0, # 30mL
|
||||||
|
barcode: str = None,
|
||||||
|
) -> Bottle:
|
||||||
|
"""创建滴定液瓶"""
|
||||||
|
return Bottle(
|
||||||
|
name=name,
|
||||||
|
diameter=diameter,
|
||||||
|
height=height,
|
||||||
|
max_volume=max_volume,
|
||||||
|
barcode=barcode,
|
||||||
|
model="BIOYOND_PolymerStation_Liquid_Vial",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def BIOYOND_PolymerStation_Solution_Beaker(
|
def BIOYOND_PolymerStation_Solution_Beaker(
|
||||||
name: str,
|
name: str,
|
||||||
diameter: float = 60.0,
|
diameter: float = 60.0,
|
||||||
|
|||||||
@@ -614,6 +614,11 @@ def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: dict =
|
|||||||
bottle.tracker.liquids = [
|
bottle.tracker.liquids = [
|
||||||
(detail["name"], float(detail.get("quantity", 0)) if detail.get("quantity") else 0)
|
(detail["name"], float(detail.get("quantity", 0)) if detail.get("quantity") else 0)
|
||||||
]
|
]
|
||||||
|
else:
|
||||||
|
bottle = plr_material[0] if plr_material.capacity > 0 else plr_material
|
||||||
|
bottle.tracker.liquids = [
|
||||||
|
(material["name"], float(material.get("quantity", 0)) if material.get("quantity") else 0)
|
||||||
|
]
|
||||||
|
|
||||||
plr_materials.append(plr_material)
|
plr_materials.append(plr_material)
|
||||||
|
|
||||||
@@ -633,6 +638,36 @@ def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: dict =
|
|||||||
return plr_materials
|
return plr_materials
|
||||||
|
|
||||||
|
|
||||||
|
def resource_plr_to_bioyond(plr_materials: list[ResourcePLR], type_mapping: dict = {}, warehouse_mapping: dict = {}) -> list[dict]:
|
||||||
|
bioyond_materials = []
|
||||||
|
for plr_material in plr_materials:
|
||||||
|
material = {
|
||||||
|
"name": plr_material.name,
|
||||||
|
"typeName": plr_material.__class__.__name__,
|
||||||
|
"code": plr_material.code,
|
||||||
|
"quantity": 0,
|
||||||
|
"detail": [],
|
||||||
|
"locations": [],
|
||||||
|
}
|
||||||
|
if hasattr(plr_material, "capacity") and plr_material.capacity > 1:
|
||||||
|
for idx in range(plr_material.capacity):
|
||||||
|
bottle = plr_material[idx]
|
||||||
|
detail = {
|
||||||
|
"x": (idx // (plr_material.num_items_x * plr_material.num_items_y)) + 1,
|
||||||
|
"y": ((idx % (plr_material.num_items_x * plr_material.num_items_y)) // plr_material.num_items_x) + 1,
|
||||||
|
"z": (idx % plr_material.num_items_x) + 1,
|
||||||
|
"code": bottle.code if hasattr(bottle, "code") else "",
|
||||||
|
"quantity": sum(qty for _, qty in bottle.tracker.liquids) if hasattr(bottle, "tracker") else 0,
|
||||||
|
}
|
||||||
|
material["detail"].append(detail)
|
||||||
|
material["quantity"] = 1.0
|
||||||
|
else:
|
||||||
|
bottle = plr_material[0] if plr_material.capacity > 0 else plr_material
|
||||||
|
material["quantity"] = sum(qty for _, qty in bottle.tracker.liquids) if hasattr(plr_material, "tracker") else 0
|
||||||
|
bioyond_materials.append(material)
|
||||||
|
return bioyond_materials
|
||||||
|
|
||||||
|
|
||||||
def initialize_resource(resource_config: dict, resource_type: Any = None) -> Union[list[dict], ResourcePLR]:
|
def initialize_resource(resource_config: dict, resource_type: Any = None) -> Union[list[dict], ResourcePLR]:
|
||||||
"""Initializes a resource based on its configuration.
|
"""Initializes a resource based on its configuration.
|
||||||
|
|
||||||
|
|||||||
@@ -5,15 +5,19 @@ Automated Liquid Handling Station Resource Classes - Simplified Version
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Dict, Optional
|
from typing import Dict, List, Optional, TypeVar, Union, Sequence, Tuple
|
||||||
|
|
||||||
|
import pylabrobot
|
||||||
|
|
||||||
from pylabrobot.resources.coordinate import Coordinate
|
|
||||||
from pylabrobot.resources.container import Container
|
|
||||||
from pylabrobot.resources.resource_holder import ResourceHolder
|
|
||||||
from pylabrobot.resources import Resource as ResourcePLR
|
from pylabrobot.resources import Resource as ResourcePLR
|
||||||
|
from pylabrobot.resources import Well, ResourceHolder
|
||||||
|
from pylabrobot.resources.coordinate import Coordinate
|
||||||
|
|
||||||
|
|
||||||
class Bottle(Container):
|
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
|
|
||||||
|
class Bottle(Well):
|
||||||
"""瓶子类 - 简化版,不追踪瓶盖"""
|
"""瓶子类 - 简化版,不追踪瓶盖"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -37,6 +41,8 @@ class Bottle(Container):
|
|||||||
max_volume=max_volume,
|
max_volume=max_volume,
|
||||||
category=category,
|
category=category,
|
||||||
model=model,
|
model=model,
|
||||||
|
bottom_type="flat",
|
||||||
|
cross_section_type="circle"
|
||||||
)
|
)
|
||||||
self.diameter = diameter
|
self.diameter = diameter
|
||||||
self.height = height
|
self.height = height
|
||||||
@@ -50,13 +56,6 @@ class Bottle(Container):
|
|||||||
"barcode": self.barcode,
|
"barcode": self.barcode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
from string import ascii_uppercase as LETTERS
|
|
||||||
from typing import Dict, List, Optional, Type, TypeVar, Union, Sequence, Tuple
|
|
||||||
|
|
||||||
import pylabrobot
|
|
||||||
from pylabrobot.resources.resource_holder import ResourceHolder
|
|
||||||
|
|
||||||
T = TypeVar("T", bound=ResourceHolder)
|
T = TypeVar("T", bound=ResourceHolder)
|
||||||
|
|
||||||
S = TypeVar("S", bound=ResourceHolder)
|
S = TypeVar("S", bound=ResourceHolder)
|
||||||
|
|||||||
Reference in New Issue
Block a user