コンテンツにスキップ
これは開発版のドキュメントである. 内容は次のリリースまでに変更される可能性がある. 最新のリリース版は 0.9.x を参照.

group

src

振動子毎に, どのパターンの emission を出力するかを選ぶ. 振動子の振り分けは TransducerGroups でキー (enum など) を割り当てて決める. どのキーも割り当てられていない振動子は無出力になる.

合成には 2 つの API がある.

  • group_compute — キー毎にキーと TransducerMask を受け取って計算し, 合成する.
  • group — 計算済みのバッファをキーから選んで合成する. 計算結果を使い回したい場合やグループ毎に並列に計算したい場合に使う.
#[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,
)?;
引数 型 説明
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,
);
引数 型 説明
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::new(&geometry, |device, tr| ...) がデバイスと振動子インデックスからキー (None = どのグループにも属さない) を返し, 振動子毎のキーを保持する. キーは Rust では Copy + Eq な型, C# では値型 (struct), Python ではハッシュ可能な値. mask(key) でキー key の振動子だけを有効にした Holo 用の TransducerMaskを取得できる.

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,
)?;