Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion db_dvc.dvc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
outs:
- md5: acf26d7ed156404534fac29ded76e2fb.dir
- md5: 9ff784fb0970065f690726c0041969d4.dir
nfiles: 797
hash: md5
path: db_dvc
3 changes: 2 additions & 1 deletion notebooks/test_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

# -

pulse = openlifu.Pulse(frequency=500e3, amplitude=1, duration=2e-5)
pulse = openlifu.Pulse(frequency=500e3, duration=2e-5)
pt = openlifu.Point(position=(0,0,30), units="mm")
sequence = openlifu.Sequence(
pulse_interval=0.1,
Expand All @@ -36,6 +36,7 @@
delays = np.zeros((1,64)),
apodizations = np.ones((1,64)),
pulse = pulse,
voltage=1.0,
sequence = sequence,
target=pt,
foci=[pt],
Expand Down
2 changes: 1 addition & 1 deletion notebooks/test_solution_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

# +
f0 = 400e3
pulse = Pulse(frequency=f0, duration=10/f0, amplitude=1)
pulse = Pulse(frequency=f0, duration=10/f0)
sequence = Sequence(pulse_interval=0.1, pulse_count=9, pulse_train_interval=0, pulse_train_count=1)
focal_pattern = focal_patterns.SinglePoint(target_pressure=1.2e6)
focal_pattern = focal_patterns.Wheel(center=False, spoke_radius=5, num_spokes=3, target_pressure=1.2e6)
Expand Down
3 changes: 2 additions & 1 deletion notebooks/test_thermal_stress.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def log_temperature():
logger.error("Failed to set High Voltage.")
sys.exit(1)

pulse = Pulse(frequency=frequency_kHz*1e3, amplitude=voltage, duration=duration_msec*1e-3)
pulse = Pulse(frequency=frequency_kHz*1e3, duration=duration_msec*1e-3)

delays = np.zeros(numelements) # Initialize delays to zero
apodizations = np.ones(numelements) # Initialize apodizations to ones
Expand All @@ -266,6 +266,7 @@ def log_temperature():
delays = delays,
apodizations = apodizations,
pulse = pulse,
voltage=voltage,
sequence = sequence
)

Expand Down
3 changes: 2 additions & 1 deletion notebooks/test_transmitter2.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
voltage = 12.0
duration = 2e-5

pulse = Pulse(frequency=frequency, amplitude=voltage, duration=duration)
pulse = Pulse(frequency=frequency, duration=duration)
pt = Point(position=(xInput,yInput,zInput), units="mm")
sequence = Sequence(
pulse_interval=0.1,
Expand All @@ -68,6 +68,7 @@
delays = np.zeros((1,64)),
apodizations = np.ones((1,64)),
pulse = pulse,
voltage=voltage,
sequence = sequence
)

Expand Down
3 changes: 2 additions & 1 deletion notebooks/test_updated_if.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
voltage = 12.0
duration = 2e-5

pulse = Pulse(frequency=frequency, amplitude=voltage, duration=duration)
pulse = Pulse(frequency=frequency, duration=duration)
pt = Point(position=(xInput,yInput,zInput), units="mm")
sequence = Sequence(
pulse_interval=0.1,
Expand All @@ -126,6 +126,7 @@
delays = np.zeros((1,64)),
apodizations = np.ones((1,64)),
pulse = pulse,
voltage=voltage,
sequence = sequence
)

Expand Down
3 changes: 2 additions & 1 deletion notebooks/test_watertank.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ def log_temperature():
logger.error("Failed to set High Voltage.")
sys.exit(1)

pulse = Pulse(frequency=frequency_kHz*1e3, amplitude=voltage, duration=duration_msec*1e-3)
pulse = Pulse(frequency=frequency_kHz*1e3, duration=duration_msec*1e-3)
pt = Point(position=(xInput,yInput,zInput), units="mm")
arr = Transducer.from_file(R".\notebooks\pinmap.json")
pin_order = np.argsort([el.pin for el in arr.elements])
Expand Down Expand Up @@ -300,6 +300,7 @@ def log_temperature():
delays = delays,
apodizations = apodizations,
pulse = pulse,
voltage=voltage,
sequence = sequence
)

Expand Down
6 changes: 3 additions & 3 deletions src/openlifu/bf/pulse.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class Pulse(DictMixin):
frequency: Annotated[float, OpenLIFUFieldData("Frequency (Hz)", "Frequency of the pulse in Hz")] = 1.0 # Hz
"""Frequency of the pulse in Hz"""

