ents 2.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ents/__init__.py ADDED
@@ -0,0 +1,23 @@
1
+ from .proto.encode import (
2
+ encode_response,
3
+ encode_power_measurement,
4
+ encode_teros12_measurement,
5
+ encode_phytos31_measurement,
6
+ encode_bme280_measurement,
7
+ )
8
+
9
+ from .proto.decode import decode_response, decode_measurement
10
+
11
+ from .proto.esp32 import encode_esp32command, decode_esp32command
12
+
13
+ __all__ = [
14
+ "encode_response",
15
+ "encode_power_measurement",
16
+ "encode_teros12_measurement",
17
+ "encode_phytos31_measurement",
18
+ "encode_bme280_measurement",
19
+ "decode_response",
20
+ "decode_measurement",
21
+ "encode_esp32command",
22
+ "decode_esp32command",
23
+ ]
@@ -0,0 +1,51 @@
1
+ """To test connection via socket to Kiethley 2450
2
+
3
+ Stephen Taylor, 5/20/2024
4
+ """
5
+
6
+ import socket
7
+
8
+
9
+ def ping_smu(host, port):
10
+ try:
11
+ # Create a TCP/IP socket
12
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
13
+
14
+ # Set a timeout for the connection attempt
15
+ sock.settimeout(1)
16
+
17
+ # Connect to the SMU
18
+ sock.connect((host, port))
19
+
20
+ # Send the *IDN? command
21
+ sock.sendall(b"*RST\n")
22
+ sock.sendall(b"*IDN?\n")
23
+
24
+ # Receive the response
25
+ response = sock.recv(1024)
26
+ response = response.strip()
27
+ print("Response from SMU:", response)
28
+
29
+ # Close the socket
30
+ sock.close()
31
+
32
+ # Return True if connection successful
33
+ return True
34
+ except Exception as e:
35
+ # Connection failed
36
+ print(f"Error: {e}")
37
+ return False
38
+
39
+
40
+ if __name__ == "__main__":
41
+ # Specify the IP address or hostname of the SMU and its port
42
+ smu_host = (
43
+ "128.114.204.56" # Replace with the actual IP address or hostname of the SMU
44
+ )
45
+ smu_port = 23 # Replace with the actual port used by the SMU
46
+
47
+ # Ping the SMU
48
+ if ping_smu(smu_host, smu_port):
49
+ print("SMU is reachable.")
50
+ else:
51
+ print("Failed to ping SMU.")
@@ -0,0 +1,66 @@
1
+ """To test connection to Soil Power Sensor over serial
2
+
3
+ Stephen Taylor 5/20/2024
4
+ """
5
+
6
+ import serial
7
+
8
+
9
+ class SerialPing:
10
+ """Simple serial ping utility"""
11
+
12
+ def __init__(self, port, baudrate=115200, xonxoff=True):
13
+ """Constructor
14
+
15
+ Initializes serial connection.
16
+
17
+ Parameters
18
+ ----------
19
+ port : str
20
+ Serial port name (e.g., COM1, /dev/ttyUSB0)
21
+ baudrate : int, optional
22
+ Baud rate for serial communication (default is 115200, STM32 functions at 115200)
23
+ xonxoff : bool, optional
24
+ Flow control (default is on)
25
+ """
26
+ self.ser = serial.Serial(port, baudrate=baudrate, xonxoff=xonxoff, timeout=1)
27
+ # Print serial port settings
28
+ print("Serial Port Settings:")
29
+ print("Port:", self.ser.port)
30
+ print("Baudrate:", self.ser.baudrate)
31
+ print("Byte size:", self.ser.bytesize)
32
+ print("Parity:", self.ser.parity)
33
+ print("Stop bits:", self.ser.stopbits)
34
+ print("Timeout:", self.ser.timeout)
35
+ print("Xon/Xoff:", self.ser.xonxoff)
36
+ print("Rts/cts:", self.ser.rtscts)
37
+ print("Dsr/dtr:", self.ser.dsrdtr)
38
+
39
+ def ping(self):
40
+ """Ping the device and return the response"""
41
+ # pdb.set_trace()
42
+ self.ser.write(b"check\n") # Send ping command
43
+ response = self.ser.readline() # Read response
44
+ return response
45
+
46
+ def close(self):
47
+ """Close serial connection"""
48
+ self.ser.close()
49
+
50
+
51
+ # Example usage
52
+ if __name__ == "__main__":
53
+ # Replace 'COM1' with the appropriate serial port on your system
54
+ port = "COM14"
55
+
56
+ # Create SerialPing object
57
+ serial_ping = SerialPing(port)
58
+
59
+ try:
60
+ # Ping the device
61
+ response = serial_ping.ping()
62
+ print("Response:", response)
63
+
64
+ finally:
65
+ # Close serial connection
66
+ serial_ping.close()
@@ -0,0 +1,3 @@
1
+ # Performing calibration
2
+
3
+ TODO: Write these instructions after merging the calibration and python resources.
File without changes
@@ -0,0 +1,78 @@
1
+ import numpy as np
2
+ from sklearn import linear_model
3
+ from sklearn.metrics import (
4
+ mean_absolute_error,
5
+ mean_squared_error,
6
+ r2_score,
7
+ mean_absolute_percentage_error,
8
+ )
9
+ from scipy.stats import norm
10
+
11
+
12
+ def linear_regression(meas: list, actual: list):
13
+ """Performs linear regression between measured and actual values
14
+
15
+ Args:
16
+ meas: Measure values
17
+ actual: Ground truth values
18
+
19
+ Returns:
20
+ Linear regression model
21
+ """
22
+
23
+ model = linear_model.LinearRegression()
24
+ model.fit(meas, actual)
25
+
26
+ return model
27
+
28
+
29
+ def print_eval(pred: list, actual: list):
30
+ """Prints various evaluation parameters of the model
31
+
32
+ The following metrics are used:
33
+ - Mean absolute error
34
+ - Root mean square error
35
+ - R2 score
36
+ - Mean absolute percentage error
37
+
38
+ Args:
39
+ pred: Predicted values
40
+ actual: Actual values
41
+ """
42
+ mae = mean_absolute_error(actual, pred)
43
+ print(f"Mean absolute error: {mae:.4f}")
44
+
45
+ rmse = np.sqrt(mean_squared_error(actual, pred))
46
+ print(f"Root mean square error: {rmse:.4f}")
47
+
48
+ r2 = r2_score(actual, pred)
49
+ print(f"R-squared: {r2:.4f}")
50
+
51
+ mape = mean_absolute_percentage_error(actual, pred)
52
+ print(f"Mean absolute percentage error: {mape:.4f}")
53
+
54
+
55
+ def print_coef(model):
56
+ """Print coefficients of a model
57
+
58
+ Args:
59
+ model: Linear model
60
+ """
61
+
62
+ slope = model.coef_
63
+ inter = model.intercept_
64
+
65
+ print(f"Slope: {slope}")
66
+ print(f"Intercept: {inter}")
67
+
68
+
69
+ def print_norm(residuals: list):
70
+ """Print mean offset and standard deviation
71
+
72
+ Args:
73
+ residuals: List of residuals
74
+ """
75
+
76
+ mu, std = norm.fit(residuals)
77
+ print(f"mu = {mu}")
78
+ print(f"std = {std}")
@@ -0,0 +1,83 @@
1
+ import matplotlib.pyplot as plt
2
+ from scipy.stats import norm
3
+ import numpy as np
4
+
5
+
6
+ def plot_measurements(actual: list, meas: list, title: str = "", block: bool = False):
7
+ """Plot actual values vs measured values
8
+
9
+ Args:
10
+ actual: Actual values
11
+ meas: Measured values
12
+ title: Suffix of plot title
13
+ block: Wait for plot to close
14
+ """
15
+
16
+ fig, ax = plt.subplots()
17
+ ax.scatter(actual, meas, s=3)
18
+ ax.set_xlabel("Actual")
19
+ ax.set_ylabel("Measured")
20
+ ax.set_title(f"Measurements: {title}")
21
+ plt.show(block=block)
22
+
23
+
24
+ def plot_calib(raw: list, pred: list, title: str = "", block: bool = False):
25
+ """Plot linear relationship between raw measured and calibrated measured
26
+
27
+ Args:
28
+ raw: Uncalibrated measurements
29
+ pred: Predicted voltages
30
+ title: Suffix of plot title
31
+ block: Wait for plot to close
32
+ """
33
+
34
+ fig, ax = plt.subplots()
35
+ ax.scatter(raw, pred, s=3)
36
+ ax.set_xlabel("Raw measurements")
37
+ ax.set_ylabel("Predicted measurements")
38
+ ax.set_title(f"Calibration: {title}")
39
+ plt.show(block=block)
40
+
41
+
42
+ def plot_residuals(pred: list, residuals: list, title: str = "", block: bool = False):
43
+ """Plot residuals vs predicted measurements
44
+
45
+ Residuals is the difference between predicted values and actual values.
46
+
47
+ Args:
48
+ pred: Predicted measurements
49
+ residuals: List of residuals
50
+ title: Suffix of plot title
51
+ block: Wait for plot to close
52
+ """
53
+
54
+ fig, ax = plt.subplots()
55
+ ax.scatter(pred, residuals)
56
+ ax.axhline(y=0, color="r", linestyle="--")
57
+ ax.set_xlabel("Predicted measurement")
58
+ ax.set_ylabel("Residuals (pred - actual)")
59
+ ax.set_title(f"Residuals: {title}")
60
+ ax.legend()
61
+ plt.show(block=block)
62
+
63
+
64
+ def plot_residuals_hist(residuals: list, title: str = "", block: bool = False):
65
+ """Plot a histogram of residual error
66
+
67
+ Args:
68
+ residuals: Residuals
69
+ title: Suffix of plot title
70
+ block: Wait for plot to close
71
+ """
72
+
73
+ mu, std = norm.fit(residuals)
74
+ normdist_x = np.linspace(mu - 3 * std, mu + 3 * std, 100)
75
+ normdist_y = norm.pdf(normdist_x, mu, std)
76
+
77
+ fig, ax = plt.subplots()
78
+ ax.hist(residuals, bins=30, edgecolor="black")
79
+ ax.plot(normdist_x, normdist_y, color="r")
80
+ ax.set_xlabel("Residuals")
81
+ ax.set_ylabel("Frequency")
82
+ ax.set_title(f"Histogram of Residuals: {title}")
83
+ plt.show(block=block)