Dear Dr. Qianqian Fang and mmcusers,
Thank you for developing and continuously improving the MMC software suite. I was recently introduced to it and have been exploring the example codes.
While reviewing demo_wide_det.m, I noticed two sections related to the detector setup:
'srcparam1', [40 0 0 40], 'srcparam2', [0 40 0 40]);
[cfg.node, cfg.elem] = mmcadddet(node, elem, detdef);
cfg.detparam1 = [40.0 0.0 0.0 40];
cfg.detparam2 = [0.0 40.0 0.0 40];
I was wondering what the difference is between these two definitions. I also noticed that cfg.saveexit is set to 2 in this demo, and when I tested it, the resulting detphoton size appeared to depend on the definition in section (2).
Lastly, could you please clarify what distinguishes a wide-field detector from a normal planar detector in this context?
Thank you very much for your time and for creating such a powerful and well-documented tool.
Best regards,
Xiuxiu
hi Xiuxiu, sorry for the delay
see my replies below
You don't often get email from zha...@seas.upenn.edu. Learn why this is important
Dear Dr. Qianqian Fang and mmcusers,
Thank you for developing and continuously improving the MMC software suite. I was recently introduced to it and have been exploring the example codes.
supporting widefield source (i.e. photons are launched or received from outside of the target domain) or detector is more complex in mmc than mcx.
in mmc, the mesh must be modified in order to cover the source or detector if they are located outside of the object mesh. for details, please see this previous BOE paper
https://opg.optica.org/boe/fulltext.cfm?uri=boe-7-1-171
we call this mesh modification (extending from the domain's
original mesh to include the source/detector aperture) as "mesh
retessellation" - this is a required pre-processing step for all
widefield mmc simulations.
While reviewing demo_wide_det.m, I noticed two sections related to the detector setup:
- detdef = struct('srctype', 'planar', 'srcpos', [10, 10, -1], 'srcdir', [0 0 1], ...
'srcparam1', [40 0 0 40], 'srcparam2', [0 40 0 40]);
[cfg.node, cfg.elem] = mmcadddet(node, elem, detdef);
the above two lines performs the mesh retesellation - and returns the extended mesh in cfg.node and cfg.elem. you can plot them before (plotmesh(node, elem)) and after (plotmesh(cfg.node, cfg.elem)) this step to see the difference.
a side note, for wide field sources, you call mmcaddsrc().
- cfg.detpos = [10.0, 10.0, -1.0, 0];
cfg.detparam1 = [40.0 0.0 0.0 40];
cfg.detparam2 = [0.0 40.0 0.0 40];
these tells mmc simulation about the detector position and x/y
spans. These parameters must match the parameter used for
extending the mesh above.
I was wondering what the difference is between these two definitions.
you need both steps for widefield detector to work
I also noticed that cfg.saveexit is set to 2 in this demo, and when I tested it, the resulting detphoton size appeared to depend on the definition in section (2).
if you don't set cfg.saveexit to 2, all individual photons
arriving at the above wideifeld detector's "aperture" will be
captured and stored as the "detected photon" data, but for
widefield detectors, this file can be huge - even you can save
those, you still need to load them and post-process.
when setting cfg.saveexit to 2, this triggers mmc to use a
simplified output mode - all photons arriving at the detectors are
binned and summed to output a 2D array of intensities, as if it is
a CCD/CMOS detector.
an alternative to cfg.saveexit=2 is to use the diffuse
reflectance output on the domain surface by setting
cfg.issaveref=1 - in this case, you obtain light intensities on
all surface triangles,
https://github.com/fangq/mmc/blob/v2025.10/mmclab/mmclab.m#L161-L167
this does not require you to add a widefield detector. how you use this surface light intensity to obtain any widefield detector readings using integration as postprocessing, or if an integration is overkill (which is often the case), you can simply interpolate the surface diffuse reflectance at the detector pixel projection on the surface.
Lastly, could you please clarify what distinguishes a wide-field detector from a normal planar detector in this context?
in our software, we call any detectors (or sources) that are
located outside of the target domain (voxel, mesh) as "widefield".
for example, even a pencil beam that is launching photon from
outside of the domain is a widefield source.
this definition is not necessarily translatable to other context,
but we use it consistently in our tools/documentations.
let me know if these explanations help
Qianqian
Thank you very much for your time and for creating such a powerful and well-documented tool.
Best regards,
Xiuxiu
--
You received this message because you are subscribed to the Google Groups "mmc-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mmc-users+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/mmc-users/a809158b-39f3-4499-bf95-5fa46c9ae833n%40googlegroups.com.
I realized that this information is never explained in the demo.
I just added an explanation on how to set the pxiel count (via detparam1(4) and detparam2(4)), see this commit
https://github.com/fangq/mmc/commit/f65b5a79f60bf7017a047cc93c97d7561f686c04
the help info is copied below:
% cfg.detparam1: a 4-element vector: [u1, u2, u3,
Nx], define the x-axis of a widefield
% detector, [u1,u2,u3] is the x-axis
vector; Nx is the pixel count in the x-axis
% cfg.detparam2: a 4-element vector: [v1, v2, v3, Ny],
define the y-axis of a widefield
% detector, [v1,v2,v3] is the y-axis
vector; Ny is the pixel count in the y-axis
% cfg.issaveexit: [0]-whether to save the position
(x,y,z) and (vx,vy,vz) for a detected photon
% When issaveexit is set to 2, this signals
mmclab to output a 2D array
% a widefield detector defined by
cfg.detparam1 and cfg.detparam2.
% Specifically, instead of output
individual detected photon data,
% the exiting weight of all detected
photons are binned and summed
% into a detparam1(4)-by-detparam2(4)
pixelated output, covering
% the quadrilateral area with 4 corners
defined by (only 1:3 elem are used)
% [detpos, detpos+detparam1,
detpos+detparam1+detaram2, detpos+detparam2].
% When a widefield detector is used,
detector radii are ignored.
To view this discussion visit https://groups.google.com/d/msgid/mmc-users/05da3f45-2908-409e-ad74-c1d029ae39d0n%40googlegroups.com.
hi Xiuxiu,
see my replies below
Dear Dr. Fang,
Following up on the widefield detector setup, I have a few questions:
1. For cfg.detparam1 and cfg.detparam2, do the Nx and Ny components need to be specified when using cfg.issaveexit = 1?
widefield detection is only triggered when setting cfg.issaveexit=2, see the demo_wide_det.m sample script under mmclab/example
if you set cfg.issaveexit=2, then yes, both cfg.detparam1(4) and cfg.detparam2(4) must be set as Nx and Ny to determine the number of pixels of the widefield detector
2. When I generate a mesh box using
[node, face, elem] = meshabox([0 0 0],[20 20 20],0.05,1)
it seems that I am unable to add a widefield detector with
detdef = struct('srctype', 'planar', 'srcpos', [0, 0, 21], 'srcdir', [0 0 -1], ...
'srcparam1', [20 0 0 20], 'srcparam2', [0 20 0 20]);
[cfg.node, cfg.elem] = mmcadddet(node, elem, detdef);
In this case, plotmesh and mmclab do not run or produce any results. However, when I generate the mesh using
[node, face, elem] = latticegrid([0 20], [0 20], [0 20]);
c0(:, 4) = [0.05];
[node, elem] = surf2mesh(node, face, [], [], 1, [], c0);
the mesh works and the simulation runs normally. Is there a reason why meshabox behaves differently in this context?
the difference is in the label column of elem - when using surf2mesh with c0 as seeds, the output elem contains a 5th column, with label 1 for all elements.
in comparison, the elem produced by meshabox does not automatically label the elements, therefore only has 4 columns.
because mmcadddet calls the meshrefine() function in iso2mesh, which is a general-purpose mesh refinement function, it does not make mm-specific assumption on mmc mesh labels - if the input mesh to mmcadddet has the 5 column, mmcadddet will properly tag the refined elements covering the widefield det with the correct label (-2); but if your input mesh has only 4 columns, it does not add the needed det/src element labels (-1/-2).
to fix your meshabox based input, you just need to add
elem(:,5)=1
it should produce the same output as the latticegrid one.
I also committed this change to force it to add labels - although it could be problematic if the domain's base label is not 1
https://github.com/fangq/mmc/commit/4cbf7b1b289cd71833cd54c8caf6725a6db0a689
3. After setting up the widefield detector and running the simulation, the generated detid values are 305158 and 305276. Since I only defined one detector, I expected the detector ID to be 1. Could you explain why these large detector IDs appear?
when you run mmclab with issaveexit=2, the 2nd output, detp, should only have a single field, data, which is a 3D array (Nx by Ny by Nt),
where do you see detID?
To view this discussion visit https://groups.google.com/d/msgid/mmc-users/37af0581-c4d1-4fe0-ae19-4d5a796758d8n%40googlegroups.com.