amplitude: Annotated[float, OpenLIFUFieldData("Amplitude (V)", "Amplitude of the pulse in volts")] = 1.0 # V
"""Amplitude of the pulse in volts"""
amplitude: Annotated[float, OpenLIFUFieldData("Amplitude (AU)", "Amplitude of the pulse (between 0 and 1). ")] = 1.0 # AU
"""Amplitude of the pulse in arbitrary units (AU) between 0 and 1"""

duration: Annotated[float, OpenLIFUFieldData("Duration (s)", "Duration of the pulse in s")] = 1.0 # s
"""Duration of the pulse in s"""
Expand Down Expand Up @@ -50,6 +50,6 @@ def get_table(self):
:returns: Pandas DataFrame of the pulse parameters
"""
records = [{"Name": "Frequency", "Value": self.frequency, "Unit": "Hz"},
{"Name": "Amplitude", "Value": self.amplitude, "Unit": "Pa"},
{"Name": "Amplitude", "Value": self.amplitude, "Unit": "AU"},
{"Name": "Duration", "Value": self.duration, "Unit": "s"}]
return pd.DataFrame.from_records(records)
3 changes: 1 addition & 2 deletions src/openlifu/io/LIFUInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,7 @@ def set_solution(self,
else:
solution_name = "Solution"

voltage = solution['pulse']['amplitude']

voltage = solution['voltage']
logger.info("Loading %s...", solution_name)
# Convert solution data and send to the device
self.txdevice.set_solution(
Expand Down
2 changes: 1 addition & 1 deletion src/openlifu/io/LIFUTXDevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ def set_solution(self,
if n > 1:
raise NotImplementedError("Multiple foci not supported yet")
for profile in range(n):
duty_cycle=DEFAULT_PATTERN_DUTY_CYCLE * max(apodizations[profile,:])
duty_cycle=DEFAULT_PATTERN_DUTY_CYCLE * max(apodizations[profile,:]) * pulse["amplitude"]
pulse_profile = Tx7332PulseProfile(
profile=profile+1,
frequency=pulse["frequency"],
Expand Down
4 changes: 3 additions & 1 deletion src/openlifu/plan/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def calc_solution(
analysis_options: SolutionAnalysisOptions | None = None,
on_pulse_mismatch: OnPulseMismatchAction = OnPulseMismatchAction.ERROR,
use_gpu: bool | None = None,
voltage: float = 1.0
) -> Tuple[Solution, xa.DataArray, SolutionAnalysis]:
"""Calculate the solution and aggregated k-wave simulation outputs.

