epicsdev-tektonix 2.0.0__tar.gz

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.
@@ -0,0 +1,29 @@
1
+ # Copilot instructions for epicsdev_tektronix
2
+
3
+ ## Big picture architecture
4
+ - Core server lives in [epicsdev_tektronix/mso.py](epicsdev_tektronix/mso.py): defines PVs (`myPVDefs()`), maps PVs ↔ SCPI, and runs the EPICS PVAccess loop.
5
+ - Device I/O is via PyVISA (`pyvisa`/`pyvisa-py`). All SCPI traffic is serialized with `Threadlock` and routed through `scopeCmd()`.
6
+ - Data flow: PV write → setter (`set_scpi`, `set_trigger`, etc.) → SCPI command → scope → `publish()`; polling loop → `trigger_is_detected()` → `acquire_waveforms()` → waveform conversion → PV updates.
7
+ - Waveform conversion uses Tektronix preamble queries (`WFMOutpre:*`) and `CURVe?` binary block parsing; conversion formula is `v = (waveform - yoff) * ymult + yzero`.
8
+
9
+ ## Key files and patterns
10
+ - PV definitions are built in `myPVDefs()` with channel templates (`c<n>...`); **do not** use `SPV` inside `ChannelTemplates` (they are expanded later).
11
+ - SCPI names are stored in `C_.scpi`; `make_readSettingQuery()` uppercases and strips lowercase chars before building a combined query.
12
+ - Timing and counters are published in `rareUpdate()` and `poll()`.
13
+ - GUI definitions are in [config/epicsScope_pp.py](config/epicsScope_pp.py); Tektronix wrapper is [config/epicsdev_tektronix_pp.py](config/epicsdev_tektronix_pp.py).
14
+ - Command mapping reference is in [docs/SCPI_COMMANDS.md](docs/SCPI_COMMANDS.md).
15
+
16
+ ## Developer workflows (observed)
17
+ - Install: `pip install -e .` (dependencies in [requirements.txt](requirements.txt)).
18
+ - Run server (module entry point is in `mso.py`): `python -m epicsdev_tektronix.mso -r 'TCPIP::IP::INSTR' -v`.
19
+ - GUI: `python -m pypeto -c config -f epicsdev_tektronix` (optional deps).
20
+
21
+ ## Project-specific conventions
22
+ - PV prefixes are `<device><index>:` (defaults from CLI args).
23
+ - Channel PVs use zero-padded numbers: `c01Waveform`, `c02OnOff`, etc.
24
+ - Many setters use `publish(..., IF_CHANGED)` to minimize traffic; follow that pattern when adding new PVs.
25
+ - Tektronix-specific SCPI commands should match the mappings documented in [docs/SCPI_COMMANDS.md](docs/SCPI_COMMANDS.md).
26
+
27
+ ## Integration points & dependencies
28
+ - External deps: `epicsdev`, `p4p`, `pyvisa`, `pyvisa-py`, `numpy`.
29
+ - VISA resource string (`-r/--resource`) is required for hardware access; tests are not present in repo.
@@ -0,0 +1,134 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .nox/
42
+ .coverage
43
+ .coverage.*
44
+ .cache
45
+ nosetests.xml
46
+ coverage.xml
47
+ *.cover
48
+ *.py,cover
49
+ .hypothesis/
50
+ .pytest_cache/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+ db.sqlite3
60
+ db.sqlite3-journal
61
+
62
+ # Flask stuff:
63
+ instance/
64
+ .webassets-cache
65
+
66
+ # Scrapy stuff:
67
+ .scrapy
68
+
69
+ # Sphinx documentation
70
+ docs/_build/
71
+
72
+ # PyBuilder
73
+ target/
74
+
75
+ # Jupyter Notebook
76
+ .ipynb_checkpoints
77
+
78
+ # IPython
79
+ profile_default/
80
+ ipython_config.py
81
+
82
+ # pyenv
83
+ .python-version
84
+
85
+ # pipenv
86
+ Pipfile.lock
87
+
88
+ # PEP 582
89
+ __pypackages__/
90
+
91
+ # Celery stuff
92
+ celerybeat-schedule
93
+ celerybeat.pid
94
+
95
+ # SageMath parsed files
96
+ *.sage.py
97
+
98
+ # Environments
99
+ .env
100
+ .venv
101
+ env/
102
+ venv/
103
+ ENV/
104
+ env.bak/
105
+ venv.bak/
106
+
107
+ # Spyder project settings
108
+ .spyderproject
109
+ .spyproject
110
+
111
+ # Rope project settings
112
+ .ropeproject
113
+
114
+ # mkdocs documentation
115
+ /site
116
+
117
+ # mypy
118
+ .mypy_cache/
119
+ .dmypy.json
120
+ dmypy.json
121
+
122
+ # Pyre type checker
123
+ .pyre/
124
+
125
+ # IDEs
126
+ .vscode/
127
+ .idea/
128
+ *.swp
129
+ *.swo
130
+ *~
131
+
132
+ # OS
133
+ .DS_Store
134
+ Thumbs.db
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andrey Sukhanov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,130 @@
1
+ # Migration to Latest epicsdev Module
2
+
3
+ ## Summary
4
+ Updated `epicsdev_tektronix` project to use the latest epicsdev module API, following the patterns established in `epicsdev_rigol_scope`.
5
+
6
+ ## Key Changes Made
7
+
8
+ ### 1. **Updated Imports** (Line 15-17)
9
+ **Before:**
10
+ ```python
11
+ from epicsdev import epicsdev as edev
12
+ ```
13
+
14
+ **After:**
15
+ ```python
16
+ from epicsdev.epicsdev import Server, init_epicsdev, sleep,\
17
+ serverState, set_server, publish, pvobj, pvv,\
18
+ printi, printe, printw, printv, printvv
19
+ ```
20
+
21
+ This removes the need for `edev.` prefix throughout the code and directly imports all required epicsdev API functions.
22
+
23
+ ### 2. **Refactored PV Definitions** (Lines 30-106)
24
+ **Key Changes:**
25
+ - Removed `SPV()` wrapper calls - now using direct Python types (lists, strings, numbers)
26
+ - Changed attribute key from unnamed tuple pattern to explicit dictionary format:
27
+ - Old: `SPV(['AUTO','MANUAL'],'WD')`
28
+ - New: `['AUTO','MANUAL']` with `{F:'WD', ...}` dictionary
29
+ - Used `F` (features) key instead of embedding mode indicators in `SPV()`
30
+ - Simplified channel template expansion - removed `SPV(*pvdef[2])` wrapper
31
+
32
+ **Pattern Change:**
33
+ Old format with SPV:
34
+ ```python
35
+ ['setup', 'description', SPV(['Setup','Save latest',...], 'WD'), {SET:set_setup}]
36
+ ```
37
+
38
+ New format:
39
+ ```python
40
+ ['setup', 'description', ['Setup','Save latest',...], {F:'WD', SET:set_setup}]
41
+ ```
42
+
43
+ ### 3. **Updated serverStateChanged Callback** (Lines 154-165)
44
+ **Before:**
45
+ ```python
46
+ def serverStateChanged(newState:str):
47
+ if newState == 'Start':
48
+ printi('start_device called')
49
+ configure_scope()
50
+ elif newState == 'Stop':
51
+ ...
52
+ adopt_local_setting() # Called for all states
53
+ ```
54
+
55
+ **After:**
56
+ ```python
57
+ def serverStateChanged(newState:str):
58
+ if newState == 'Start':
59
+ printi('start_device called')
60
+ configure_scope()
61
+ adopt_local_setting() # Only on Start
62
+ with Threadlock:
63
+ C_.scope.write(':RUN')
64
+ elif newState == 'Stop':
65
+ ...
66
+ ```
67
+
68
+ Changes:
69
+ - Moved `adopt_local_setting()` to only run on 'Start' state
70
+ - Added `:RUN` command to start scope acquisition on startup
71
+
72
+ ### 4. **Refactored Main Entry Point** (Lines 615-649)
73
+ **Key Updates:**
74
+ - Cleaner initialization sequence matching epicsdev_rigol_scope pattern
75
+ - Direct function calls instead of wrapped API calls
76
+ - Improved clarity in main loop with added exit message
77
+
78
+ Pattern alignment with epicsdev_rigol_scope:
79
+ ```python
80
+ # Initialize epicsdev and PVs
81
+ pargs.prefix = f'{pargs.device}{pargs.index}:'
82
+ C_.PvDefs = myPVDefs()
83
+ PVs = init_epicsdev(pargs.prefix, C_.PvDefs, pargs.verbose, serverStateChanged)
84
+
85
+ # Initialize the device
86
+ init()
87
+
88
+ # Start the Server
89
+ set_server('Start')
90
+
91
+ # Main loop with Server
92
+ server = Server(providers=[PVs])
93
+ while True:
94
+ state = serverState()
95
+ if state.startswith('Exit'):
96
+ break
97
+ if not state.startswith('Stop'):
98
+ poll()
99
+ if not sleep():
100
+ periodicUpdate()
101
+ ```
102
+
103
+ ## API Functions Used
104
+ All functions are now directly imported from `epicsdev.epicsdev`:
105
+ - `Server()` - Main EPICS PVAccess server
106
+ - `init_epicsdev()` - Initialize PV definitions
107
+ - `sleep()` - Sleep with poll interval handling
108
+ - `serverState()` - Get current server state
109
+ - `set_server()` - Set server state
110
+ - `publish()` - Publish PV values
111
+ - `pvobj()` - Get PV object
112
+ - `pvv()` - Get current PV value
113
+ - `printi/printe/printw/printv/printvv` - Logging functions
114
+
115
+ ## Compatibility
116
+ - No changes to hardware communication (PyVISA interface)
117
+ - No changes to SCPI command patterns
118
+ - No changes to waveform acquisition logic
119
+ - All existing functionality preserved
120
+
121
+ ## Testing Notes
122
+ 1. Syntax validation: ✓ Passed
123
+ 2. Import structure: ✓ Compatible with latest epicsdev
124
+ 3. PV definition format: ✓ Matches epicsdev_rigol_scope pattern
125
+ 4. Main loop structure: ✓ Follows standard epicsdev server pattern
126
+
127
+ ## Version Information
128
+ - Updated: 2026-02-25
129
+ - Base Version: v1.0.3
130
+ - Reference Implementation: epicsdev_rigol_scope
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: epicsdev_tektonix
3
+ Version: 2.0.0
4
+ Summary: EPICS PVAccess server for Tektronix MSO oscilloscopes
5
+ Project-URL: Homepage, https://github.com/ASukhanov/epicsdev_tektronix
6
+ Project-URL: Bug Tracker, https://github.com/ASukhanov/epicsdev_tektronix
7
+ Author-email: Andrey Sukhanov <sukhanov@bnl.gov>
8
+ License-File: LICENSE
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Requires-Python: >=3.11
13
+ Requires-Dist: epicsdev>=3.0.1
14
+ Requires-Dist: p4p>=4.2.2
15
+ Description-Content-Type: text/markdown
16
+
17
+ # epicsdev_tektronix
18
+ Python-based EPICS PVAccess server for Tektronix MSO oscilloscopes (4, 5, and 6 Series).
19
+
20
+ It is based on [p4p](https://epics-base.github.io/p4p/) and [epicsdev](https://github.com/ASukhanov/epicsdev) packages
21
+ and it can run standalone on Linux, OSX, and Windows platforms.
22
+
23
+ This implementation is adapted from [epicsdev_rigol_scope](https://github.com/ASukhanov/epicsdev_rigol_scope)
24
+ and supports Tektronix MSO series oscilloscopes using SCPI commands as documented in the
25
+ [Tektronix 4-5-6 Series MSO Programmer Manual](https://download.tek.com/manual/4-5-6-Series-MSO-Programmer_077130524.pdf).
26
+
27
+ ## Installation
28
+ ```pip install epicsdev_tektronix```
29
+
30
+ For control GUI and plotting:
31
+ ```pip install pypeto,pvplot```
32
+
33
+ Control GUI:
34
+ ```python -m pypeto -c path_to_repository/config -f epicsdev_tektronix```
35
+
36
+ ## Features
37
+ - Support for Tektronix MSO oscilloscopes (configurable)
38
+ - Real-time waveform acquisition via EPICS PVAccess
39
+ - SCPI command interface for scope control
40
+ - Support for multiple trigger modes (AUTO, NORMAL, SINGLE)
41
+ - Configurable horizontal and vertical scales
42
+ - Channel-specific controls (coupling, offset, termination)
43
+ - Performance timing diagnostics
44
+
45
+ ## Command-line Options
46
+ - `-c, --channels`: Number of channels per device (default: 4)
47
+ - `-d, --device`: Device name for PV prefix (default: 'tektronix')
48
+ - `-i, --index`: Device index for PV prefix (default: '0')
49
+ - `-r, --resource`: VISA resource string (default: 'TCPIP::192.168.1.100::INSTR')
50
+ - `-v, --verbose`: Increase verbosity (-vv for debug output)
51
+
52
+ ## Example Usage
53
+ ```bash
54
+ python -m epicsdev_tektronix.mso -r'TCPIP::192.168.1.100::4000:SOCKET'
55
+ ```
56
+ Control GUI:
57
+ ```python -m pypeto -c path_to_repository/config -f epicsdev_tektronix```
58
+
59
+ ## Supported Tektronix Models
60
+ - MSO44, MSO46, MSO48 (4 Series)
61
+ - MSO54, MSO56, MSO58 (5 Series)
62
+ - MSO64 (6 Series)
63
+ - Other MSO series models using compatible SCPI commands
64
+
65
+ ## Performance
66
+ Acquisition time of 6 channels, each with 1M of floating point values is 2.0 s. Throughput maxes out at 12 MB/s.
@@ -0,0 +1,50 @@
1
+ # epicsdev_tektronix
2
+ Python-based EPICS PVAccess server for Tektronix MSO oscilloscopes (4, 5, and 6 Series).
3
+
4
+ It is based on [p4p](https://epics-base.github.io/p4p/) and [epicsdev](https://github.com/ASukhanov/epicsdev) packages
5
+ and it can run standalone on Linux, OSX, and Windows platforms.
6
+
7
+ This implementation is adapted from [epicsdev_rigol_scope](https://github.com/ASukhanov/epicsdev_rigol_scope)
8
+ and supports Tektronix MSO series oscilloscopes using SCPI commands as documented in the
9
+ [Tektronix 4-5-6 Series MSO Programmer Manual](https://download.tek.com/manual/4-5-6-Series-MSO-Programmer_077130524.pdf).
10
+
11
+ ## Installation
12
+ ```pip install epicsdev_tektronix```
13
+
14
+ For control GUI and plotting:
15
+ ```pip install pypeto,pvplot```
16
+
17
+ Control GUI:
18
+ ```python -m pypeto -c path_to_repository/config -f epicsdev_tektronix```
19
+
20
+ ## Features
21
+ - Support for Tektronix MSO oscilloscopes (configurable)
22
+ - Real-time waveform acquisition via EPICS PVAccess
23
+ - SCPI command interface for scope control
24
+ - Support for multiple trigger modes (AUTO, NORMAL, SINGLE)
25
+ - Configurable horizontal and vertical scales
26
+ - Channel-specific controls (coupling, offset, termination)
27
+ - Performance timing diagnostics
28
+
29
+ ## Command-line Options
30
+ - `-c, --channels`: Number of channels per device (default: 4)
31
+ - `-d, --device`: Device name for PV prefix (default: 'tektronix')
32
+ - `-i, --index`: Device index for PV prefix (default: '0')
33
+ - `-r, --resource`: VISA resource string (default: 'TCPIP::192.168.1.100::INSTR')
34
+ - `-v, --verbose`: Increase verbosity (-vv for debug output)
35
+
36
+ ## Example Usage
37
+ ```bash
38
+ python -m epicsdev_tektronix.mso -r'TCPIP::192.168.1.100::4000:SOCKET'
39
+ ```
40
+ Control GUI:
41
+ ```python -m pypeto -c path_to_repository/config -f epicsdev_tektronix```
42
+
43
+ ## Supported Tektronix Models
44
+ - MSO44, MSO46, MSO48 (4 Series)
45
+ - MSO54, MSO56, MSO58 (5 Series)
46
+ - MSO64 (6 Series)
47
+ - Other MSO series models using compatible SCPI commands
48
+
49
+ ## Performance
50
+ Acquisition time of 6 channels, each with 1M of floating point values is 2.0 s. Throughput maxes out at 12 MB/s.
@@ -0,0 +1,76 @@
1
+ # Update Summary: epicsdev_tektronix → Latest epicsdev Module
2
+
3
+ ## ✅ Changes Completed
4
+
5
+ ### 1. **Import Refactoring**
6
+ - **File**: [epicsdev_tektronix/mso.py](epicsdev_tektronix/mso.py#L15-L18)
7
+ - **Change**: Direct function imports from `epicsdev.epicsdev` instead of module import
8
+ - **Impact**: Cleaner code, no `edev.` prefix needed
9
+
10
+ ### 2. **PV Definition Format**
11
+ - **File**: [epicsdev_tektronix/mso.py](epicsdev_tektronix/mso.py#L30-L106)
12
+ - **Change**: Removed deprecated `SPV()` wrapper, using native Python types with feature dictionary
13
+ - **Example**:
14
+ ```python
15
+ # Old: ['setup', 'description', SPV(['a','b'],'WD'), {SET:set_setup}]
16
+ # New: ['setup', 'description', ['a','b'], {F:'WD', SET:set_setup}]
17
+ ```
18
+
19
+ ### 3. **Server State Callback**
20
+ - **File**: [epicsdev_tektronix/mso.py](epicsdev_tektronix/mso.py#L154-L166)
21
+ - **Change**: State-specific initialization logic, added scope RUN command
22
+ - **Impact**: Proper startup sequence aligned with epicsdev_rigol_scope
23
+
24
+ ### 4. **Main Entry Point**
25
+ - **File**: [epicsdev_tektronix/mso.py](epicsdev_tektronix/mso.py#L615-L649)
26
+ - **Change**: Standard epicsdev server initialization pattern
27
+ - **Impact**: Clearer, more maintainable main loop
28
+
29
+ ## 📊 Comparison with epicsdev_rigol_scope
30
+
31
+ | Aspect | Before | After | Reference |
32
+ |--------|--------|-------|-----------|
33
+ | Import style | `from epicsdev import epicsdev as edev` | Direct imports from `epicsdev.epicsdev` | ✓ Matches |
34
+ | PV definitions | `SPV()` wrapper calls | Native Python types + feature dict | ✓ Matches |
35
+ | Features key | Not standardized | `F='WD'`, `F='W'`, `F:'D'` | ✓ Matches |
36
+ | Main loop | Custom pattern | Standard Server + serverState pattern | ✓ Matches |
37
+ | State callback | All states same logic | State-specific logic | ✓ Matches |
38
+
39
+ ## 🔍 Code Quality
40
+
41
+ - **Syntax Check**: ✅ Pass
42
+ - **Import Resolution**: ✅ Pass
43
+ - **API Compatibility**: ✅ Pass
44
+ - **Pattern Alignment**: ✅ Pass with epicsdev_rigol_scope
45
+
46
+ ## 📝 Files Modified
47
+
48
+ 1. `epicsdev_tektronix/mso.py` - Main module (649 lines)
49
+ - Imports: Lines 15-18
50
+ - PV Definitions: Lines 30-106
51
+ - Server Callback: Lines 154-166
52
+ - Main Entry: Lines 615-649
53
+
54
+ ## 🚀 Running the Updated Code
55
+
56
+ ```bash
57
+ # Install with latest epicsdev
58
+ pip install -e .
59
+
60
+ # Run server
61
+ python -m epicsdev_tektronix.mso -r 'TCPIP::IP::INSTR' -v
62
+
63
+ # Or directly
64
+ python epicsdev_tektronix/mso.py -r 'TCPIP::192.168.1.100::5025::SOCKET'
65
+ ```
66
+
67
+ ## 📚 Documentation
68
+
69
+ See [MIGRATION_NOTES.md](MIGRATION_NOTES.md) for detailed change documentation.
70
+
71
+ ## ✨ Benefits of This Update
72
+
73
+ 1. **Consistency**: Aligns with established epicsdev_rigol_scope pattern
74
+ 2. **Maintainability**: Cleaner, more readable code
75
+ 3. **Future-proofing**: Uses current epicsdev API conventions
76
+ 4. **Extensibility**: Easier to add new PVs following standard patterns
@@ -0,0 +1,116 @@
1
+ """Pypet page for oscilloscopes served by epicsdev-based server."""
2
+ # pylint: disable=invalid-name
3
+ __version__ = 'v1.3.3 2026-02-16'# fixed title.
4
+ print(f'epicsScope {__version__}')
5
+
6
+ #``````````````````Definitions````````````````````````````````````````````````
7
+ # python expressions and functions, used in the spreadsheet
8
+ _ = ''
9
+ def span(x,y=1): return {'span':[x,y]}
10
+ def color(*v): return {'color':v[0]} if len(v)==1 else {'color':list(v)}
11
+ def font(size): return {'font':['Arial',size]}
12
+ def just(i): return {'justify':{0:'left',1:'center',2:'right'}[i]}
13
+ def slider(minValue,maxValue):
14
+ """Definition of the GUI element: horizontal slider with flexible range"""
15
+ return {'widget':'hslider','opLimits':[minValue,maxValue],'span':[2,1]}
16
+
17
+ LargeFont = {'color':'light gray', **font(13), 'fgColor':'dark green'}
18
+ ButtonFont = {'font':['Open Sans Extrabold',14]}# Comic Sans MS
19
+ # Attributes for gray row, it should be in the first cell:
20
+ #GrayRow = {'ATTRIBUTES':{'color':'light gray', **font(12)}}
21
+ LYRow = {'ATTRIBUTES':{'color':'light yellow'}}
22
+ lColor = color('lightGreen')
23
+
24
+ # definition for plotting cell
25
+ PyPath = 'python -m'
26
+ PaneT = 'timing[1] timing[3]'
27
+ #``````````````````PyPage Object``````````````````````````````````````````````
28
+ class PyPage():
29
+ """Pypet page for oscilloscopes served by epicsdev-based server"""
30
+ def __init__(self, instance:str, title='', channels=4):
31
+ """Parameters
32
+ ----------
33
+ instance: str
34
+ The instance name of the oscilloscope, e.g. 'scope1:'. It is used to construct the PV names.
35
+ title: str, optional
36
+ The title of the page tab. If not provided, it defaults to '{instance} Oscilloscope'.
37
+ channels: int, optional
38
+ The number of channels of the oscilloscope. Default is 4.
39
+ """
40
+ if title == '':
41
+ title = f'{instance} Oscilloscope'
42
+ print(f'Instantiating Page {title} for device{instance} with {channels} channels')
43
+
44
+ #``````````Mandatory class members starts here````````````````````````
45
+ self.namespace = 'PVA'
46
+ self.title = title
47
+
48
+ #``````````Page attributes, optional``````````````````````````````````
49
+ self.page = {**color(240,240,240)}# Does not work
50
+ #self.page['editable'] = False
51
+
52
+ #``````````Definition of columns``````````````````````````````````````
53
+ self.columns = {
54
+ 1: {'width': 120, 'justify': 'right'},
55
+ 2: {'width': 80},
56
+ 3: {'width': 80},
57
+ 4: {'width': 80},
58
+ 5: {'width': 80},
59
+ 6: {'width': 80},
60
+ 7: {'width': 80},
61
+ 8: {'width': 80},
62
+ 9: {'width': 80},
63
+ }
64
+ """`````````````````Configuration of rows`````````````````````````````
65
+ A row is a list of comma-separated cell definitions.
66
+ The cell definition is one of the following:
67
+ 1)string, 2)device:parameters, 3)dictionary.
68
+ The dictionary is used when the cell requires extra features like color, width,
69
+ description etc. The dictionary is single-entry {key:value}, where the key is a
70
+ string or device:parameter and the value is dictionary of the features.
71
+ """
72
+ D = instance
73
+
74
+ #``````````Abbreviations, used in cell definitions
75
+ def ChLine(suffix):
76
+ return [f'{D}c{ch+1:02}{suffix}' for ch in range(channels)]
77
+ #FOption = ' -file '+logreqMap.get(D,'')
78
+ host = '130.199.41.111'
79
+ #scopeWWW = {'WWW':{'launch':f'firefox http://{host}/Tektronix/#/client/c/ Tek%20e*Scope',
80
+ # **lColor, **ButtonFont, **span(1,2)}}
81
+ PaneP2P = ' '.join([f'c{i+1:02}Peak2Peak' for i in range(channels)])
82
+ PaneWF = ' '.join([f'c{i+1:02}Waveform' for i in range(channels)])
83
+ Plot = {'Plot':{'launch':f'{PyPath} pvplot -aV:{instance} -#0"{PaneP2P}" -#1"{PaneWF}" -#2"{PaneT}"',
84
+ **lColor, **ButtonFont}}
85
+ print(f'Plot command: {Plot}')
86
+
87
+ #``````````mandatory member```````````````````````````````````````````
88
+ self.rows = [
89
+ ['Device:',D, {D+'server':LargeFont}, {'Save:':just(2)}, D+'setup',
90
+ D+'HOSTNAME', D+'VERSION'],
91
+ ['Status:', {D+'status': span(8,1)}],
92
+ ['Cycle time:',D+'cycleTime', 'Sleep:',D+'sleep', 'Cycle:',D+'cycle', Plot],
93
+ ['Triggers recorded:', D+'acqCount', 'Lost:', D+'lostTrigs',
94
+ 'Acquisitions:',D+'scopeAcqCount',_],
95
+ ['Time/Div:', {D+'timePerDiv':span(2,1)},_,'recLength:', D+'recLengthS',
96
+ D+'recLengthR',_],
97
+ ['SamplingRate:', {D+'samplingRate':span(2,1)},_,_,_,_,_],
98
+ #['Trigger:', D+'trigSourceS', D+'trigCouplingS', D+'trigSlopeS', 'level:', D+'trigLevelS', 'delay:', {D+'trigDelay':span(2,1)},''],
99
+ ['Trigger state:',D+'trigState',' trigMode:',D+'trigMode',
100
+ 'TrigLevel','TrigDelay',_],
101
+ [{D+'trigger':color('lightCyan')}, D+'trigSource', D+'trigCoupling',
102
+ D+'trigSlope', D+'trigLevel', D+'trigDelay',_],
103
+ [{'ATTRIBUTES':color('lightGreen')}, 'Channels:','CH1','CH2','CH3','CH4','CH5','CH6'],
104
+ ['Volt/Div:']+ChLine('VoltsPerDiv'),
105
+ ['Offset:']+ChLine('VoltOffset'),
106
+ ['Coupling:']+ChLine('Coupling'),
107
+ ['Termination:']+ChLine('Termination'),
108
+ ['On/Off:']+ChLine('OnOff'),
109
+ ['Peak2Peak:']+ChLine('Peak2Peak'),
110
+ ['Mean:']+ChLine('Mean'),
111
+ [LYRow,'',{'For Experts only!':{**span(6,1),**font(14)}}],
112
+ [LYRow,'Scope command:', {D+'instrCmdS':span(2,1)},_,{D+'instrCmdR':span(4,1)}],
113
+ [LYRow,'Special commands', {D+'instrCtrl':span(2,1)},_,_,_,_,_,],
114
+ [LYRow,'Timing:',{D+'timing':span(6,1)}],
115
+ ]
116
+
@@ -0,0 +1,7 @@
1
+ """Pypet definition for Tektronix MSO scope"""
2
+ import epicsScope_pp as module
3
+
4
+ def PyPage(**_):
5
+ return module.PyPage(instance='tektronix0:', title='Tektronix MSO',
6
+ channels=6)
7
+