Newer
Older
Laura Nervo
committed
function out = gtForwardSimulate_v2(first, last, workingdirectory, phaseID, varargin)
% GTFORWARDSIMULATE_V2 Finds missing diffraction spots and updates grain structure
Nicola Vigano
committed
% out = gtForwardSimulate_v2(first, last, workingdirectory, [phaseID], varargin)
% ------------------------------------------------------------------------------
Nicola Vigano
committed
% first = <int> first grainid
% last = <int> last grainid
% workingdirectory = <string> working directory
% phaseID = <int> phase ID
% varargin = parameters.fsim plus some additional
% options as in gtAppFsimExtraPars():
Nicola Vigano
committed
% OPTIONAL INPUT (p/v pairs):
% updateSample = <logical> true/false to update sample.mat and
% spot2grain.mat {true}
% updateDBtables = <logical> true/false to update DB table with
% 'grainID', 'phaseID', 'flag' {false}
% area_factor = <double> Weight for area criterion {1}
% position_factor = <double> Weight for UV position criterion {1}
% image_factor = <double> Weight for image criterion {1}
% int_factor = <double> Weight for intensity criterion {0}
%
% OPTIONAL INPUT for twin variants calculation (p/v pairs):
% variants = <logical> Use fsim relative to twin variants
% {false}
% plot_variants = <logical> Plot the variants orientation wrt to
% the parent orientation as XYZ crystal
% axes {false}
% num_variant = <double> Variant number to forward simulate
% {[]}
% twin_angle = <double> twin angle {[]}
% twin_axis = <double> twin axis {[]}
% twin_center = <double> alternative center for the twin (mm)
% or the twinID if available from the
% same indexed dataset {[]}
% twin_grain = <struct> twin grain structure for common spot
% properties and full image {[]}
Nicola Vigano
committed
% out = <struct> updated grain structure. Fields:
% .bl = <struct N> stack of normalized difblobs, along with metadata
% .proj.geom = <double> input for grain reconstruction
% / forward projection using ROI
% (hsize, vsize) (Nx12)
% .proj.geom_full = <double> input for grain reconstruction
% / forward projection (full images) (Nx12)
% .proj.geom_abs = <double> input for grain reconstruction
% / forward projection of extinction spots (Nx12)
% .proj.difstack = <double> stack of normalized difspots (XxYxN)
% .ondet = <double> indices of those spots (from the list in allblobs)
% which are expected on the detector
% .uvw = <double> spot positions on the detector (Nx3)
% .hklsp = <double> signed hk(i)l of reflection (Nx3(4))
% .hkl = <double> hk(i)l family for each reflection (Nx3(4))
% .flag = <int> status flag indicating result of forward simulation
% .allblobs = <struct> forward simulation output produced by gtIndexFwdSimGrains
% .used_fam = <double> List of unique HKL families used
% (theoretical)
% .used_famsp = <double> List of all the HKL families used
% (theoretical)
Nicola Vigano
committed
% We will classify spots with a flag [1...6]:
% - 1 : No intensity at expected spot position
% - 2 : Found intensity in FULL images at predicted position
% - 3 : Found segmented difspot at expected position - but position
% / size do not match strict criteria
% - 4 : Found segmented difspot in database matching the strict
% search criteria - we will use theoretically predicted
% angles for reconstruction
% - 5 : Difspot is part of a pair identified by INDEXTER - use
% Friedelpair information for reconstruction
% - 6 : Conflict difspot (if existing)
Nicola Vigano
committed
% Version 010 21-07-2014 by LNervo
% Extracted the ASTRA geometry and the gtFwdSimFindCandidates routines
% Version 009 14-05-2014 by LNervo
% Added check of used hkl families
%
Nicola Vigano
committed
% Version 008 25-04-2014 by LNervo
% Adapted to use twin forward simulation
%
% Version 007 Beginning-2014 by LNervo
% Modulized, simplified, added application parameters to update
% sample.mat and DB difspot table
%
% Version 006 18-12-2013 by LNervo
% Moduling a bit more...
Laura Nervo
committed
%
Nicola Vigano
committed
% Version 005 05/03/2013 by Nicola Vigano (nicola.vigano@esrf.fr)
% Re-structured completely, to be more clear and easy to debug.
Nicola Vigano
committed
%
% Version 004 21/06/2012 by AKing
% Trivial change to make segbb zeros(1, 6)
%
% Version 003 14-06-2012 by LNervo
% Use gtFsimDefaultParameters
Nicola Vigano
committed
if (isdeployed)
Nicola Vigano
committed
global GT_DB %#ok<NUSED,TLEV>
global GT_MATLAB_HOME %#ok<NUSED,TLEV>
load('workspaceGlobal.mat');
end
Laura Nervo
committed
cd(workingdirectory);
gtDBConnect();
Nicola Vigano
committed
parameters = gtLoadParameters();
if (~isfield(parameters, 'detgeo') || isempty(parameters.detgeo))
parameters.detgeo = gtGeoConvertLegacyLabgeo2Detgeo(parameters.labgeo);
Nicola Vigano
committed
end
detgeo = parameters.detgeo;
if (~isfield(parameters.labgeo, 'omstep') || isempty(parameters.labgeo.omstep))
parameters.labgeo.omstep = gtGetOmegaStepDeg(parameters);
Nicola Vigano
committed
end
labgeo = parameters.labgeo;
samgeo = parameters.samgeo;
Nicola Vigano
committed
Nicola Vigano
committed
if (~isfield(parameters.seg, 'writehdf5') || ~parameters.seg.writehdf5)
error('gtForwardSimulate_v2:wrong_parameter', ...
[ 'Segmentation has to write HDF5 blobs in order for ' ...
'ForwardSimulation to work properly. You can now create them ' ...
'using some of the conversion functions like "gtConvertRawImages2Blobs"' ])
end
if (~isfield(parameters.fsim, 'save_grain'))
Nicola Vigano
committed
parameters.fsim.save_grain = true;
end
Nicola Vigano
committed
if (~exist('phaseID', 'var') || isempty(phaseID))
phaseID = 1;
end
Nicola Vigano
committed
if (isdeployed)
Laura Nervo
committed
first = str2double(first);
last = str2double(last);
Nicola Vigano
committed
parameters.fsim.display_figure = false;
Nicola Vigano
committed
elseif (~isempty(varargin))
% in interactive mode we can modify parameters
Nicola Vigano
committed
[parameters.fsim, rej_pars] = parse_pv_pairs(parameters.fsim, varargin);
end
Nicola Vigano
committed
if (~exist('rej_pars', 'var'))
Nicola Vigano
committed
rej_pars = {};
Nicola Vigano
committed
indexgrainModel = fullfile(parameters.acq.dir, '4_grains', 'phase_%02d', 'index.mat');
Wolfgang Ludwig
committed
fprintf('\nLoading indexing results...\n');
grain = [];
Nicola Vigano
committed
load(sprintf(indexgrainModel, phaseID), 'grain');
Nicola Vigano
committed
totGrains = length(grain);
Nicola Vigano
committed
if (last > totGrains)
warning('gtForwardSimulate_v2:wrong_parameter', ...
'Last was bigger than the total number of grains, setting it to max')
last = totGrains;
end
difspotfile = fullfile(parameters.acq.dir, '2_difspot', '00000', 'difspot00001.edf');
Nicola Vigano
committed
if (exist(difspotfile, 'file'))
info = edf_info(difspotfile);
else
info = [];
end
Laura Nervo
committed
%%% this section should be replaced with a function dealing with different
% versions of parameters names: fed, v1, v2...
Nicola Vigano
committed
% !!! using a mean pixel size is uncertain; ideally fwd simulation should
% use mm-s
Nicola Vigano
committed
fprintf('\nLoading reflections from database..');
Nicola Vigano
committed
% Initialization of spot table and info about pairs
segmentedSpots = gtDBLoadTable([parameters.acq.name 'difspot'], 'difspotID');
pairsTable = gtDBLoadTable(parameters.acq.pair_tablename, 'pairID');
Nicola Vigano
committed
fprintf('(Done).\n')
Wolfgang Ludwig
committed
Nicola Vigano
committed
difspot_num = numel(segmentedSpots.difspotID); % number of difspots in database
Wolfgang Ludwig
committed
spot2grain = cell(difspot_num, 1); % cell array linking difspots with grainids
spot2phase = cell(difspot_num, 1);
Nicola Vigano
committed
filetable = [parameters.acq.name '_filetable'];
filename = fullfile(parameters.acq.dir, '4_grains', 'spot2grain.mat');
Wolfgang Ludwig
committed
spotTable = GtMergeTable(filetable, filename, {'spot2grain', 'spot2phase'});
Nicola Vigano
committed
samplefile = fullfile(parameters.acq.dir, '4_grains', 'sample.mat');
sample = GtSample.loadFromLockedFile(filetable, samplefile);
Wolfgang Ludwig
committed
% initialise sample structure
Nicola Vigano
committed
phase = GtPhase(parameters.cryst(phaseID).name, totGrains);
Wolfgang Ludwig
committed
sample.phases{phaseID} = phase;
Nicola Vigano
committed
% initialize output
out = [];
if (parameters.fsim.verbose)
Nicola Vigano
committed
disp('FwdSim parameters:')
Nicola Vigano
committed
print_structure(parameters.fsim, 'parameters.fsim', false, true)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Wolfgang Ludwig
committed
for n = first : last
Nicola Vigano
committed
fprintf('\nRunning forward simulation for grain %d:\n', n);
fprintf(' - Computing grain properties..');
gr = grain{n}; % output from INDEXTER
Laura Nervo
committed
%%% Predict spot positions
Nicola Vigano
committed
gr = gtCalculateGrain(gr, parameters);
uvw = gr.allblobs.detector(det_index).uvw;
Nicola Vigano
committed
%%% Get:
% - average difspot X and Y sizes for the current spots in the grain
% - theshold values used during the database search
% - offset in possible lateral grain orientation
% - diffstack Vertical and Horizontal sizes
spotsCommProps = gtFwdSimGetDiffspotsCommonProperties(gr, parameters, det_index);
Nicola Vigano
committed
%%% Get the indices of all spots which fully intersect the active
% region of the detector
Nicola Vigano
committed
onDet = gtFwdSimFindSpotsOnDetector(spotsCommProps, uvw, parameters);
fprintf(' (Done).\n - Producing blob masks..')
proj_bls = predict_spot_masks_from_indexed( ...
gr, grain, segmentedSpots, spotsCommProps, onDet, parameters);
fprintf(' (Done).\n - Preallocating structs..')
Nicola Vigano
committed
Nicola Vigano
committed
if (parameters.fsim.assemble_figure)
full = zeros(detgeo(det_index).detsizev, detgeo(det_index).detsizeu);
Nicola Vigano
committed
else
full = [];
end
% number of exspected diffraction spots
numspots = numel(onDet);
% Diffraction vectors directions
diff_beam_dirs = zeros(numspots, 3);
Nicola Vigano
committed
fprintf(' (Done).\n - Matching reflections and spots..');
Nicola Vigano
committed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nicola Vigano
committed
%%% Forward simulation:
% We try to match the reflections with the segmented spots, so we
% examine all hklsp and search corresponding spots / intensity on the
% detector..
Nicola Vigano
committed
%%% But also build the diffraction blob stack
[fwd_sim, bl] = forward_simulate_grain(gr, onDet, spotsCommProps, ...
segmentedSpots, proj_bls, parameters, det_index);
Nicola Vigano
committed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nicola Vigano
committed
%%% Re-check flag == 1, to see if there's intensity at the predicted
Nicola Vigano
committed
% position, if requested.
if (parameters.fsim.check_spot)
Nicola Vigano
committed
fprintf(' (Done).\n - Checking spots in Raw images..');
toBeChecked = find(fwd_sim.flag == 1);
for ii = reshape(toBeChecked, 1, []);
Nicola Vigano
committed
[found_intensity, spotInfo] = gtFwdSimCheckSpotInRawImages(...
Nicola Vigano
committed
uvw(onDet(ii), :), spotsCommProps, parameters);
Nicola Vigano
committed
if (found_intensity)
% Found intensity in FULL images at predicted position
Nicola Vigano
committed
if (parameters.fsim.assemble_figure)
full = gtPlaceSubImage2(spotInfo.spot, full, spotInfo.bb(1), spotInfo.bb(2), 'summed');
end
fwd_sim.check_spots(ii).info = spotInfo;
Nicola Vigano
committed
end
Nicola Vigano
committed
end
Nicola Vigano
committed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nicola Vigano
committed
% Reflections that have been matched to segmented spots
included = find(fwd_sim.flag >= 3);
Nicola Vigano
committed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nicola Vigano
committed
%%% We now build the diffraction stack
Nicola Vigano
committed
fprintf(' (Done).\n - Building difstack..');
difstack = gtFwdSimBuildDifstackSpots(fwd_sim.spotid, included, ...
parameters, spotsCommProps.stackUSize, spotsCommProps.stackVSize, ...
Nicola Vigano
committed
spotsCommProps.Xsize, spotsCommProps.Ysize, ...
Nicola Vigano
committed
if (parameters.fsim.assemble_figure)
% no padded spots
full = sfBuildFull(fwd_sim.spotid(included), ...
parameters, spotsCommProps, fwd_sim.bb(included, :));
Nicola Vigano
committed
end
Nicola Vigano
committed
fprintf(' (Done).\n - Building geometry..');
Nicola Vigano
committed
%%% Diffraction geometry
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
% diff_beam_dirs: direction of diffracted beam used in ASTRA
identif_indexed = fwd_sim.flag(included) == 5;
incl_indx = included(identif_indexed);
incl_not_indx = included(~identif_indexed);
% we found a segmented spot - can use the theoretically
% predicted direction or apparent direction (based on CoM of
% grain and spot) for backprojection
% If available, we want to use the angles as determined from
% the Friedel pairs - interrogate spotpair table
[diff_beam_dirs(incl_indx, :), fwd_sim.uvw(incl_indx, 3)] = sfGetFriedelPair( ...
pairsTable, fwd_sim.spotid(incl_indx), fwd_sim.spot_type(incl_indx) == 'a');
% Otherwise we have two choices
if (parameters.fsim.use_th)
% use theoretically predited directions (default)
fwd_sim.uvw(incl_not_indx, 3) = gr.allblobs.omega(onDet(incl_not_indx));
% theoretically predicted beam direction (in sample
% coordinate system)
diff_beam_dirs(incl_not_indx, :) = gr.allblobs.dvecsam(onDet(incl_not_indx), :);
else
% use experimentally determined omega angles (which we find in:
% fwd_sim.uvw(incl_not_indx, 3))
% projection direction as inferred from grain / spot center
% positions
diff_beam_dirs(incl_not_indx, :) = gtGeoDiffVecInSample( ...
fwd_sim.uvw(incl_not_indx, 1:2), fwd_sim.uvw(incl_not_indx, 3), ...
gr.center, detgeo(det_index), labgeo, samgeo);
Nicola Vigano
committed
end
%%% Selection of the spots
[selected, goodness] = gtFwdSimSelectSpots(fwd_sim.likelihood, fwd_sim.intensity, ...
fwd_sim.avg_pixel_int, fwd_sim.flag, included, parameters);
Nicola Vigano
committed
%%% We now Build ASTRA's geometry
proj = gtFwdSimBuildProjGeometry(...
diff_beam_dirs(included, :), gr.center, fwd_sim.uvw(included, 3), ...
fwd_sim.bb(included, :), parameters, ...
Nicola Vigano
committed
spotsCommProps.stackUSize, spotsCommProps.stackVSize, ...
selected);
Nicola Vigano
committed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Laura Nervo
committed
%%% Now fill in the information for the output
Wolfgang Ludwig
committed
% remove reflections for which no segmented spot has been found
out.id = gr.id;
out.phaseid = phaseID;
out.R_vector = gr.R_vector;
out.center = gr.center;
Nicola Vigano
committed
out.check = fwd_sim.check;
out.flag = fwd_sim.flag;
out.pairid = gr.pairid;
out.spotid = fwd_sim.spotid;
Nicola Vigano
committed
% only included spots info
out.cands = fwd_sim.cands(included);
out.likelihood = fwd_sim.likelihood(included);
out.difspotID = fwd_sim.spotid(included);
out.uv_exp = fwd_sim.uvw(included, 1:2);
out.om_exp = fwd_sim.uvw(included, 3);
out.bb_exp = fwd_sim.bb(included, :);
out.intensity = fwd_sim.intensity(included);
Nicola Vigano
committed
Nicola Vigano
committed
% save full image
out.full = full;
Nicola Vigano
committed
Nicola Vigano
committed
% check spot info
out.checkSpots = fwd_sim.check_spots;
Nicola Vigano
committed
% diffraction geometry
out.proj = proj;
Nicola Vigano
committed
% Selections
out.proj.ondet = onDet;
out.proj.included = included;
out.proj.selected = selected; % logicals with pre-selected active spots
Nicola Vigano
committed
% blob/spot stacks
Nicola Vigano
committed
out.proj.bl = bl(included);
Nicola Vigano
committed
out.proj.stack = difstack(:, included, :);
found_reflections = numel(find(fwd_sim.flag > 1));
Nicola Vigano
committed
out.completeness = found_reflections / numspots;
out.completeness_incl = numel(find(fwd_sim.flag >= 3)) / numspots;
Nicola Vigano
committed
out.goodness = goodness;
out.goodness_sel = mean(out.likelihood(selected));
out.confidence = out.goodness * out.completeness_incl;
Nicola Vigano
committed
if (parameters.fsim.save_grain)
Nicola Vigano
committed
fprintf(' (Done).\n - Saving ouput..');
Nicola Vigano
committed
end
Nicola Vigano
committed
if (parameters.fsim.display_figure)
fprintf(' (Done).\n - Displaying figure..');
Nicola Vigano
committed
Nicola Vigano
committed
displayShowFsim(phaseID, out, rej_pars{:})
end
Nicola Vigano
committed
fprintf(' (Done).\n\n');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Now update spotTables and sample
Nicola Vigano
committed
spot2grain(out.difspotID) = {n};
spot2phase(out.difspotID) = {phaseID};
Wolfgang Ludwig
committed
sample.phases{phaseID}.setR_vector(n, gr.R_vector);
Nicola Vigano
committed
sample.phases{phaseID}.setCompleteness(n, out.completeness);
Nicola Vigano
committed
sample.phases{phaseID}.setCenter(n, out.center); % center in pixels
if (isempty(out.proj.selected))
Nicola Vigano
committed
warning('gtForwardSimulate_v2:bad_value', ...
'No spot was selected! This will make reconstruction impossible')
elseif (numel(out.proj.selected) < 10)
Nicola Vigano
committed
warning('gtForwardSimulate_v2:bad_value', ...
'Too few selected spots! This will give a very bad reconstruction')
end
Nicola Vigano
committed
if (out.goodness < 0.25)
warning('gtForwardSimulate_v2:very_low_goodness', ...
[ 'Very low goodness (included %f, selected %f) indicates a' ...
' probably poor quality of grain reconstruction' ], ...
out.goodness, out.goodness_sel)
elseif (out.goodness < 0.5)
warning('gtForwardSimulate_v2:low_goodness', ...
[ 'Low goodness (included %f, selected %f) indicates a' ...
' possibly poor quality of grain reconstruction' ], ...
out.goodness, out.goodness_sel)
end
Nicola Vigano
committed
if (~parameters.fsim.check_spot)
Nicola Vigano
committed
fprintf(['Completeness estimates may be too pessimistic - activate ' ...
'option ''check_spot'' for more reliable results\n'])
end
fprintf('\n Grain number %d:\n', n);
newspots = length(find(fwd_sim.flag == 4));
Nicola Vigano
committed
fprintf(['Forward simulation found intensity at %d out of %d expected ' ...
'spot positions \n'], found_reflections, numspots);
fprintf('Completeness estimate: %f\n', out.completeness);
Nicola Vigano
committed
fprintf('Goodness estimate: included %f, selected %f\n', ...
out.goodness, out.goodness_sel);
fprintf('%d spots will be used for reconstruction\n', length(out.proj.selected));
Nicola Vigano
committed
fprintf(['%d new spots have been detected in addition to the %d ' ...
'spotpairs identified by INDEXTER\n'], newspots, gr.nof_pairs);
Nicola Vigano
committed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nicola Vigano
committed
if (parameters.fsim.save_grain)
Nicola Vigano
committed
% update difspot table in the DB
% keep list of difspots
Nicola Vigano
committed
spotID = out.spotid;
spotID(out.spotid == 0) = [];
flags = out.flag;
flags(out.spotid == 0) = [];
Nicola Vigano
committed
gtDBFillUpdateColumn([parameters.acq.name 'difspot'], ...
'grainID', 'int', 'integral', 'difspotID', {out.difspotID}, n)
gtDBFillUpdateColumn([parameters.acq.name 'difspot'], ...
'phaseID', 'int', 'integral', 'difspotID', {out.difspotID}, phaseID)
gtDBFillUpdateColumn([parameters.acq.name 'difspot'], ...
Nicola Vigano
committed
'flag', 'int', 'integral', 'difspotID', {spotID}, {flags});
Nicola Vigano
committed
end
Wolfgang Ludwig
committed
end
Nicola Vigano
committed
if (parameters.fsim.save_grain)
% fill spotTables
spotTable.fillTable(spot2grain, 'spot2grain');
spotTable.fillTable(spot2phase, 'spot2phase');
% save sample.mat
sample.mergeToFile(filetable, samplefile, 'sample');
end
Nicola Vigano
committed
end
Nicola Vigano
committed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% sub-functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nicola Vigano
committed
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Forward Simulation
function fwd_sim = gtFwdSimDataStructureDefinition(numspots)
fwd_sim = struct( ...
'flag', ones(numspots, 1), ... % see above
'bb', zeros(numspots, 4), ... % difspot BoundingBox from database
'cent', zeros(numspots, 1), ... % centroid distance from database added 06-02-2014 LNervo
'spotid', zeros(numspots, 1), ... % Mysql difspottable difspotID
'check', false(numspots, 2), ...
'intensity', zeros(numspots, 1), ... % Integrated blob intensity
'avg_pixel_int', zeros(numspots, 1), ... % Average pixel intensity in blob
'likelihood', zeros(numspots, 1), ... % Blob likelihood
'cands', struct( ...
'id', cell(numspots, 1), ...
'likelihood_tot', cell(numspots, 1), ...
'likelihood_proj_mask', cell(numspots, 1), ...
'likelihood_dev_uv', cell(numspots, 1), ...
'likelihood_dev_w', cell(numspots, 1) ), ...
'uvw', zeros(numspots, 3), ... % CoM positions of difspots from difspottable
'spot_type', char(zeros(numspots, 1)), ...
'check_spots', struct('info', cell(numspots, 1)) );
end
function [fwd_sim, bl] = forward_simulate_grain(gr, onDet, ...
spotsCommProps, segmentedSpots, proj_bls, parameters, det_index)
uvw = gr.allblobs.detector(det_index).uvw;
% number of exspected diffraction spots
numspots = numel(onDet);
% stack of zero padded diffraction spots (projections used for 3D reconstruction)
bl(1:numspots) = gtFwdSimBlobDefinition();
fwd_sim = gtFwdSimDataStructureDefinition(numspots);
% We try to match the reflections with the segmented spots, so we
% examine all hklsp and search corresponding spots / intensity on the
% detector..
%%% But also build the diffraction blob stack
for ii = 1:numspots
% Producing predicted spot's properties
spot_props = predict_spot_properties(spotsCommProps, proj_bls(ii), gr.stat, parameters);
% Look for difspots appying loose search criteria - is there any intensity at the predicted spot
% position ? Choose the one which is closest to the expected size
[candidateIDs, spotsCands] = gtFwdSimFindCandidates(spot_props, uvw(onDet(ii), :), segmentedSpots);
if (isempty(candidateIDs))
% NO CANDIDATES FOUND:
% segmentation / overlap / intensity / ... problem ?
if (spotsCands.found_intensity)
% A bigger spot was found in the region.. it may be an
% overlap
fwd_sim.flag(ii) = 2;
end
% If requested, we will check into the raw images later.
continue;
end
bls = gtFwdSimBuildDifstackBlobs(candidateIDs, [], parameters, ...
spotsCommProps.stackUSize, spotsCommProps.stackVSize);
proj_bl = proj_bls(ii * ones(numel(bls), 1));
% Computing spot area/shape deviation/likelihood
ls_pb = compute_proj_bbs_partial_likelihoods(bls, proj_bl);
refl_indx = onDet(ii) * ones(numel(bls), 1);
% Computing UV deviation/likelihood
th_uv = uvw(refl_indx, 1:2);
blobs_uv = [ spotsCands.CentroidX, spotsCands.CentroidY ];
ls_uv = compute_uv_partial_likelihoods(blobs_uv, th_uv, proj_bl);
% Computing W deviation/likelihood
th_w = gr.allblobs.omega(refl_indx);
blob_w = spotsCands.CentroidImage * parameters.labgeo.omstep;
ls_w = compute_w_partial_likelihoods(blob_w, th_w);
% in case there are several candidates, take the one with best
% likelihood in terms of: shape, UV position, and W position.
ls = ls_pb .* ls_uv .* ls_w;
[~, cand_inc_index] = max(ls);
fwd_sim.cands(ii).id = candidateIDs';
fwd_sim.cands(ii).likelihood_tot = ls';
fwd_sim.cands(ii).likelihood_proj_mask = ls_pb';
fwd_sim.cands(ii).likelihood_dev_uv = ls_uv';
fwd_sim.cands(ii).likelihood_dev_w = ls_w';
fwd_sim.spotid(ii) = candidateIDs(cand_inc_index);
bl(ii) = bls(cand_inc_index);
fwd_sim.uvw(ii, :) = [ ...
spotsCands.CentroidX(cand_inc_index), ...
spotsCands.CentroidY(cand_inc_index), ...
spotsCands.CentroidImage(cand_inc_index) * parameters.labgeo.omstep ];
fwd_sim.bb(ii, :) = [...
spotsCands.BoundingBoxXorigin(cand_inc_index), ...
spotsCands.BoundingBoxYorigin(cand_inc_index), ...
spotsCands.BoundingBoxXsize(cand_inc_index), ...
spotsCands.BoundingBoxYsize(cand_inc_index) ];
% The following should be beter than the previous, but it seems to
% geneterate problems
% fwd_sim.bb(ii, :) = bls(cand_inc_index).mbbsize([1 2 4 5]);
fwd_sim.intensity(ii) = bls(cand_inc_index).intensity;
fwd_sim.avg_pixel_int(ii) = fwd_sim.intensity(ii) / sum(bls(cand_inc_index).mask(:));
fwd_sim.likelihood(ii) = ls(cand_inc_index);
% Found a segmented difspot at expected position:
% we will check if it does match strict criteria
uv_ok = fwd_sim.cent(ii, :) <= spotsCommProps.Offset;
bb_ok = all( [...
between(fwd_sim.bb(ii, 3), spotsCommProps.XsizeMin, spotsCommProps.XsizeMax), ...
between(fwd_sim.bb(ii, 4), spotsCommProps.YsizeMin, spotsCommProps.YsizeMax) ] );
fwd_sim.check(ii, :) = [uv_ok, bb_ok];
isSpotA = any(gr.difspotidA == fwd_sim.spotid(ii));
isSpotB = any(gr.difspotidB == fwd_sim.spotid(ii));
if (isSpotA || isSpotB)
% This spot is part of a pair and has been used by INDEXTER
fwd_sim.flag(ii) = 5;
fwd_sim.spot_type(ii) = char('a' * isSpotA + 'b' * isSpotB);
elseif all(fwd_sim.check(ii, :))
fwd_sim.flag(ii) = 4; % This flag is kinda obsolete
else
fwd_sim.flag(ii) = 3;
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Support Functions
Nicola Vigano
committed
function full = sfBuildFull(spotid, parameters, spotsCommProps, bb)
% full = sfBuildFull(spotid, parameters, spotsCommProps, bb)
%
% spotid : spotid from grain
% parameters : parameters.mat
% spotsCommProps : spots common properties
% bb : bounding boxes from DB
Nicola Vigano
committed
full = zeros(parameters.detgeo.detsizev, parameters.detgeo.detsizeu, 'single');
Nicola Vigano
committed
Nicola Vigano
committed
for ii = 1:numel(spotid)
[spot, ~] = gtFwdSimBuildSpot(spotid(ii), parameters, spotsCommProps.Xsize, spotsCommProps.Ysize, bb(ii, :));
Nicola Vigano
committed
Nicola Vigano
committed
full = gtPlaceSubImage2(spot, full, bb(ii, 1), bb(ii, 2), 'summed');
Nicola Vigano
committed
end
end
Nicola Vigano
committed
function [diff_beam_dir, omega] = sfGetFriedelPair(pairsTable, spotID, isSpotA)
% [diff_beam_dirs, omega] = sfGetFriedelPair(pairsTable, spotID, isSpotA)
for ii = numel(spotID):-1:1
if (isSpotA(ii))
idx = find(pairsTable.difAID == spotID(ii));
omega(ii) = pairsTable.omega(idx);
diff_beam_dir(ii, :) = [pairsTable.ldirX(idx), pairsTable.ldirY(idx), pairsTable.ldirZ(idx)];
else
idx = find(pairsTable.difBID == spotID(ii));
omega(ii) = pairsTable.omegaB(idx);
% in this case we have to reverse the line direction
diff_beam_dir(ii, :) = -[pairsTable.ldirX(idx), pairsTable.ldirY(idx), pairsTable.ldirZ(idx)];
end
Nicola Vigano
committed
end
end
Nicola Vigano
committed
function displayShowFsim(phaseID, grain, varargin)
% displayShowFsim(phaseID, grain, varargin)
Nicola Vigano
committed
Nicola Vigano
committed
if isempty(varargin)
[vars_pars, vars_list] = gtAppFsimDefaultPars();
ind = findValueIntoCell(fieldnames(vars_pars), {'fsimtype', 'f_title'});
vars_list(ind(:, 1), 4) = {2};
Nicola Vigano
committed
Nicola Vigano
committed
vars_pars = gtModifyStructure(vars_pars, vars_list, 1, 'Options for displaying the Forward Sim:');
varargin = struct2pv(vars_pars);
Nicola Vigano
committed
gtShowFsim(grain, phaseID, varargin{:});
Nicola Vigano
committed
end
Nicola Vigano
committed
function proj_bls = predict_spot_masks_from_indexed(gr, grain_INDX, ...
segmentedSpots, spotsCommProps, onDet, parameters)
% First argument: included_INDXTR, might be needed in the future for
% some reason...
[~, difspotID_INDXTR] = gtFwdSimGetIndexterReflections(gr, grain_INDX{gr.id}, segmentedSpots);
% Producing blobs' boundingboxes (as by dilated segmentation info)
bls_INDXTR = gtFwdSimBuildDifstackBlobs(difspotID_INDXTR, [], ...
Nicola Vigano
committed
parameters, spotsCommProps.stackUSize, spotsCommProps.stackVSize);
Nicola Vigano
committed
% INDEXTER Data
Nicola Vigano
committed
BBus = cat(1, bls_INDXTR(:).mbbu);
BBvs = cat(1, bls_INDXTR(:).mbbv);
BBsizes = cat(1, bls_INDXTR(:).mbbsize);
BBs = [BBus(:, 1), BBvs(:, 1), BBsizes(:, 1:2)];
Nicola Vigano
committed
Ws = segmentedSpots.CentroidImage(difspotID_INDXTR) .* parameters.labgeo.omstep;
Nicola Vigano
committed
proj_bls = gtFwdSimPredictProjectedGrainBBox(gr, BBs, Ws, onDet, parameters);
% Producing original blobs' boundingboxes (as by original segmentation
% info)
BBs = [...
segmentedSpots.BoundingBoxXorigin(difspotID_INDXTR), ...
segmentedSpots.BoundingBoxYorigin(difspotID_INDXTR), ...
segmentedSpots.BoundingBoxXsize(difspotID_INDXTR), ...
segmentedSpots.BoundingBoxYsize(difspotID_INDXTR) ];
proj_bls_original = gtFwdSimPredictProjectedGrainBBox(gr, BBs, Ws, onDet, parameters);
for ii_b = 1:numel(proj_bls)
Nicola Vigano
committed
proj_bls(ii_b).mbbsize = proj_bls_original(ii_b).bbsize;
Nicola Vigano
committed
proj_bls(ii_b).mbbu = proj_bls_original(ii_b).bbuim;
proj_bls(ii_b).mbbv = proj_bls_original(ii_b).bbvim;
proj_bls(ii_b).mbbw = proj_bls_original(ii_b).bbwim;
Nicola Vigano
committed
end
end
function spot_props = predict_spot_properties(spotsCommProps, proj_bl, gr_stats, parameters)
bb_size_factor = parameters.fsim.bbsize_factor;
% Minimums could be wrong by up to 2 pixels (roundings)
Nicola Vigano
committed
spot_props.XsizeMin = max(5, proj_bl.mbbsize(1) - bb_size_factor * gr_stats.bbxsstd - 2);
spot_props.YsizeMin = max(5, proj_bl.mbbsize(2) - bb_size_factor * gr_stats.bbysstd - 2);
Nicola Vigano
committed
% Allowing for matching spots, even if the convex shape of the grain
% computed from indexter's selection had a limited angle view on the
% grain volume
spot_props.XsizeMin = min(spot_props.XsizeMin, spotsCommProps.XsizeMin);
spot_props.YsizeMin = min(spot_props.YsizeMin, spotsCommProps.YsizeMin);
Nicola Vigano
committed
spot_props.XsizeMax = proj_bl.mbbsize(1) + bb_size_factor * gr_stats.bbxsstd;
spot_props.YsizeMax = proj_bl.mbbsize(2) + bb_size_factor * gr_stats.bbysstd;
Nicola Vigano
committed
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
spot_props.thr_max_offset = spotsCommProps.thr_max_offset;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Likelihood computation
function ls = compute_uv_partial_likelihoods(blob_uv, th_uv, proj_bls)
proj_bbox(:, [1 3]) = cat(1, proj_bls(:).bbuim);
proj_bbox(:, [2 4]) = cat(1, proj_bls(:).bbvim);
blob_expected_sizes = proj_bbox(:, [3 4]) - proj_bbox(:, [1 2]) + 1;
ls = (th_uv - blob_uv) ./ max(blob_expected_sizes ./ 10, 10);
ls = exp(- (ls .^ 2) );
ls = ls(:, 1) .* ls(:, 2);
end
function ls = compute_w_partial_likelihoods(blob_w, th_w)
ls = 2 .* (th_w - blob_w);
ls = exp(- (ls .^ 2));
end
function ls = compute_proj_bbs_partial_likelihoods(bls, proj_bls)
bls_bboxes(:, [1, 3]) = cat(1, bls(:).bbuim);
bls_bboxes(:, [2, 4]) = cat(1, bls(:).bbvim);
proj_bls_bboxes(:, [1, 3]) = cat(1, proj_bls(:).bbuim);
proj_bls_bboxes(:, [2, 4]) = cat(1, proj_bls(:).bbvim);
cont_bbxes = [ ...
min(bls_bboxes(:, 1:2), proj_bls_bboxes(:, 1:2)), ...
max(bls_bboxes(:, 3:4), proj_bls_bboxes(:, 3:4)) ...
];
cont_bbxes = [cont_bbxes(:, 1:2), (cont_bbxes(:, 3:4) - cont_bbxes(:, 1:2) + 1)];
bls_shifts = bls_bboxes(:, 1:2) - cont_bbxes(:, 1:2);
bls_shifts(:, 3) = 0;
proj_bls_shifts = proj_bls_bboxes(:, 1:2) - cont_bbxes(:, 1:2);
proj_bls_shifts(:, 3) = 0;
num_bls = numel(proj_bls);
mismatch_more = zeros(num_bls, 1);
mismatch_less = zeros(num_bls, 1);
proj_count = zeros(num_bls, 1);
for ii = 1:num_bls
cont_size = cont_bbxes(ii, 3:4);
proj_count(ii) = sum(proj_bls(ii).mask(:));
bl_mask = bls(ii).mask;
bl_mask = sum(bl_mask, 3);
bl_mask = bl_mask > 0;
proj_bl_mask = logical(proj_bls(ii).mask);
bl_mask = gtPlaceSubVolume( ...
zeros(cont_size, 'uint8'), bl_mask, bls_shifts(ii, :));
proj_bl_mask = gtPlaceSubVolume( ...
zeros(cont_size, 'uint8'), proj_bl_mask, proj_bls_shifts(ii, :));
overlap = bl_mask & proj_bl_mask;
bl_mask(overlap) = 0;
proj_bl_mask(overlap) = 0;
mismatch_more(ii) = sum(bl_mask(:));
mismatch_less(ii) = sum(proj_bl_mask(:));
end
% 3 and 2 are temporary
ls = (1 .* mismatch_more + 1 .* mismatch_less) ./ proj_count;
ls = exp(- (ls .^ 2));
end