spikesafe-python 1.11.22__tar.gz → 1.13.5__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.
- {spikesafe_python-1.11.22/spikesafe_python.egg-info → spikesafe_python-1.13.5}/PKG-INFO +1 -1
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/pyproject.toml +1 -1
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/DigitizerDataFetch.py +6 -7
- spikesafe_python-1.13.5/spikesafe_python/Discharge.py +105 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/PulseWidthCorrection.py +21 -14
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/ReadAllEvents.py +15 -3
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/SpikeSafeEvents.py +5 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/SpikeSafeInfo.py +2 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/SpikeSafeInfoParser.py +1 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/TcpSocket.py +2 -1
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5/spikesafe_python.egg-info}/PKG-INFO +1 -1
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python.egg-info/SOURCES.txt +1 -0
- spikesafe_python-1.13.5/tests/test_get_new_voltage_data_estimated_complete_time.py +26 -0
- spikesafe_python-1.13.5/tests/test_optimum_pulse_width_correction.py +38 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_optimum_pulse_width_correction_old.py +2 -2
- spikesafe_python-1.11.22/spikesafe_python/Discharge.py +0 -75
- spikesafe_python-1.11.22/tests/test_optimum_pulse_width_correction.py +0 -29
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/LICENSE +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/README.md +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/setup.cfg +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/setup.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/ChannelData.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/Compensation.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/DigitizerData.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/DigitizerEnums.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/DigitizerInfo.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/DigitizerVfCustomSequence.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/DigitizerVfCustomSequenceStep.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/EventData.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/MemoryTableReadData.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/Precision.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/ScpiFormatter.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/SerialPortConnection.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/SpikeSafeEnums.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/SpikeSafeError.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/TemperatureData.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/Threading.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/__init__.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python.egg-info/dependency_links.txt +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python.egg-info/requires.txt +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python.egg-info/top_level.txt +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_custom_compensation.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_custom_compensation_old.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_digitizer_fetch_time_of_sampling.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_digitizer_fetch_time_of_sampling_old.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_event_data.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_event_data_old.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_optimum_compensation.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_optimum_compensation_old.py +0 -0
- {spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_spikesafe_info_compare_rev_version.py +0 -0
|
@@ -299,7 +299,7 @@ class DigitizerDataFetch:
|
|
|
299
299
|
@staticmethod
|
|
300
300
|
def wait_for_new_voltage_data(
|
|
301
301
|
spike_safe_socket: TcpSocket,
|
|
302
|
-
wait_time: float = 0.
|
|
302
|
+
wait_time: float = 0.010,
|
|
303
303
|
enable_logging: bool | None = None,
|
|
304
304
|
timeout: float | None = None,
|
|
305
305
|
digitizer_number: int | None = None
|
|
@@ -312,8 +312,8 @@ class DigitizerDataFetch:
|
|
|
312
312
|
----------
|
|
313
313
|
spike_safe_socket : TcpSocket
|
|
314
314
|
Socket object used to communicate with SpikeSafe
|
|
315
|
-
wait_time: float
|
|
316
|
-
Wait time in between each set of VOLT:NDAT? queries in seconds. Use get_new_voltage_data_estimated_complete_time() for the recommended value
|
|
315
|
+
wait_time: float, Optional
|
|
316
|
+
Wait time in between each set of VOLT:NDAT? queries in seconds (default 0.010s). Use get_new_voltage_data_estimated_complete_time() for the recommended value
|
|
317
317
|
enable_logging : bool, Optional
|
|
318
318
|
Overrides spike_safe_socket.enable_logging attribute (default to None will use spike_safe_socket.enable_logging value)
|
|
319
319
|
timeout : float, Optional
|
|
@@ -392,12 +392,11 @@ class DigitizerDataFetch:
|
|
|
392
392
|
|
|
393
393
|
if hardware_trigger_count == 1:
|
|
394
394
|
# 𝑀𝑖𝑛𝑖𝑚𝑢𝑚 𝑇𝑜𝑡𝑎𝑙 𝐴𝑐𝑞𝑢𝑖𝑠𝑖𝑡𝑖𝑜𝑛 𝑇𝑖𝑚𝑒 = 𝑇𝑟𝑖𝑔𝑔𝑒𝑟 𝐶𝑜𝑢𝑛𝑡 (𝑇𝑟𝑖𝑔𝑔𝑒𝑟 𝐷𝑒𝑙𝑎𝑦+𝐴𝑝𝑒𝑟𝑡𝑢𝑟𝑒 𝑇𝑖𝑚𝑒×𝑅𝑒𝑎𝑑𝑖𝑛𝑔 𝐶𝑜𝑢𝑛𝑡)
|
|
395
|
-
estimated_complete_time_seconds = (hardware_trigger_count * (hardware_trigger_delay_microseconds + aperture_microseconds * reading_count)) /
|
|
395
|
+
estimated_complete_time_seconds = (hardware_trigger_count * (hardware_trigger_delay_microseconds + aperture_microseconds * reading_count)) / 1_000_000.0
|
|
396
396
|
else:
|
|
397
397
|
retrigger_time_microseconds = 600
|
|
398
398
|
# 𝑀𝑖𝑛𝑖𝑚𝑢𝑚 𝑇𝑜𝑡𝑎𝑙 𝐴𝑐𝑞𝑢𝑖𝑠𝑖𝑡𝑖𝑜𝑛 𝑇𝑖𝑚𝑒 = 𝑇𝑟𝑖𝑔𝑔𝑒𝑟 𝐶𝑜𝑢𝑛𝑡 (𝑇𝑟𝑖𝑔𝑔𝑒𝑟 𝐷𝑒𝑙𝑎𝑦 + Retrigger Time + 𝐴𝑝𝑒𝑟𝑡𝑢𝑟𝑒 𝑇𝑖𝑚𝑒 × 𝑅𝑒𝑎𝑑𝑖𝑛𝑔 𝐶𝑜𝑢𝑛𝑡) - Retrigger Time (ignore time last trigger)
|
|
399
|
-
estimated_complete_time_seconds = (hardware_trigger_count * (hardware_trigger_delay_microseconds + retrigger_time_microseconds + aperture_microseconds * reading_count) - retrigger_time_microseconds) /
|
|
400
|
-
|
|
399
|
+
estimated_complete_time_seconds = (hardware_trigger_count * (hardware_trigger_delay_microseconds + retrigger_time_microseconds + aperture_microseconds * reading_count) - retrigger_time_microseconds) / 1_000_000.0
|
|
401
400
|
# wait time cannot be less than 0s
|
|
402
401
|
estimated_complete_time_seconds = max(estimated_complete_time_seconds, 0)
|
|
403
402
|
|
|
@@ -616,7 +615,7 @@ def get_new_voltage_data_estimated_complete_time(
|
|
|
616
615
|
|
|
617
616
|
def wait_for_new_voltage_data(
|
|
618
617
|
spike_safe_socket: TcpSocket,
|
|
619
|
-
wait_time: float = 0.
|
|
618
|
+
wait_time: float = 0.010,
|
|
620
619
|
enable_logging: bool | None = None,
|
|
621
620
|
timeout: float | None = None,
|
|
622
621
|
digitizer_number: int | None = None
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from .SpikeSafeInfo import SpikeSafeInfo
|
|
3
|
+
from .TcpSocket import TcpSocket
|
|
4
|
+
from .Threading import wait
|
|
5
|
+
|
|
6
|
+
class Discharge:
|
|
7
|
+
"""
|
|
8
|
+
Class for calculating SpikeSafe channel discharge time based on compliance voltage.
|
|
9
|
+
|
|
10
|
+
Methods
|
|
11
|
+
-------
|
|
12
|
+
get_spikesafe_channel_discharge_time(compliance_voltage: float) -> float
|
|
13
|
+
Returns the time in seconds to fully discharge the SpikeSafe channel based on the compliance voltage
|
|
14
|
+
wait_for_spikesafe_channel_discharge(spike_safe_socket: TcpSocket, spikesafe_info: SpikeSafeInfo, compliance_voltage: float, channel_number: int = 1, enable_logging: bool | None = None) -> None
|
|
15
|
+
Automatically waits for the SpikeSafe channel to fully discharge based on SpikeSafe capabilities.
|
|
16
|
+
If the SpikeSafe supports the Discharge Complete query, it will poll the channel until discharge is complete.
|
|
17
|
+
If not, it will wait for a calculated time based on the compliance voltage.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def get_spikesafe_channel_discharge_time(compliance_voltage: float) -> float:
|
|
22
|
+
"""
|
|
23
|
+
Returns the time in seconds to fully discharge the SpikeSafe channel based on the compliance voltage
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
compliance_voltage : float
|
|
28
|
+
Compliance voltage to factor in discharge time
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
float
|
|
33
|
+
Discharge time in seconds
|
|
34
|
+
|
|
35
|
+
Raises
|
|
36
|
+
------
|
|
37
|
+
None
|
|
38
|
+
"""
|
|
39
|
+
# Discharge time accounting for compliance voltage, voltage readroom, and discharge voltage per second
|
|
40
|
+
voltage_headroom_voltage = 7
|
|
41
|
+
discharge_voltage_per_second = 1000
|
|
42
|
+
discharge_time = (compliance_voltage + voltage_headroom_voltage) / discharge_voltage_per_second
|
|
43
|
+
return discharge_time
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def wait_for_spikesafe_channel_discharge(
|
|
47
|
+
spikesafe_socket: TcpSocket,
|
|
48
|
+
spikesafe_info: SpikeSafeInfo,
|
|
49
|
+
compliance_voltage: float,
|
|
50
|
+
channel_number: int = 1,
|
|
51
|
+
enable_logging: bool | None = None
|
|
52
|
+
) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Automatically waits for the SpikeSafe channel to fully discharge based on SpikeSafe capabilities.
|
|
55
|
+
If the SpikeSafe supports the Discharge Complete query, it will poll the channel until discharge is complete.
|
|
56
|
+
If not, it will wait for a calculated time based on the compliance voltage.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
spikesafe_socket : TcpSocket
|
|
61
|
+
Socket object used to communicate with SpikeSafe.
|
|
62
|
+
spikesafe_info : SpikeSafeInfo
|
|
63
|
+
An object containing the SpikeSafe information.
|
|
64
|
+
compliance_voltage : float
|
|
65
|
+
Compliance voltage to factor in discharge time.
|
|
66
|
+
channel_number : int, optional
|
|
67
|
+
Channel number to wait for discharge. By default, this is 1.
|
|
68
|
+
enable_logging : bool, optional
|
|
69
|
+
Overrides spikesafe_socket.enable_logging attribute (default to None will use spikesafe_socket.enable_logging value).
|
|
70
|
+
|
|
71
|
+
Raises
|
|
72
|
+
------
|
|
73
|
+
TimeoutError
|
|
74
|
+
Thrown when the wait times out.
|
|
75
|
+
Exception
|
|
76
|
+
On any error.
|
|
77
|
+
"""
|
|
78
|
+
if spikesafe_info.supports_discharge_query:
|
|
79
|
+
# when Discharge Complete query is supported, query for completion
|
|
80
|
+
expected_compliance_voltage_discharge_time = Discharge.get_spikesafe_channel_discharge_time(compliance_voltage)
|
|
81
|
+
expected_max_model_discharge_time = Discharge.get_spikesafe_channel_discharge_time(spikesafe_info.maximum_compliance_voltage + 35) # 35V gives extra time, some windows pcs return early from wait function
|
|
82
|
+
|
|
83
|
+
start_time = time.time()
|
|
84
|
+
# wait until the channel is fully discharged before disconnecting the load
|
|
85
|
+
is_discharge_complete = ""
|
|
86
|
+
while True:
|
|
87
|
+
spikesafe_socket.send_scpi_command(f"OUTP{channel_number}:DISC:COMP?", enable_logging)
|
|
88
|
+
is_discharge_complete = spikesafe_socket.read_data(enable_logging)
|
|
89
|
+
|
|
90
|
+
if is_discharge_complete == "TRUE":
|
|
91
|
+
break
|
|
92
|
+
|
|
93
|
+
elapsed_seconds = time.time() - start_time
|
|
94
|
+
if elapsed_seconds > expected_max_model_discharge_time:
|
|
95
|
+
raise TimeoutError(f"SpikeSafe channel discharge expected discharge time is {expected_compliance_voltage_discharge_time} seconds, but this exceeded the model {spikesafe_info.maximum_compliance_voltage}V maximum time of {expected_max_model_discharge_time} seconds.")
|
|
96
|
+
else:
|
|
97
|
+
# when Discharge Complete query is not supported, use a calculated wait time
|
|
98
|
+
wait_time = Discharge.get_spikesafe_channel_discharge_time(compliance_voltage + 35) # 35V gives extra time, some windows pcs return early from wait function
|
|
99
|
+
wait(wait_time)
|
|
100
|
+
|
|
101
|
+
def get_spikesafe_channel_discharge_time(compliance_voltage: float) -> float:
|
|
102
|
+
"""
|
|
103
|
+
Obsolete: use Discharge.get_spikesafe_channel_discharge_time instead
|
|
104
|
+
"""
|
|
105
|
+
return Discharge.get_spikesafe_channel_discharge_time(compliance_voltage)
|
{spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/PulseWidthCorrection.py
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from .SpikeSafeEnums import LoadImpedance, RiseTime
|
|
2
|
+
from .SpikeSafeInfo import SpikeSafeInfo
|
|
2
3
|
|
|
3
4
|
class PulseWidthCorrection:
|
|
4
5
|
"""
|
|
@@ -12,7 +13,7 @@ class PulseWidthCorrection:
|
|
|
12
13
|
|
|
13
14
|
@staticmethod
|
|
14
15
|
def get_optimum_pulse_width_correction(
|
|
15
|
-
|
|
16
|
+
spikesafe_info: SpikeSafeInfo,
|
|
16
17
|
set_current_amps: float,
|
|
17
18
|
load_impedance: LoadImpedance,
|
|
18
19
|
rise_time: RiseTime
|
|
@@ -22,8 +23,8 @@ class PulseWidthCorrection:
|
|
|
22
23
|
|
|
23
24
|
Parameters
|
|
24
25
|
----------
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
spikesafe_info : SpikeSafeInfo
|
|
27
|
+
An object containing the SpikeSafe information.
|
|
27
28
|
set_current_amps : float
|
|
28
29
|
Current to be set on SpikeSafe.
|
|
29
30
|
load_impedance : LoadImpedance
|
|
@@ -48,25 +49,25 @@ class PulseWidthCorrection:
|
|
|
48
49
|
default_correction = "1.250"
|
|
49
50
|
|
|
50
51
|
# Test to see if the current is above the model capability
|
|
51
|
-
if set_current_amps >
|
|
52
|
-
raise ValueError(f'Measurement current {set_current_amps}A exceeds SpikeSafe model maximum current capability of {
|
|
52
|
+
if set_current_amps > spikesafe_info.maximum_set_current:
|
|
53
|
+
raise ValueError(f'Measurement current {set_current_amps}A exceeds SpikeSafe model maximum current capability of {spikesafe_info.maximum_set_current}A.')
|
|
53
54
|
|
|
54
55
|
# Dictionary to store values for different model max currents, arranged by max current of model number. The 9th order coefficient is first.
|
|
55
56
|
model_params = PulseWidthCorrection.__get_optimum_pulse_width_correction_table()
|
|
56
57
|
|
|
57
58
|
# Check if the given spikesafe_model_max_current_amps is in the model_params, if it is not, just return the default correction
|
|
58
|
-
if
|
|
59
|
+
if spikesafe_info.maximum_set_current not in model_params:
|
|
59
60
|
return default_correction
|
|
60
61
|
|
|
61
62
|
# Determine if we are in the high or low range
|
|
62
|
-
low_current_range_maximum = model_params[
|
|
63
|
+
low_current_range_maximum = model_params[spikesafe_info.maximum_set_current]['low_current_range_maximum']
|
|
63
64
|
if set_current_amps > low_current_range_maximum:
|
|
64
65
|
current_range = 'HIGH'
|
|
65
66
|
else:
|
|
66
67
|
current_range = 'LOW'
|
|
67
68
|
|
|
68
69
|
# Retrieve dictionary
|
|
69
|
-
dictionary = model_params[
|
|
70
|
+
dictionary = model_params[spikesafe_info.maximum_set_current][(current_range, load_impedance, rise_time)]
|
|
70
71
|
|
|
71
72
|
# Check if the set current exceeds the max test current, if it does evaluate polynomial at max test current
|
|
72
73
|
if set_current_amps > dictionary['max_test_current']:
|
|
@@ -74,7 +75,7 @@ class PulseWidthCorrection:
|
|
|
74
75
|
|
|
75
76
|
# Retrieve the polynomial coefficients for the given conditions, if there is no definition for these conditions, return the default correction value
|
|
76
77
|
try:
|
|
77
|
-
coefficient_data = model_params[
|
|
78
|
+
coefficient_data = model_params[spikesafe_info.maximum_set_current][(current_range, load_impedance, rise_time)]
|
|
78
79
|
# Extract nested coefficients
|
|
79
80
|
polynomial_coefficients = coefficient_data['coefficients']
|
|
80
81
|
except KeyError:
|
|
@@ -86,10 +87,12 @@ class PulseWidthCorrection:
|
|
|
86
87
|
# Evaluate the polynomial
|
|
87
88
|
correction_value = sum(c * (set_current_amps ** i) for i, c in enumerate(reversed(polynomial_coefficients)))
|
|
88
89
|
|
|
89
|
-
#
|
|
90
|
-
if correction_value >
|
|
91
|
-
correction_value =
|
|
92
|
-
|
|
90
|
+
# Force to maximum pulse correction due to firmware limitations
|
|
91
|
+
if correction_value > spikesafe_info.maximum_pulse_width_correction_override:
|
|
92
|
+
correction_value = spikesafe_info.maximum_pulse_width_correction_override
|
|
93
|
+
|
|
94
|
+
# Negative values are not valid and should not be taken into account when generated by the polynomial
|
|
95
|
+
if correction_value < 0:
|
|
93
96
|
correction_value = 0
|
|
94
97
|
|
|
95
98
|
return f"{correction_value:.3f}"
|
|
@@ -2624,4 +2627,8 @@ def get_optimum_pulse_width_correction(
|
|
|
2624
2627
|
"""
|
|
2625
2628
|
Obsolete: use PulseWidthCorrection.get_optimum_pulse_width_correction() instead
|
|
2626
2629
|
"""
|
|
2627
|
-
|
|
2630
|
+
spikesafe_info = SpikeSafeInfo()
|
|
2631
|
+
spikesafe_info.maximum_pulse_width_correction_override = 9
|
|
2632
|
+
spikesafe_info.maximum_set_current = spikesafe_model_max_current_amps
|
|
2633
|
+
|
|
2634
|
+
return PulseWidthCorrection.get_optimum_pulse_width_correction(spikesafe_info, set_current_amps, load_impedance, rise_time)
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
import logging
|
|
10
|
+
import time
|
|
10
11
|
from .EventData import EventData
|
|
11
12
|
from .SpikeSafeError import SpikeSafeError
|
|
12
13
|
from .TcpSocket import TcpSocket
|
|
@@ -99,7 +100,8 @@ class ReadAllEvents:
|
|
|
99
100
|
def read_until_event(
|
|
100
101
|
spike_safe_socket: TcpSocket,
|
|
101
102
|
code: int,
|
|
102
|
-
enable_logging: bool | None = None
|
|
103
|
+
enable_logging: bool | None = None,
|
|
104
|
+
timeout: float | None = None
|
|
103
105
|
) -> list[EventData]:
|
|
104
106
|
"""Returns an array of all events from the SpikeSafe event queue until a specific event is read.
|
|
105
107
|
|
|
@@ -111,6 +113,8 @@ class ReadAllEvents:
|
|
|
111
113
|
Event code for desired event
|
|
112
114
|
enable_logging : bool, Optional
|
|
113
115
|
Overrides spike_safe_socket.enable_logging attribute (default to None will use spike_safe_socket.enable_logging value)
|
|
116
|
+
timeout: float, Optional
|
|
117
|
+
Maximum time in seconds to wait for the desired event before raising an exception (default to None will wait indefinitely)
|
|
114
118
|
|
|
115
119
|
Returns
|
|
116
120
|
-------
|
|
@@ -130,7 +134,10 @@ class ReadAllEvents:
|
|
|
130
134
|
event_data_list = []
|
|
131
135
|
|
|
132
136
|
# initialize flag to check if event queue is empty
|
|
133
|
-
has_desired_event_occurred = False
|
|
137
|
+
has_desired_event_occurred = False
|
|
138
|
+
|
|
139
|
+
# Record the start time
|
|
140
|
+
start_time = time.time()
|
|
134
141
|
|
|
135
142
|
# run as long as there is an event in the SpikeSafe queue
|
|
136
143
|
while has_desired_event_occurred == False:
|
|
@@ -157,7 +164,12 @@ class ReadAllEvents:
|
|
|
157
164
|
has_desired_event_occurred = True
|
|
158
165
|
else:
|
|
159
166
|
# unexpected response detected from SpikeSafe, end checking
|
|
160
|
-
raise Exception('No event response from SpikeSafe: {}'.format(event_response))
|
|
167
|
+
raise Exception('No event response from SpikeSafe: {}'.format(event_response))
|
|
168
|
+
|
|
169
|
+
# if a timeout value was provided, check if the timeout has been exceeded and raise an exception if so
|
|
170
|
+
if timeout is not None:
|
|
171
|
+
if time.time() - start_time > timeout:
|
|
172
|
+
raise Exception(f'Timeout of {timeout} seconds exceeded while waiting for event code {code}')
|
|
161
173
|
|
|
162
174
|
# return event list to caller
|
|
163
175
|
return event_data_list
|
|
@@ -28,6 +28,9 @@ class SpikeSafeEvents(IntEnum):
|
|
|
28
28
|
MAC_ADDRESS_IS_NOT_CONFIGURED = 123
|
|
29
29
|
NO_EXTERNAL_SOURCE_TRIGGER_OUTPUT_DUE_TO_PULSE_WIDTH_ADJUSTMENT_IS_DISABLED_INTERNALLY = 124
|
|
30
30
|
MAX_COMPLIANCE_VOLTAGE_EXCEEDED_LIMIT = 125
|
|
31
|
+
CURRENT_RAMP_RATE_RESTORED = 126
|
|
32
|
+
STAIRCASE_SWEEP_IS_COMPLETED = 127
|
|
33
|
+
STAIRCASE_SWEEP_SHUTDOWN_DUE_TO_ERROR = 128
|
|
31
34
|
MAX_COMPLIANCE_VOLTAGE_EXCEEDED = 200
|
|
32
35
|
HIGH_SIDE_OVER_CURRENT = 201
|
|
33
36
|
LOW_SIDE_OVER_CURRENT = 202
|
|
@@ -180,3 +183,5 @@ class SpikeSafeEvents(IntEnum):
|
|
|
180
183
|
EXCEED_MAX_SAMPLING_CUSTOM_SEQUENCE_APERTURE = 509
|
|
181
184
|
CANNOT_COMMUNICATE_WITH_DIGITIZER = 510
|
|
182
185
|
INVALID_VOLTAGE_PROTECTION_MODE = 600
|
|
186
|
+
INVALID_STAIRCASE_SWEEP_ON_TIME = 602
|
|
187
|
+
INVALID_STAIRCASE_SWEEP_STEP_COUNT = 603
|
|
@@ -76,6 +76,7 @@ class SpikeSafeInfo:
|
|
|
76
76
|
maximum_set_current: float | None
|
|
77
77
|
minimum_pulse_width: float | None
|
|
78
78
|
maximum_pulse_width: float | None
|
|
79
|
+
maximum_pulse_width_correction_override: float | None
|
|
79
80
|
minimum_pulse_width_offset: float | None
|
|
80
81
|
maximum_pulse_width_offset: float | None
|
|
81
82
|
|
|
@@ -107,6 +108,7 @@ class SpikeSafeInfo:
|
|
|
107
108
|
self.maximum_set_current = None
|
|
108
109
|
self.minimum_pulse_width = None
|
|
109
110
|
self.maximum_pulse_width = None
|
|
111
|
+
self.maximum_pulse_width_correction_override = None
|
|
110
112
|
self.minimum_pulse_width_offset = None
|
|
111
113
|
self.maximum_pulse_width_offset = None
|
|
112
114
|
|
{spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/SpikeSafeInfoParser.py
RENAMED
|
@@ -49,6 +49,7 @@ class SpikeSafeInfoParser:
|
|
|
49
49
|
spikesafe_info.maximum_pulse_width = SpikeSafeInfoParser._query_float(spike_safe_socket, 'SOUR0:PULS:TON? MAX', enable_logging)
|
|
50
50
|
spikesafe_info.minimum_pulse_width_offset = SpikeSafeInfoParser._query_float(spike_safe_socket, 'SOUR0:PULS:OFFS? MIN', enable_logging)
|
|
51
51
|
spikesafe_info.maximum_pulse_width_offset = SpikeSafeInfoParser._query_float(spike_safe_socket, 'SOUR0:PULS:OFFS? MAX', enable_logging)
|
|
52
|
+
spikesafe_info.maximum_pulse_width_correction_override = 50 if SpikeSafeInfoParser.compare_rev_version(spikesafe_info.version, "3.0.15.5") else 9 # Older firmware had a max correction of 9us, but newer firmware supports up to 50us to compensate for the Pulse Width Adjustment algorithm's maximum adjustment
|
|
52
53
|
|
|
53
54
|
spike_safe_socket.send_scpi_command('MEM:DATA ZINNUM?')
|
|
54
55
|
zin_number = spike_safe_socket.read_data(enable_logging)
|
|
@@ -63,9 +63,10 @@ class TcpSocket:
|
|
|
63
63
|
try:
|
|
64
64
|
self.socket_ip_address = ip_address
|
|
65
65
|
|
|
66
|
-
# create socket with 2 second timeout and connect to SpikeSafe
|
|
66
|
+
# create socket with 2 second timeout, 512 byte send max buffer to match SpikeSafe's command buffer, and connect to SpikeSafe
|
|
67
67
|
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
68
68
|
self.tcp_socket.settimeout(2)
|
|
69
|
+
self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 512)
|
|
69
70
|
|
|
70
71
|
if (self.enable_logging):
|
|
71
72
|
log.log(self.default_log_level, self.__get_formatted_log_message__('Connecting...'))
|
|
@@ -38,6 +38,7 @@ tests/test_digitizer_fetch_time_of_sampling.py
|
|
|
38
38
|
tests/test_digitizer_fetch_time_of_sampling_old.py
|
|
39
39
|
tests/test_event_data.py
|
|
40
40
|
tests/test_event_data_old.py
|
|
41
|
+
tests/test_get_new_voltage_data_estimated_complete_time.py
|
|
41
42
|
tests/test_optimum_compensation.py
|
|
42
43
|
tests/test_optimum_compensation_old.py
|
|
43
44
|
tests/test_optimum_pulse_width_correction.py
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from spikesafe_python.DigitizerDataFetch import DigitizerDataFetch
|
|
3
|
+
|
|
4
|
+
@pytest.mark.parametrize(
|
|
5
|
+
"aperture_microseconds, reading_count, hardware_trigger_count, hardware_trigger_delay_microseconds, expected",
|
|
6
|
+
[
|
|
7
|
+
# 488us aperture, 1 reading, 1 hardware trigger, 200us delay
|
|
8
|
+
(488, 1, 1, 200, 0.000688),
|
|
9
|
+
# 500us aperture, 1 reading, 1 hardware trigger, 150us delay
|
|
10
|
+
(500, 1, 1, 150, 0.00065),
|
|
11
|
+
# 694us aperture, 1 reading, 1 hardware trigger, 0us delay
|
|
12
|
+
(694, 1, 1, 0, 0.000694),
|
|
13
|
+
# 25ms aperture, 1 reading, 1 hardware trigger, 3ms delay
|
|
14
|
+
(25000, 1, 1, 3000, 0.028),
|
|
15
|
+
]
|
|
16
|
+
)
|
|
17
|
+
def test_get_new_voltage_data_estimated_complete_time(
|
|
18
|
+
aperture_microseconds, reading_count, hardware_trigger_count, hardware_trigger_delay_microseconds, expected
|
|
19
|
+
):
|
|
20
|
+
result = DigitizerDataFetch.get_new_voltage_data_estimated_complete_time(
|
|
21
|
+
aperture_microseconds,
|
|
22
|
+
reading_count,
|
|
23
|
+
hardware_trigger_count,
|
|
24
|
+
hardware_trigger_delay_microseconds
|
|
25
|
+
)
|
|
26
|
+
assert pytest.approx(result, rel=1e-6) == expected
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import spikesafe_python
|
|
3
|
+
|
|
4
|
+
@pytest.mark.parametrize("maximum_pulse_width_correction_override, model_max_current, set_current, load_impedance, rise_time, expected", [
|
|
5
|
+
(50, 10, 4, spikesafe_python.SpikeSafeEnums.LoadImpedance.VERY_LOW, spikesafe_python.SpikeSafeEnums.RiseTime.VERY_SLOW, '2.476'), # Add expected value
|
|
6
|
+
(9, 0.05, 0.0039, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '9.000'), # test 50mA low range first entry for older firmware with 9us max correction override
|
|
7
|
+
(50, 0.05, 0.0039, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '11.289'), # test 50mA low range first entry
|
|
8
|
+
(50, 0.5, 0.0159, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.943'), # test 500mA low range first entry < 0.016 max_test_current
|
|
9
|
+
(50, 0.5, 0.0160, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.924'), # test 500mA low range first entry = 0.016 max_test_current
|
|
10
|
+
(50, 0.5, 0.0161, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.924'), # test 500mA low range first entry > 0.016 max_test_current
|
|
11
|
+
(50, 0.5, 0.038, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.924'), # test 500mA low range second entry = 0.038 max_test_current
|
|
12
|
+
(50, 0.5, 0.470, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.495'), # test high 500mA range first entry < 0.470 max_test_current
|
|
13
|
+
(50, 0.5, 0.471, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.496'), # test high 500mA range first entry = 0.471 max_test_current
|
|
14
|
+
(50, 0.5, 0.472, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.496'), # test high 500mA range first entry > 0.472 max_test_current
|
|
15
|
+
(50, 0.5, 0.5, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.496'), # test high model_max_current 500mA range = 0.5 set_current_amps
|
|
16
|
+
(50, 5, 0.001, spikesafe_python.SpikeSafeEnums.LoadImpedance.VERY_LOW, spikesafe_python.SpikeSafeEnums.RiseTime.VERY_SLOW, '50.000'), # test calculated >9us correction coerced to 9us
|
|
17
|
+
(50, 0.5, 0.0438, spikesafe_python.SpikeSafeEnums.LoadImpedance.MEDIUM, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '0.000'), # test calculated negative correction coerced to 0
|
|
18
|
+
(50, 25, 21, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.250'), # test invalid 25A model
|
|
19
|
+
])
|
|
20
|
+
def test_get_optimum_pulse_width_correction_value(maximum_pulse_width_correction_override, model_max_current, set_current, load_impedance, rise_time, expected):
|
|
21
|
+
spikesafe_info = spikesafe_python.SpikeSafeInfo()
|
|
22
|
+
spikesafe_info.maximum_pulse_width_correction_override = maximum_pulse_width_correction_override
|
|
23
|
+
spikesafe_info.maximum_set_current = model_max_current
|
|
24
|
+
|
|
25
|
+
correction_value = spikesafe_python.PulseWidthCorrection.get_optimum_pulse_width_correction(spikesafe_info, set_current, load_impedance, rise_time)
|
|
26
|
+
assert correction_value == expected
|
|
27
|
+
|
|
28
|
+
@pytest.mark.parametrize("model_max_current, set_current, load_impedance, rise_time, expected_error_message", [
|
|
29
|
+
(0.05, 0.051, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, 'Measurement current 0.051A exceeds SpikeSafe model maximum current capability of 0.05A.'), # test set_current > model_max_current
|
|
30
|
+
])
|
|
31
|
+
def test_test_get_optimum_pulse_width_correction_exceptions(model_max_current, set_current, load_impedance, rise_time, expected_error_message):
|
|
32
|
+
spikesafe_info = spikesafe_python.SpikeSafeInfo()
|
|
33
|
+
spikesafe_info.maximum_pulse_width_correction_override = 9
|
|
34
|
+
spikesafe_info.maximum_set_current = model_max_current
|
|
35
|
+
|
|
36
|
+
with pytest.raises(ValueError) as exc_info:
|
|
37
|
+
spikesafe_python.PulseWidthCorrection.get_optimum_pulse_width_correction(spikesafe_info, set_current, load_impedance, rise_time)
|
|
38
|
+
assert expected_error_message in str(exc_info.value)
|
|
@@ -4,7 +4,7 @@ from spikesafe_python.SpikeSafeEnums import LoadImpedance, RiseTime
|
|
|
4
4
|
|
|
5
5
|
@pytest.mark.parametrize("model_max_current, set_current, load_impedance, rise_time, expected", [
|
|
6
6
|
(10, 4, LoadImpedance.VERY_LOW, RiseTime.VERY_SLOW, '2.476'), # Add expected value
|
|
7
|
-
(0.05, 0.0039, LoadImpedance.HIGH, RiseTime.FAST, '
|
|
7
|
+
(0.05, 0.0039, LoadImpedance.HIGH, RiseTime.FAST, '9.000'), # test 50mA low range first entry
|
|
8
8
|
(0.5, 0.0159, LoadImpedance.HIGH, RiseTime.FAST, '1.943'), # test 500mA low range first entry < 0.016 max_test_current
|
|
9
9
|
(0.5, 0.0160, LoadImpedance.HIGH, RiseTime.FAST, '1.924'), # test 500mA low range first entry = 0.016 max_test_current
|
|
10
10
|
(0.5, 0.0161, LoadImpedance.HIGH, RiseTime.FAST, '1.924'), # test 500mA low range first entry > 0.016 max_test_current
|
|
@@ -13,7 +13,7 @@ from spikesafe_python.SpikeSafeEnums import LoadImpedance, RiseTime
|
|
|
13
13
|
(0.5, 0.471, LoadImpedance.HIGH, RiseTime.FAST, '1.496'), # test high 500mA range first entry = 0.471 max_test_current
|
|
14
14
|
(0.5, 0.472, LoadImpedance.HIGH, RiseTime.FAST, '1.496'), # test high 500mA range first entry > 0.472 max_test_current
|
|
15
15
|
(0.5, 0.5, LoadImpedance.HIGH, RiseTime.FAST, '1.496'), # test high model_max_current 500mA range = 0.5 set_current_amps
|
|
16
|
-
(5, 0.001, LoadImpedance.VERY_LOW, RiseTime.VERY_SLOW, '
|
|
16
|
+
(5, 0.001, LoadImpedance.VERY_LOW, RiseTime.VERY_SLOW, '9.000'), # test calculated >9us correction coerced to 9us
|
|
17
17
|
(0.5, 0.0438, LoadImpedance.MEDIUM, RiseTime.FAST, '0.000'), # test calculated negative correction coerced to 0
|
|
18
18
|
(25, 21, LoadImpedance.HIGH, RiseTime.FAST, '1.250'), # test invalid 25A model
|
|
19
19
|
])
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
from .TcpSocket import TcpSocket
|
|
2
|
-
|
|
3
|
-
class Discharge:
|
|
4
|
-
"""
|
|
5
|
-
Class for calculating SpikeSafe channel discharge time based on compliance voltage.
|
|
6
|
-
|
|
7
|
-
Methods
|
|
8
|
-
-------
|
|
9
|
-
get_spikesafe_channel_discharge_time(compliance_voltage: float) -> float
|
|
10
|
-
Returns the time in seconds to fully discharge the SpikeSafe channel based on the compliance voltage
|
|
11
|
-
wait_for_spikesafe_channel_discharge(tcp_socket: TcpSocket, channel_number: int) -> None
|
|
12
|
-
Waits for the SpikeSafe channel to fully discharge
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
@staticmethod
|
|
16
|
-
def get_spikesafe_channel_discharge_time(compliance_voltage: float) -> float:
|
|
17
|
-
"""
|
|
18
|
-
Returns the time in seconds to fully discharge the SpikeSafe channel based on the compliance voltage
|
|
19
|
-
|
|
20
|
-
Parameters
|
|
21
|
-
----------
|
|
22
|
-
compliance_voltage : float
|
|
23
|
-
Compliance voltage to factor in discharge time
|
|
24
|
-
|
|
25
|
-
Returns
|
|
26
|
-
-------
|
|
27
|
-
float
|
|
28
|
-
Discharge time in seconds
|
|
29
|
-
|
|
30
|
-
Raises
|
|
31
|
-
------
|
|
32
|
-
None
|
|
33
|
-
"""
|
|
34
|
-
# Discharge time accounting for compliance voltage, voltage readroom, and discharge voltage per second
|
|
35
|
-
voltage_headroom_voltage = 7
|
|
36
|
-
discharge_voltage_per_second = 1000
|
|
37
|
-
discharge_time = (compliance_voltage + voltage_headroom_voltage) / discharge_voltage_per_second
|
|
38
|
-
return discharge_time
|
|
39
|
-
|
|
40
|
-
@staticmethod
|
|
41
|
-
def wait_for_spikesafe_channel_discharge(
|
|
42
|
-
tcp_socket: TcpSocket,
|
|
43
|
-
channel_number: int,
|
|
44
|
-
enable_logging: bool | None = None
|
|
45
|
-
) -> None:
|
|
46
|
-
"""
|
|
47
|
-
Waits for the SpikeSafe channel to fully discharge
|
|
48
|
-
|
|
49
|
-
Parameters
|
|
50
|
-
----------
|
|
51
|
-
tcp_socket : TcpSocket
|
|
52
|
-
TCP socket connection to the SpikeSafe device
|
|
53
|
-
channel_number : int
|
|
54
|
-
Channel number to poll discharge state of
|
|
55
|
-
|
|
56
|
-
Returns
|
|
57
|
-
-------
|
|
58
|
-
None
|
|
59
|
-
|
|
60
|
-
Raises
|
|
61
|
-
------
|
|
62
|
-
Exception
|
|
63
|
-
On any error
|
|
64
|
-
"""
|
|
65
|
-
# wait until the channel is fully discharged before disconnecting the load
|
|
66
|
-
is_discharge_complete = ''
|
|
67
|
-
while is_discharge_complete != 'TRUE':
|
|
68
|
-
tcp_socket.send_scpi_command(f'OUTP{channel_number}:DISC:COMP?', enable_logging)
|
|
69
|
-
is_discharge_complete = tcp_socket.read_data(enable_logging)
|
|
70
|
-
|
|
71
|
-
def get_spikesafe_channel_discharge_time(compliance_voltage: float) -> float:
|
|
72
|
-
"""
|
|
73
|
-
Obsolete: use Discharge.get_spikesafe_channel_discharge_time instead
|
|
74
|
-
"""
|
|
75
|
-
return Discharge.get_spikesafe_channel_discharge_time(compliance_voltage)
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
import spikesafe_python
|
|
3
|
-
|
|
4
|
-
@pytest.mark.parametrize("model_max_current, set_current, load_impedance, rise_time, expected", [
|
|
5
|
-
(10, 4, spikesafe_python.SpikeSafeEnums.LoadImpedance.VERY_LOW, spikesafe_python.SpikeSafeEnums.RiseTime.VERY_SLOW, '2.476'), # Add expected value
|
|
6
|
-
(0.05, 0.0039, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '11.289'), # test 50mA low range first entry
|
|
7
|
-
(0.5, 0.0159, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.943'), # test 500mA low range first entry < 0.016 max_test_current
|
|
8
|
-
(0.5, 0.0160, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.924'), # test 500mA low range first entry = 0.016 max_test_current
|
|
9
|
-
(0.5, 0.0161, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.924'), # test 500mA low range first entry > 0.016 max_test_current
|
|
10
|
-
(0.5, 0.038, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.924'), # test 500mA low range second entry = 0.038 max_test_current
|
|
11
|
-
(0.5, 0.470, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.495'), # test high 500mA range first entry < 0.470 max_test_current
|
|
12
|
-
(0.5, 0.471, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.496'), # test high 500mA range first entry = 0.471 max_test_current
|
|
13
|
-
(0.5, 0.472, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.496'), # test high 500mA range first entry > 0.472 max_test_current
|
|
14
|
-
(0.5, 0.5, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.496'), # test high model_max_current 500mA range = 0.5 set_current_amps
|
|
15
|
-
(5, 0.001, spikesafe_python.SpikeSafeEnums.LoadImpedance.VERY_LOW, spikesafe_python.SpikeSafeEnums.RiseTime.VERY_SLOW, '50.000'), # test calculated >50us correction coerced to 50us
|
|
16
|
-
(0.5, 0.0438, spikesafe_python.SpikeSafeEnums.LoadImpedance.MEDIUM, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '0.000'), # test calculated negative correction coerced to 0
|
|
17
|
-
(25, 21, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, '1.250'), # test invalid 25A model
|
|
18
|
-
])
|
|
19
|
-
def test_get_optimum_pulse_width_correction_value(model_max_current, set_current, load_impedance, rise_time, expected):
|
|
20
|
-
correction_value = spikesafe_python.PulseWidthCorrection.get_optimum_pulse_width_correction(model_max_current, set_current, load_impedance, rise_time)
|
|
21
|
-
assert correction_value == expected
|
|
22
|
-
|
|
23
|
-
@pytest.mark.parametrize("model_max_current, set_current, load_impedance, rise_time, expected_error_message", [
|
|
24
|
-
(0.05, 0.051, spikesafe_python.SpikeSafeEnums.LoadImpedance.HIGH, spikesafe_python.SpikeSafeEnums.RiseTime.FAST, 'Measurement current 0.051A exceeds SpikeSafe model maximum current capability of 0.05A.'), # test set_current > model_max_current
|
|
25
|
-
])
|
|
26
|
-
def test_test_get_optimum_pulse_width_correction_exceptions(model_max_current, set_current, load_impedance, rise_time, expected_error_message):
|
|
27
|
-
with pytest.raises(ValueError) as exc_info:
|
|
28
|
-
spikesafe_python.PulseWidthCorrection.get_optimum_pulse_width_correction(model_max_current, set_current, load_impedance, rise_time)
|
|
29
|
-
assert expected_error_message in str(exc_info.value)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/DigitizerVfCustomSequence.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/MemoryTableReadData.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python/SerialPortConnection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/spikesafe_python.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spikesafe_python-1.11.22 → spikesafe_python-1.13.5}/tests/test_digitizer_fetch_time_of_sampling.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|