We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
How to include Channels in API documentation
In #819 I encountered the question, how to include the Channel best into the documentation.
It does not seem right, to put the channel in the same level as the instruments of that manufacturer.
Any ideas?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pymeasure/instruments/siglenttechnologies/siglent_spdbase.py`
Content:
```
1 #
2 # This file is part of the PyMeasure package.
3 #
4 # Copyright (c) 2013-2023 PyMeasure Developers
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23 #
24 import logging
25 from pymeasure.instruments.instrument import Instrument
26 from pymeasure.instruments.channel import Channel
27 from pymeasure.instruments.validators import (strict_discrete_range,
28                                               strict_discrete_set,
29                                               truncated_range
30                                               )
31 from enum import IntFlag
32 
33 log = logging.getLogger(__name__)  # https://docs.python.org/3/howto/logging.html#library-config
34 log.addHandler(logging.NullHandler())
35 
36 
37 class SystemStatusCode(IntFlag):
38     """System status enums based on ``IntFlag``
39 
40     Used in conjunction with :attr:`~.system_status_code`.
41 
42         ======  ======
43         Value   Enum
44         ======  ======
45         256     WAVEFORM_DISPLAY
46         64      TIMER_ENABLED
47         32      FOUR_WIRE
48         16      OUTPUT_ENABLED
49         1       CONSTANT_CURRENT
50         0       CONSTANT_VOLTAGE
51         ======  ======
52 
53     """
54 
55     WAVEFORM_DISPLAY = 256  # bit 8 -- waveform display enabled
56     TIMER_ENABLED = 64  # bit 6 -- timer enabled
57     FOUR_WIRE = 32  # bit 5 -- four-wire mode enabled
58     OUTPUT_ENABLED = 16  # bit 4 -- output enabled
59     CONSTANT_CURRENT = 1   # bit 0 -- constant current mode
60     CONSTANT_VOLTAGE = 0   # bit 0 -- constant voltage mode
61 
62 
63 class SPDChannel(Channel):
64     """ The channel class for Siglent SPDxxxxX instruments.
65     """
66 
67     def __init__(self, parent, id,
68                  voltage_range: list = [0, 16],
69                  current_range: list = [0, 8]):
70         super().__init__(parent, id)
71         self.voltage_range = voltage_range
72         self.current_range = current_range
73 
74     voltage = Instrument.measurement(
75         "MEAS:VOLT? CH{ch}",
76         """Measure the channel output voltage.
77 
78         :type: float
79         """
80     )
81 
82     current = Instrument.measurement(
83         "MEAS:CURR? CH{ch}",
84         """Measure the channel output current.
85 
86         :type: float
87         """
88     )
89 
90     power = Instrument.measurement(
91         "MEAS:POWE? CH{ch}",
92         """Measure the channel output power.
93 
94         :type: float
95         """
96     )
97 
98     current_limit = Instrument.control(
99         "CH{ch}:CURR?", "CH{ch}:CURR %g",
100         """Control the output current configuration of the channel.
101 
102         :type : float
103         """,
104         validator=truncated_range,
105         values=[0, 8],
106         dynamic=True
107     )
108 
109     voltage_setpoint = Instrument.control(
110         "CH{ch}:VOLT?", "CH{ch}:VOLT %g",
111         """Control the output voltage configuration of the channel.
112 
113         :type : float
114         """,
115         validator=truncated_range,
116         values=[0, 16],
117         dynamic=True
118     )
119 
120     def enable_output(self, enable: bool = True):
121         """Enable the channel output.
122 
123         :type: bool
124             ``True``: enables the output
125             ``False``: disables it
126         """
127         self.parent.selected_channel = self.id
128         self.write('OUTP CH{ch},' + ("ON" if enable else "OFF"))
129 
130     def enable_timer(self, enable: bool = True):
131         """Enable the channel timer.
132 
133         :type: bool
134             ``True``: enables the timer
135             ``False``: disables it
136         """
137         self.write('TIME CH{ch},' + ("ON" if enable else "OFF"))
138 
139     def configure_timer(self, step, voltage, current, duration):
140         """Configure the timer step.
141 
142         :param step:
143             int: index of the step to save the configuration
144         :param voltage:
145             float: voltage setpoint of the step
146         :param current:
147             float: current limit of the step
148         :param duration:
149             int: duration of the step in seconds
150         """
151         step = strict_discrete_range(step, [1, 5], 1)
152         voltage = truncated_range(voltage, self.voltage_range)
153         current = truncated_range(current, self.current_range)
154         duration = truncated_range(duration, [0, 10000])
155         self.write(f'TIME:SET CH{{ch}},{step:d},{voltage:1.3f},{current:1.3f},{duration:d}')
156 
157 
158 class SPDBase(Instrument):
159     """ The base class for Siglent SPDxxxxX instruments.
160     """
161 
162     def __init__(self, adapter, **kwargs):
163         kwargs.setdefault('name', 'Siglent SPDxxxxX instrument Base Class')
164         super().__init__(
165             adapter,
166             usb=dict(write_termination='\n',
167                      read_termination='\n'),
168             tcpip=dict(write_termination='\n',
169                        read_termination='\n'),
170             **kwargs
171         )
172 
173     error = Instrument.measurement(
174         "SYST:ERR?",
175         """Read the error code and information of the instrument.
176 
177         :type: string
178         """
179     )
180 
181     fw_version = Instrument.measurement(
182         "SYST:VERS?",
183         """Read the software version of the instrument.
184 
185         :type: string
186         """
187     )
188 
189     system_status_code = Instrument.measurement(
190         "SYST:STAT?",
191         """Read the system status register.
192 
193         :type: :class:`.SystemStatusCode`
194         """,
195         get_process=lambda v: SystemStatusCode(int(v, base=16)),
196     )
197 
198     selected_channel = Instrument.control(
199         "INST?", "INST %s",
200         """Control the selected channel of the instrument.
201 
202         :type : int
203         """,
204         validator=strict_discrete_set,
205         values={1: "CH1"},  # This dynamic property should be updated for multi-channel instruments
206         map_values=True,
207         dynamic=True
208     )
209 
210     def save_config(self, index):
211         """Save the current config to memory.
212 
213         :param index:
214             int: index of the location to save the configuration
215         """
216         index = strict_discrete_range(index, [1, 5], 1)
217         self.write(f"*SAV {index:d}")
218 
219     def recall_config(self, index):
220         """Recall a config from memory.
221 
222         :param index:
223             int: index of the location from which to recall the configuration
224         """
225         index = strict_discrete_range(index, [1, 5], 1)
226         self.write(f"*RCL {index:d}")
227 
228     def enable_local_interface(self, enable: bool = True):
229         """Configure the availability of the local interface.
230 
231         :type: bool
232             ``True``: enables the local interface
233             ``False``: disables it.
234         """
235         self.write("*UNLOCK" if enable else "*LOCK")
236 
237     def shutdown(self):
238         """ Ensure that the voltage is turned to zero
239         and disable the output. """
240         for ch in self.channels.values():
241             ch.voltage_setpoint = 0
242             ch.enable_output(False)
243         super().shutdown()
244 
245 
246 class SPDSingleChannelBase(SPDBase):
247     def enable_4W_mode(self, enable: bool = True):
248         """Enable 4-wire mode.
249 
250         :type: bool
251             ``True``: enables 4-wire mode
252             ``False``: disables it.
253         """
254         self.write(f'MODE:SET {"4W" if enable else "2W"}')
255
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pymeasure/instruments/siglenttechnologies/siglent_spdbase.py b/pymeasure/instruments/siglenttechnologies/siglent_spdbase.py
--- a/pymeasure/instruments/siglenttechnologies/siglent_spdbase.py
+++ b/pymeasure/instruments/siglenttechnologies/siglent_spdbase.py
@@ -157,6 +157,8 @@
 
 class SPDBase(Instrument):
     """ The base class for Siglent SPDxxxxX instruments.
+
+    Uses :class:`SPDChannel` for measurement channels.
     """
 
     def __init__(self, adapter, **kwargs):

