OSCR

Real-time volumetric imaging of cells and molecules in deep tissues with Takoyaki ultrasound.

Code ↔ Paper

9 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 9 matches
  1. [1] § Methods › Takoyaki AM/B-mode sequences ↔ Code/SetupMatrix1024_15MHz_Takoyaki_LiveImaging.m, lines 1–38 · score 0.87 · sparse random apertures, full amplitude, half amplitude, transmission aperture, receive apertures, 3.3 mm
  2. [2] § Methods › Takoyaki BURST sequence ↔ Code/SetupMatrix1024_15MHz_Takoyaki_BURST.m, lines 1–47 · score 0.85 · BURST scheme, BURST script, half cycles, transmit aperture, receive aperture, accumulated
  3. [3] § Methods › Image similarity analysis ↔ Data/Fig2/a-h/similarity_analysis.m, lines 22–73 · score 0.81 · multi scale SSIM, MS SSIM, bounding box, transformation matrices, mask, phantoms
  4. [4] § Results › The Takoyaki sequence allows efficient acquisition of 3D volumes ↔ Code/SetupMatrix1024_15MHz_Takoyaki_LiveImaging.m, lines 1–38 · score 0.80 · sparse random apertures, full amplitude, half amplitude, transmit aperture, receive apertures, complementary
  5. [5] § Results › The Takoyaki sequence allows efficient acquisition of 3D volumes ↔ Code/SetupMatrix1024_15MHz_Takoyaki_BURST.m, lines 1–47 · score 0.80 · full amplitude, half amplitude, Takoyaki BURST, transmit aperture, receive apertures, sparse
  6. [6] § Methods › Image similarity analysis ↔ Data/Fig2/a-h/similarity_analysis.m, lines 1–19 · score 0.70 · Medical Registration, transformation matrices, registered mask, phantom, axis
  7. [7] § Methods › Takoyaki AM/B-mode sequences ↔ Code/SetupMatrix1024_15MHz_Takoyaki_LiveImaging.m, lines 112–171 · score 0.61 · longer jump caused, Frustum, compensate, gap, Takoyaki, depth
  8. [8] § Methods › Contrast-to-background ratio (CBR) calculation for in vitro experiments ↔ Data/Fig2/a-h/CBR_anisotropy.m, lines 54–153 · score 0.56 · eroded masks, rectangular, interspace, box, slice, CBR
  9. [9] § Results › The Takoyaki sequence allows efficient acquisition of 3D volumes ↔ Code/SetupMatrix1024_15MHz_Takoyaki_LiveImaging.m, lines 234–302 · score 0.52 · delay laws, focused beams, translated, matrix, Takoyaki, apertures

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