Expand Down Expand Up @@ -286,7 +287,7 @@ def calc_solution(
dt=sim_options.dt,
t_end=sim_options.t_end,
cfl=sim_options.cfl,
amplitude = self.pulse.amplitude,
amplitude = self.pulse.amplitude * voltage,
gpu = use_gpu
)
delays_to_stack.append(delays)
Expand All @@ -313,6 +314,7 @@ def calc_solution(
delays=np.stack(delays_to_stack, axis=0),
apodizations=np.stack(apodizations_to_stack, axis=0),
pulse=self.pulse,
voltage=voltage,
sequence=self.sequence,
foci=foci,
target=target,
Expand Down
20 changes: 12 additions & 8 deletions src/openlifu/plan/solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class Solution:
pulse: Annotated[Pulse, OpenLIFUFieldData("Pulse", "Pulse to send to the transducer when running sonication")] = field(default_factory=Pulse)
"""Pulse to send to the transducer when running sonication"""

voltage: Annotated[float, OpenLIFUFieldData("Voltage", "Voltage to use when running sonication. This is the voltage that will be set on the HV power supply.")] = 1.0
"""Voltage to use when running sonication. This is the voltage that will be set on the HV power supply."""

sequence: Annotated[Sequence, OpenLIFUFieldData("Pulse sequence", "Pulse sequence to use when running sonication")] = field(default_factory=Sequence)
"""Pulse sequence to use when running sonication"""

Expand Down Expand Up @@ -120,7 +123,7 @@ def analyze(self,

dt = 1 / (self.pulse.frequency * 20)
t = self.pulse.calc_time(dt)
input_signal = self.pulse.calc_pulse(t)
input_signal_V = self.pulse.calc_pulse(t) * self.voltage

pnp_MPa_all = rescale_data_arr(rescale_coords(self.simulation_result['p_min'], options.distance_units),"MPa")
ipa_Wcm2_all = rescale_data_arr(rescale_coords(self.simulation_result['intensity'], options.distance_units), "W/cm^2")
Expand Down Expand Up @@ -151,13 +154,13 @@ def analyze(self,
apodization = self.apodizations[focus_index]
origin = transducer.get_effective_origin(apodizations=apodization, units=options.distance_units)

output_signal = []
output_signal = np.zeros((transducer.numelements(), len(input_signal)))
output_signal_Pa = []
output_signal_Pa = np.zeros((transducer.numelements(), len(input_signal_V)))
for i in range(transducer.numelements()):
apod_signal = input_signal * self.apodizations[focus_index, i]
output_signal[i] = transducer.elements[i].calc_output(apod_signal, dt)
apod_signal_V = input_signal_V * self.apodizations[focus_index, i]
output_signal_Pa[i] = transducer.elements[i].calc_output(apod_signal_V, dt)

p0_Pa = np.max(output_signal, axis=1)
p0_Pa = np.max(output_signal_Pa, axis=1)

# get focus region masks (for mainlobe, sidelobe and beamwidth)
# mainlobe_mask = mask_focus(
Expand Down Expand Up @@ -222,6 +225,7 @@ def analyze(self,
solution_analysis.p0_MPa += [1e-6*np.max(p0_Pa)]
solution_analysis.TIC = np.mean(TIC)
solution_analysis.power_W = np.mean(power_W)
solution_analysis.voltage_V = self.voltage
solution_analysis.MI = (np.max(solution_analysis.mainlobe_pnp_MPa)/np.sqrt(self.pulse.frequency*1e-6))
solution_analysis.global_ispta_mWcm2 = float((ita_mWcm2*z_mask).max())
solution_analysis.param_constraints = param_constraints
Expand Down Expand Up @@ -251,7 +255,7 @@ def compute_scaling_factors(
focal_pattern_pressure_in_MPa = focal_pattern.target_pressure * getunitconversion(focal_pattern.units, "MPa")
scaling_factors[i] = focal_pattern_pressure_in_MPa / analysis.mainlobe_pnp_MPa[i]
max_scaling = np.max(scaling_factors)
v0 = self.pulse.amplitude
v0 = self.voltage
v1 = v0 * max_scaling
apod_factors = scaling_factors / max_scaling

Expand Down Expand Up @@ -284,7 +288,7 @@ def scale(
self.simulation_result['p_max'][i].data *= scaling
self.simulation_result['intensity'][i].data *= scaling**2
self.apodizations[i] = self.apodizations[i]*apod_factors[i]
self.pulse.amplitude = v1
self.voltage = v1

def get_pulsetrain_dutycycle(self) -> float:
"""
Expand Down
4 changes: 4 additions & 0 deletions src/openlifu/plan/solution_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"global_ispta_mWcm2": [None, "0.3f", "mW/cm^2", "Global I_SPTA"],
"p0_MPa": ["max", "0.3f", "MPa", "Emitted Pressure"],
"power_W": [None, "0.3f", "W", "Emitted Power"],
"voltage_V": [None, "0.3f", "V", "Voltage"],
"TIC": [None, "0.3f", "", "TIC"],
"MI": [None, "0.3f", "", "MI"]}

Expand Down Expand Up @@ -84,6 +85,9 @@ class SolutionAnalysis(DictMixin):
power_W: Annotated[float | None, OpenLIFUFieldData("Emitted Power (W)", "Emitted power from the transducer face (W)")] = None
"""Emitted power from the transducer face (W)"""

voltage_V: Annotated[float | None, OpenLIFUFieldData("Voltage (V)", "Voltage applied to the transducer (V)")] = None
"""Voltage applied to the transducer (V)"""

MI: Annotated[float | None, OpenLIFUFieldData("Mechanical index (MI)", "Mechanical index (MI)")] = None
"""Mechanical index (MI)"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Example protocol created 30-Jan-2024 09:16:02",
"pulse": {
"frequency": 500000,
"amplitude": 1,
"amplitude": 1.0,
"duration": 2e-5,
"class": "Pulse"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@
],
"pulse": {
"frequency": 500000,
"amplitude": 2.3167290687561035,
"amplitude": 1.0,
"duration": 2e-5
},
"voltage": 2.3167290687561035,
"sequence": {
"pulse_interval": 0.1,
"pulse_count": 10,
Expand Down
3 changes: 2 additions & 1 deletion tests/test_sonication_control_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def example_solution() -> Solution:
transducer_id="example_transducer",
delays = np.zeros((1,64)),
apodizations = np.ones((1,64)),
pulse = Pulse(frequency=500e3, amplitude=1, duration=2e-5),
pulse = Pulse(frequency=500e3, duration=2e-5),
voltage=1.0,
sequence = Sequence(
pulse_interval=0.1,
pulse_count=10,
Expand Down
Loading