ophyd-async 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ophyd_async/__init__.py +1 -4
- ophyd_async/_version.py +2 -2
- ophyd_async/core/__init__.py +91 -19
- ophyd_async/core/_providers.py +68 -0
- ophyd_async/core/async_status.py +90 -42
- ophyd_async/core/detector.py +341 -0
- ophyd_async/core/device.py +226 -0
- ophyd_async/core/device_save_loader.py +286 -0
- ophyd_async/core/flyer.py +85 -0
- ophyd_async/core/mock_signal_backend.py +82 -0
- ophyd_async/core/mock_signal_utils.py +145 -0
- ophyd_async/core/{_device/_signal/signal.py → signal.py} +249 -61
- ophyd_async/core/{_device/_backend/signal_backend.py → signal_backend.py} +12 -5
- ophyd_async/core/{_device/_backend/sim_signal_backend.py → soft_signal_backend.py} +54 -48
- ophyd_async/core/standard_readable.py +261 -0
- ophyd_async/core/utils.py +127 -30
- ophyd_async/epics/_backend/_aioca.py +62 -43
- ophyd_async/epics/_backend/_p4p.py +100 -52
- ophyd_async/epics/_backend/common.py +25 -0
- ophyd_async/epics/areadetector/__init__.py +16 -15
- ophyd_async/epics/areadetector/aravis.py +63 -0
- ophyd_async/epics/areadetector/controllers/__init__.py +5 -0
- ophyd_async/epics/areadetector/controllers/ad_sim_controller.py +52 -0
- ophyd_async/epics/areadetector/controllers/aravis_controller.py +78 -0
- ophyd_async/epics/areadetector/controllers/kinetix_controller.py +49 -0
- ophyd_async/epics/areadetector/controllers/pilatus_controller.py +61 -0
- ophyd_async/epics/areadetector/controllers/vimba_controller.py +66 -0
- ophyd_async/epics/areadetector/drivers/__init__.py +21 -0
- ophyd_async/epics/areadetector/drivers/ad_base.py +107 -0
- ophyd_async/epics/areadetector/drivers/aravis_driver.py +38 -0
- ophyd_async/epics/areadetector/drivers/kinetix_driver.py +27 -0
- ophyd_async/epics/areadetector/drivers/pilatus_driver.py +21 -0
- ophyd_async/epics/areadetector/drivers/vimba_driver.py +63 -0
- ophyd_async/epics/areadetector/kinetix.py +46 -0
- ophyd_async/epics/areadetector/pilatus.py +45 -0
- ophyd_async/epics/areadetector/single_trigger_det.py +18 -10
- ophyd_async/epics/areadetector/utils.py +91 -13
- ophyd_async/epics/areadetector/vimba.py +43 -0
- ophyd_async/epics/areadetector/writers/__init__.py +5 -0
- ophyd_async/epics/areadetector/writers/_hdfdataset.py +10 -0
- ophyd_async/epics/areadetector/writers/_hdffile.py +54 -0
- ophyd_async/epics/areadetector/writers/hdf_writer.py +142 -0
- ophyd_async/epics/areadetector/writers/nd_file_hdf.py +40 -0
- ophyd_async/epics/areadetector/writers/nd_plugin.py +38 -0
- ophyd_async/epics/demo/__init__.py +78 -51
- ophyd_async/epics/demo/demo_ad_sim_detector.py +35 -0
- ophyd_async/epics/motion/motor.py +67 -52
- ophyd_async/epics/pvi/__init__.py +3 -0
- ophyd_async/epics/pvi/pvi.py +318 -0
- ophyd_async/epics/signal/__init__.py +8 -3
- ophyd_async/epics/signal/signal.py +27 -10
- ophyd_async/log.py +130 -0
- ophyd_async/panda/__init__.py +24 -7
- ophyd_async/panda/_common_blocks.py +49 -0
- ophyd_async/panda/_hdf_panda.py +48 -0
- ophyd_async/panda/_panda_controller.py +37 -0
- ophyd_async/panda/_table.py +158 -0
- ophyd_async/panda/_trigger.py +39 -0
- ophyd_async/panda/_utils.py +15 -0
- ophyd_async/panda/writers/__init__.py +3 -0
- ophyd_async/panda/writers/_hdf_writer.py +220 -0
- ophyd_async/panda/writers/_panda_hdf_file.py +58 -0
- ophyd_async/plan_stubs/__init__.py +13 -0
- ophyd_async/plan_stubs/ensure_connected.py +22 -0
- ophyd_async/plan_stubs/fly.py +149 -0
- ophyd_async/protocols.py +126 -0
- ophyd_async/sim/__init__.py +11 -0
- ophyd_async/sim/demo/__init__.py +3 -0
- ophyd_async/sim/demo/sim_motor.py +103 -0
- ophyd_async/sim/pattern_generator.py +318 -0
- ophyd_async/sim/sim_pattern_detector_control.py +55 -0
- ophyd_async/sim/sim_pattern_detector_writer.py +34 -0
- ophyd_async/sim/sim_pattern_generator.py +37 -0
- {ophyd_async-0.1.0.dist-info → ophyd_async-0.3.0.dist-info}/METADATA +35 -67
- ophyd_async-0.3.0.dist-info/RECORD +86 -0
- {ophyd_async-0.1.0.dist-info → ophyd_async-0.3.0.dist-info}/WHEEL +1 -1
- ophyd_async/core/_device/__init__.py +0 -0
- ophyd_async/core/_device/_backend/__init__.py +0 -0
- ophyd_async/core/_device/_signal/__init__.py +0 -0
- ophyd_async/core/_device/device.py +0 -60
- ophyd_async/core/_device/device_collector.py +0 -121
- ophyd_async/core/_device/device_vector.py +0 -14
- ophyd_async/core/_device/standard_readable.py +0 -72
- ophyd_async/epics/areadetector/ad_driver.py +0 -18
- ophyd_async/epics/areadetector/directory_provider.py +0 -18
- ophyd_async/epics/areadetector/hdf_streamer_det.py +0 -167
- ophyd_async/epics/areadetector/nd_file_hdf.py +0 -22
- ophyd_async/epics/areadetector/nd_plugin.py +0 -13
- ophyd_async/epics/signal/pvi_get.py +0 -22
- ophyd_async/panda/panda.py +0 -332
- ophyd_async-0.1.0.dist-info/RECORD +0 -45
- {ophyd_async-0.1.0.dist-info → ophyd_async-0.3.0.dist-info}/LICENSE +0 -0
- {ophyd_async-0.1.0.dist-info → ophyd_async-0.3.0.dist-info}/entry_points.txt +0 -0
- {ophyd_async-0.1.0.dist-info → ophyd_async-0.3.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
ophyd_async/__init__.py,sha256=v-rRiDOgZ3sQSMQKq0vgUQZvpeOkoHFXissAx6Ktg84,61
|
|
2
|
+
ophyd_async/__main__.py,sha256=G-Zcv_G9zK7Nhx6o5L5w-wyhMxdl_WgyMELu8IMFqAE,328
|
|
3
|
+
ophyd_async/_version.py,sha256=Jk2iAU7m-7Vx9XV1TtdD9ZoJraIncDq_4_Wd-qtUotg,411
|
|
4
|
+
ophyd_async/log.py,sha256=DbMjt0bkfUOLHIinZYt0Q0FHZmCXXi5x8y0uFiEmqoQ,3587
|
|
5
|
+
ophyd_async/protocols.py,sha256=EF2W9nfElV-0QNMYrX1zusL1PqDJR3kNsjlalR29j0I,3412
|
|
6
|
+
ophyd_async/core/__init__.py,sha256=znjVeRfrDVJbGLEkUczeKMW46kV6HDrlE4lV0SqvZt4,2952
|
|
7
|
+
ophyd_async/core/_providers.py,sha256=LrlTMPHKXWOPVkpAOw-pqBq0kip-c3C9ZZPoFfiaV4M,2212
|
|
8
|
+
ophyd_async/core/async_status.py,sha256=9TOgOXIAuH62RDo5t-Y5GdjrJ76d_6TFlBxYv-5_a88,4367
|
|
9
|
+
ophyd_async/core/detector.py,sha256=8mdLKphirgit5CVCklJI9eHqKKiCz4CYs9BElo10-lc,11007
|
|
10
|
+
ophyd_async/core/device.py,sha256=280zFnLCoiMZAA-Dh1_AjUSnhxUfKYGgj4H_2S1njOA,7086
|
|
11
|
+
ophyd_async/core/device_save_loader.py,sha256=RXA3dPUPihAR2ZGDStlGiA-TAsr_xqL0snsCjMsMnfA,9138
|
|
12
|
+
ophyd_async/core/flyer.py,sha256=bIjzBkrl8HVAlKgsZ_FF0WL69Qvksyzp9ZWmTLl8Yrw,2304
|
|
13
|
+
ophyd_async/core/mock_signal_backend.py,sha256=Ug6jK72wm9vM6EueoUrYgcXtiFzdPUEISRe86LdyYKc,2844
|
|
14
|
+
ophyd_async/core/mock_signal_utils.py,sha256=bF8MVZA1j9zCmS2tBbgUdfwNmcHniHixnmotjd0g7hs,4083
|
|
15
|
+
ophyd_async/core/signal.py,sha256=FbTb5qDPLhVxEbh6gimqXfkZwcqB4ymHTEYVXZVZYrk,16456
|
|
16
|
+
ophyd_async/core/signal_backend.py,sha256=fT3q0WED3JHmNKYCs7PzDLCK4cUPVin3wQjDNPdHqAY,1525
|
|
17
|
+
ophyd_async/core/soft_signal_backend.py,sha256=56zvcEi4c8n1yYbafTbp7X0VhSkhoehm3L8RBhu2fik,5596
|
|
18
|
+
ophyd_async/core/standard_readable.py,sha256=uVG3vs3s7-Kzg5dRCtT4I2mhZPqwVGYy2dxNmaOpDVU,8980
|
|
19
|
+
ophyd_async/core/utils.py,sha256=3oZcXNqAUHX4ZWMBH5gSuK6cFWEhSkZ9GSDYv0pf8jc,5783
|
|
20
|
+
ophyd_async/epics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
+
ophyd_async/epics/_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
+
ophyd_async/epics/_backend/_aioca.py,sha256=cpPNZmRMi7FnAh2-3ec5uklLVFOqsmEmpI1nh5Ud1Ls,8794
|
|
23
|
+
ophyd_async/epics/_backend/_p4p.py,sha256=lIKx7kQ2o8h3M4wPwrq8JBo8xuDnasJxpDH2ATVBY78,12257
|
|
24
|
+
ophyd_async/epics/_backend/common.py,sha256=16mAuxDwA3eZFjUW8DHMabaW3CtEI0Qe8DLpP2xlW7Y,814
|
|
25
|
+
ophyd_async/epics/areadetector/__init__.py,sha256=ViKzx-wUxkRyNR33wfpL11QB97o0J47_KMyI2C_NphI,510
|
|
26
|
+
ophyd_async/epics/areadetector/aravis.py,sha256=YklN4V0loqUQBs4swVX304N49JIGPvrNOk8iA5EWofg,2127
|
|
27
|
+
ophyd_async/epics/areadetector/kinetix.py,sha256=7rE2MLnz9DEmeiN9pCekDfpXuZ2DErnMajRp_9eoLZY,1359
|
|
28
|
+
ophyd_async/epics/areadetector/pilatus.py,sha256=ki-BOBCEIiUD2wAtmujBIB1eX-nbXB4yMLJK_Q3opRM,1398
|
|
29
|
+
ophyd_async/epics/areadetector/single_trigger_det.py,sha256=U92dqhioIfnve3jtCThq9gXBCdEzzqzY4ezk6rZV19g,1182
|
|
30
|
+
ophyd_async/epics/areadetector/utils.py,sha256=p66UbVdKRFj6Sm1Qvm23kmlVyBMMqIvXFxA3x17YnSk,2824
|
|
31
|
+
ophyd_async/epics/areadetector/vimba.py,sha256=IxG8KLzfb84iLtzf6ZoX9JikqZLP49lwkWu33bkDV9Y,1291
|
|
32
|
+
ophyd_async/epics/areadetector/controllers/__init__.py,sha256=af58ci7X2z2s_FyUwR3IGQrws8q4TKcBw7vFyIS5FoI,217
|
|
33
|
+
ophyd_async/epics/areadetector/controllers/ad_sim_controller.py,sha256=mthZ6WxajMEgUKptq3bnkIctbLhjzTagV66i1auB8cg,1587
|
|
34
|
+
ophyd_async/epics/areadetector/controllers/aravis_controller.py,sha256=CIfnZdq_NobO_UMC2TJoAfUEP9GlzZg5z5bz6Dn1DxY,2669
|
|
35
|
+
ophyd_async/epics/areadetector/controllers/kinetix_controller.py,sha256=9QmydX85QOXfQL_UX49M9EQ2b2hUZPVzLxgGQn-A9Oc,1611
|
|
36
|
+
ophyd_async/epics/areadetector/controllers/pilatus_controller.py,sha256=cd1CKkaXlwkpQ0I1VL7nN0U8R4VweTsa08WhvHYI4nY,2243
|
|
37
|
+
ophyd_async/epics/areadetector/controllers/vimba_controller.py,sha256=Eh4Hr9rWgq1mKvE93JzgixntjPHxF3_07GTFqiOdZqE,2123
|
|
38
|
+
ophyd_async/epics/areadetector/drivers/__init__.py,sha256=-Ib0Lz4fFQQmB7K0uFxMDvAerkLxadMQERH7lNAvrs4,495
|
|
39
|
+
ophyd_async/epics/areadetector/drivers/ad_base.py,sha256=18WFAiWEUg0H2LcvTQHrKYj2wThGafQzDpiyAWki6vo,3411
|
|
40
|
+
ophyd_async/epics/areadetector/drivers/aravis_driver.py,sha256=PmIygsVNoxxYHvZZzFAbAm2DXmXFc13nAzL_DJB6YSU,1464
|
|
41
|
+
ophyd_async/epics/areadetector/drivers/kinetix_driver.py,sha256=yIV23BkGBJ4i0VskLiLL7AFbadCCR6Ch1UwUDJ9r2YM,743
|
|
42
|
+
ophyd_async/epics/areadetector/drivers/pilatus_driver.py,sha256=0DsUu9vAPXDa2v8_V0f_kPjBtLu3y4_EkmFfFjYO4Gk,553
|
|
43
|
+
ophyd_async/epics/areadetector/drivers/vimba_driver.py,sha256=J54VtWkOklfbSqZYxGWH1e6Uzm9_Gph_ZbCf9Zax0LU,1713
|
|
44
|
+
ophyd_async/epics/areadetector/writers/__init__.py,sha256=tpPcrYd1hs8WS7C0gmCnR2EBwjE5RzCljI7WwZ2V_LM,191
|
|
45
|
+
ophyd_async/epics/areadetector/writers/_hdfdataset.py,sha256=E0C9VgsPyY35h7k0mvcIhjsIVNavApLxizqNWlM388w,167
|
|
46
|
+
ophyd_async/epics/areadetector/writers/_hdffile.py,sha256=YtUgOKX53m0TaFEGBW671qXqNuuEKxEyLV5Ein1fjvo,1799
|
|
47
|
+
ophyd_async/epics/areadetector/writers/hdf_writer.py,sha256=ZpbVilNVv81OpbCrqaeZUoHLarrjzRWEGe-zI1Wxyyw,5436
|
|
48
|
+
ophyd_async/epics/areadetector/writers/nd_file_hdf.py,sha256=EkiaEh_0U6Iz17jFi2IIsRPsVQTQIJRG8EPNCiAHkkU,1762
|
|
49
|
+
ophyd_async/epics/areadetector/writers/nd_plugin.py,sha256=GUzaeTMdG07Rb1x0WzBBxMEltBhr10jb5dL29tEWXEQ,1547
|
|
50
|
+
ophyd_async/epics/demo/__init__.py,sha256=ZcuZ66aIQ58WSydLOSKnk-h_W-aWjhDRZkWQA6f3sig,5790
|
|
51
|
+
ophyd_async/epics/demo/demo_ad_sim_detector.py,sha256=06y65yvaqXvL2rDocjYyLz9kTVzuwV-LeuPhEfExdOA,944
|
|
52
|
+
ophyd_async/epics/demo/mover.db,sha256=RFz0rxZue689Wh1sWTZwWeFMUrH04ttPq2u5xJH_Fp4,998
|
|
53
|
+
ophyd_async/epics/demo/sensor.db,sha256=AVtiydrdtwAz2EFurO2Ult9SSRtre3r0akOBbL98LT0,554
|
|
54
|
+
ophyd_async/epics/motion/__init__.py,sha256=tnmVRIwKa9PdN_xonJdAUD04UpEceh-hoD7XI62yDB0,46
|
|
55
|
+
ophyd_async/epics/motion/motor.py,sha256=G8cc-okSXJ6s2fGxRO155xm7PrBbVImBmBMRWts895k,3630
|
|
56
|
+
ophyd_async/epics/pvi/__init__.py,sha256=TbOQNY4enQWgtr1T7x129vpo2p7FIFlr8cyZqqv5Lk4,158
|
|
57
|
+
ophyd_async/epics/pvi/pvi.py,sha256=PJdY3rCRyIQbsbHDru-TJ-IVOItyaQwCQKAC0Widu6A,11363
|
|
58
|
+
ophyd_async/epics/signal/__init__.py,sha256=JXKBSGpRL9y3auh27JRxsqDn_rBOXpJjtd4nCuDOX2g,261
|
|
59
|
+
ophyd_async/epics/signal/_epics_transport.py,sha256=DEIL0iYUAWssysVEgWGu1fHSM1l-ATV2kjUgPtDN9LY,858
|
|
60
|
+
ophyd_async/epics/signal/signal.py,sha256=M8ZVG_zLdYJfroCRX-u_w8c3yIhswSRw8e3RkW2szio,3166
|
|
61
|
+
ophyd_async/panda/__init__.py,sha256=FuSnvp-RtdA0X4RcHEF0nTiXymRts2MNdFmF_1_i41w,775
|
|
62
|
+
ophyd_async/panda/_common_blocks.py,sha256=n0PPc1rar43oDSIA-yNubTc8fR5YCW1tyjQU58whsg0,1038
|
|
63
|
+
ophyd_async/panda/_hdf_panda.py,sha256=QjfZyYos0ZBlIqBiZ5UbyEd_wuh_cGzwV8QE9jvLiIY,1419
|
|
64
|
+
ophyd_async/panda/_panda_controller.py,sha256=dIqcjmaIHVrki8UXSoDx46kk6I2Lhpe2o3sXNg5f-RQ,1238
|
|
65
|
+
ophyd_async/panda/_table.py,sha256=dLoRP4zYNOkD_s0Vkp2wVYAwkjVG8nNdf8-FaXOTfPo,5655
|
|
66
|
+
ophyd_async/panda/_trigger.py,sha256=tBH8uq_4o1ASG9yofVxq3tjf5v8LPzniDTRL4yjramI,1195
|
|
67
|
+
ophyd_async/panda/_utils.py,sha256=VHW5kPVISyEkmse_qQcyisBkkEwMO6GG2Ago-CH1AFA,487
|
|
68
|
+
ophyd_async/panda/writers/__init__.py,sha256=xy7BguVQG4HNIDBfKPjMj0KQo1tptC9LbCpEuMcVGaM,70
|
|
69
|
+
ophyd_async/panda/writers/_hdf_writer.py,sha256=vnyIg3JmlzMIIq75o0IDMfGzBm_GJAhOUisAZE_0cyg,7597
|
|
70
|
+
ophyd_async/panda/writers/_panda_hdf_file.py,sha256=42iHaTax4JjOBpNC7d4nkNL9SM14OTnFPTIcXv2jg-4,1759
|
|
71
|
+
ophyd_async/plan_stubs/__init__.py,sha256=nO9ELG9J7fYwfVTVRWVorz4kffeszYpwk1ROh6Ha--w,405
|
|
72
|
+
ophyd_async/plan_stubs/ensure_connected.py,sha256=1MkDu8UqVRPHLnW9IXRn-QvKiG8-rCV8T4KDbjf9K6w,557
|
|
73
|
+
ophyd_async/plan_stubs/fly.py,sha256=nl8XLoY7hvlam6H3zl4NcPRUiEJ3xIjopHEfA0ehTDg,4845
|
|
74
|
+
ophyd_async/sim/__init__.py,sha256=ScjH1g7FMo5yPACfJRZE6xGBWCHU4bKDzNQk1tqObnA,366
|
|
75
|
+
ophyd_async/sim/pattern_generator.py,sha256=pvSk2zb82D08j2jiKAMqMAfRohGnYd_rpjUraLrCD6c,10640
|
|
76
|
+
ophyd_async/sim/sim_pattern_detector_control.py,sha256=Ypz8IuRYAY2J243IhVbNyGr_Z-XtpJZ1qxma6NR3TgM,1838
|
|
77
|
+
ophyd_async/sim/sim_pattern_detector_writer.py,sha256=ESpcVyHd1TP7Cojznv2hJAwLinu3XbgAiVKfX12FCII,1237
|
|
78
|
+
ophyd_async/sim/sim_pattern_generator.py,sha256=fbcwWxTPYKLK33OzIY15vGylnonOO8HIudz1y_56GZU,1336
|
|
79
|
+
ophyd_async/sim/demo/__init__.py,sha256=9mxKpslrL89cfSj4g3og8Br3O--pMj3hhWZS-Xu6kyA,56
|
|
80
|
+
ophyd_async/sim/demo/sim_motor.py,sha256=a2p5wnHXjF-V5zOFai7jnszk4kbGmrZRnUqBtkOgEfQ,3733
|
|
81
|
+
ophyd_async-0.3.0.dist-info/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
|
|
82
|
+
ophyd_async-0.3.0.dist-info/METADATA,sha256=aNVgEtFpaffvpH6YavrgqWN48m0HO0m38POJ17FPjGM,6285
|
|
83
|
+
ophyd_async-0.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
84
|
+
ophyd_async-0.3.0.dist-info/entry_points.txt,sha256=O0YNJTEufO0w9BozXi-JurTy2U1_o0ypeCgJLQ727Jk,58
|
|
85
|
+
ophyd_async-0.3.0.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
|
|
86
|
+
ophyd_async-0.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"""Base device"""
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
from typing import Iterator, Optional, Tuple
|
|
5
|
-
|
|
6
|
-
from bluesky.protocols import HasName
|
|
7
|
-
|
|
8
|
-
from ..utils import wait_for_connection
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class Device(HasName):
|
|
12
|
-
"""Common base class for all Ophyd Async Devices.
|
|
13
|
-
|
|
14
|
-
By default, names and connects all Device children.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
_name: str = ""
|
|
18
|
-
#: The parent Device if it exists
|
|
19
|
-
parent: Optional[Device] = None
|
|
20
|
-
|
|
21
|
-
def __init__(self, name: str = "") -> None:
|
|
22
|
-
self.set_name(name)
|
|
23
|
-
|
|
24
|
-
@property
|
|
25
|
-
def name(self) -> str:
|
|
26
|
-
"""Return the name of the Device"""
|
|
27
|
-
return self._name
|
|
28
|
-
|
|
29
|
-
def children(self) -> Iterator[Tuple[str, Device]]:
|
|
30
|
-
for attr_name, attr in self.__dict__.items():
|
|
31
|
-
if attr_name != "parent" and isinstance(attr, Device):
|
|
32
|
-
yield attr_name, attr
|
|
33
|
-
|
|
34
|
-
def set_name(self, name: str):
|
|
35
|
-
"""Set ``self.name=name`` and each ``self.child.name=name+"-child"``.
|
|
36
|
-
|
|
37
|
-
Parameters
|
|
38
|
-
----------
|
|
39
|
-
name:
|
|
40
|
-
New name to set
|
|
41
|
-
"""
|
|
42
|
-
self._name = name
|
|
43
|
-
for attr_name, child in self.children():
|
|
44
|
-
child_name = f"{name}-{attr_name.rstrip('_')}" if name else ""
|
|
45
|
-
child.set_name(child_name)
|
|
46
|
-
child.parent = self
|
|
47
|
-
|
|
48
|
-
async def connect(self, sim: bool = False):
|
|
49
|
-
"""Connect self and all child Devices.
|
|
50
|
-
|
|
51
|
-
Parameters
|
|
52
|
-
----------
|
|
53
|
-
sim:
|
|
54
|
-
If True then connect in simulation mode.
|
|
55
|
-
"""
|
|
56
|
-
coros = {
|
|
57
|
-
name: child_device.connect(sim) for name, child_device in self.children()
|
|
58
|
-
}
|
|
59
|
-
if coros:
|
|
60
|
-
await wait_for_connection(**coros)
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
"""Interface for connecting and naming multiple devices"""
|
|
2
|
-
import asyncio
|
|
3
|
-
import logging
|
|
4
|
-
import sys
|
|
5
|
-
from contextlib import suppress
|
|
6
|
-
from typing import Any, Dict, Set
|
|
7
|
-
|
|
8
|
-
from bluesky.run_engine import call_in_bluesky_event_loop
|
|
9
|
-
|
|
10
|
-
from ..utils import NotConnected
|
|
11
|
-
from .device import Device
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class DeviceCollector:
|
|
15
|
-
"""Collector of top level Device instances to be used as a context manager
|
|
16
|
-
|
|
17
|
-
Parameters
|
|
18
|
-
----------
|
|
19
|
-
set_name:
|
|
20
|
-
If True, call ``device.set_name(variable_name)`` on all collected
|
|
21
|
-
Devices
|
|
22
|
-
connect:
|
|
23
|
-
If True, call ``device.connect(sim)`` in parallel on all
|
|
24
|
-
collected Devices
|
|
25
|
-
sim:
|
|
26
|
-
If True, connect Signals in simulation mode
|
|
27
|
-
timeout:
|
|
28
|
-
How long to wait for connect before logging an exception
|
|
29
|
-
|
|
30
|
-
Notes
|
|
31
|
-
-----
|
|
32
|
-
Example usage::
|
|
33
|
-
|
|
34
|
-
[async] with DeviceCollector():
|
|
35
|
-
t1x = motor.Motor("BLxxI-MO-TABLE-01:X")
|
|
36
|
-
t1y = motor.Motor("pva://BLxxI-MO-TABLE-01:Y")
|
|
37
|
-
# Names and connects devices here
|
|
38
|
-
assert t1x.comm.velocity.source
|
|
39
|
-
assert t1x.name == "t1x"
|
|
40
|
-
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
def __init__(
|
|
44
|
-
self,
|
|
45
|
-
set_name=True,
|
|
46
|
-
connect=True,
|
|
47
|
-
sim=False,
|
|
48
|
-
timeout: float = 10.0,
|
|
49
|
-
):
|
|
50
|
-
self._set_name = set_name
|
|
51
|
-
self._connect = connect
|
|
52
|
-
self._sim = sim
|
|
53
|
-
self._timeout = timeout
|
|
54
|
-
self._names_on_enter: Set[str] = set()
|
|
55
|
-
self._objects_on_exit: Dict[str, Any] = {}
|
|
56
|
-
|
|
57
|
-
def _caller_locals(self):
|
|
58
|
-
"""Walk up until we find a stack frame that doesn't have us as self"""
|
|
59
|
-
try:
|
|
60
|
-
raise ValueError
|
|
61
|
-
except ValueError:
|
|
62
|
-
_, _, tb = sys.exc_info()
|
|
63
|
-
assert tb, "Can't get traceback, this shouldn't happen"
|
|
64
|
-
caller_frame = tb.tb_frame
|
|
65
|
-
while caller_frame.f_locals.get("self", None) is self:
|
|
66
|
-
caller_frame = caller_frame.f_back
|
|
67
|
-
return caller_frame.f_locals
|
|
68
|
-
|
|
69
|
-
def __enter__(self) -> "DeviceCollector":
|
|
70
|
-
# Stash the names that were defined before we were called
|
|
71
|
-
self._names_on_enter = set(self._caller_locals())
|
|
72
|
-
return self
|
|
73
|
-
|
|
74
|
-
async def __aenter__(self) -> "DeviceCollector":
|
|
75
|
-
return self.__enter__()
|
|
76
|
-
|
|
77
|
-
async def _on_exit(self) -> None:
|
|
78
|
-
# Name and kick off connect for devices
|
|
79
|
-
tasks: Dict[asyncio.Task, str] = {}
|
|
80
|
-
for name, obj in self._objects_on_exit.items():
|
|
81
|
-
if name not in self._names_on_enter and isinstance(obj, Device):
|
|
82
|
-
if self._set_name and not obj.name:
|
|
83
|
-
obj.set_name(name)
|
|
84
|
-
if self._connect:
|
|
85
|
-
task = asyncio.create_task(obj.connect(self._sim))
|
|
86
|
-
tasks[task] = name
|
|
87
|
-
# Wait for all the signals to have finished
|
|
88
|
-
if tasks:
|
|
89
|
-
await self._wait_for_tasks(tasks)
|
|
90
|
-
|
|
91
|
-
async def _wait_for_tasks(self, tasks: Dict[asyncio.Task, str]):
|
|
92
|
-
done, pending = await asyncio.wait(tasks, timeout=self._timeout)
|
|
93
|
-
if pending:
|
|
94
|
-
msg = f"{len(pending)} Devices did not connect:"
|
|
95
|
-
for t in pending:
|
|
96
|
-
t.cancel()
|
|
97
|
-
with suppress(Exception):
|
|
98
|
-
await t
|
|
99
|
-
e = t.exception()
|
|
100
|
-
msg += f"\n {tasks[t]}: {type(e).__name__}"
|
|
101
|
-
lines = str(e).splitlines()
|
|
102
|
-
if len(lines) <= 1:
|
|
103
|
-
msg += f": {e}"
|
|
104
|
-
else:
|
|
105
|
-
msg += "".join(f"\n {line}" for line in lines)
|
|
106
|
-
logging.error(msg)
|
|
107
|
-
raised = [t for t in done if t.exception()]
|
|
108
|
-
if raised:
|
|
109
|
-
logging.error(f"{len(raised)} Devices raised an error:")
|
|
110
|
-
for t in raised:
|
|
111
|
-
logging.exception(f" {tasks[t]}:", exc_info=t.exception())
|
|
112
|
-
if pending or raised:
|
|
113
|
-
raise NotConnected("Not all Devices connected")
|
|
114
|
-
|
|
115
|
-
async def __aexit__(self, type, value, traceback):
|
|
116
|
-
self._objects_on_exit = self._caller_locals()
|
|
117
|
-
await self._on_exit()
|
|
118
|
-
|
|
119
|
-
def __exit__(self, type_, value, traceback):
|
|
120
|
-
self._objects_on_exit = self._caller_locals()
|
|
121
|
-
return call_in_bluesky_event_loop(self._on_exit())
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"""Dictionary which can contain mappings between integers and devices."""
|
|
2
|
-
|
|
3
|
-
from typing import Dict, Generator, Tuple, TypeVar
|
|
4
|
-
|
|
5
|
-
from .device import Device
|
|
6
|
-
|
|
7
|
-
VT = TypeVar("VT", bound=Device)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class DeviceVector(Dict[int, VT], Device):
|
|
11
|
-
def children(self) -> Generator[Tuple[str, Device], None, None]:
|
|
12
|
-
for attr_name, attr in self.items():
|
|
13
|
-
if isinstance(attr, Device):
|
|
14
|
-
yield str(attr_name), attr
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
from typing import Dict, Sequence, Tuple
|
|
2
|
-
|
|
3
|
-
from bluesky.protocols import Configurable, Descriptor, Readable, Reading, Stageable
|
|
4
|
-
|
|
5
|
-
from ..async_status import AsyncStatus
|
|
6
|
-
from ..utils import merge_gathered_dicts
|
|
7
|
-
from ._signal.signal import SignalR
|
|
8
|
-
from .device import Device
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class StandardReadable(Device, Readable, Configurable, Stageable):
|
|
12
|
-
"""Device that owns its children and provides useful default behavior.
|
|
13
|
-
|
|
14
|
-
- When its name is set it renames child Devices
|
|
15
|
-
- Signals can be registered for read() and read_configuration()
|
|
16
|
-
- These signals will be subscribed for read() between stage() and unstage()
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
_read_signals: Tuple[SignalR, ...] = ()
|
|
20
|
-
_configuration_signals: Tuple[SignalR, ...] = ()
|
|
21
|
-
_read_uncached_signals: Tuple[SignalR, ...] = ()
|
|
22
|
-
|
|
23
|
-
def set_readable_signals(
|
|
24
|
-
self,
|
|
25
|
-
read: Sequence[SignalR] = (),
|
|
26
|
-
config: Sequence[SignalR] = (),
|
|
27
|
-
read_uncached: Sequence[SignalR] = (),
|
|
28
|
-
):
|
|
29
|
-
"""
|
|
30
|
-
Parameters
|
|
31
|
-
----------
|
|
32
|
-
read:
|
|
33
|
-
Signals to make up :meth:`~StandardReadable.read`
|
|
34
|
-
conf:
|
|
35
|
-
Signals to make up :meth:`~StandardReadable.read_configuration`
|
|
36
|
-
read_uncached:
|
|
37
|
-
Signals to make up :meth:`~StandardReadable.read` that won't be cached
|
|
38
|
-
"""
|
|
39
|
-
self._read_signals = tuple(read)
|
|
40
|
-
self._configuration_signals = tuple(config)
|
|
41
|
-
self._read_uncached_signals = tuple(read_uncached)
|
|
42
|
-
|
|
43
|
-
@AsyncStatus.wrap
|
|
44
|
-
async def stage(self) -> None:
|
|
45
|
-
for sig in self._read_signals + self._configuration_signals:
|
|
46
|
-
await sig.stage().task
|
|
47
|
-
|
|
48
|
-
@AsyncStatus.wrap
|
|
49
|
-
async def unstage(self) -> None:
|
|
50
|
-
for sig in self._read_signals + self._configuration_signals:
|
|
51
|
-
await sig.unstage().task
|
|
52
|
-
|
|
53
|
-
async def describe_configuration(self) -> Dict[str, Descriptor]:
|
|
54
|
-
return await merge_gathered_dicts(
|
|
55
|
-
[sig.describe() for sig in self._configuration_signals]
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
async def read_configuration(self) -> Dict[str, Reading]:
|
|
59
|
-
return await merge_gathered_dicts(
|
|
60
|
-
[sig.read() for sig in self._configuration_signals]
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
async def describe(self) -> Dict[str, Descriptor]:
|
|
64
|
-
return await merge_gathered_dicts(
|
|
65
|
-
[sig.describe() for sig in self._read_signals + self._read_uncached_signals]
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
async def read(self) -> Dict[str, Reading]:
|
|
69
|
-
return await merge_gathered_dicts(
|
|
70
|
-
[sig.read() for sig in self._read_signals]
|
|
71
|
-
+ [sig.read(cached=False) for sig in self._read_uncached_signals]
|
|
72
|
-
)
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from ophyd_async.core import Device
|
|
2
|
-
|
|
3
|
-
from ..signal.signal import epics_signal_rw
|
|
4
|
-
from .utils import ImageMode, ad_r, ad_rw
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class ADDriver(Device):
|
|
8
|
-
def __init__(self, prefix: str) -> None:
|
|
9
|
-
# Define some signals
|
|
10
|
-
self.acquire = ad_rw(bool, prefix + "Acquire")
|
|
11
|
-
self.acquire_time = ad_rw(float, prefix + "AcquireTime")
|
|
12
|
-
self.num_images = ad_rw(int, prefix + "NumImages")
|
|
13
|
-
self.image_mode = ad_rw(ImageMode, prefix + "ImageMode")
|
|
14
|
-
self.array_counter = ad_rw(int, prefix + "ArrayCounter")
|
|
15
|
-
self.array_size_x = ad_r(int, prefix + "ArraySizeX")
|
|
16
|
-
self.array_size_y = ad_r(int, prefix + "ArraySizeY")
|
|
17
|
-
# There is no _RBV for this one
|
|
18
|
-
self.wait_for_plugins = epics_signal_rw(bool, prefix + "WaitForPlugins")
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import tempfile
|
|
2
|
-
from abc import abstractmethod
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Protocol
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class DirectoryProvider(Protocol):
|
|
8
|
-
@abstractmethod
|
|
9
|
-
async def get_directory(self) -> Path:
|
|
10
|
-
...
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TmpDirectoryProvider(DirectoryProvider):
|
|
14
|
-
def __init__(self) -> None:
|
|
15
|
-
self._directory = Path(tempfile.mkdtemp())
|
|
16
|
-
|
|
17
|
-
async def get_directory(self) -> Path:
|
|
18
|
-
return self._directory
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import collections
|
|
3
|
-
import time
|
|
4
|
-
from typing import Callable, Dict, Iterator, Optional, Sized
|
|
5
|
-
|
|
6
|
-
from bluesky.protocols import (
|
|
7
|
-
Asset,
|
|
8
|
-
Descriptor,
|
|
9
|
-
Flyable,
|
|
10
|
-
PartialEvent,
|
|
11
|
-
WritesExternalAssets,
|
|
12
|
-
)
|
|
13
|
-
from bluesky.utils import new_uid
|
|
14
|
-
from event_model import compose_stream_resource
|
|
15
|
-
|
|
16
|
-
from ophyd_async.core import (
|
|
17
|
-
DEFAULT_TIMEOUT,
|
|
18
|
-
AsyncStatus,
|
|
19
|
-
StandardReadable,
|
|
20
|
-
set_and_wait_for_value,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
from .ad_driver import ADDriver
|
|
24
|
-
from .directory_provider import DirectoryProvider
|
|
25
|
-
from .nd_file_hdf import NDFileHDF
|
|
26
|
-
from .utils import FileWriteMode, ImageMode
|
|
27
|
-
|
|
28
|
-
# How long in seconds to wait between flushes of HDF datasets
|
|
29
|
-
FLUSH_PERIOD = 0.5
|
|
30
|
-
|
|
31
|
-
# How long to wait for new frames before timing out
|
|
32
|
-
FRAME_TIMEOUT = 120
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class _HDFResource:
|
|
36
|
-
def __init__(self) -> None:
|
|
37
|
-
# TODO: set to Deque[Asset] after protocols updated for stream*
|
|
38
|
-
# https://github.com/bluesky/bluesky/issues/1558
|
|
39
|
-
self.asset_docs = collections.deque() # type: ignore
|
|
40
|
-
self._last_emitted = 0
|
|
41
|
-
self._last_flush = time.monotonic()
|
|
42
|
-
self._compose_datum: Optional[Callable] = None
|
|
43
|
-
|
|
44
|
-
def _append_resource(self, full_file_name: str):
|
|
45
|
-
resource_doc, (self._compose_datum,) = compose_stream_resource(
|
|
46
|
-
spec="AD_HDF5_SWMR_SLICE",
|
|
47
|
-
root="/",
|
|
48
|
-
resource_path=full_file_name,
|
|
49
|
-
resource_kwargs={},
|
|
50
|
-
stream_names=["primary"],
|
|
51
|
-
)
|
|
52
|
-
self.asset_docs.append(("stream_resource", resource_doc))
|
|
53
|
-
|
|
54
|
-
def _append_datum(self, event_count: int):
|
|
55
|
-
assert self._compose_datum, "Resource not emitted yet"
|
|
56
|
-
datum_doc = self._compose_datum(
|
|
57
|
-
datum_kwargs={},
|
|
58
|
-
event_offset=self._last_emitted,
|
|
59
|
-
event_count=event_count,
|
|
60
|
-
)
|
|
61
|
-
self._last_emitted += event_count
|
|
62
|
-
self.asset_docs.append(("stream_datum", datum_doc))
|
|
63
|
-
|
|
64
|
-
async def flush_and_publish(self, hdf: NDFileHDF):
|
|
65
|
-
num_captured = await hdf.num_captured.get_value()
|
|
66
|
-
if num_captured:
|
|
67
|
-
if self._compose_datum is None:
|
|
68
|
-
self._append_resource(await hdf.full_file_name.get_value())
|
|
69
|
-
event_count = num_captured - self._last_emitted
|
|
70
|
-
if event_count:
|
|
71
|
-
self._append_datum(event_count)
|
|
72
|
-
await hdf.flush_now.set(True)
|
|
73
|
-
self._last_flush = time.monotonic()
|
|
74
|
-
if time.monotonic() - self._last_flush > FRAME_TIMEOUT:
|
|
75
|
-
raise TimeoutError(f"{hdf.name}: writing stalled on frame {num_captured}")
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
class HDFStreamerDet(StandardReadable, Flyable, WritesExternalAssets):
|
|
79
|
-
def __init__(
|
|
80
|
-
self, drv: ADDriver, hdf: NDFileHDF, dp: DirectoryProvider, name=""
|
|
81
|
-
) -> None:
|
|
82
|
-
self.drv = drv
|
|
83
|
-
self.hdf = hdf
|
|
84
|
-
self._dp = dp
|
|
85
|
-
self._resource = _HDFResource()
|
|
86
|
-
self._capture_status: Optional[AsyncStatus] = None
|
|
87
|
-
self._start_status: Optional[AsyncStatus] = None
|
|
88
|
-
self.set_readable_signals(config=[self.drv.acquire_time])
|
|
89
|
-
super().__init__(name)
|
|
90
|
-
|
|
91
|
-
@AsyncStatus.wrap
|
|
92
|
-
async def stage(self) -> None:
|
|
93
|
-
# Make a new resource for the new HDF file we're going to open
|
|
94
|
-
self._resource = _HDFResource()
|
|
95
|
-
await asyncio.gather(
|
|
96
|
-
self.drv.wait_for_plugins.set(True),
|
|
97
|
-
self.hdf.lazy_open.set(True),
|
|
98
|
-
self.hdf.swmr_mode.set(True),
|
|
99
|
-
self.hdf.file_path.set(str(await self._dp.get_directory())),
|
|
100
|
-
self.hdf.file_name.set(f"{self.name}-{new_uid()}"),
|
|
101
|
-
self.hdf.file_template.set("%s/%s.h5"),
|
|
102
|
-
# Go forever
|
|
103
|
-
self.hdf.num_capture.set(0),
|
|
104
|
-
self.hdf.file_write_mode.set(FileWriteMode.stream),
|
|
105
|
-
)
|
|
106
|
-
# Wait for it to start, stashing the status that tells us when it finishes
|
|
107
|
-
self._capture_status = await set_and_wait_for_value(self.hdf.capture, True)
|
|
108
|
-
await super().stage()
|
|
109
|
-
|
|
110
|
-
async def describe(self) -> Dict[str, Descriptor]:
|
|
111
|
-
datakeys = await super().describe()
|
|
112
|
-
# Insert a descriptor for the HDF resource, this will not appear
|
|
113
|
-
# in read() as it describes StreamResource outputs only
|
|
114
|
-
datakeys[self.name] = Descriptor(
|
|
115
|
-
source=self.hdf.full_file_name.source,
|
|
116
|
-
shape=await asyncio.gather(
|
|
117
|
-
self.drv.array_size_y.get_value(),
|
|
118
|
-
self.drv.array_size_x.get_value(),
|
|
119
|
-
),
|
|
120
|
-
dtype="array",
|
|
121
|
-
external="STREAM:",
|
|
122
|
-
)
|
|
123
|
-
return datakeys
|
|
124
|
-
|
|
125
|
-
# For step scan, take a single frame
|
|
126
|
-
@AsyncStatus.wrap
|
|
127
|
-
async def trigger(self):
|
|
128
|
-
await self.drv.image_mode.set(ImageMode.single)
|
|
129
|
-
frame_timeout = DEFAULT_TIMEOUT + await self.drv.acquire_time.get_value()
|
|
130
|
-
await self.drv.acquire.set(1, timeout=frame_timeout)
|
|
131
|
-
await self._resource.flush_and_publish(self.hdf)
|
|
132
|
-
|
|
133
|
-
def collect_asset_docs(self) -> Iterator[Asset]:
|
|
134
|
-
while self._resource.asset_docs:
|
|
135
|
-
yield self._resource.asset_docs.popleft()
|
|
136
|
-
|
|
137
|
-
# For flyscan, take the number of frames we wanted
|
|
138
|
-
@AsyncStatus.wrap
|
|
139
|
-
async def kickoff(self) -> None:
|
|
140
|
-
await self.drv.image_mode.set(ImageMode.multiple)
|
|
141
|
-
# Wait for it to start, stashing the status that tells us when it finishes
|
|
142
|
-
self._start_status = await set_and_wait_for_value(self.drv.acquire, True)
|
|
143
|
-
|
|
144
|
-
# Do the same thing for flyscans and step scans
|
|
145
|
-
async def describe_collect(self) -> Dict[str, Dict[str, Descriptor]]:
|
|
146
|
-
return {self.name: await self.describe()}
|
|
147
|
-
|
|
148
|
-
def collect(self) -> Iterator[PartialEvent]:
|
|
149
|
-
yield from iter([])
|
|
150
|
-
|
|
151
|
-
@AsyncStatus.wrap
|
|
152
|
-
async def complete(self) -> None:
|
|
153
|
-
done: Sized = ()
|
|
154
|
-
while not done:
|
|
155
|
-
assert self._start_status, "Kickoff not run"
|
|
156
|
-
done, _ = await asyncio.wait(
|
|
157
|
-
(self._start_status.task,), timeout=FLUSH_PERIOD
|
|
158
|
-
)
|
|
159
|
-
await self._resource.flush_and_publish(self.hdf)
|
|
160
|
-
|
|
161
|
-
@AsyncStatus.wrap
|
|
162
|
-
async def unstage(self) -> None:
|
|
163
|
-
# Already done a caput callback in _capture_status, so can't do one here
|
|
164
|
-
await self.hdf.capture.set(False, wait=False)
|
|
165
|
-
assert self._capture_status, "Stage not run"
|
|
166
|
-
await self._capture_status
|
|
167
|
-
await super().unstage()
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from ophyd_async.core import Device
|
|
2
|
-
|
|
3
|
-
from ..signal.signal import epics_signal_rw
|
|
4
|
-
from .utils import FileWriteMode, ad_r, ad_rw
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class NDFileHDF(Device):
|
|
8
|
-
def __init__(self, prefix: str) -> None:
|
|
9
|
-
# Define some signals
|
|
10
|
-
self.file_path = ad_rw(str, prefix + "FilePath")
|
|
11
|
-
self.file_name = ad_rw(str, prefix + "FileName")
|
|
12
|
-
self.file_template = ad_rw(str, prefix + "FileTemplate")
|
|
13
|
-
self.full_file_name = ad_r(str, prefix + "FullFileName")
|
|
14
|
-
self.file_write_mode = ad_rw(FileWriteMode, prefix + "FileWriteMode")
|
|
15
|
-
self.num_capture = ad_rw(int, prefix + "NumCapture")
|
|
16
|
-
self.num_captured = ad_r(int, prefix + "NumCaptured")
|
|
17
|
-
self.swmr_mode = ad_rw(bool, prefix + "SWMRMode")
|
|
18
|
-
self.lazy_open = ad_rw(bool, prefix + "LazyOpen")
|
|
19
|
-
self.capture = ad_rw(bool, prefix + "Capture")
|
|
20
|
-
self.flush_now = epics_signal_rw(bool, prefix + "FlushNow")
|
|
21
|
-
self.array_size0 = ad_r(int, prefix + "ArraySize0")
|
|
22
|
-
self.array_size1 = ad_r(int, prefix + "ArraySize1")
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from ophyd_async.core import Device
|
|
2
|
-
|
|
3
|
-
from .utils import ad_r
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class NDPlugin(Device):
|
|
7
|
-
pass
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class NDPluginStats(NDPlugin):
|
|
11
|
-
def __init__(self, prefix: str) -> None:
|
|
12
|
-
# Define some signals
|
|
13
|
-
self.unique_id = ad_r(int, prefix + "UniqueId")
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from typing import Dict, TypedDict
|
|
2
|
-
|
|
3
|
-
from p4p.client.asyncio import Context
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class PVIEntry(TypedDict, total=False):
|
|
7
|
-
d: str
|
|
8
|
-
r: str
|
|
9
|
-
rw: str
|
|
10
|
-
w: str
|
|
11
|
-
x: str
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
async def pvi_get(pv: str, ctxt: Context, timeout: float = 5.0) -> Dict[str, PVIEntry]:
|
|
15
|
-
pv_info = ctxt.get(pv, timeout=timeout).get("pvi").todict()
|
|
16
|
-
|
|
17
|
-
result = {}
|
|
18
|
-
|
|
19
|
-
for attr_name, attr_info in pv_info.items():
|
|
20
|
-
result[attr_name] = PVIEntry(**attr_info) # type: ignore
|
|
21
|
-
|
|
22
|
-
return result
|