MATLAB · 1,007 lines · 34 KB · no license · 4 matches

  1. %% Takoyaki live imaging script
  2. % This script scans multiple focal points simultaneously using the 1024 element 15 MHz
  3. % 2D matrix array probe from Vermon with the UTA 1024-MUX adapter on a
  4. % Vantage 256 system. All 4 banks are used for transmission. For receive apertures,
  5. % one complementary set of 4 sparse random apertures are used. The 4
  6. % receive apertures are synthesized for each transmit aperture.
  7. %
  8. % P.nCode = 3, Takoyaki AM / P.nCode = 1, Takoyaki Bmode
  9. % At the beginning, the sequence shows live imaging without saving images.
  10. % After clicking "save the images", it starts to store the images.
  11. %
  12. % To run this script, there are two required files:
  13. % computeTrans_MatrixProbeIncluded.m
  14. % saved100CompRndApod.mat
  15. %
  16. % written by Sunho Lee
  17. % Parameter settings
  18. clear;
  19. P.pathName = 'D:\Sunho\TakoyakiAM' ;
  20. P.numberImagesToSave = 2;
  21. P.startDepth_mm = 3.3;
  22. P.endDepth_mm = 10;
  23. P.Voltage = 1.6;
  24. P.numFrames = 2 ;
  25. P.numSyntheticRcvs = 4; % 4 receives for Fully-Sampled Array
  26. P.txFocus_mm = 7; % focal depth
  27. P.aperpatch = 8;
  28. P.numRays = 32 - P.aperpatch + 1; % no. of Rays (for each dimension)
  29. P.nCode = 3; % 3 = 1 full amplitude + 2 half amplitude
  30. Display_output = 20; %Display mode only: 20 gives a power of 1.0 for a linear output, 40 gives a power of 0.5 for a square root compression
  31. RcvProfile.AntiAliasCutoff = 15; % 10, 15, 20, 30
  32. %% Specify system parameters.
  33. Resource.Parameters.numTransmit = 256; % number of transmit channels.
  34. Resource.Parameters.numRcvChannels = 256; % number of receive channels.
  35. Resource.Parameters.verbose = 2; % 2: warnings and status 1: warnings 0: errors only
  36. Resource.Parameters.speedOfSound = 1540; % set speed of sound in m/sec before calling computeTrans
  37. Resource.Parameters.speedCorrectionFactor = 1.0;
  38. Resource.Parameters.fakeScanhead = 0; % allow system HW operation with nothing connected
  39. Resource.Parameters.simulateMode = 0;
  40. % Resource.Parameters.simulateMode = 1 forces simulate mode, even if hardware is present.
  41. % Resource.Parameters.simulateMode = 2 stops sequence and processes RcvData continuously.
  42. Resource.Parameters.Connector = 1;
  43. %% Specify Trans structure array.
  44. Trans.name = 'Matrix1024-15';
  45. Trans.units = 'mm';
  46. Trans = computeTrans_MatrixProbeIncluded(Trans);
  47. Trans.HVMux = computeUTAMux1024; % add the HV Mux programming for the UTA 1024-MUX
  48. % this files contains 100 sets of 4 Rnd Apertures that are complementary.
  49. % CompRndApod is matrix of 100x4x1024. The sum of every 4 matrices (of the
  50. % second dimention) account for the full aperture.
  51. load('saved100CompRndApod'); %This file has 100x4x1024
  52. CompRndApod=CompRndApod(1,:,:); % for rcv aperture - will use only one set
  53. % patch-like aperture
  54. Papod = zeros(P.numRays^2, 5, 1024);
  55. for i = 1:P.numRays
  56. for j = 1:P.numRays
  57. center1 = floor(P.aperpatch/2)+i-1;
  58. center2 = floor(P.aperpatch/2)+j-1;
  59. M = zeros(32); % initialize 32 x 32 matrix
  60. M(center1-floor(P.aperpatch/2)+1:center1+ceil(P.aperpatch/2),...
  61. center2-floor(P.aperpatch/2)+1:center2+ceil(P.aperpatch/2)) = 1;
  62. Papod((i-1)*P.numRays + j, 1, :) = reshape(M, [1, 1024]);
  63. Papod((i-1)*P.numRays + j,2:5,:) = CompRndApod;
  64. end
  65. end
  66. Papod2 = Papod;
  67. Papod(:,1,:) = ones(size(Papod,1),1,1024);
  68. % create aperture index for each Papod
  69. for i = 1:size(Papod, 1)
  70. for j = 1:size(Papod, 2)
  71. Paper(i,j) = computeMuxAperture(squeeze(Papod(i,j,:))', Trans);
  72. end
  73. end
  74. % Intermediate Variables
  75. waveLength = (Resource.Parameters.speedOfSound/1000)/Trans.frequency;
  76. if strcmp(Trans.units,'mm')
  77. Trans.ElementPosMm = Trans.ElementPos;
  78. Trans.ElementPosWL = Trans.ElementPos./waveLength;
  79. else
  80. Trans.ElementPosMm = Trans.ElementPos.*waveLength;
  81. Trans.ElementPosWL = Trans.ElementPos;
  82. end
  83. ElementPosx = unique(Trans.ElementPosWL(:,1));
  84. ElementPosy = unique(Trans.ElementPosWL(:,2)); % y direction has a gap
  85. % Convert mm to wavelength
  86. demodFreq = Trans.frequency; % demodulation frequency
  87. P.startDepth = P.startDepth_mm/waveLength; % Acquisition depth in wavelengths
  88. P.endDepth = P.endDepth_mm/waveLength; % This should preferrably be a multiple of 128 samples
  89. P.txFocus = P.txFocus_mm/waveLength;
  90. %% PData
  91. PData(1).PDelta = [1 1 1]/2;
  92. PData(1).Size(1) = ceil(((P.numRays+3)*Trans.spacing)/PData(1).PDelta(1)); % +3 compensates for gaps
  93. PData(1).Size(2) = ceil(((P.numRays)*Trans.spacing)/PData(1).PDelta(2));
  94. PData(1).Size(3) = ceil((P.endDepth-P.startDepth)/PData(1).PDelta(3));
  95. PData(1).Origin = [-((PData(1).Size(2)-1)/2)*PData(1).PDelta(2), ((PData(1).Size(1)-1)/2)*PData(1).PDelta(1), P.startDepth];
  96. P.lateral_voxel_size = PData(1).PDelta(1)*100e-6 ;
  97. P.axial_voxel_size = PData(1).PDelta(3)*100e-6 ;
  98. % specify Region structures.
  99. PData(1).Region = repmat(struct('Shape',struct( ...
  100. 'Name','Frustum',...
  101. 'Position',[0,0,P.startDepth],...
  102. 'l1',Trans.spacing,...
  103. 'w1',Trans.spacing,...
  104. 'height',P.endDepth-P.startDepth,...
  105. 'l2',Trans.spacing,...
  106. 'w2',Trans.spacing)),1,P.numRays^2);
  107. for i = 1:P.numRays
  108. for j = 1:P.numRays
  109. PData.Region((i-1)*P.numRays + j).Shape.Position(1) = (ElementPosx(i)+ElementPosx(i+P.aperpatch-1))/2;
  110. PData.Region((i-1)*P.numRays + j).Shape.Position(2) = -(ElementPosy(j)+ElementPosy(j+P.aperpatch-1))/2;
  111. if ismember(j, [2:8:P.numRays])
  112. PData.Region((i-1)*P.numRays + j).Shape.Position(2) = -(ElementPosy(j)+ElementPosy(j+8-1)-Trans.spacing/2)/2;
  113. PData.Region((i-1)*P.numRays + j).Shape.w1 = 1.5*Trans.spacing; % to compensate longer jump caused by gaps
  114. PData.Region((i-1)*P.numRays + j).Shape.w2 = 1.5*Trans.spacing;
  115. end
  116. if ismember(j, [8:8:P.numRays])
  117. PData.Region((i-1)*P.numRays + j).Shape.Position(2) = -(ElementPosy(j)+ElementPosy(j+8-1)+Trans.spacing/2)/2;
  118. PData.Region((i-1)*P.numRays + j).Shape.w1 = 1.5*Trans.spacing;
  119. PData.Region((i-1)*P.numRays + j).Shape.w2 = 1.5*Trans.spacing;
  120. end
  121. end
  122. end
  123. PData(1).Region = computeRegions(PData(1));
  124. for i = 1:8
  125. for j = 1:8
  126. PData.Region(P.numRays^2 + (i-1)*8 + j).Shape.Name = 'Custom';
  127. center_idx = (j:8:P.numRays)' + P.numRays*((i:8:P.numRays)-1); center_idx = center_idx(:);
  128. pixels_set = PData.Region(center_idx(1)).PixelsLA;
  129. for set_n = 2:length(center_idx)
  130. pixels_set = union(pixels_set, PData.Region(center_idx(set_n)).PixelsLA);
  131. end
  132. PData.Region(P.numRays^2 + (i-1)*8 + j).PixelsLA = pixels_set;
  133. PData.Region(P.numRays^2 + (i-1)*8 + j).numPixels = length(PData.Region(P.numRays^2 + (i-1)*8 + j).PixelsLA);
  134. end
  135. end
  136. PData.Region = PData.Region(end-8^2+1:end);
  137. %% Specify Media. Use point targets in middle of PData.
  138. Media.MP(1,:) = [0,0,60,1.0]; % single point.
  139. Media.numPoints = size(Media.MP,1);
  140. %% Resources
  141. % Resource.VDAS.el2ChMapDisable = 1;
  142. Resource.RcvBuffer(1).datatype = 'int16';
  143. Resource.RcvBuffer(1).rowsPerFrame = 4096*8^2*P.nCode*P.numSyntheticRcvs ;
  144. Resource.RcvBuffer(1).colsPerFrame = 256;
  145. Resource.RcvBuffer(1).numFrames = P.numFrames;
  146. Resource.ImageBuffer(1).numFrames = P.numFrames;
  147. % Resource.ImageBuffer(2).numFrames = P.numFrames;
  148. Resource.InterBuffer(1).datatype = 'complex';
  149. Resource.InterBuffer(1).numFrames = 1;
  150. Resource.DisplayWindow(1).Type = 'Verasonics';
  151. Resource.DisplayWindow(1).Title = '3D Flash Image - XZ plane';
  152. Resource.DisplayWindow(1).pdelta = 0.25;
  153. Resource.DisplayWindow(1).Position = [0,580, ...
  154. ceil(PData(1).Size(2)*PData(1).PDelta(2)/Resource.DisplayWindow(1).pdelta), ... % width
  155. ceil(PData(1).Size(3)*PData(1).PDelta(3)/Resource.DisplayWindow(1).pdelta)]; % height
  156. Resource.DisplayWindow(1).Orientation = 'xz';
  157. Resource.DisplayWindow(1).ReferencePt = [PData(1).Origin(1),-15,PData(1).Origin(3)];
  158. Resource.DisplayWindow(1).Colormap = gray(256);
  159. Resource.DisplayWindow(1).AxesUnits = 'mm';
  160. % Resource.DisplayWindow(2).mode = '2d';
  161. Resource.DisplayWindow(2).Type = 'Verasonics';
  162. Resource.DisplayWindow(2).Title = '3D Flash Image - YZ plane';
  163. Resource.DisplayWindow(2).pdelta = Resource.DisplayWindow(1).pdelta;
  164. Resource.DisplayWindow(2).Position = [430,580, ...
  165. ceil(PData(1).Size(1)*PData(1).PDelta(1)/Resource.DisplayWindow(2).pdelta), ... % width
  166. ceil(PData(1).Size(3)*PData(1).PDelta(3)/Resource.DisplayWindow(2).pdelta)]; % height
  167. Resource.DisplayWindow(2).Orientation = 'yz';
  168. Resource.DisplayWindow(2).ReferencePt = [-15,-PData(1).Origin(2),PData(1).Origin(3)];
  169. Resource.DisplayWindow(2).Colormap = gray(256);
  170. Resource.DisplayWindow(2).AxesUnits = 'mm';
  171. % Resource.DisplayWindow(3).mode = '2d';
  172. Resource.DisplayWindow(3).Type = 'Verasonics';
  173. Resource.DisplayWindow(3).Title = '3D Flash Image - XY plane';
  174. Resource.DisplayWindow(3).pdelta = Resource.DisplayWindow(1).pdelta;
  175. Resource.DisplayWindow(3).Position = [0,40, ...
  176. ceil(PData(1).Size(2)*PData(1).PDelta(2)/Resource.DisplayWindow(3).pdelta), ... % width
  177. ceil(PData(1).Size(1)*PData(1).PDelta(1)/Resource.DisplayWindow(3).pdelta)]; % height
  178. Resource.DisplayWindow(3).Orientation = 'xy';
  179. Resource.DisplayWindow(3).ReferencePt = [PData(1).Origin(1),-PData(1).Origin(2),60];%PData.Region(end).Shape.oPAIntersect];
  180. Resource.DisplayWindow(3).Colormap = gray(256);
  181. Resource.DisplayWindow(3).AxesUnits = 'mm';
  182. % Resource.DisplayWindow(3).mode = '2d';
  183. %% Specify Transmit waveform structure.
  184. TW.type = 'parametric';
  185. TW.Parameters = [Trans.frequency,.67,2,1]; % A, B, C, D
  186. P.TW = TW;
  187. % Specify TPC structure.
  188. TPC(1).hv = P.Voltage;
  189. %% Specify TX structure array.
  190. TX = repmat(struct('waveform', 1, ...
  191. 'Origin', [0.0,0.0,0.0], ...
  192. 'focus', P.txFocus, ...
  193. 'Steer', [0.0,0.0], ...
  194. 'Apod', ones(1,1024), ...
  195. 'Delay', zeros(1,256),...
  196. 'peakCutOff', 2,...
  197. 'peakBLMax', 20,...
  198. 'Angle', 0,...
  199. 'aperture',1,...
  200. 'TXPD',[]), 1,P.numRays^2);
  201. % generate parabolic delay law for each patch
  202. for i=1:P.numRays
  203. for j = 1:P.numRays
  204. TX((i-1)*P.numRays+j).Apod = squeeze(Papod2((i-1)*P.numRays+j,1,:))';
  205. TX((i-1)*P.numRays+j).aperture = Paper((i-1)*P.numRays+j,1);
  206. TX((i-1)*P.numRays+j).Origin = [(ElementPosx(i)+ElementPosx(i+P.aperpatch-1))/2, -(ElementPosy(j)+ElementPosy(j+P.aperpatch-1))/2, 0];
  207. TX((i-1)*P.numRays+j).Delay = computeTXDelays(TX((i-1)*P.numRays+j));
  208. % TX((i-1)*P.numRays+j).TXPD = computeTXPD(TX((i-1)*(P.numRays-1)+j),PData(1));
  209. end
  210. end
  211. k = P.numRays^2;
  212. Paper_real = zeros(1,64);
  213. % multiple focused points
  214. for i = 1:8
  215. for j = 1:8
  216. delay_matrix = reshape(TX(j+25*(i-1)).Delay, [32 32]);
  217. delay_matrix = repmat(delay_matrix(i:i+7,j:j+7),4,4);
  218. translated_D = reshape(circshift(delay_matrix, [i-1, j-1]), 1, 1024);
  219. Ap = ones(32);
  220. % remove truncated unit arrays that do not fully form focused beams
  221. if i > 1; Ap([1:i-1, 32-8+i:32], :) = 0; end
  222. if j > 1; Ap(:, [1:j-1, 32-8+j:32]) = 0; end
  223. Ap = reshape(Ap, 1, 1024);
  224. TX(k+j+8*(i-1)) = TX(1);
  225. TX(k+j+8*(i-1)).Delay = translated_D;
  226. TX(k+j+8*(i-1)).focus = 0.0;
  227. TX(k+j+8*(i-1)).Origin = [0.0, 0.0, 0.0];
  228. TX(k+j+8*(i-1)).Apod = Ap;
  229. Paper_real(j+(i-1)*8) = computeMuxAperture(Ap, Trans);
  230. TX(k+j+8*(i-1)).aperture = Paper_real(j+(i-1)*8);
  231. if P.nCode > 1
  232. TX(k+(i-1)*8+j+8^2) = TX(k+j+8*(i-1));
  233. TX(k+(i-1)*8+j+2*8^2) = TX(k+j+8*(i-1));
  234. % checkerboard masking for AM
  235. mask = repmat([repmat([1 0], 1, 16) repmat([0 1], 1, 16)], 1, 16);
  236. TX(k+(i-1)*8+j+8^2).Apod = TX(k+j+8*(i-1)).Apod.*mask;
  237. TX(k+(i-1)*8+j+2*8^2).Apod = TX(k+j+8*(i-1)).Apod.*(~mask);
  238. end
  239. end
  240. end
  241. TX = TX(end-8^2*P.nCode+1:end);
  242. % showTXPD
  243. %% allows to visualize the TX in 3D (similar to the EventAnalysisTool)
  244. % f = figure;
  245. %
  246. % for i=1:64
  247. % plot3(Trans.ElementPos(find(TX(i).Apod==1),1),Trans.ElementPos(find(TX(i).Apod==1),2),TX(i).Delay(find(TX(i).Apod==1)),'k*');
  248. % zlim([0 5]);
  249. % xlim([min(Trans.ElementPos(:,1)) max(Trans.ElementPos(:,1))]);
  250. % ylim([min(Trans.ElementPos(:,2)) max(Trans.ElementPos(:,2))]);
  251. % view(gca,-40,49);grid on;
  252. % zlabel('Delay (wavelength)'); xlabel('X (mm)'); ylabel('Y (mm)')
  253. %
  254. % pause(.5);
  255. %
  256. % end
  257. %% Specify TGC Waveform structure.
  258. TGC(1).CntrlPts = [100 1010 1023 1023 1023 1023 1023 1023];
  259. TGC(1).rangeMax = 128;
  260. TGC(1).Waveform = computeTGCWaveform(TGC);
  261. maxAcqLength = sqrt(P.endDepth^2 + (32*Trans.spacing)^2 + (35*Trans.spacing)^2 );
  262. %% Receive
  263. Receive = repmat(struct(...
  264. 'Apod', zeros(1,Trans.numelements), ...
  265. 'startDepth', P.startDepth, ...
  266. 'endDepth', 128/(4*2)*ceil(maxAcqLength/(128/(4*2))), ...
  267. 'TGC', 1, ...
  268. 'mode', 0, ...
  269. 'bufnum', 1, ...
  270. 'framenum', 1, ...
  271. 'acqNum', 1, ...
  272. 'aperture',0, ...
  273. 'sampleMode', 'NS200BW', ...
  274. 'callMediaFunc', 0), 1, P.numFrames*P.numSyntheticRcvs*P.nCode*8^2);
  275. for j = 1:P.numFrames
  276. k=P.numSyntheticRcvs*8^2*P.nCode*(j-1);
  277. for n = 1:P.nCode
  278. kk = P.numSyntheticRcvs*8^2*(n-1);
  279. for i = 1:8^2
  280. kkk=P.numSyntheticRcvs*(i-1);
  281. for w=1:P.numSyntheticRcvs
  282. Receive(w+kkk+kk+k).acqNum = w+kkk;
  283. Receive(w+kkk+kk+k).framenum = j;
  284. Receive(w+kkk+kk+k).aperture = Paper(i,w+1);
  285. if n==1
  286. Receive(w+kkk+kk+k).Apod = squeeze(Papod(i,w+1,:))';
  287. else % for AM
  288. Receive(w+kkk+kk+k).Apod = -squeeze(Papod(i,w+1,:))'; % subtract
  289. Receive(w+kkk+kk+k).mode = 1; % accumulate
  290. end
  291. end
  292. end
  293. end
  294. end
  295. %% Recon
  296. senscutoff = 0.6;
  297. Recon(1) = struct('senscutoff', senscutoff, ...
  298. 'pdatanum', 1, ...
  299. 'rcvBufFrame', -1, ...
  300. 'IntBufDest', [1,1],...
  301. 'ImgBufDest', [1,-1], ...
  302. 'RINums', 1:8^2*P.numSyntheticRcvs) ;
  303. % Define ReconInfo structures.
  304. ReconInfo = repmat(struct('mode', 'accumIQ', ...
  305. 'txnum', 1, ...
  306. 'rcvnum', 1, ...
  307. 'scaleFactor', 1, ...
  308. 'regionnum', 1), 1, 8^2*P.numSyntheticRcvs);
  309. ReconInfo(1).mode = 3;
  310. for w=1:8^2
  311. k= P.numSyntheticRcvs*(w-1);
  312. for i = 1:P.numSyntheticRcvs
  313. ReconInfo(i+k).txnum = w;
  314. ReconInfo(i+k).rcvnum = i+k;
  315. ReconInfo(i+k).regionnum = w;
  316. if i == 1
  317. ReconInfo(i+k).mode = 3;
  318. end
  319. if i == P.numSyntheticRcvs
  320. ReconInfo(i+k).mode = 5;
  321. end
  322. end
  323. end
  324. ReconInfo(end).mode = 5;
  325. %% Specify Process structure arrays.
  326. pgain=20;
  327. Process(1).classname = 'Image';
  328. Process(1).method = 'imageDisplay';
  329. Process(1).Parameters = {'imgbufnum',1,...
  330. 'framenum',-1,...
  331. 'pdatanum',1,...
  332. 'srcData','intensity3D',...
  333. 'pgain', pgain,...
  334. 'persistMethod','none',...
  335. 'persistLevel',30,...
  336. 'interpMethod','4pt',...
  337. 'compressMethod','power',...
  338. 'compressFactor',75,...
  339. 'mappingMethod','full',...
  340. 'display',1,...
  341. 'displayWindow',1};
  342. Process(2).classname = 'Image';
  343. Process(2).method = 'imageDisplay';
  344. Process(2).Parameters = {'imgbufnum',1,...
  345. 'framenum',-1,...
  346. 'pdatanum',1,...
  347. 'srcData','intensity3D',...
  348. 'pgain', pgain,...
  349. 'persistMethod','none',...
  350. 'persistLevel',30,...
  351. 'interpMethod','4pt',...
  352. 'compressMethod','power',...
  353. 'compressFactor',75,...
  354. 'mappingMethod','full',...
  355. 'display',1,...
  356. 'displayWindow',2};
  357. Process(3).classname = 'Image';
  358. Process(3).method = 'imageDisplay';
  359. Process(3).Parameters = {'imgbufnum',1,...
  360. 'framenum',-1,...
  361. 'pdatanum',1,...
  362. 'srcData','intensity3D',...
  363. 'pgain', pgain,...
  364. 'persistMethod','none',...
  365. 'persistLevel',30,...
  366. 'interpMethod','4pt',...
  367. 'compressMethod','power',...
  368. 'compressFactor',75,...
  369. 'mappingMethod','full',...
  370. 'display',1,...
  371. 'displayWindow',3};
  372. Process(4).classname = 'External';
  373. Process(4).method = 'volumetricPlot';
  374. Process(4).Parameters = {'srcbuffer','image',...
  375. 'srcbufnum',1,...
  376. 'srcframenum',-1,...
  377. 'dstbuffer','none'};
  378. % Save Image Data
  379. Process(5).classname = 'External';
  380. Process(5).method = 'saveImageData';
  381. Process(5).Parameters = {'srcbuffer','image',... % name of buffer to process.
  382. 'srcbufnum',1,...
  383. 'srcframenum',-1,... % process the most recent frame.
  384. 'dstbuffer','none'};
  385. Process(6).classname = 'External';
  386. Process(6).method = 'vstic';
  387. Process(6).Parameters = {'srcbuffer','none'};
  388. Process(7).classname = 'External';
  389. Process(7).method = 'vstoc';
  390. Process(7).Parameters = {'srcbuffer','none'};
  391. % Save RF Data
  392. Process(8).classname = 'External';
  393. Process(8).method = 'saveRFData';
  394. Process(8).Parameters = {'srcbuffer','receive',... % name of buffer to process.
  395. 'srcbufnum',1,...
  396. 'srcframenum',-1,... % process the most recent frame.
  397. 'dstbuffer','none'};
  398. %external function
  399. EF(1).Function = vsv.seq.function.ExFunctionDef('volumetricPlot', @volumetricPlot);
  400. EF(2).Function = vsv.seq.function.ExFunctionDef('saveImageData', @saveImageData);
  401. EF(3).Function = vsv.seq.function.ExFunctionDef('vstic', @vstic);
  402. EF(4).Function = vsv.seq.function.ExFunctionDef('vstoc', @vstoc);
  403. EF(5).Function = vsv.seq.function.ExFunctionDef('saveRFData', @saveRFData);
  404. % Specify SeqControl structure arrays.
  405. SeqControl(1).command = 'jump'; % jump back to start
  406. SeqControl(1).argument = 1;
  407. SeqControl(2).command = 'timeToNextAcq'; % time between synthetic aperture acquisitions
  408. SeqControl(2).argument = 250;
  409. SeqControl(3).command = 'timeToNextAcq'; % time between frames
  410. % SeqControl(3).argument = 20000; % 20 msec
  411. SeqControl(3).argument = 1000000; % 2s
  412. SeqControl(3).condition = 'ignore'; %Recon processing time
  413. SeqControl(4).command = 'returnToMatlab';
  414. SeqControl(5).command = 'triggerOut';
  415. SeqControl(6).command = 'loopCnt'; % - Set loop count. for looping on blocs
  416. SeqControl(6).argument = P.numberImagesToSave/P.numFrames-1; %
  417. SeqControl(6).condition = 'counter1';
  418. SeqControl(7).command = 'loopTst'; % loop test
  419. SeqControl(7).argument = []; % set apres
  420. SeqControl(7).condition = 'counter1';
  421. nsc = 8; % nsc is count of SeqControl objects
  422. %% Specify Event Structure arrays
  423. n = 1; % start index for Events
  424. for j = 1:Resource.RcvBuffer(1).numFrames
  425. v=P.numSyntheticRcvs*8^2*P.nCode*(j-1);
  426. for w=1:8^2
  427. k= P.numSyntheticRcvs*(w-1);
  428. for i = 1:P.numSyntheticRcvs
  429. for m = 1:P.nCode
  430. Event(n).info = 'Transmit/Receive.';
  431. Event(n).tx = w + (m-1)*8^2;
  432. Event(n).rcv = i+k+v+(m-1)*8^2*P.numSyntheticRcvs;
  433. Event(n).recon = 0; % no reconstruction.
  434. Event(n).process = 0; % no processing
  435. Event(n).seqControl = [2,5]; %
  436. n = n+1;
  437. end
  438. end
  439. end
  440. Event(n-1).seqControl = [3,5];
  441. Event(n).info = 'Transfer To Host';
  442. Event(n).tx = 0;
  443. Event(n).rcv = 0;
  444. Event(n).recon = 0; % no reconstruction.
  445. Event(n).process = 0; % no processing
  446. Event(n).seqControl = [nsc,nsc+1]; % set wait time and transfer data
  447. SeqControl(nsc).command = 'transferToHost';
  448. nsc = nsc + 1;
  449. SeqControl(nsc).command = 'waitForTransferComplete';
  450. SeqControl(nsc).argument = nsc-1;
  451. nsc = nsc + 1;
  452. n = n+1;
  453. Event(n).info = ['3D Reconstruct Frame ' num2str(i)];
  454. Event(n).tx = 0;
  455. Event(n).rcv = 0;
  456. Event(n).recon = 1;
  457. Event(n).process = 0;
  458. Event(n).seqControl = 0;
  459. n = n+1;
  460. Event(n).info = ['Process XZ - Frame ' num2str(i)];
  461. Event(n).tx = 0;
  462. Event(n).rcv = 0;
  463. Event(n).recon = 0;
  464. Event(n).process = 1;
  465. Event(n).seqControl = 0;
  466. n = n+1;
  467. Event(n).info = ['Process YZ - Frame ' num2str(i)];
  468. Event(n).tx = 0;
  469. Event(n).rcv = 0;
  470. Event(n).recon = 0;
  471. Event(n).process = 2;
  472. Event(n).seqControl = 0;
  473. n = n+1;
  474. Event(n).info = ['Process XY - Frame ' num2str(i)];
  475. Event(n).tx = 0;
  476. Event(n).rcv = 0;
  477. Event(n).recon = 0;
  478. Event(n).process = 3;
  479. Event(n).seqControl = 0;
  480. n = n+1;
  481. Event(n).info = ['3D Process - Frame' num2str(i)];
  482. Event(n).tx = 0;
  483. Event(n).rcv = 0;
  484. Event(n).recon = 0;
  485. Event(n).process = 4;
  486. Event(n).seqControl = 0;
  487. n = n+1;
  488. Event(n).info = 'Return to Matlab';
  489. Event(n).tx = 0;
  490. Event(n).rcv = 0;
  491. Event(n).recon = 0;
  492. Event(n).process = 0;
  493. Event(n).seqControl = 4;
  494. n = n+1;
  495. Event(n).info = 'HW/SW Sync';
  496. Event(n).tx = 0;
  497. Event(n).rcv = 0;
  498. Event(n).recon = 0;
  499. Event(n).process = 0;
  500. Event(n).seqControl = nsc;
  501. SeqControl(nsc).command = 'sync';
  502. nsc = nsc + 1;
  503. n = n+1;
  504. end
  505. Event(n).info = 'Jump';
  506. Event(n).tx = 0; % no TX structure.
  507. Event(n).rcv = 0; % no Rcv structure.
  508. Event(n).recon = 0; % no reconstruction.
  509. Event(n).process = 0; % call processing function
  510. Event(n).seqControl = 1; %
  511. n = n+1;
  512. % Acquire Image Data
  513. nStartAcquire = n;
  514. Event(n).info = 'tic ';
  515. Event(n).tx = 0;
  516. Event(n).rcv = 0;
  517. Event(n).recon = 0;
  518. Event(n).process = 6;
  519. Event(n).seqControl = 0;
  520. n = n+1;
  521. % set loop count
  522. Event(n).info = 'start counter';
  523. Event(n).tx = 0;
  524. Event(n).rcv = 0;
  525. Event(n).recon = 0; % no reconstruction.
  526. Event(n).process = 0; % no processing
  527. Event(n).seqControl = 6;
  528. n = n+1;
  529. SeqControl(7).argument = n;
  530. for j = 1:Resource.RcvBuffer(1).numFrames
  531. v=P.numSyntheticRcvs*8^2*P.nCode*(j-1);
  532. for w=1:8^2
  533. k= P.numSyntheticRcvs*(w-1);
  534. for i = 1:P.numSyntheticRcvs
  535. for m = 1:P.nCode
  536. Event(n).info = 'Transmit/Receive.';
  537. Event(n).tx = w + (m-1)*8^2;
  538. Event(n).rcv = i+k+v+(m-1)*8^2*P.numSyntheticRcvs;
  539. Event(n).recon = 0; % no reconstruction.
  540. Event(n).process = 0; % no processing
  541. Event(n).seqControl = [2,5]; %
  542. n = n+1;
  543. end
  544. end
  545. end
  546. Event(n-1).seqControl = [3,5];
  547. Event(n).info = 'Transfer To Host';
  548. Event(n).tx = 0;
  549. Event(n).rcv = 0;
  550. Event(n).recon = 0; % no reconstruction.
  551. Event(n).process = 0; % no processing
  552. Event(n).seqControl = [nsc, nsc+1]; % set wait time and transfer data [nsc,nsc+1]
  553. SeqControl(nsc).command = 'transferToHost';
  554. nsc = nsc + 1;
  555. SeqControl(nsc).command = 'waitForTransferComplete';
  556. SeqControl(nsc).argument = nsc-1;
  557. nsc = nsc + 1;
  558. n = n+1;
  559. Event(n).info = ['3D Reconstruct Frame ' num2str(i)];
  560. Event(n).tx = 0;
  561. Event(n).rcv = 0;
  562. Event(n).recon = 1;
  563. Event(n).process = 0;
  564. Event(n).seqControl = 0;
  565. n = n+1;
  566. Event(n).info = ['Process XZ - Frame ' num2str(i)];
  567. Event(n).tx = 0;
  568. Event(n).rcv = 0;
  569. Event(n).recon = 0;
  570. Event(n).process = 1;
  571. Event(n).seqControl = 0;
  572. n = n+1;
  573. Event(n).info = ['Process YZ - Frame ' num2str(i)];
  574. Event(n).tx = 0;
  575. Event(n).rcv = 0;
  576. Event(n).recon = 0;
  577. Event(n).process = 2;
  578. Event(n).seqControl = 0;
  579. n = n+1;
  580. Event(n).info = ['Process XY - Frame ' num2str(i)];
  581. Event(n).tx = 0;
  582. Event(n).rcv = 0;
  583. Event(n).recon = 0;
  584. Event(n).process = 3;
  585. Event(n).seqControl = 0;
  586. n = n+1;
  587. Event(n).info = ['3D Process - Frame' num2str(i)];
  588. Event(n).tx = 0;
  589. Event(n).rcv = 0;
  590. Event(n).recon = 0;
  591. Event(n).process = 4;
  592. Event(n).seqControl = 0;
  593. n = n+1;
  594. %
  595. Event(n).info = 'Return to Matlab';
  596. Event(n).tx = 0;
  597. Event(n).rcv = 0;
  598. Event(n).recon = 0;
  599. Event(n).process = 0;
  600. Event(n).seqControl = 4;
  601. n = n+1;
  602. Event(n).info = 'HW/SW Sync';
  603. Event(n).tx = 0;
  604. Event(n).rcv = 0;
  605. Event(n).recon = 0;
  606. Event(n).process = 0;
  607. Event(n).seqControl = nsc;
  608. SeqControl(nsc).command = 'sync';
  609. nsc = nsc + 1;
  610. n = n+1;
  611. Event(n).info = 'save Image Data';
  612. Event(n).tx = 0; % no transmit
  613. Event(n).rcv = 0; % no rcv
  614. Event(n).recon = 0; % no reconstruction
  615. Event(n).process = 5; % process
  616. Event(n).seqControl = 0;
  617. n = n+1;
  618. % Event(n).info = 'save RF Data';
  619. % Event(n).tx = 0; % no transmit
  620. % Event(n).rcv = 0; % no rcv
  621. % Event(n).recon = 0; % no reconstruction
  622. % Event(n).process = 8; % process
  623. % Event(n).seqControl = 0;
  624. % n = n+1;
  625. Event(n).info = 'toc ';
  626. Event(n).tx = 0;
  627. Event(n).rcv = 0;
  628. Event(n).recon = 0;
  629. Event(n).process = 7;
  630. Event(n).seqControl = 0;
  631. n = n+1;
  632. end
  633. % Event(n).info = 'save Image Data';
  634. % Event(n).tx = 0; % no transmit
  635. % Event(n).rcv = 0; % no rcv
  636. % Event(n).recon = 0; % no reconstruction
  637. % Event(n).process = 5; % process
  638. % Event(n).seqControl = 0;
  639. % n = n+1;
  640. Event(n).info = 'Loop back until all images are acquired';
  641. Event(n).tx = 0; % no transmit
  642. Event(n).rcv = 0; % no rcv
  643. Event(n).recon = 0; % no reconstruction
  644. Event(n).process = 0; % process
  645. Event(n).seqControl = 7;
  646. n = n+1;
  647. %% User specified UI Control Elements
  648. import vsv.seq.uicontrol.VsSliderControl;
  649. % - Sensitivity Cutoff
  650. UI(1).Control = VsSliderControl('LocationCode','UserB7','Label','Sens. Cutoff',...
  651. 'SliderMinMaxVal',[0,1.0,Recon(1).senscutoff],...
  652. 'SliderStep',[0.025,0.1],'ValueFormat','%1.3f', ...
  653. 'Callback', @SensCutoffCallback );
  654. % - Section number change
  655. UI(2).Control = VsSliderControl('LocationCode','UserB1','Label','Z-Section',...
  656. 'SliderMinMaxVal',[1,P.endDepth,Resource.DisplayWindow(3).ReferencePt(3)],...
  657. 'SliderStep',[1/(P.endDepth-1) 10/(P.endDepth-1)],'ValueFormat','%3.0f', ...
  658. 'Callback', @ZSectionChange );
  659. % - Section number change
  660. UI(3).Control = VsSliderControl('LocationCode','UserB2','Label','Y-Section',...
  661. 'SliderMinMaxVal',[PData(1).Origin(2)-(PData(1).Size(1)-1)*PData(1).PDelta(1), PData(1).Origin(2), Resource.DisplayWindow(1).ReferencePt(2)],...
  662. 'SliderStep',[1/((PData(1).Size(2)-1)*PData(1).PDelta(2)-1) 10/((PData(1).Size(2)-1)*PData(1).PDelta(2)-1)],'ValueFormat','%3.0f', ...
  663. 'Callback', @YSectionChange);
  664. % - Section number change
  665. UI(4).Control = VsSliderControl('LocationCode','UserB3','Label','X-Section',...
  666. 'SliderMinMaxVal',[PData(1).Origin(1), PData(1).Origin(1)+(PData(1).Size(2)-1)*PData(1).PDelta(2), Resource.DisplayWindow(2).ReferencePt(1)],...
  667. 'SliderStep',[1/((PData(1).Size(1)-1)*PData(1).PDelta(1)-1) 10/((PData(1).Size(1)-1)*PData(1).PDelta(1)-1)],'ValueFormat','%3.0f', ...
  668. 'Callback', @XSectionChange);
  669. % - compression
  670. CompressionFactor=1.3;
  671. UI(5).Control = VsSliderControl('LocationCode','UserA2','Label','CompressionP',...
  672. 'SliderMinMaxVal',[1,11,CompressionFactor],...
  673. 'SliderStep',[1/40,4/40],'ValueFormat','%1.1f', ...
  674. 'Callback', @CompressionP );
  675. UI(6).Control = {'UserC1','Style','VsPushButton','Label','Save Image'};
  676. UI(6).Callback = text2cell('%StartSaving');
  677. % Specify factor for converting sequenceRate to frameRate.
  678. frameRateFactor = 3;
  679. % Save all the structures to a .mat file.
  680. filename = 'SetupMatrix1024_15MHz_Takoyaki_LiveImaging';
  681. save(['MatFiles/',filename]);
  682. VSX
  683. return
  684. %StartSaving
  685. display('Start Saving')
  686. Control = repmat(struct('Command','set&Run','Parameters',[]),1,1);
  687. nStartAcquire = evalin('base','nStartAcquire');
  688. Control(1).Parameters = {'Parameters',1,'startEvent',nStartAcquire};
  689. evalin('base','Resource.Parameters.startEvent = nStartAcquire;');
  690. assignin('base','Control', Control);
  691. %StartSaving
  692. %% **** Callback routines used by UIControls (UI) ****
  693. function SensCutoffCallback(~,~,UIValue)
  694. %SensCutoff - Sensitivity cutoff change
  695. ReconL = evalin('base', 'Recon');
  696. for i = 1:size(ReconL,2)
  697. ReconL(i).senscutoff = UIValue;
  698. end
  699. assignin('base','Recon',ReconL);
  700. Control = evalin('base','Control');
  701. Control.Command = 'update&Run';
  702. Control.Parameters = {'Recon'};
  703. assignin('base','Control', Control);
  704. end
  705. function YSectionChange(~,~,UIValue)
  706. %YSectionChange
  707. RS = evalin('base','Resource');
  708. RefPt = RS.DisplayWindow(1).ReferencePt;
  709. RefPt(2) = UIValue;
  710. RS.DisplayWindow(1).ReferencePt = RefPt;
  711. assignin('base','Resource',RS);
  712. PDataT = evalin('base','PData');
  713. P = evalin('base','P');
  714. PDataT(1).Region(1).Shape.oPAIntersect = RefPt(2);
  715. PDataT(1).Region = computeRegions(PDataT(1));
  716. assignin('base','PData',PDataT);
  717. Control = repmat(struct('Command',[],'Parameters',[]),1,2);
  718. Control(1).Command = 'set&Run';
  719. Control(1).Parameters = {'DisplayWindow',1,'ReferencePt',RefPt};
  720. Control(2).Command = 'update&Run';
  721. Control(2).Parameters = {'PData'};
  722. assignin('base','Control', Control);
  723. end
  724. function XSectionChange(~,~,UIValue)
  725. %XSectionChange
  726. RS = evalin('base','Resource');
  727. RefPt = RS.DisplayWindow(2).ReferencePt;
  728. RefPt(1) = UIValue;
  729. RS.DisplayWindow(2).ReferencePt = RefPt;
  730. assignin('base','Resource',RS);
  731. PDataT = evalin('base','PData');
  732. P = evalin('base','P');
  733. PDataT(1).Region(1).Shape.oPAIntersect = RefPt(1);
  734. PDataT(1).Region = computeRegions(PDataT(1));
  735. assignin('base','PData',PDataT);
  736. Control = repmat(struct('Command',[],'Parameters',[]),1,2);
  737. Control(1).Command = 'set&Run';
  738. Control(1).Parameters = {'DisplayWindow',2,'ReferencePt',RefPt};
  739. Control(2).Command = 'update&Run';
  740. Control(2).Parameters = {'PData'};
  741. assignin('base','Control', Control);
  742. end
  743. function ZSectionChange(~,~,UIValue)
  744. %ZSectionChange
  745. RS = evalin('base','Resource');
  746. RefPt = RS.DisplayWindow(3).ReferencePt;
  747. RefPt(3) = UIValue;
  748. RS.DisplayWindow(3).ReferencePt = RefPt;
  749. assignin('base','Resource',RS);
  750. PDataT = evalin('base','PData');
  751. P = evalin('base','P');
  752. PDataT(1).Region(1).Shape.oPAIntersect = RefPt(3);
  753. PDataT(1).Region = computeRegions(PDataT(1));
  754. assignin('base','PData',PDataT);
  755. Control = repmat(struct('Command',[],'Parameters',[]),1,2);
  756. Control(1).Command = 'set&Run';
  757. Control(1).Parameters = {'DisplayWindow',3,'ReferencePt',RefPt};
  758. Control(2).Command = 'update&Run';
  759. Control(2).Parameters = {'PData'};
  760. assignin('base','Control', Control);
  761. end
  762. function CompressionP(~,~,UIValue)
  763. %CompressionP
  764. CompressionFactor = UIValue;
  765. assignin('base','CompressionFactor',CompressionFactor);
  766. end
  767. %% **** Callback routines used by External function definition (EF) ****
  768. function volumetricPlot(ImgData)
  769. persistent handle3D
  770. PData = evalin('base','PData');
  771. Trans = evalin('base','Trans');
  772. P = evalin('base','P');
  773. v_depth = 1;
  774. CFactor = evalin('base','CompressionFactor');
  775. ImgData=ImgData.^(1/CFactor);
  776. ImgData(:,:,1:v_depth)=0;
  777. ImgData = flipdim(ImgData,3);
  778. if isempty(handle3D) || ~ishandle(handle3D)
  779. figure('Position', [430, 50, 450, 450]);
  780. handle3D = axes;
  781. end
  782. set(handle3D,'NextPlot','replacechildren');
  783. vol3d('cdata', ImgData,'texture', '2D','Parent', handle3D);
  784. grid(handle3D, 'on'); colormap(handle3D,'gray');
  785. set(handle3D,'NextPlot','add');
  786. xl=PData(1).Size(2);
  787. yl=PData(1).Size(1);
  788. zl=PData(1).Size(3);
  789. dx=PData(1).PDelta(2);
  790. dy=PData(1).PDelta(1);
  791. dz=PData(1).PDelta(3);
  792. plot3(handle3D,Trans.ElementPosWL(:,1)./dx+(xl-1)/2,Trans.ElementPosWL(:,2)./dy+(yl-1)/2,(Trans.ElementPosWL(:,3)+P.endDepth)./dz,'k.');
  793. view(handle3D,-45,30);
  794. end
  795. function saveImageData(ImgData)
  796. persistent bloc_count;
  797. if isempty(bloc_count)
  798. bloc_count = 1;
  799. end
  800. P = evalin('base','P');
  801. Path = P.pathName;
  802. if bloc_count == 1
  803. mkdir(Path)
  804. save([Path '\P.mat'],'P');
  805. end
  806. eval(['pAM3D_',num2str(bloc_count),' = squeeze(ImgData);']);
  807. save([Path '\pAM3D_' num2str(bloc_count) '.mat'],['pAM3D_',num2str(bloc_count)]);
  808. display(['Saved image #',num2str(bloc_count) '!'])
  809. bloc_count = bloc_count+1;
  810. if bloc_count == P.numberImagesToSave + 1
  811. display('End of the acquisition!')
  812. end
  813. end
  814. function vstic(varargin)
  815. tic
  816. end
  817. function vstoc(varargin)
  818. persistent Tend;
  819. if isempty(Tend)
  820. Tend = toc;
  821. disp(['Elapsed time is ', num2str(Tend), ' seconds.'])
  822. else
  823. Tend(end+1) = toc;
  824. disp(['Elapsed time is ', num2str(Tend(end)), ' seconds.'])
  825. end
  826. P = evalin('base','P');
  827. if length(Tend) == P.numberImagesToSave
  828. Path = P.pathName;
  829. save([Path '\timelog.mat'],'Tend');
  830. end
  831. end
  832. function saveRFData(RFData)
  833. persistent RF_count;
  834. if isempty(RF_count)
  835. RF_count = 1;
  836. end
  837. P = evalin('base','P');
  838. Path = P.pathName;
  839. if RF_count == 1
  840. mkdir(Path)
  841. save([Path '\P.mat'],'P');
  842. end
  843. eval(['RFData_',num2str(RF_count),' = squeeze(RFData);']);
  844. save([Path '\RFData_' num2str(RF_count) '.mat'],['RFData_',num2str(RF_count)]);
  845. display(['Saved RFData #',num2str(RF_count) '!'])
  846. RF_count = RF_count+1;
  847. if RF_count == P.numberImagesToSave + 1
  848. display('End of the acquisition!')
  849. end
  850. end

