Skip to content

Commit d397ef3

Browse files
committed
Update optics.py
1 parent 1b00a32 commit d397ef3

File tree

1 file changed

+55
-22
lines changed

1 file changed

+55
-22
lines changed

deeptrack/optics.py

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ def get(
285285
# Grab objective properties to pass to sample
286286
objective_properties = self._objective.properties()
287287

288+
#TODO: TBE
289+
"""
288290
# Calculate required output image for the given upscale.
289291
# This upscale way will be deprecated in favor of dt.Upscale().
290292
_upscale_given_by_optics = objective_properties["upscale"]
@@ -296,79 +298,110 @@ def get(
296298
*objective_properties["voxel_size"], *_upscale_given_by_optics
297299
)
298300
):
301+
"""
302+
303+
with u.context(create_context(*objective_properties["voxel_size"])):
299304

300305
upscale = np.round(get_active_scale())
301306

302-
output_region = objective_properties.pop("output_region")
303-
objective_properties["output_region"] = [
304-
int(o * upsc)
305-
for o, upsc in zip(
306-
output_region, (upscale[0], upscale[1], upscale[0], upscale[1])
307-
)
308-
]
309-
310-
padding = objective_properties.pop("padding")
311-
objective_properties["padding"] = [
312-
int(p * upsc)
313-
for p, upsc in zip(
314-
padding, (upscale[0], upscale[1], upscale[0], upscale[1])
315-
)
316-
]
307+
def _scale_region_2d(
308+
region: list[int],
309+
upscale: tuple[float, float, float],
310+
) -> list[int]:
311+
"""Scale a 4-tuple region (x_min, y_min, x_max, y_max) or
312+
padding using the lateral upscale factors (ux, uy)."""
313+
ux, uy, _ = upscale
314+
return [int(v * f) for v, f in zip(region, (ux, uy, ux, uy))]
317315

316+
# Scale output region from optics into sample voxel units.
317+
output_region = objective_properties.pop("output_region")
318+
objective_properties["output_region"] = _scale_region_2d(
319+
output_region,
320+
upscale,
321+
)
318322
self._objective.output_region.set_value(
319323
objective_properties["output_region"]
320324
)
325+
326+
# Scale padding region in the same way (left, top, right, bottom).
327+
padding = objective_properties.pop("padding")
328+
objective_properties["padding"] = _scale_region_2d(
329+
padding,
330+
upscale,
331+
)
321332
self._objective.padding.set_value(objective_properties["padding"])
322333

334+
# Propagate all relevant properties from the objective to the
335+
# sample graph. This ensures scatterers are evaluated in the
336+
# same voxel size, output region, and padding as the optics.
337+
# The extra flag `return_fft=True` is forced here because most
338+
# objectives (e.g., Brightfield, Holography) operate in Fourier
339+
# space, and they require scatterers to provide Fourier-domain
340+
# data in addition to real-space volumes.
323341
propagate_data_to_dependencies(
324-
self._sample, **{"return_fft": True, **objective_properties}
342+
self._sample,
343+
**{"return_fft": True, **objective_properties},
325344
)
326345

346+
# Evaluate the sample feature to obtain scatterers.
347+
# The result may be a single scatterer or a list of them.
327348
list_of_scatterers = self._sample()
328-
329349
if not isinstance(list_of_scatterers, list):
330350
list_of_scatterers = [list_of_scatterers]
331351

332352
# All scatterers that are defined as volumes.
333-
volume_samples = [
353+
# Volume scatterers occupy voxels in 3D (e.g. PointParticle).
354+
volume_scatterers = [
334355
scatterer
335356
for scatterer in list_of_scatterers
336357
if not scatterer.get_property("is_field", default=False)
337358
]
338359

339360
# All scatterers that are defined as fields.
340-
field_samples = [
361+
# Field scatterers provide a complex field directly,
362+
# bypassing volume merge.
363+
field_scatterers = [
341364
scatterer
342365
for scatterer in list_of_scatterers
343366
if scatterer.get_property("is_field", default=False)
344367
]
345368

369+
370+
371+
372+
373+
374+
375+
346376
# Merge all volumes into a single volume.
347377
sample_volume, limits = _create_volume(
348-
volume_samples,
378+
volume_scatterers,
349379
**objective_properties,
350380
)
351381
sample_volume = Image(sample_volume)
352382

353383
# Merge all properties into the volume.
354-
for scatterer in volume_samples + field_samples:
384+
for scatterer in volume_scatterers + field_scatterers:
355385
sample_volume.merge_properties_from(scatterer)
356386

357387
# Let the objective know about the limits of the volume and all the fields.
358388
propagate_data_to_dependencies(
359389
self._objective,
360390
limits=limits,
361-
fields=field_samples,
391+
fields=field_scatterers,
362392
)
363393

364394
imaged_sample = self._objective.resolve(sample_volume)
365395

396+
#TODO: TBE
397+
"""
366398
# Handling separately upscale given by optics.
367399
# This upscale way will be deprecated in favor of dt.Upscale().
368400
if _upscale_given_by_optics != (1, 1, 1):
369401
imaged_sample = AveragePooling((*_upscale_given_by_optics[:2], 1))(
370402
imaged_sample
371403
)
404+
"""
372405

373406
return imaged_sample
374407

0 commit comments

Comments
 (0)