これは開発版のドキュメントである. 内容は次のリリースまでに変更される可能性がある. 最新のリリース版は 0.9.x を参照.
group
src振動子毎に, どのパターンの emission を出力するかを選ぶ.
振動子の振り分けは TransducerGroups でキー (enum など) を割り当てて決める. どのキーも割り当てられていない振動子は無出力になる.
合成には 2 つの API がある.
group_compute— キー毎にキーとTransducerMaskを受け取って計算し, 合成する.group— 計算済みのバッファをキーから選んで合成する. 計算結果を使い回したい場合やグループ毎に並列に計算したい場合に使う.
group_compute
Section titled “group_compute”#[derive(Clone, Copy, PartialEq, Eq)]enum Side { Left, Right,}
group_compute( &geometry, &groups, |side, mask, phases, intensities| match side { Side::Left => gspat( &NalgebraBackend, &geometry, &foci, wavelength, &GspatOption { mask, ..Default::default() }, phases, intensities, ), Side::Right => { focus(&geometry, target, wavelength, phases); Ok(()) } }, &mut phases, &mut intensities,)?;class Side(Enum): LEFT = auto() RIGHT = auto()
def compute(side: Side, mask: TransducerMask, phases: PhaseBuffer, intensities: IntensityBuffer) -> None: if side is Side.LEFT: gspat(geometry, foci, wavelength, GspatOption(mask=mask), phases, intensities) else: focus(geometry, target, wavelength, phases)
group_compute(geometry, groups, compute, phases, intensities)internal enum Side{ Left, Right,}
Pattern.GroupCompute(geometry, groups, (side, mask, p, i) =>{ if (side == Side.Left) { Holo.Gspat(geometry, foci, wavelength, new GspatOption { Mask = mask }, p, i); } else { Pattern.Focus(geometry, target, wavelength, p); }}, phases, intensities);| 引数 | 型 | 説明 |
|---|---|---|
geometry |
&Geometry |
ジオメトリ |
groups |
&TransducerGroups<K> |
振動子毎のキー |
compute |
FnMut(K, TransducerMask, &mut [Vec<Phase>], &mut [Vec<Intensity>]) -> Result<(), E> |
キーとマスクを受け取り, 作業バッファ (位相・振幅) へ計算する |
phases |
&mut [Vec<Phase>] |
位相の出力バッファ |
intensities |
&mut [Vec<Intensity>] |
振幅の出力バッファ |
compute はキー毎に 1 回 (キーの初出順) 呼ばれ, 計算結果のうちそのキーの振動子分だけが phases / intensities に書き込まれる.
作業バッファはキー毎に位相 0・最大振幅で初期化される.
どのキーにも割り当てられていない振動子は無出力 (位相 0・振幅 Intensity::MIN) になる.
#[derive(Clone, Copy, PartialEq, Eq)]enum Side { Left, Right,}
let groups = TransducerGroups::new(&geometry, |device, tr| { Some(if device.position(tr).x < center.x { Side::Left } else { Side::Right })});group( &geometry, &groups, |side| match side { Side::Left => &left, Side::Right => &right, }, Phase::ZERO, &mut dst,);class Side(Enum): LEFT = auto() RIGHT = auto()
groups = TransducerGroups( geometry, lambda device, tr: Side.LEFT if device.position(tr)[0] < center[0] else Side.RIGHT,)group(geometry, groups, {Side.LEFT: left, Side.RIGHT: right}, dst)internal enum Side{ Left, Right,}
var groups = new TransducerGroups<Side>(geometry, (device, tr) => device.Position(tr).X < center.X ? Side.Left : Side.Right);Pattern.Group(geometry, groups, side => side == Side.Left ? left : right, dst);| 引数 | 型 | 説明 |
|---|---|---|
geometry |
&Geometry |
ジオメトリ |
groups |
&TransducerGroups<K> |
振動子毎のキー |
source |
FnMut(K) -> impl AsRef<[Vec<T>]> |
キーから出力元バッファを返す |
null |
T |
どのキーにも属さない振動子に書く値 |
dst |
&mut [Vec<T>] |
出力バッファ |
T は Phase または Intensity で, 位相・振幅それぞれのバッファに対して呼ぶ.
Python / C# では null 引数はなく, dst が位相バッファなら位相 0, 振幅バッファなら Intensity.MIN (無出力) になる.
TransducerGroups
Section titled “TransducerGroups”TransducerGroups::new(&geometry, |device, tr| ...) がデバイスと振動子インデックスからキー (None = どのグループにも属さない) を返し, 振動子毎のキーを保持する.
キーは Rust では Copy + Eq な型, C# では値型 (struct), Python ではハッシュ可能な値.
mask(key) でキー key の振動子だけを有効にした Holo 用の TransducerMaskを取得できる.
Example
Section titled “Example”use anyhow::Result;
use autd3_rs::geometry::{Autd3, Geometry, TransducerGroups, offset};use autd3_rs::units::{m, mm, s};use autd3_rs_pattern::{focus, group_compute, wavelength};use autd3_rs_pattern_holo::{AmplitudeTarget, GspatOption, NalgebraBackend, Pa, gspat};
#[derive(Clone, Copy, PartialEq, Eq)]enum Side { Left, Right,}
let geometry = Geometry::new(vec![Autd3::default()]);let wavelength = wavelength(340.0 * m / s);let center = geometry.center();
let groups = TransducerGroups::new(&geometry, |device, tr| { Some(if device.position(tr).x < center.x { Side::Left } else { Side::Right })});
let foci = [ AmplitudeTarget { point: center + offset(-50.0 * mm, 0.0 * mm, 150.0 * mm), amplitude: 5e3 * Pa, }, AmplitudeTarget { point: center + offset(-20.0 * mm, 0.0 * mm, 150.0 * mm), amplitude: 5e3 * Pa, },];
let mut phases = geometry.phase_buffer();let mut intensities = geometry.intensity_buffer();group_compute( &geometry, &groups, |side, mask, phases, intensities| match side { Side::Left => gspat( &NalgebraBackend, &geometry, &foci, wavelength, &GspatOption { mask, ..Default::default() }, phases, intensities, ), Side::Right => { focus( &geometry, center + offset(40.0 * mm, 0.0 * mm, 150.0 * mm), wavelength, phases, ); Ok(()) } }, &mut phases, &mut intensities,)?;from enum import Enum, auto
import numpy as np
from autd3.geometry import Autd3, Geometryfrom autd3.units import m, sfrom autd3_pattern import ( IntensityBuffer, PhaseBuffer, TransducerGroups, TransducerMask, focus, group_compute,)from autd3_pattern import wavelength as calc_wavelengthfrom autd3_pattern_holo import AmplitudeTarget, GspatOption, Pa, gspat
class Side(Enum): LEFT = auto() RIGHT = auto()
geometry = Geometry([Autd3([0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0])])wavelength = calc_wavelength(340 * m / s)center = geometry.center()
groups = TransducerGroups( geometry, lambda device, tr: Side.LEFT if device.position(tr)[0] < center[0] else Side.RIGHT,)
foci = [ AmplitudeTarget(point=center + np.array([-50.0, 0.0, 150.0]), amplitude=5e3 * Pa), AmplitudeTarget(point=center + np.array([-20.0, 0.0, 150.0]), amplitude=5e3 * Pa),]
def compute(side: Side, mask: TransducerMask, phases: PhaseBuffer, intensities: IntensityBuffer) -> None: if side is Side.LEFT: gspat(geometry, foci, wavelength, GspatOption(mask=mask), phases, intensities) else: focus(geometry, center + np.array([40.0, 0.0, 150.0]), wavelength, phases)
phases = geometry.phase_buffer()intensities = geometry.intensity_buffer()group_compute(geometry, groups, compute, phases, intensities)using System.Numerics;using AUTD3;using AUTD3.Holo;using static AUTD3.Units;using static AUTD3.Holo.HoloUnits;
internal enum Side{ Left, Right,}
var geometry = new Geometry(new[] { new Autd3(Vector3.Zero) });var wavelength = Pattern.Wavelength(340.0f * m / s);var center = geometry.Center;
var groups = new TransducerGroups<Side>(geometry, (device, tr) => device.Position(tr).X < center.X ? Side.Left : Side.Right);
var foci = new[]{ new AmplitudeTarget(center + new Vector3(-50.0f, 0.0f, 150.0f), 5e3f * Pa), new AmplitudeTarget(center + new Vector3(-20.0f, 0.0f, 150.0f), 5e3f * Pa),};
var phases = geometry.PhaseBuffer();var intensities = geometry.IntensityBuffer();Pattern.GroupCompute(geometry, groups, (side, mask, p, i) =>{ if (side == Side.Left) { Holo.Gspat(geometry, foci, wavelength, new GspatOption { Mask = mask }, p, i); } else { Pattern.Focus(geometry, center + new Vector3(40.0f, 0.0f, 150.0f), wavelength, p); }}, phases, intensities);