SetupMatrix1024_15MHz_Takoyaki_LiveImaging.m at commit e3bab2d, no license · at the source

Overview

Authors: Sunho Lee1, Di Wu2, Dina Malounda2, Claire Rabut2, Mikhail G Shapiro1,2,3
  1. Andrew and Peggy Cherng Department of Medical Engineering, California Institute of Technology, Pasadena, CA USA
  2. Division of Chemistry and Chemical Engineering, California Institute of Technology, Pasadena, CA USA
  3. Howard Hughes Medical Institute, Pasadena, CA USA
Institutions: California Institute of Technology (United States); Howard Hughes Medical Institute (United States)
Journal: Nature communications, volume 17, issue 1, article 7281
Dates: received 16 June 2025; accepted 28 April 2026; published online 21 May 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41467-026-72961-0 · PMID 42168209 · PMCID PMC13402839 · OpenAlex W4404406274
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: other (modality), human (organism), mouse (organism), other condition (population), cellular / molecular (subfield)
Methods: Statistics, Connectivity, Preprocessing, fMRI & imaging
Keywords: Ultrasound, Molecular imaging, Synthetic biology, Nanoparticles, Microbiology
MeSH: Glioblastoma*, Imaging, Three-Dimensional*, Animals, Brain, Brain Neoplasms, Cell Line, Tumor, Contrast Media, Genes, Reporter, Humans, Mice, Microbubbles, Ultrasonography (* major topic)
Topic: Photoacoustic and Ultrasonic Imaging (Biomedical Engineering, Engineering), according to OpenAlex
Funding: NIBIB NIH HHS (R01 EB018975); U.S. Department of Health & Human Services | National Institutes of Health (NIH) (R01NS120828, R01EB018975); Chan Zuckerberg Initiative; NINDS NIH HHS (R01 NS120828); U.S. Department of Health & Human Services | National Institutes of Health (R01EB018975, R01NS120828); Howard Hughes Medical Institute
Citations: not cited yet (Europe PMC); 66 references in the paper

