feat: still update basic concepts
This commit is contained in:
275
legacy/common.py
275
legacy/common.py
@@ -1,14 +1,15 @@
|
||||
import enum
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
class LcrConnException(Exception):
|
||||
"""The exception thrown by LCR Connector"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class DeviceKind(enum.IntEnum):
|
||||
"""The kind of device"""
|
||||
|
||||
|
||||
RESISTOR = enum.auto()
|
||||
"""Resistor device"""
|
||||
CAPACITOR = enum.auto()
|
||||
@@ -19,16 +20,16 @@ class DeviceKind(enum.IntEnum):
|
||||
|
||||
class JointKind(enum.IntEnum):
|
||||
"""The joint type between 2 devices"""
|
||||
|
||||
|
||||
SERIES = enum.auto()
|
||||
"""Series connection"""
|
||||
PARALLEL = enum.auto()
|
||||
"""Parallel connection"""
|
||||
|
||||
def flip(self) -> 'JointKind':
|
||||
|
||||
def flip(self) -> "JointKind":
|
||||
"""
|
||||
Flip the joint kind
|
||||
|
||||
|
||||
Flip the joint kind from series to parallel or vice versa
|
||||
|
||||
:return: The flipped joint kind
|
||||
@@ -40,16 +41,19 @@ class JointKind(enum.IntEnum):
|
||||
return JointKind.SERIES
|
||||
|
||||
|
||||
@dataclass
|
||||
class CircuitJoint:
|
||||
class SubCircuit:
|
||||
"""The part of circuit composed of two devices and the joint kind"""
|
||||
|
||||
device_value: float
|
||||
__device_value: float
|
||||
"""The value of the device"""
|
||||
joint_kind: JointKind
|
||||
__joint_kind: JointKind
|
||||
"""The joint kind between this device and the next device"""
|
||||
|
||||
def compute(self, value: float, device_kind: DeviceKind) -> float:
|
||||
|
||||
def __init__(self, device_value: float, joint_kind: JointKind):
|
||||
self.__device_value = device_value
|
||||
self.__joint_kind = joint_kind
|
||||
|
||||
def compute(self, value: float, device_kind: DeviceKind) -> float:
|
||||
"""
|
||||
Compute the joint value
|
||||
|
||||
@@ -57,39 +61,175 @@ class CircuitJoint:
|
||||
:param device_kind: The kind of the device
|
||||
:return: The joint value computed
|
||||
"""
|
||||
if self.device_value <= 0 or value <= 0:
|
||||
if self.__device_value <= 0 or value <= 0:
|
||||
raise LcrConnException("Device value must be greater than 0")
|
||||
|
||||
|
||||
# We perform series connect for: series resistor, series inductor and parallel capacitor.
|
||||
# We perform parallel connect for: parallel resistor, parallel inductor and series capacitor.
|
||||
joint_kind = self.joint_kind
|
||||
joint_kind = self.__joint_kind
|
||||
if device_kind == DeviceKind.CAPACITOR:
|
||||
joint_kind = joint_kind.flip()
|
||||
|
||||
match joint_kind:
|
||||
case JointKind.SERIES:
|
||||
return self.device_value + value
|
||||
return self.__device_value + value
|
||||
case JointKind.PARALLEL:
|
||||
return (self.device_value * value) / (self.device_value + value)
|
||||
return (self.__device_value * value) / (self.__device_value + value)
|
||||
|
||||
def get_device_value(self) -> float:
|
||||
"""
|
||||
Get the device value
|
||||
|
||||
:return: The device value
|
||||
"""
|
||||
return self.__device_value
|
||||
|
||||
def get_joint_kind(self) -> JointKind:
|
||||
"""
|
||||
Get the joint kind
|
||||
|
||||
:return: The joint kind
|
||||
"""
|
||||
return self.__joint_kind
|
||||
|
||||
|
||||
class CircuitDeviceCount(enum.IntEnum):
|
||||
"""The number of devices in the circuit"""
|
||||
|
||||
ONE = enum.auto()
|
||||
"""One device"""
|
||||
TWO = enum.auto()
|
||||
"""Two devices"""
|
||||
THREE = enum.auto()
|
||||
"""Three devices"""
|
||||
|
||||
def to_device_count(self) -> int:
|
||||
match self:
|
||||
case CircuitDeviceCount.ONE:
|
||||
return 1
|
||||
case CircuitDeviceCount.TWO:
|
||||
return 2
|
||||
case CircuitDeviceCount.THREE:
|
||||
return 3
|
||||
|
||||
|
||||
class Circuit:
|
||||
"""The circuit composed of multiple joints"""
|
||||
|
||||
device_value: float
|
||||
__first_device_value: float
|
||||
"""The value of the first device"""
|
||||
joints: list[CircuitJoint]
|
||||
"""The joints between devices"""
|
||||
__second_device_subckt: SubCircuit | None
|
||||
"""The second device and its joint property"""
|
||||
__third_device_subckt: SubCircuit | None
|
||||
"""The third device and its joint property"""
|
||||
|
||||
def __init__(self, value: float):
|
||||
self.device_value = value
|
||||
self.joints = []
|
||||
def __init__(
|
||||
self,
|
||||
first_device_value: float,
|
||||
second_device_subckt: SubCircuit | None,
|
||||
third_device_subckt: SubCircuit | None,
|
||||
):
|
||||
"""
|
||||
Initialize the circuit
|
||||
|
||||
def add_joint(self, joint: CircuitJoint):
|
||||
self.joints.append(joint)
|
||||
:param first_device_value: The value of the first device
|
||||
:param second_device_subckt: The second device and its joint property
|
||||
:param third_device_subckt: The third device and its joint property
|
||||
"""
|
||||
if second_device_subckt is None and third_device_subckt is not None:
|
||||
raise LcrConnException("Third device cannot exist without second device")
|
||||
|
||||
def len_devices(self) -> int:
|
||||
return len(self.joints) + 1
|
||||
self.__first_device_value = first_device_value
|
||||
self.__second_device_subckt = second_device_subckt
|
||||
self.__third_device_subckt = third_device_subckt
|
||||
|
||||
@staticmethod
|
||||
def from_one_device(device1_value: float) -> "Circuit":
|
||||
return Circuit(device1_value, None, None)
|
||||
|
||||
@staticmethod
|
||||
def from_two_devices(
|
||||
device1_value: float, device2_value: float, device2_joint: JointKind
|
||||
) -> "Circuit":
|
||||
return Circuit(device1_value, SubCircuit(device2_value, device2_joint), None)
|
||||
|
||||
@staticmethod
|
||||
def from_three_devices(
|
||||
device1_value: float,
|
||||
device2_value: float,
|
||||
device2_joint: JointKind,
|
||||
device3_value: float,
|
||||
device3_joint: JointKind,
|
||||
) -> "Circuit":
|
||||
return Circuit(
|
||||
device1_value,
|
||||
SubCircuit(device2_value, device2_joint),
|
||||
SubCircuit(device3_value, device3_joint),
|
||||
)
|
||||
|
||||
def get_device_count(self) -> CircuitDeviceCount:
|
||||
if self.__third_device_subckt is not None:
|
||||
return CircuitDeviceCount.THREE
|
||||
elif self.__second_device_subckt is not None:
|
||||
return CircuitDeviceCount.TWO
|
||||
else:
|
||||
return CircuitDeviceCount.ONE
|
||||
|
||||
def get_first_device_value(self) -> float:
|
||||
"""
|
||||
Get the value of the first device
|
||||
|
||||
:return: The value of the first device
|
||||
"""
|
||||
return self.__first_device_value
|
||||
|
||||
def get_second_device_joint(self) -> JointKind:
|
||||
"""
|
||||
Get the joint kind of the second device
|
||||
|
||||
:return: The joint kind of the second device
|
||||
:raises LcrConnException: If there is no second device
|
||||
"""
|
||||
if self.__second_device_subckt is not None:
|
||||
return self.__second_device_subckt.get_joint_kind()
|
||||
else:
|
||||
raise LcrConnException("No second device")
|
||||
|
||||
def get_second_device_value(self) -> float:
|
||||
"""
|
||||
Get the value of the second device
|
||||
|
||||
:return: The value of the second device
|
||||
:raises LcrConnException: If there is no second device
|
||||
"""
|
||||
if self.__second_device_subckt is not None:
|
||||
return self.__second_device_subckt.get_device_value()
|
||||
else:
|
||||
raise LcrConnException("No second device")
|
||||
|
||||
def get_third_device_joint(self) -> JointKind:
|
||||
"""
|
||||
Get the joint kind of the third device
|
||||
|
||||
:return: The joint kind of the third device
|
||||
:raises LcrConnException: If there is no third device
|
||||
"""
|
||||
if self.__third_device_subckt is not None:
|
||||
return self.__third_device_subckt.get_joint_kind()
|
||||
else:
|
||||
raise LcrConnException("No third device")
|
||||
|
||||
def get_third_device_value(self) -> float:
|
||||
"""
|
||||
Get the value of the third device
|
||||
|
||||
:return: The value of the third device
|
||||
:raises LcrConnException: If there is no third device
|
||||
"""
|
||||
if self.__third_device_subckt is not None:
|
||||
return self.__third_device_subckt.get_device_value()
|
||||
else:
|
||||
raise LcrConnException("No third device")
|
||||
|
||||
def compute(self, device_kind: DeviceKind) -> float:
|
||||
"""
|
||||
@@ -98,77 +238,14 @@ class Circuit:
|
||||
:param device_kind: The kind of the device
|
||||
:return: The circuit value
|
||||
"""
|
||||
if self.device_value <= 0:
|
||||
if self.__first_device_value <= 0:
|
||||
raise LcrConnException("Device value must be greater than 0")
|
||||
|
||||
value = self.device_value
|
||||
for joint in self.joints:
|
||||
value = joint.compute(value, device_kind)
|
||||
|
||||
value = self.__first_device_value
|
||||
if self.__second_device_subckt is None:
|
||||
return value
|
||||
value = self.__second_device_subckt.compute(value, device_kind)
|
||||
if self.__third_device_subckt is None:
|
||||
return value
|
||||
value = self.__third_device_subckt.compute(value, device_kind)
|
||||
return value
|
||||
|
||||
|
||||
def from_human_readable_value(strl: str) -> float:
|
||||
"""
|
||||
Convert human readable value to float
|
||||
|
||||
:param strl: The human readable value
|
||||
:return: The parsed float value
|
||||
:raises ValueError: If the input string is not a valid number
|
||||
"""
|
||||
strl = strl.strip()
|
||||
|
||||
if strl.endswith('n'):
|
||||
return float(strl[0:-1]) * 1e-12
|
||||
if strl.endswith('p'):
|
||||
return float(strl[0:-1]) * 1e-9
|
||||
if strl.endswith('u'):
|
||||
return float(strl[0:-1]) * 1e-6
|
||||
if strl.endswith('m'):
|
||||
return float(strl[0:-1]) * 1e-3
|
||||
if strl.endswith('k'):
|
||||
return float(strl[0:-1]) * 1e3
|
||||
if strl.endswith('M'):
|
||||
return float(strl[0:-1]) * 1e6
|
||||
if strl.endswith('G'):
|
||||
return float(strl[0:-1]) * 1e9
|
||||
return float(strl)
|
||||
|
||||
|
||||
|
||||
def to_human_readable_value(v: float) -> str:
|
||||
"""
|
||||
Convert float value to human readable value
|
||||
|
||||
:param value: The float value
|
||||
:return: The human readable value
|
||||
"""
|
||||
if v / 1e-12 < 1e3:
|
||||
return "{:e} n".format(v / 1e-12)
|
||||
if v / 1e-9 < 1e3:
|
||||
return "{:.4f} p".format(v / 1e-9)
|
||||
if v / 1e-6 < 1e3:
|
||||
return "{:.4f} u".format(v / 1e-6)
|
||||
if v / 1e-3 < 1e3:
|
||||
return "{:.4f} m".format(v / 1e-3)
|
||||
if v < 1e3:
|
||||
return "{:.4f}".format(v)
|
||||
if v / 1e3 < 1e3:
|
||||
return "{:.4f} k".format(v / 1e3)
|
||||
if v / 1e6 < 1e3:
|
||||
return "{:.4f} M".format(v / 1e6)
|
||||
if v / 1e9 < 1e3:
|
||||
return "{:.4f} G".format(v / 1e9)
|
||||
|
||||
return "{:e}".format(v)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user