{"golden_diff": "diff --git a/pymeasure/instruments/siglenttechnologies/siglent_spdbase.py b/pymeasure/instruments/siglenttechnologies/siglent_spdbase.py\n--- a/pymeasure/instruments/siglenttechnologies/siglent_spdbase.py\n+++ b/pymeasure/instruments/siglenttechnologies/siglent_spdbase.py\n@@ -157,6 +157,8 @@\n \n class SPDBase(Instrument):\n     \"\"\" The base class for Siglent SPDxxxxX instruments.\n+\n+    Uses :class:`SPDChannel` for measurement channels.\n     \"\"\"\n \n     def __init__(self, adapter, **kwargs):\n", "issue": "How to include Channels in API documentation\nIn #819 I encountered the question, how to include the Channel best into the documentation.\r\nIt does not seem right, to put the channel in the same level as the instruments of that manufacturer.\r\nAny ideas?\n", "before_files": [{"content": "#\n# This file is part of the PyMeasure package.\n#\n# Copyright (c) 2013-2023 PyMeasure Developers\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\nimport logging\nfrom pymeasure.instruments.instrument import Instrument\nfrom pymeasure.instruments.channel import Channel\nfrom pymeasure.instruments.validators import (strict_discrete_range,\n                                              strict_discrete_set,\n                                              truncated_range\n                                              )\nfrom enum import IntFlag\n\nlog = logging.getLogger(__name__)  # https://docs.python.org/3/howto/logging.html#library-config\nlog.addHandler(logging.NullHandler())\n\n\nclass SystemStatusCode(IntFlag):\n    \"\"\"System status enums based on ``IntFlag``\n\n    Used in conjunction with :attr:`~.system_status_code`.\n\n        ======  ======\n        Value   Enum\n        ======  ======\n        256     WAVEFORM_DISPLAY\n        64      TIMER_ENABLED\n        32      FOUR_WIRE\n        16      OUTPUT_ENABLED\n        1       CONSTANT_CURRENT\n        0       CONSTANT_VOLTAGE\n        ======  ======\n\n    \"\"\"\n\n    WAVEFORM_DISPLAY = 256  # bit 8 -- waveform display enabled\n    TIMER_ENABLED = 64  # bit 6 -- timer enabled\n    FOUR_WIRE = 32  # bit 5 -- four-wire mode enabled\n    OUTPUT_ENABLED = 16  # bit 4 -- output enabled\n    CONSTANT_CURRENT = 1   # bit 0 -- constant current mode\n    CONSTANT_VOLTAGE = 0   # bit 0 -- constant voltage mode\n\n\nclass SPDChannel(Channel):\n    \"\"\" The channel class for Siglent SPDxxxxX instruments.\n    \"\"\"\n\n    def __init__(self, parent, id,\n                 voltage_range: list = [0, 16],\n                 current_range: list = [0, 8]):\n        super().__init__(parent, id)\n        self.voltage_range = voltage_range\n        self.current_range = current_range\n\n    voltage = Instrument.measurement(\n        \"MEAS:VOLT? CH{ch}\",\n        \"\"\"Measure the channel output voltage.\n\n        :type: float\n        \"\"\"\n    )\n\n    current = Instrument.measurement(\n        \"MEAS:CURR? CH{ch}\",\n        \"\"\"Measure the channel output current.\n\n        :type: float\n        \"\"\"\n    )\n\n    power = Instrument.measurement(\n        \"MEAS:POWE? CH{ch}\",\n        \"\"\"Measure the channel output power.\n\n        :type: float\n        \"\"\"\n    )\n\n    current_limit = Instrument.control(\n        \"CH{ch}:CURR?\", \"CH{ch}:CURR %g\",\n        \"\"\"Control the output current configuration of the channel.\n\n        :type : float\n        \"\"\",\n        validator=truncated_range,\n        values=[0, 8],\n        dynamic=True\n    )\n\n    voltage_setpoint = Instrument.control(\n        \"CH{ch}:VOLT?\", \"CH{ch}:VOLT %g\",\n        \"\"\"Control the output voltage configuration of the channel.\n\n        :type : float\n        \"\"\",\n        validator=truncated_range,\n        values=[0, 16],\n        dynamic=True\n    )\n\n    def enable_output(self, enable: bool = True):\n        \"\"\"Enable the channel output.\n\n        :type: bool\n            ``True``: enables the output\n            ``False``: disables it\n        \"\"\"\n        self.parent.selected_channel = self.id\n        self.write('OUTP CH{ch},' + (\"ON\" if enable else \"OFF\"))\n\n    def enable_timer(self, enable: bool = True):\n        \"\"\"Enable the channel timer.\n\n        :type: bool\n            ``True``: enables the timer\n            ``False``: disables it\n        \"\"\"\n        self.write('TIME CH{ch},' + (\"ON\" if enable else \"OFF\"))\n\n    def configure_timer(self, step, voltage, current, duration):\n        \"\"\"Configure the timer step.\n\n        :param step:\n            int: index of the step to save the configuration\n        :param voltage:\n            float: voltage setpoint of the step\n        :param current:\n            float: current limit of the step\n        :param duration:\n            int: duration of the step in seconds\n        \"\"\"\n        step = strict_discrete_range(step, [1, 5], 1)\n        voltage = truncated_range(voltage, self.voltage_range)\n        current = truncated_range(current, self.current_range)\n        duration = truncated_range(duration, [0, 10000])\n        self.write(f'TIME:SET CH{{ch}},{step:d},{voltage:1.3f},{current:1.3f},{duration:d}')\n\n\nclass SPDBase(Instrument):\n    \"\"\" The base class for Siglent SPDxxxxX instruments.\n    \"\"\"\n\n    def __init__(self, adapter, **kwargs):\n        kwargs.setdefault('name', 'Siglent SPDxxxxX instrument Base Class')\n        super().__init__(\n            adapter,\n            usb=dict(write_termination='\\n',\n                     read_termination='\\n'),\n            tcpip=dict(write_termination='\\n',\n                       read_termination='\\n'),\n            **kwargs\n        )\n\n    error = Instrument.measurement(\n        \"SYST:ERR?\",\n        \"\"\"Read the error code and information of the instrument.\n\n        :type: string\n        \"\"\"\n    )\n\n    fw_version = Instrument.measurement(\n        \"SYST:VERS?\",\n        \"\"\"Read the software version of the instrument.\n\n        :type: string\n        \"\"\"\n    )\n\n    system_status_code = Instrument.measurement(\n        \"SYST:STAT?\",\n        \"\"\"Read the system status register.\n\n        :type: :class:`.SystemStatusCode`\n        \"\"\",\n        get_process=lambda v: SystemStatusCode(int(v, base=16)),\n    )\n\n    selected_channel = Instrument.control(\n        \"INST?\", \"INST %s\",\n        \"\"\"Control the selected channel of the instrument.\n\n        :type : int\n        \"\"\",\n        validator=strict_discrete_set,\n        values={1: \"CH1\"},  # This dynamic property should be updated for multi-channel instruments\n        map_values=True,\n        dynamic=True\n    )\n\n    def save_config(self, index):\n        \"\"\"Save the current config to memory.\n\n        :param index:\n            int: index of the location to save the configuration\n        \"\"\"\n        index = strict_discrete_range(index, [1, 5], 1)\n        self.write(f\"*SAV {index:d}\")\n\n    def recall_config(self, index):\n        \"\"\"Recall a config from memory.\n\n        :param index:\n            int: index of the location from which to recall the configuration\n        \"\"\"\n        index = strict_discrete_range(index, [1, 5], 1)\n        self.write(f\"*RCL {index:d}\")\n\n    def enable_local_interface(self, enable: bool = True):\n        \"\"\"Configure the availability of the local interface.\n\n        :type: bool\n            ``True``: enables the local interface\n            ``False``: disables it.\n        \"\"\"\n        self.write(\"*UNLOCK\" if enable else \"*LOCK\")\n\n    def shutdown(self):\n        \"\"\" Ensure that the voltage is turned to zero\n        and disable the output. \"\"\"\n        for ch in self.channels.values():\n            ch.voltage_setpoint = 0\n            ch.enable_output(False)\n        super().shutdown()\n\n\nclass SPDSingleChannelBase(SPDBase):\n    def enable_4W_mode(self, enable: bool = True):\n        \"\"\"Enable 4-wire mode.\n\n        :type: bool\n            ``True``: enables 4-wire mode\n            ``False``: disables it.\n        \"\"\"\n        self.write(f'MODE:SET {\"4W\" if enable else \"2W\"}')\n", "path": "pymeasure/instruments/siglenttechnologies/siglent_spdbase.py"}], "after_files": [{"content": "#\n# This file is part of the PyMeasure package.\n#\n# Copyright (c) 2013-2023 PyMeasure Developers\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\nimport logging\nfrom pymeasure.instruments.instrument import Instrument\nfrom pymeasure.instruments.channel import Channel\nfrom pymeasure.instruments.validators import (strict_discrete_range,\n                                              strict_discrete_set,\n                                              truncated_range\n                                              )\nfrom enum import IntFlag\n\nlog = logging.getLogger(__name__)  # https://docs.python.org/3/howto/logging.html#library-config\nlog.addHandler(logging.NullHandler())\n\n\nclass SystemStatusCode(IntFlag):\n    \"\"\"System status enums based on ``IntFlag``\n\n    Used in conjunction with :attr:`~.system_status_code`.\n\n        ======  ======\n        Value   Enum\n        ======  ======\n        256     WAVEFORM_DISPLAY\n        64      TIMER_ENABLED\n        32      FOUR_WIRE\n        16      OUTPUT_ENABLED\n        1       CONSTANT_CURRENT\n        0       CONSTANT_VOLTAGE\n        ======  ======\n\n    \"\"\"\n\n    WAVEFORM_DISPLAY = 256  # bit 8 -- waveform display enabled\n    TIMER_ENABLED = 64  # bit 6 -- timer enabled\n    FOUR_WIRE = 32  # bit 5 -- four-wire mode enabled\n    OUTPUT_ENABLED = 16  # bit 4 -- output enabled\n    CONSTANT_CURRENT = 1   # bit 0 -- constant current mode\n    CONSTANT_VOLTAGE = 0   # bit 0 -- constant voltage mode\n\n\nclass SPDChannel(Channel):\n    \"\"\" The channel class for Siglent SPDxxxxX instruments.\n    \"\"\"\n\n    def __init__(self, parent, id,\n                 voltage_range: list = [0, 16],\n                 current_range: list = [0, 8]):\n        super().__init__(parent, id)\n        self.voltage_range = voltage_range\n        self.current_range = current_range\n\n    voltage = Instrument.measurement(\n        \"MEAS:VOLT? CH{ch}\",\n        \"\"\"Measure the channel output voltage.\n\n        :type: float\n        \"\"\"\n    )\n\n    current = Instrument.measurement(\n        \"MEAS:CURR? CH{ch}\",\n        \"\"\"Measure the channel output current.\n\n        :type: float\n        \"\"\"\n    )\n\n    power = Instrument.measurement(\n        \"MEAS:POWE? CH{ch}\",\n        \"\"\"Measure the channel output power.\n\n        :type: float\n        \"\"\"\n    )\n\n    current_limit = Instrument.control(\n        \"CH{ch}:CURR?\", \"CH{ch}:CURR %g\",\n        \"\"\"Control the output current configuration of the channel.\n\n        :type : float\n        \"\"\",\n        validator=truncated_range,\n        values=[0, 8],\n        dynamic=True\n    )\n\n    voltage_setpoint = Instrument.control(\n        \"CH{ch}:VOLT?\", \"CH{ch}:VOLT %g\",\n        \"\"\"Control the output voltage configuration of the channel.\n\n        :type : float\n        \"\"\",\n        validator=truncated_range,\n        values=[0, 16],\n        dynamic=True\n    )\n\n    def enable_output(self, enable: bool = True):\n        \"\"\"Enable the channel output.\n\n        :type: bool\n            ``True``: enables the output\n            ``False``: disables it\n        \"\"\"\n        self.parent.selected_channel = self.id\n        self.write('OUTP CH{ch},' + (\"ON\" if enable else \"OFF\"))\n\n    def enable_timer(self, enable: bool = True):\n        \"\"\"Enable the channel timer.\n\n        :type: bool\n            ``True``: enables the timer\n            ``False``: disables it\n        \"\"\"\n        self.write('TIME CH{ch},' + (\"ON\" if enable else \"OFF\"))\n\n    def configure_timer(self, step, voltage, current, duration):\n        \"\"\"Configure the timer step.\n\n        :param step:\n            int: index of the step to save the configuration\n        :param voltage:\n            float: voltage setpoint of the step\n        :param current:\n            float: current limit of the step\n        :param duration:\n            int: duration of the step in seconds\n        \"\"\"\n        step = strict_discrete_range(step, [1, 5], 1)\n        voltage = truncated_range(voltage, self.voltage_range)\n        current = truncated_range(current, self.current_range)\n        duration = truncated_range(duration, [0, 10000])\n        self.write(f'TIME:SET CH{{ch}},{step:d},{voltage:1.3f},{current:1.3f},{duration:d}')\n\n\nclass SPDBase(Instrument):\n    \"\"\" The base class for Siglent SPDxxxxX instruments.\n\n    Uses :class:`SPDChannel` for measurement channels.\n    \"\"\"\n\n    def __init__(self, adapter, **kwargs):\n        kwargs.setdefault('name', 'Siglent SPDxxxxX instrument Base Class')\n        super().__init__(\n            adapter,\n            usb=dict(write_termination='\\n',\n                     read_termination='\\n'),\n            tcpip=dict(write_termination='\\n',\n                       read_termination='\\n'),\n            **kwargs\n        )\n\n    error = Instrument.measurement(\n        \"SYST:ERR?\",\n        \"\"\"Read the error code and information of the instrument.\n\n        :type: string\n        \"\"\"\n    )\n\n    fw_version = Instrument.measurement(\n        \"SYST:VERS?\",\n        \"\"\"Read the software version of the instrument.\n\n        :type: string\n        \"\"\"\n    )\n\n    system_status_code = Instrument.measurement(\n        \"SYST:STAT?\",\n        \"\"\"Read the system status register.\n\n        :type: :class:`.SystemStatusCode`\n        \"\"\",\n        get_process=lambda v: SystemStatusCode(int(v, base=16)),\n    )\n\n    selected_channel = Instrument.control(\n        \"INST?\", \"INST %s\",\n        \"\"\"Control the selected channel of the instrument.\n\n        :type : int\n        \"\"\",\n        validator=strict_discrete_set,\n        values={1: \"CH1\"},  # This dynamic property should be updated for multi-channel instruments\n        map_values=True,\n        dynamic=True\n    )\n\n    def save_config(self, index):\n        \"\"\"Save the current config to memory.\n\n        :param index:\n            int: index of the location to save the configuration\n        \"\"\"\n        index = strict_discrete_range(index, [1, 5], 1)\n        self.write(f\"*SAV {index:d}\")\n\n    def recall_config(self, index):\n        \"\"\"Recall a config from memory.\n\n        :param index:\n            int: index of the location from which to recall the configuration\n        \"\"\"\n        index = strict_discrete_range(index, [1, 5], 1)\n        self.write(f\"*RCL {index:d}\")\n\n    def enable_local_interface(self, enable: bool = True):\n        \"\"\"Configure the availability of the local interface.\n\n        :type: bool\n            ``True``: enables the local interface\n            ``False``: disables it.\n        \"\"\"\n        self.write(\"*UNLOCK\" if enable else \"*LOCK\")\n\n    def shutdown(self):\n        \"\"\" Ensure that the voltage is turned to zero\n        and disable the output. \"\"\"\n        for ch in self.channels.values():\n            ch.voltage_setpoint = 0\n            ch.enable_output(False)\n        super().shutdown()\n\n\nclass SPDSingleChannelBase(SPDBase):\n    def enable_4W_mode(self, enable: bool = True):\n        \"\"\"Enable 4-wire mode.\n\n        :type: bool\n            ``True``: enables 4-wire mode\n            ``False``: disables it.\n        \"\"\"\n        self.write(f'MODE:SET {\"4W\" if enable else \"2W\"}')\n", "path": "pymeasure/instruments/siglenttechnologies/siglent_spdbase.py"}]}