Abstract

Acoustic contrast agents and reporter genes play a critical role in allowing ultrasound to visualize blood flow, map molecules and track cellular function in optically opaque living organisms. However, many advanced agents requiring high acoustic pressures have been imaged primarily in 2D, while biological phenomena of interest unfurl in three dimensions. Here, we introduce a method for efficient, dynamic imaging of contrast agents and reporter genes in 3D using multiplexed matrix array transducers. Our “Takoyaki” pulse sequence uses the simultaneous scanning of multiple focal points to excite contrast agents with sufficient acoustic pressure for nonlinear imaging while efficiently covering 3D space. We first characterize and benchmark Takoyaki imaging performance with gas vesicle contrast agents in vitro. Then we establish utility in cellular imaging by visualizing acoustic reporter gene expression in a mouse model of glioblastoma. Finally, we demonstrate real-time volumetric imaging by tracking the dynamics of fluid motion in mouse brain ventricles during and after intraventricular contrast injection. Takoyaki imaging enables a more comprehensive understanding of biological processes by providing spatiotemporal information in 3D within the constraints of accessible multiplexed matrix-array systems.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 9 matches between paragraphs and lines of code.

shapiro-lab/Takoyaki-imaging

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: e3bab2d2b11eee2aaeb479eaf530bf6efea03ef2, 19 March 2026
Languages: MATLAB (7), Python (4)
Size: 23 files, 11 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: napari (4 files), NumPy (4 files), scikit-image (4 files), SciPy (4 files), Image Processing Toolbox (2 files)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
12 files

