mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-19 05:51:17 +00:00
Ready for open source (#47)
* Create app/main API * create example device * create ROS backend and example device SDK Wrapper * Add ROS host and host starting from app.py * Add gripper device and mock implementation * add "status_types" & "action_types" to ROS device decorator * add ActionServer debug example * [bugfix] complete mock gripper example * ROS Backend Host for Device action calling and Resource management * add conda/mamba ENV file * add host_node communication with app/main.py * add action message value mappings and converters * Update ilabos.yaml * Update issue templates * example devices.json and resources.json * Fix Device wrapper to use async property and actions (#7) * Fix Device wrapper to use async property and actions * Resolve #1 : support async get methods and actions. Give new examples. * add both sync/async GRBL controller SDK * 2 call device actions from appmainpy api to ros hostpy (#8) * feature: add job * fix:node start * feature:add get job status * fix:get device * clean * Resolve #5 device connection diagram and workflow compilation support (#9) * add syringe pump device and its compilation using device connection diagram * add RunzeSyringePump real device with ROS2 example * Prototype machine with 1 pump and 1 CNC * add ROS2ProtocolNode and related functions * add ilabos_msgs (to use PumpTransfer action) * add example device connection graph * refactor protocol_node code into separate file * add ROS2SerialNode * add SerialCommand srv in ilabos_msgs * add pump_protocol example, and fix bugs * [fix] serial service: avoid async service deadlock by directly call serial `send_command` * use SendCmd instead of SingleJointPosition for valve control * initialize device connection graph when server starts * Fix #5: async workflow execution (#16) * add rclpyx and protocol example for async-native workflow * use async in ROS2ProtocolNode, and host initialization * add examples of "ros-async" protocol implementation, and `run_in_event_loop` for using native async functions * use "ros-async" in protocols and device nodes * fix pump_protocol: push to 0.0 μL * Envs, docs, and conda recipes (#19) * update ENV: use python 3.11 and deprecate ros-humble-gazebo-ros * add ilabos-msgs conda recipe * Update ilabos.yaml * fix recipe and env yaml * Add sphinx docs * add aichemeco * add bioyong * add bioyong * Support XDL devices & protocols (#20) * [Feature] support multiple protocols in a single ProtocolNode * add Junjie's code * Support "Clean" protocol * Update Grignard_flow_batchreact_single_pumpvalve.json * test_grignard_add * add stir device node and example * Update device_node.py add print_publish flag to control the node's log output * NH4Cl_add * add "HeaterStirrer" device and "HeatChill" action * add wait time after each pump action for equilibration * fix stir * add Separate protocol * Refactor Separator device and Stir action * add rotavap_node * fix stir * add chiller node * Move rinsings into PumpTransfer * Fix SeparateProtocol under refactored Separator device and Stir action * Supports automatically add new protocol action_types * fix PumpTransfer protocol because of rinsing * Add Rotavap and Chiller devices * fix SeparateProtocol * add EvaporateProtocol * add rotavap devices config * fix HeaterStirrer and SeparatorController IO * Fix automatically add new protocol action_types * Add HeaterStirrer and SeparatorController device config * fix pump protocols * Fix Evaporate action * Update evaporate_protocol.py * add temp_sensor node and add function remap * update docs --------- Co-authored-by: 王俊杰 <1800011822@pku.edu.cn> Co-authored-by: q434343 <554662886@qq.com> * fix aichemeco * [Bugfix] fix Windows conda packaging * add file upload api * update dependencies: force to use 3.11 and remove conflict in WIN64 and OSX64 * update dependencies: force to use 3.11 and remove conflict in WIN64 and OSX64 * Create aichemeco_simple.py * fix * update * add aichemeco file * MQTT [1/2]: action start (#25) * add mq * fix * clean * add class * fix excel * update bioyong * add api * fix --------- Co-authored-by: caok@dp.tech <xiaoyeqiannian@163.com> * motor & grasp * Add Grasp motor support and enhance EleGripper class - Introduced a new motor configuration for Grasp in sjtu.json. - Updated EleGripper class to inherit from UniversalDriver and added status property. - Implemented move_and_rotate method for coordinated movement. - Adjusted threading logic in EleGripper initialization. - Registered Grasp motor in ROS2 device node configuration. This commit enhances the motor control capabilities by integrating the Grasp motor and improving the existing EleGripper functionality. * fix read data lenth * Update Grasp.py * MQTT (2/2): publish Device Status, Action Feedback & Results (#27) * Add bridges in HostNode for device_status publishing * Add "bridges" selection (fastapi & mqtt) when app start * add MQ feedback & result publisher, and fix message converter * fix UUID converting between ROS and MQ * lint api model.py * Continuous controllers: PID, MPC, custom controllers etc. (#23) * add controller config & wrapper * add controller setup at app.main * control loop example * fix com port * add agv , ur_arm and raman * MQTT (3/4): Unified Resources and Sync when starting the server (#28) * update http upload api * generate uuid when init device * example resource json * fix * add new example full-content json (device, resource, graph) * fix full-content json and related reading code * fix * add json_schema when initialize resources * fix * update schema * refactor heaterstirrer.dalong * fix * fix refactor heaterstirrer.dalong * refactor syringepump.runze: use ml instead of μL * Update ilabos/ros/host.py Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --------- Co-authored-by: 王俊杰 <1800011822@pku.edu.cn> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Distributed initialization with self-organizing network (#29) * add distributed launching option "--without_host" * fix --------- Co-authored-by: 王俊杰 <1800011822@pku.edu.cn> * Refactor Workstation: Add resource service and tracking (#30) * move ilabos/ros/rpc to ilabos/device_comms/rpc, and merge bioyond/aichemeco files under /devices * add Resource srv and message_converter * move graphio to ilabos/resources * refactor resources type conversion * add resource clients in device_node * add mock resources service * pass Gripper1 resource test * update http resource services * add AGV compile function * add AGV transfer protocol * update full mock_gripper edit_id example * update full mock_gripper edit_id example * get and update resource also in protocol_node * mock resource update in AichemecoHiwo * Create HT_hiwo.json * add children in resources * bugfixes * fix rpc * add Revvity winprep --------- Co-authored-by: wjjxxx <43375851+wjjxxx@users.noreply.github.com> Co-authored-by: 3218923350 <105201755+3218923350@users.noreply.github.com> * Distributed launch (2/2): distributed resource create (#32) * add resource_add request to host for slave mode * add AGV * fix protocol resources * optimize host callbacks * bugfixes * add revvity registry --------- Co-authored-by: 王俊杰 <1800011822@pku.edu.cn> Co-authored-by: wjjxxx <43375851+wjjxxx@users.noreply.github.com> * Refactor Driver Files Structure (#33) * Integration with pywinauto & recorder Added execute run and initialize procdure * 酶标仪状态检测、使用示例,整体流程待测试 * nivo ready version * Add HPLC driver and example script - Introduced HPLCDriver class for managing HPLC device status and operations. - Implemented device status monitoring and command execution via ROS2 actions. - Added example script (hplc.py) demonstrating how to run commands on the HPLC device. - Created PlayerUtil and UniversalDriver classes for shared functionality across devices. - Refactored NivoDriver to utilize the new UniversalDriver structure. - Enhanced error handling and process management in the NivoDriver. * 修复start的错误定位 * hplc tested ok * relative path to build msgs * template_driver & jiageng devices * fetch correct status type and action type * fix mtype fetch * gpc bus integration * ilab build * remove chs * recipe rename * modbus update 1 * json available * hplc & modbus rewrite * Update AgilentHPLC.py hplc datafile reader * move ilabos/ros/rpc to ilabos/device_comms/rpc, and merge bioyond/aichemeco files under /devices * modbus分设备 * gpc * gpc 2 * fix address * default register node * fix MainScreenGPC * add Resource srv and message_converter * move graphio to ilabos/resources * refactor resources type conversion * add resource clients in device_node * add mock resources service * pass Gripper1 resource test * update http resource services * add AGV compile function * add AGV transfer protocol * update recipe.yaml * update full mock_gripper edit_id example * update full mock_gripper edit_id example * get and update resource also in protocol_node * mock resource update in AichemecoHiwo * feat: add other jiageng PLC device code * ilabos compile * correct format * correct recipe format * correct setup.py format * remove unnecessary files * remove unnecessary files * Create HT_hiwo.json * add children in resources * hplc support sample_id * correct hplc sample_id * correct hplc sample_id * hplc upload * fix type hint * oss upload tested ver * recipe yaml fix for linux * update installation yaml * refactor: moved all driver files according to its feat * merge main to dev --------- Co-authored-by: 王俊杰 <2201110460@stu.pku.edu.cn> Co-authored-by: Junhan Chang <changjh@pku.edu.cn> Co-authored-by: jiawei <miaojiawei@dp.tech> * add: NMR LH and RU device control (#34) * Add Registry for device drivers and Support GraphML (#35) * read chemputer graphml * read graphml in app/main * add devices in ros/devices * add schema for devices * read registry directory and initialize when entry from main * Delete devices.py * Update add_protocol.md * delete unecessary files * feat: 2278 devices registry yaml (#36) * read chemputer graphml * read graphml in app/main * add devices in ros/devices * add schema for devices * read registry directory and initialize when entry from main * Delete devices.py * add: NMR LH and RU device control * fix: modify jiageng devices registry --------- Co-authored-by: Junhan Chang <changjh@pku.edu.cn> * Device/Resource Registry and GraphML support (#37) * add resource type conversion to PLR * add resource registry and test * add docs * fix registry * add solenoid_valve_mock, its registry and test * fix registry for directly using examples * add EvacuateAndRefillProtocol and testcases * allow function sequence call in ACTION * add read & write & extra_info for hardware_interface * Update device_node.py * add solenoid valve * add doc developer guide yaml * fixes for starting IK station * add graphml grouping parser * fix graphml grouping parser * add communication edge parser * fix io solenoid valve * Update .gitignore * Update plates.yaml --------- Co-authored-by: ColumbiaCC <2100011801@stu.pku.edu.cn> * Uni-Lab Doc v0.2 (#39) * add Uni-Lab docs * change doc name * Dev (#41) * Integration with pywinauto & recorder Added execute run and initialize procdure * 酶标仪状态检测、使用示例,整体流程待测试 * nivo ready version * Add HPLC driver and example script - Introduced HPLCDriver class for managing HPLC device status and operations. - Implemented device status monitoring and command execution via ROS2 actions. - Added example script (hplc.py) demonstrating how to run commands on the HPLC device. - Created PlayerUtil and UniversalDriver classes for shared functionality across devices. - Refactored NivoDriver to utilize the new UniversalDriver structure. - Enhanced error handling and process management in the NivoDriver. * 修复start的错误定位 * hplc tested ok * relative path to build msgs * template_driver & jiageng devices * fetch correct status type and action type * fix mtype fetch * gpc bus integration * ilab build * remove chs * recipe rename * modbus update 1 * json available * hplc & modbus rewrite * Update AgilentHPLC.py hplc datafile reader * move ilabos/ros/rpc to ilabos/device_comms/rpc, and merge bioyond/aichemeco files under /devices * modbus分设备 * gpc * gpc 2 * fix address * default register node * fix MainScreenGPC * add Resource srv and message_converter * move graphio to ilabos/resources * refactor resources type conversion * add resource clients in device_node * add mock resources service * pass Gripper1 resource test * update http resource services * add AGV compile function * add AGV transfer protocol * update recipe.yaml * update full mock_gripper edit_id example * update full mock_gripper edit_id example * get and update resource also in protocol_node * mock resource update in AichemecoHiwo * feat: add other jiageng PLC device code * ilabos compile * correct format * correct recipe format * correct setup.py format * remove unnecessary files * remove unnecessary files * Create HT_hiwo.json * add children in resources * hplc support sample_id * correct hplc sample_id * correct hplc sample_id * hplc upload * fix type hint * oss upload tested ver * recipe yaml fix for linux * update installation yaml * refactor: moved all driver files according to its feat * merge main to dev * add HPLC registry and json * 升级 ros2-distro-mutex 依赖版本至 0.6 * 修改 ros2-distro-mutex 依赖版本为通配符匹配 * 更新 ros-humble-ilabos-msgs 依赖为 robostack-humble 命名空间 * add resource type conversion to PLR * add resource registry and test * feat: 更新oss上传 * fix device id * add docs * fix registry * add solenoid_valve_mock, its registry and test * fix registry for directly using examples * add EvacuateAndRefillProtocol and testcases * allow function sequence call in ACTION * add read & write & extra_info for hardware_interface * Update device_node.py * add solenoid valve * add doc developer guide yaml * use robostack-staging * rclpy version test * lower rclpy * ensure 0.6* env * fixes for starting IK station * add graphml grouping parser * fix graphml grouping parser * add communication edge parser * fix io solenoid valve * Update .gitignore * Update plates.yaml * Feature/device node later init (#40) * 修改config路径,方便后续打包 增加device_node打印 * 支持plr序列化/init创建 * 统一命名 * import mgr logger optimize banner print * 日志OK * fix unicorn frame * banner print * correct import format * file path changes * 取消后补全,在加载设备的时候直接替换 * converter update * web page update * 在线device更新,node继承替换 * 修复动作、状态的类型缺失 和 命令提示 * web功能实现结束 * host节点更改完成 新增status时间戳管理 新增每10s动态发现其他node * ros2类型的节点也应该被包一次 * 修复类型提示 * websocket 动态显示状态 * add workflow & book theme for docs * add workflow & book theme for docs * fix workflow build * fix workflow build * 理清启动关系 * stm32 example * mac . name * device_instance device_cls * 新增config添加方式 更新mqtt提示 * plr test * 移动is_host_mode 新增slave_no_host * 确保config优先修改生效 * fix graph io * 支持带参数传入 * 支持物料解析 * 支持物料解析 * device为空的时候不进行绑定或初始化 * protocol node new * protocol node runnable * protocol node runnable --------- Co-authored-by: 王俊杰 <2201110460@stu.pku.edu.cn> Co-authored-by: Junhan Chang <changjh@pku.edu.cn> Co-authored-by: jiawei <miaojiawei@dp.tech> Co-authored-by: ColumbiaCC <2100011801@stu.pku.edu.cn> * Dev (#45) * Integration with pywinauto & recorder Added execute run and initialize procdure * 酶标仪状态检测、使用示例,整体流程待测试 * nivo ready version * Add HPLC driver and example script - Introduced HPLCDriver class for managing HPLC device status and operations. - Implemented device status monitoring and command execution via ROS2 actions. - Added example script (hplc.py) demonstrating how to run commands on the HPLC device. - Created PlayerUtil and UniversalDriver classes for shared functionality across devices. - Refactored NivoDriver to utilize the new UniversalDriver structure. - Enhanced error handling and process management in the NivoDriver. * 修复start的错误定位 * hplc tested ok * relative path to build msgs * template_driver & jiageng devices * fetch correct status type and action type * fix mtype fetch * gpc bus integration * ilab build * remove chs * recipe rename * modbus update 1 * json available * hplc & modbus rewrite * Update AgilentHPLC.py hplc datafile reader * move ilabos/ros/rpc to ilabos/device_comms/rpc, and merge bioyond/aichemeco files under /devices * modbus分设备 * gpc * gpc 2 * fix address * default register node * fix MainScreenGPC * add Resource srv and message_converter * move graphio to ilabos/resources * refactor resources type conversion * add resource clients in device_node * add mock resources service * pass Gripper1 resource test * update http resource services * add AGV compile function * add AGV transfer protocol * update recipe.yaml * update full mock_gripper edit_id example * update full mock_gripper edit_id example * get and update resource also in protocol_node * mock resource update in AichemecoHiwo * feat: add other jiageng PLC device code * ilabos compile * correct format * correct recipe format * correct setup.py format * remove unnecessary files * remove unnecessary files * Create HT_hiwo.json * add children in resources * hplc support sample_id * correct hplc sample_id * correct hplc sample_id * hplc upload * fix type hint * oss upload tested ver * recipe yaml fix for linux * update installation yaml * refactor: moved all driver files according to its feat * merge main to dev * add HPLC registry and json * 升级 ros2-distro-mutex 依赖版本至 0.6 * 修改 ros2-distro-mutex 依赖版本为通配符匹配 * 更新 ros-humble-ilabos-msgs 依赖为 robostack-humble 命名空间 * add resource type conversion to PLR * add resource registry and test * feat: 更新oss上传 * fix device id * add docs * fix registry * add solenoid_valve_mock, its registry and test * fix registry for directly using examples * add EvacuateAndRefillProtocol and testcases * allow function sequence call in ACTION * add read & write & extra_info for hardware_interface * Update device_node.py * add solenoid valve * add doc developer guide yaml * use robostack-staging * rclpy version test * lower rclpy * ensure 0.6* env * fixes for starting IK station * add graphml grouping parser * fix graphml grouping parser * add communication edge parser * fix io solenoid valve * Update .gitignore * Update plates.yaml * Feature/device node later init (#40) * 修改config路径,方便后续打包 增加device_node打印 * 支持plr序列化/init创建 * 统一命名 * import mgr logger optimize banner print * 日志OK * fix unicorn frame * banner print * correct import format * file path changes * 取消后补全,在加载设备的时候直接替换 * converter update * web page update * 在线device更新,node继承替换 * 修复动作、状态的类型缺失 和 命令提示 * web功能实现结束 * host节点更改完成 新增status时间戳管理 新增每10s动态发现其他node * ros2类型的节点也应该被包一次 * 修复类型提示 * websocket 动态显示状态 * add workflow & book theme for docs * add workflow & book theme for docs * fix workflow build * fix workflow build * 理清启动关系 * stm32 example * mac . name * device_instance device_cls * 新增config添加方式 更新mqtt提示 * plr test * 移动is_host_mode 新增slave_no_host * 确保config优先修改生效 * fix graph io * 支持带参数传入 * 支持物料解析 * 支持物料解析 * device为空的时候不进行绑定或初始化 * protocol node new * protocol node runnable * protocol node runnable * Feature/device node later init (#42) * 修改config路径,方便后续打包 增加device_node打印 * 支持plr序列化/init创建 * 统一命名 * import mgr logger optimize banner print * 日志OK * fix unicorn frame * banner print * correct import format * file path changes * 取消后补全,在加载设备的时候直接替换 * converter update * web page update * 在线device更新,node继承替换 * 修复动作、状态的类型缺失 和 命令提示 * web功能实现结束 * host节点更改完成 新增status时间戳管理 新增每10s动态发现其他node * ros2类型的节点也应该被包一次 * 修复类型提示 * websocket 动态显示状态 * add workflow & book theme for docs * add workflow & book theme for docs * fix workflow build * fix workflow build * 理清启动关系 * stm32 example * mac . name * device_instance device_cls * 新增config添加方式 更新mqtt提示 * plr test * 移动is_host_mode 新增slave_no_host * 确保config优先修改生效 * fix graph io * 支持带参数传入 * 支持物料解析 * 支持物料解析 * device为空的时候不进行绑定或初始化 * protocol node new * protocol node runnable * protocol node runnable * action * plr suc * plr suc!! * plr suc!! * plr suc!! * plr msgs * Feature/device node later init (#43) * 修改config路径,方便后续打包 增加device_node打印 * 支持plr序列化/init创建 * 统一命名 * import mgr logger optimize banner print * 日志OK * fix unicorn frame * banner print * correct import format * file path changes * 取消后补全,在加载设备的时候直接替换 * converter update * web page update * 在线device更新,node继承替换 * 修复动作、状态的类型缺失 和 命令提示 * web功能实现结束 * host节点更改完成 新增status时间戳管理 新增每10s动态发现其他node * ros2类型的节点也应该被包一次 * 修复类型提示 * websocket 动态显示状态 * add workflow & book theme for docs * add workflow & book theme for docs * fix workflow build * fix workflow build * 理清启动关系 * stm32 example * mac . name * device_instance device_cls * 新增config添加方式 更新mqtt提示 * plr test * 移动is_host_mode 新增slave_no_host * 确保config优先修改生效 * fix graph io * 支持带参数传入 * 支持物料解析 * 支持物料解析 * device为空的时候不进行绑定或初始化 * protocol node new * protocol node runnable * protocol node runnable * action * plr suc * plr suc!! * plr suc!! * plr suc!! * plr msgs * plr * action * plr reg fix * Feature/device node later init (#44) * 修改config路径,方便后续打包 增加device_node打印 * 支持plr序列化/init创建 * 统一命名 * import mgr logger optimize banner print * 日志OK * fix unicorn frame * banner print * correct import format * file path changes * 取消后补全,在加载设备的时候直接替换 * converter update * web page update * 在线device更新,node继承替换 * 修复动作、状态的类型缺失 和 命令提示 * web功能实现结束 * host节点更改完成 新增status时间戳管理 新增每10s动态发现其他node * ros2类型的节点也应该被包一次 * 修复类型提示 * websocket 动态显示状态 * add workflow & book theme for docs * add workflow & book theme for docs * fix workflow build * fix workflow build * 理清启动关系 * stm32 example * mac . name * device_instance device_cls * 新增config添加方式 更新mqtt提示 * plr test * 移动is_host_mode 新增slave_no_host * 确保config优先修改生效 * fix graph io * 支持带参数传入 * 支持物料解析 * 支持物料解析 * device为空的时候不进行绑定或初始化 * protocol node new * protocol node runnable * protocol node runnable * action * plr suc * plr suc!! * plr suc!! * plr suc!! * plr msgs * plr * fix convert error fix async logic error added async error print * new device test * test resource add * test resource add * test resource add * test resource add * local env setup * node type fix temp fix root_node error fix convert res from type error * resource tracker * fix bug from qhh * fix bug from qhh * fix bug from qhh * fix bug from qhh * refactor MQTT client logging and connection handling; update group ID in config * driver_params allow empty * allow other init param * fix driver param and enhance type hint * refactor MQConfig to use double quotes for string literals * fix wrong function calling * fix wrong function calling * fix log for mac * fix networkx compatibility * add mqtt loggers * add action to jsonschema converter * random client id * type converter & registry * correct conversion * fix action publish only from discovered devices * add "Bio" tag for action doc generation * 改进module提示 * Fix doc * mqtt不连接也可用 性价样例提示 * add docs * 更新plr test案例 * Update intro.md * 更新有机案例 * skip --------- Co-authored-by: Harvey Que <Q-Query@outlook.com> Co-authored-by: Junhan Chang <1700011741@pku.edu.cn> --------- Co-authored-by: 王俊杰 <2201110460@stu.pku.edu.cn> Co-authored-by: Junhan Chang <changjh@pku.edu.cn> Co-authored-by: jiawei <miaojiawei@dp.tech> Co-authored-by: ColumbiaCC <2100011801@stu.pku.edu.cn> Co-authored-by: Harvey Que <Q-Query@outlook.com> Co-authored-by: Junhan Chang <1700011741@pku.edu.cn> * Canonicalize before Open Source (#46) * big big refactor try01 * refactor 02 --------- Co-authored-by: ck <xiaoyeqiannian@163.com> Co-authored-by: 王俊杰 <1800011822@pku.edu.cn> Co-authored-by: q434343 <554662886@qq.com> Co-authored-by: Xuwznln <xuwznln@gmail.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Co-authored-by: wjjxxx <43375851+wjjxxx@users.noreply.github.com> Co-authored-by: 3218923350 <105201755+3218923350@users.noreply.github.com> Co-authored-by: Xuwznln <1023025701@qq.com> Co-authored-by: 王俊杰 <2201110460@stu.pku.edu.cn> Co-authored-by: jiawei <miaojiawei@dp.tech> Co-authored-by: Jiawei <91898272+jiawei723@users.noreply.github.com> Co-authored-by: ColumbiaCC <2100011801@stu.pku.edu.cn> Co-authored-by: Harvey Que <Q-Query@outlook.com>
This commit is contained in:
0
unilabos/devices/UV_test/__init__.py
Normal file
0
unilabos/devices/UV_test/__init__.py
Normal file
333
unilabos/devices/UV_test/fuxiang2.py
Normal file
333
unilabos/devices/UV_test/fuxiang2.py
Normal file
@@ -0,0 +1,333 @@
|
||||
import tkinter as tk
|
||||
from tkinter import ttk # 使用 ttk 替换 tk 控件
|
||||
from tkinter import messagebox
|
||||
from tkinter.font import Font
|
||||
from threading import Thread
|
||||
from ttkthemes import ThemedTk
|
||||
import time
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||
import clr # pythonnet library
|
||||
import sys
|
||||
import threading
|
||||
import datetime
|
||||
|
||||
jifenshijian = 10 #积分时间
|
||||
shuaxinshijian = 0.01 #刷新时间
|
||||
zihaodaxiao = 16 #字号大小
|
||||
ymax = 70000
|
||||
ymin = -2000
|
||||
|
||||
# 加载DLL
|
||||
dll_path = "C:\\auto\\UV_spec\\idea-sdk 3.0.9\\idea-sdk.UPI\\IdeaOptics.dll"
|
||||
clr.AddReference(dll_path)
|
||||
from IdeaOptics import Wrapper
|
||||
|
||||
# 初始化Wrapper对象和光谱仪
|
||||
wrapper = Wrapper()
|
||||
number_of_spectrometers = wrapper.OpenAllSpectrometers()
|
||||
if number_of_spectrometers > 0:
|
||||
spectrometer_index = 0 # 假设使用第一个光谱仪
|
||||
integration_time = jifenshijian # 设置积分时间
|
||||
wrapper.setIntegrationTime(spectrometer_index, integration_time)
|
||||
|
||||
class App:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("光谱测试")
|
||||
self.is_continuous = False
|
||||
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
|
||||
self.stop_event = threading.Event() # 使用Event代替布尔标志
|
||||
self.continuous_thread = None # 在这里初始化
|
||||
self.background_spectrum = None
|
||||
self.correct_background = False
|
||||
self.test_count = 0
|
||||
self.background_count = 0
|
||||
|
||||
self.source_spectrum = None # 初始化光源强度变量
|
||||
self.transmission_mode = False # 初始化透射模式标志
|
||||
|
||||
self.data_ready = False
|
||||
|
||||
# 使用 grid 布局
|
||||
self.root.columnconfigure(0, weight=1)
|
||||
self.root.rowconfigure(0, weight=1)
|
||||
self.root.rowconfigure(1, weight=1)
|
||||
self.root.rowconfigure(2, weight=1)
|
||||
self.root.rowconfigure(3, weight=1)
|
||||
|
||||
self.current_ylim = [-100, 1000] # 初始化y轴范围
|
||||
|
||||
# 创建一个 Style 对象
|
||||
style = ttk.Style()
|
||||
|
||||
# 定义一个新的样式
|
||||
style.configure('Custom.TButton', font=('Helvetica', zihaodaxiao, 'bold'), foreground='white')
|
||||
|
||||
# 创建滑动条和按钮的容器 Frame
|
||||
control_frame = ttk.Frame(self.root)
|
||||
control_frame.grid(row=0, column=0, sticky="ew")
|
||||
|
||||
# 创建一个滑动条来选择平滑次数
|
||||
self.boxcar_width_slider = tk.Scale(control_frame, from_=0, to=10, orient=tk.HORIZONTAL, length=300, label="平滑次数", font=("Helvetica", zihaodaxiao, 'bold'))
|
||||
self.boxcar_width_slider.grid(row=0, column=0, padx=10, pady=10)
|
||||
|
||||
# 创建一个滑动条来选择平均次数
|
||||
self.scans_to_average_slider = tk.Scale(control_frame, from_=1, to=10, orient=tk.HORIZONTAL, length=300, label="平均次数", font=("Helvetica", zihaodaxiao, 'bold'))
|
||||
self.scans_to_average_slider.grid(row=0, column=1, padx=10, pady=10)
|
||||
|
||||
# 调整 Scale 控件的外观
|
||||
self.boxcar_width_slider.config(bg='grey', fg='white')
|
||||
self.scans_to_average_slider.config(bg='grey', fg='white')
|
||||
|
||||
# 字体设置
|
||||
entry_font = ('Helvetica', zihaodaxiao, 'bold')
|
||||
|
||||
# 添加输入框的容器 Frame
|
||||
entry_frame = ttk.Frame(self.root)
|
||||
entry_frame.grid(row=1, column=0, sticky="ew")
|
||||
|
||||
# 创建并放置"积分时间(ms)"输入框
|
||||
ttk.Label(entry_frame, text="积分时间(ms):", font=entry_font).grid(row=0, column=0, padx=10, pady=10)
|
||||
self.integration_time_entry = ttk.Entry(entry_frame, font=entry_font)
|
||||
self.integration_time_entry.grid(row=0, column=1, padx=10, pady=10)
|
||||
self.integration_time_entry.insert(0, "10") # 设置默认值
|
||||
|
||||
# 创建并放置"刷新间隔(s)"输入框
|
||||
ttk.Label(entry_frame, text="刷新间隔(s):", font=entry_font).grid(row=0, column=2, padx=10, pady=10)
|
||||
self.refresh_interval_entry = ttk.Entry(entry_frame, font=entry_font)
|
||||
self.refresh_interval_entry.grid(row=0, column=3, padx=10, pady=10)
|
||||
self.refresh_interval_entry.insert(0, "0.01") # 设置默认值
|
||||
|
||||
# 创建按钮的容器 Frame
|
||||
button_frame = ttk.Frame(self.root)
|
||||
button_frame.grid(row=2, column=0, sticky="ew")
|
||||
|
||||
# 创建并放置按钮
|
||||
ttk.Button(button_frame, text="测试一下", style='Custom.TButton', command=self.single_test).grid(row=0, column=0, padx=10, pady=10)
|
||||
ttk.Button(button_frame, text="连续测试", style='Custom.TButton', command=self.start_continuous_test).grid(row=0, column=1, padx=10, pady=10)
|
||||
ttk.Button(button_frame, text="停止测试", style='Custom.TButton', command=self.stop_continuous_test).grid(row=0, column=2, padx=10, pady=10)
|
||||
|
||||
# 创建背景相关按钮的容器 Frame
|
||||
background_frame = ttk.Frame(self.root)
|
||||
background_frame.grid(row=3, column=0, sticky="ew")
|
||||
|
||||
# 创建并放置“采集背景”按钮
|
||||
self.collect_background_button = ttk.Button(background_frame, text="采集背景", style='Custom.TButton', command=self.collect_background)
|
||||
self.collect_background_button.grid(row=0, column=0, padx=10, pady=10)
|
||||
|
||||
# 创建并放置“背景校正”按钮
|
||||
self.correct_background_button = ttk.Button(background_frame, text="背景校正", style='Custom.TButton', command=self.toggle_background_correction)
|
||||
self.correct_background_button.grid(row=0, column=1, padx=10, pady=10)
|
||||
|
||||
# 创建“光源采集”按钮
|
||||
ttk.Button(background_frame, text="光源采集", style='Custom.TButton', command=self.collect_source).grid(row=0, column=2, padx=10, pady=10)
|
||||
|
||||
# 创建“透射模式”按钮
|
||||
self.transmission_button = ttk.Button(background_frame, text="透射模式", style='Custom.TButton', command=self.toggle_transmission_mode)
|
||||
self.transmission_button.grid(row=0, column=3, padx=10, pady=10)
|
||||
|
||||
# 创建 matplotlib 画布
|
||||
plt.style.use('ggplot') # 使用预定义的样式,如 'ggplot'
|
||||
self.figure, self.ax = plt.subplots(figsize=(10, 8))
|
||||
self.canvas = FigureCanvasTkAgg(self.figure, self.root)
|
||||
self.canvas_widget = self.canvas.get_tk_widget()
|
||||
self.canvas_widget.grid(row=3, column=0, sticky="ew")
|
||||
|
||||
# 使用 grid 布局来放置 matplotlib 画布
|
||||
self.canvas_widget = self.canvas.get_tk_widget()
|
||||
self.canvas_widget.grid(row=4, column=0, sticky="ew")
|
||||
|
||||
# 创建文件名并打开文件
|
||||
start_time = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
self.data_file = open(f"C:\\auto\\UV_spec\\data\\{start_time}.txt", "w")
|
||||
|
||||
def get_spectrum_data(self):
|
||||
# 获取波长和光谱值
|
||||
pixels = wrapper.getNumberOfPixels(spectrometer_index)
|
||||
spectrum = wrapper.getSpectrum(spectrometer_index)
|
||||
wavelengths = wrapper.getWavelengths(spectrometer_index)
|
||||
|
||||
# 转换.NET数组到Python列表
|
||||
spectrum_list = [spectrum[i] for i in range(pixels)]
|
||||
wavelengths_list = [wavelengths[i] for i in range(pixels)]
|
||||
|
||||
self.data_ready = True
|
||||
return wavelengths_list, spectrum_list
|
||||
|
||||
def collect_source(self):
|
||||
# 采集光源强度数据
|
||||
wavelengths, self.source_spectrum = self.get_spectrum_data()
|
||||
conditions = f"jifenshijian = {jifenshijian} shuaxinshijian = {shuaxinshijian} zihaodaxiao = {zihaodaxiao}"
|
||||
self.write_data_to_file("source", 1, conditions, self.source_spectrum)
|
||||
self.update_plot(wavelengths, self.source_spectrum)
|
||||
|
||||
def toggle_transmission_mode(self):
|
||||
# 切换透射模式
|
||||
self.transmission_mode = not self.transmission_mode
|
||||
self.transmission_button.config(text="正在透射" if self.transmission_mode else "透射模式")
|
||||
|
||||
def calculate_transmission(self, spectrum):
|
||||
# 计算透射率
|
||||
transmission = []
|
||||
for s, b, src in zip(spectrum, self.background_spectrum, self.source_spectrum):
|
||||
denominator = max(src - b, 0.1)
|
||||
trans_value = (s - b) / denominator * 100
|
||||
trans_value = max(0, min(trans_value, 100))
|
||||
transmission.append(trans_value)
|
||||
return transmission
|
||||
|
||||
def update_plot(self, wavelengths, spectrum, plot_type='spectrum'):
|
||||
|
||||
if not self.data_ready:
|
||||
return
|
||||
|
||||
self.ax.clear()
|
||||
|
||||
if plot_type == 'transmission':
|
||||
# 透射率模式的绘图设置
|
||||
self.ax.plot(wavelengths, spectrum, label='Transmission (%)')
|
||||
self.ax.set_ylim(-10, 110) # 设置y轴范围为0%到100%
|
||||
self.ax.set_ylabel('Transmission (%)', fontname='Arial', fontsize=zihaodaxiao)
|
||||
else:
|
||||
# 普通光谱模式的绘图设置
|
||||
self.ax.plot(wavelengths, spectrum)
|
||||
self.ax.set_ylim(self.current_ylim) # 使用当前y轴范围
|
||||
|
||||
# 计算新的最大值和最小值
|
||||
new_min, new_max = min(spectrum), max(spectrum)
|
||||
|
||||
# 检查新的最大值或最小值是否超过当前y轴范围
|
||||
while new_min < self.current_ylim[0] or new_max > self.current_ylim[1]:
|
||||
# 扩大y轴范围
|
||||
self.current_ylim = [self.current_ylim[0] * 2, self.current_ylim[1] * 2]
|
||||
|
||||
# 确保新的y轴范围不超过最大限制
|
||||
if self.current_ylim[0] < ymin:
|
||||
self.current_ylim[0] = ymin
|
||||
if self.current_ylim[1] > ymax:
|
||||
self.current_ylim[1] = ymax
|
||||
break
|
||||
|
||||
self.ax.set_ylabel('Intensity', fontname='Arial', fontsize=zihaodaxiao)
|
||||
|
||||
self.ax.set_xlabel('Wavelength (nm)', fontname='Arial', fontsize=zihaodaxiao)
|
||||
self.ax.set_title('Spectrum', fontname='Arial', fontsize=zihaodaxiao)
|
||||
|
||||
self.canvas.draw()
|
||||
|
||||
self.data_ready = False
|
||||
|
||||
def draw_plot(self):
|
||||
self.canvas.draw()
|
||||
|
||||
def write_data_to_file(self, test_type, test_number, conditions, spectrum):
|
||||
data_str = " ".join(map(str, spectrum))
|
||||
self.data_file.write(f"{test_type}{test_number}\n{conditions}\n{data_str}\n\n")
|
||||
self.data_file.flush()
|
||||
|
||||
def collect_background(self):
|
||||
# 设置平滑次数
|
||||
boxcar_width = self.boxcar_width_slider.get()
|
||||
wrapper.setBoxcarWidth(spectrometer_index, boxcar_width)
|
||||
|
||||
# 设置平均次数
|
||||
scans_to_average = self.scans_to_average_slider.get()
|
||||
wrapper.setScansToAverage(spectrometer_index, scans_to_average)
|
||||
|
||||
# 采集背景数据
|
||||
wavelengths, self.background_spectrum = self.get_spectrum_data()
|
||||
conditions = f"jifenshijian = {jifenshijian} shuaxinshijian = {shuaxinshijian} zihaodaxiao = {zihaodaxiao} pinghuacishu = {self.boxcar_width_slider.get()} pingjuncishu = {self.scans_to_average_slider.get()}"
|
||||
self.background_count += 1
|
||||
self.write_data_to_file("background", self.background_count, conditions, self.background_spectrum)
|
||||
self.update_plot(wavelengths, self.background_spectrum)
|
||||
|
||||
def toggle_background_correction(self):
|
||||
self.correct_background = not self.correct_background
|
||||
self.correct_background_button.config(text="正在校正" if self.correct_background else "背景校正")
|
||||
|
||||
def apply_background_correction(self, spectrum):
|
||||
if self.background_spectrum is not None and self.correct_background:
|
||||
return [s - b for s, b in zip(spectrum, self.background_spectrum)]
|
||||
return spectrum
|
||||
|
||||
def single_test(self):
|
||||
# 获取输入框的值
|
||||
jifenshijian = float(self.integration_time_entry.get())
|
||||
shuaxinshijian = float(self.refresh_interval_entry.get())
|
||||
|
||||
# 设置平滑次数
|
||||
boxcar_width = self.boxcar_width_slider.get()
|
||||
wrapper.setBoxcarWidth(spectrometer_index, boxcar_width)
|
||||
|
||||
# 设置平均次数
|
||||
scans_to_average = self.scans_to_average_slider.get()
|
||||
wrapper.setScansToAverage(spectrometer_index, scans_to_average)
|
||||
|
||||
conditions = f"jifenshijian = {jifenshijian} shuaxinshijian = {shuaxinshijian} zihaodaxiao = {zihaodaxiao} pinghuacishu = {self.boxcar_width_slider.get()} pingjuncishu = {self.scans_to_average_slider.get()}"
|
||||
self.test_count += 1
|
||||
|
||||
wavelengths, spectrum = self.get_spectrum_data()
|
||||
|
||||
# 在透射模式下计算透射率,否则应用背景校正
|
||||
if self.transmission_mode and self.background_spectrum is not None and self.source_spectrum is not None:
|
||||
transmission = self.calculate_transmission(spectrum)
|
||||
self.update_plot(wavelengths, transmission, plot_type='transmission')
|
||||
else:
|
||||
corrected_spectrum = self.apply_background_correction(spectrum)
|
||||
self.update_plot(wavelengths, corrected_spectrum, plot_type='spectrum')
|
||||
|
||||
def continuous_test(self):
|
||||
while not self.stop_event.is_set():
|
||||
# 获取输入框的值
|
||||
jifenshijian = float(self.integration_time_entry.get())
|
||||
shuaxinshijian = float(self.refresh_interval_entry.get())
|
||||
|
||||
# 设置平滑次数和平均次数
|
||||
boxcar_width = self.boxcar_width_slider.get()
|
||||
wrapper.setBoxcarWidth(spectrometer_index, boxcar_width)
|
||||
scans_to_average = self.scans_to_average_slider.get()
|
||||
wrapper.setScansToAverage(spectrometer_index, scans_to_average)
|
||||
|
||||
conditions = f"jifenshijian = {jifenshijian} shuaxinshijian = {shuaxinshijian} zihaodaxiao = {zihaodaxiao} pinghuacishu = {self.boxcar_width_slider.get()} pingjuncishu = {self.scans_to_average_slider.get()}"
|
||||
self.test_count += 1
|
||||
wavelengths, spectrum = self.get_spectrum_data()
|
||||
self.write_data_to_file("test", self.test_count, conditions, spectrum)
|
||||
|
||||
# 根据当前模式计算并更新图表
|
||||
if self.transmission_mode and self.background_spectrum is not None and self.source_spectrum is not None:
|
||||
transmission = self.calculate_transmission(spectrum)
|
||||
self.update_plot(wavelengths, transmission, plot_type='transmission')
|
||||
else:
|
||||
corrected_spectrum = self.apply_background_correction(spectrum)
|
||||
self.update_plot(wavelengths, corrected_spectrum)
|
||||
|
||||
time.sleep(shuaxinshijian)
|
||||
|
||||
def start_continuous_test(self):
|
||||
self.stop_event.clear() # 重置事件
|
||||
self.continuous_thread = Thread(target=self.continuous_test)
|
||||
self.continuous_thread.start()
|
||||
|
||||
def stop_continuous_test(self):
|
||||
self.stop_event.set() # 设置事件通知线程停止
|
||||
self.continuous_thread = None
|
||||
|
||||
def on_closing(self):
|
||||
if self.data_file:
|
||||
self.data_file.close()
|
||||
if messagebox.askyesno("退出", "实验g了?"):
|
||||
self.stop_continuous_test()
|
||||
self.root.destroy()
|
||||
sys.exit()
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 使用 ThemedTk 而不是普通的 Tk
|
||||
root = ThemedTk(theme="equilux") # 使用 'arc' 主题
|
||||
|
||||
# 由于我们已经使用了 ttkthemes 来设置主题,下面这些行可以省略
|
||||
# style = ttk.Style()
|
||||
# style.theme_use('arc')
|
||||
|
||||
app = App(root)
|
||||
root.mainloop()
|
||||
Reference in New Issue
Block a user