Zenodo 19124225

License: CC-BY-4.0
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: napari (4 files), NumPy (4 files), scikit-image (4 files), SciPy (4 files), Image Processing Toolbox (2 files)
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
  • 28 September 2026: the link answers (HTTP 200)
12 files
At the source:

Code availability

The ultrasound sequence scripts and data analysis codes used to generate key figures and results are available on GitHub (https://github.com/shapiro-lab/Takoyaki-imaging)65.

Reproduced under the paper's license (CC BY), from the paper cited above.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 22 scripts, each with its path and the digest of its content;
  • 9 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability

Primary image data have been deposited in the CaltechDATA repository at 10.22002/knnyt-x4762, available at https://data.caltech.edu/records/knnyt-x4762. Source data are provided with this paper.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 5 authors, 5 keywords, 12 MeSH terms, 6 funders, 58 references.

Cite

This paper

Lee, S., Wu, D., Malounda, D., Rabut, C., & Shapiro, M. G. (2026). Real-time volumetric imaging of cells and molecules in deep tissues with Takoyaki ultrasound. Nature communications, 17(1), 7281. https://doi.org/10.1038/s41467-026-72961-0

BibTeX

@article{lee2026real,
author = {Lee, Sunho and Wu, Di and Malounda, Dina and Rabut, Claire and Shapiro, Mikhail G},
title = {{Real-time volumetric imaging of cells and molecules in deep tissues with Takoyaki ultrasound}},
journal = {Nature communications},
year = {2026},
month = may,
volume = {17},
number = {1},
pages = {7281},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-72961-0},
url = {https://doi.org/10.1038/s41467-026-72961-0},
pmid = {42168209},
pmcid = {PMC13402839}
}

RIS

TY - JOUR
AU - Lee, Sunho
AU - Wu, Di
AU - Malounda, Dina
AU - Rabut, Claire
AU - Shapiro, Mikhail G
TI - Real-time volumetric imaging of cells and molecules in deep tissues with Takoyaki ultrasound
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/05/21
VL - 17
IS - 1
SP - 7281
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-72961-0
UR - https://doi.org/10.1038/s41467-026-72961-0
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-72961-0",
"type": "article-journal",
"title": "Real-time volumetric imaging of cells and molecules in deep tissues with Takoyaki ultrasound",
"container-title": "Nature communications",
"author": [
{
"family": "Lee",
"given": "Sunho"
},
{
"family": "Wu",
"given": "Di"
},
{
"family": "Malounda",
"given": "Dina"
},
{
"family": "Rabut",
"given": "Claire"
},
{
"family": "Shapiro",
"given": "Mikhail G"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "7281",
"DOI": "10.1038/s41467-026-72961-0",
"PMID": "42168209",
"PMCID": "PMC13402839",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-72961-0",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
21
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1111/ejn.70582 [code]
Multifiber Array-Based Photometry System for Multiregional Functional Mapping in the Mouse Brain.
Journal: The European journal of neuroscience
In common: scikit-image, SciPy, NumPy, mouse, 3 references
[2] doi: [code]
Real-time closed-loop feedback system for mouse mesoscale cortical signal and movement control
Journal: eLife
In common: napari, scikit-image, SciPy, 1 other tool, mouse, 1 reference
[3] doi:10.1016/j.celrep.2026.117420 [code]
Neural population dynamics of direct electrical stimulation of neocortex.
Journal: Cell reports
In common: napari, scikit-image, SciPy, 1 other tool, mouse, 1 reference
[4] doi:10.1038/s42003-026-10063-9 [code]
Conserved Kir channel mechanisms governing intrinsic excitability in human and rodent parvalbumin neurons.
Journal: Communications biology
In common: napari, scikit-image, SciPy, 1 other tool, mouse, cellular / molecular
[5] doi:10.1038/s41586-026-10323-y [code]
Genetically encoded assembly recorder temporally resolves cellular history.
Journal: Nature
In common: napari, scikit-image, SciPy, 1 other tool, mouse, cellular / molecular
[6] doi:10.1126/sciadv.aed5548 [code]
In situ proteomics unveils specialized domains for extrasynaptic signaling on neuronal cilia.
Journal: Science advances
In common: napari, scikit-image, SciPy, 1 other tool, mouse, cellular / molecular
[7] doi:10.1093/neuonc/noag128 [code]
Spatially-resolved single-cell imaging of melanoma brain metastases identifies localized immune patterns predictive of immune checkpoint blockade response.
Journal: Neuro-oncology
In common: napari, scikit-image, SciPy, 1 other tool, other condition
[8] doi:10.1038/s41467-026-73770-1 [code]
Non-coding structural variants disrupt FOXG1 transcriptional regulation in early neurodevelopment.
Journal: Nature communications
In common: napari, scikit-image, SciPy, 1 other tool, other condition
[9] doi:10.1038/s41593-026-02262-8 [code]
Cheese3D enables sensitive detection and analysis of whole-face movement in mice.
Journal: Nature neuroscience
In common: napari, scikit-image, SciPy, 1 other tool, mouse
[10] doi:10.1002/advs.77822 [code]
Temporal Trajectories of the Tau Aggregate Interactome Reveal Stage-Specific Vulnerabilities in Alzheimer's Disease.
Journal: Advanced science (Weinheim, Baden-Wurttemberg, Germany)
In common: napari, scikit-image, SciPy, 1 other tool, cellular / molecular

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.