function output = gtPlaceSubVolume(output, input, shift, index, assign_op, use_c_functions) % GTPLACESUBVOLUME Analogous to gtPlaceSubImage % output = gtPlaceSubVolume(output, input, shift, index, assign_op, use_c_functions) % ---------------------------------------------------------------------------------- % places the input volume in the output vol, with the origin of the % input volume at point defined by shift = [x y z] in the output % volume. % Any part of the input volume falling outside of the output volume is % cropped. % Origin can contain negative coordinates, again anything outside the % output volume is cropped. % So... shift = [0 0 0] means that the voxel (a, b, c) in input will be % at point (a, b, c) in the output. % shift=[2 -2 0] means that voxel (a, b, c) will be at (a+2, b-2, c) in % output. % % if the output volume has more than 3 dimensions, the shifts have to % be extended in order to select the position in the next dimensions. % Otherwhise ones will be placed % However, the placing will still happen in the first 3 dimensions % % Note - this is used to add on volume to another one, rather than % placing one image in the other. % I have modified so it no longer adds it. I hope this doesn't break % anything. % % Note 2 - If index is 0, the volume will be copied as it is, otherwise % all the voxels will have value of the index if (~exist('use_c_functions', 'var') || isempty(use_c_functions)) use_c_functions = false; end if (~exist('index', 'var') || isempty(index)) index = 0; end if (~exist('assign_op', 'var') || isempty(assign_op)) assign_op = 'assign'; end if (index ~= 0) input = index .* input; end if (all(shift == round(shift))) output = place_sub_volume(output, input, shift, assign_op, use_c_functions); else inds = shift ~= round(shift); pos_inds = find(inds); output = place_sub_volume_at_inds(pos_inds, 1, output, input, shift, assign_op, use_c_functions); end end function output = place_sub_volume_at_inds(pos_inds, coeff, output, input, shift, assign_op, use_c_functions) if (isempty(pos_inds)) output = place_sub_volume(output, coeff * input, shift, assign_op, use_c_functions); else ind = pos_inds(1); l_s_ind = floor(shift(ind)); u_s_ind = l_s_ind + 1; l_c_ind = u_s_ind - shift(ind); u_c_ind = 1 - l_c_ind; l_shift = shift; l_shift(ind) = l_s_ind; u_shift = shift; u_shift(ind) = u_s_ind; if (l_c_ind > 0) output = place_sub_volume_at_inds(pos_inds(2:end), l_c_ind * coeff, output, input, l_shift, assign_op, use_c_functions); end if (u_c_ind > 0) output = place_sub_volume_at_inds(pos_inds(2:end), u_c_ind * coeff, output, input, u_shift, assign_op, use_c_functions); end end end function output = place_sub_volume(output, input, shift, assign_op, use_c_functions) inputSize = size(input); outputSize = size(output); num_input_dims = numel(inputSize); num_output_dims = numel(outputSize); if (num_input_dims > 3) error('gtPlaceSubVolume:wrong_argument', ... 'the subvolume to place should have dimensionality only up to 3D') end if (num_input_dims > num_output_dims) warning('gtPlaceSubVolume:wrong_argument', ... 'the subvolume has a bigger dimensionality than the output volume') end % Force third dimension to be explicitly given inputSize((num_input_dims+1):3) = 1; outputSize((num_output_dims+1):3) = 1; shift((numel(shift)+1):num_output_dims) = 0; % output and input volume limits [outLims, inLims] = gtGetVolsIntersectLimits(outputSize(1:3), inputSize, shift(1:3)); if (use_c_functions) shifts_op = [outLims(1, :) - 1, shift(4:end)]; shifts_ip = inLims(1, :) - 1; dims = outLims(2, :) - outLims(1, :) + 1; % Logicals are not handled in the C++ function is_out_logical = islogical(output); if (is_out_logical) output = uint8(output); end if (islogical(input)) input = uint8(input); end type_input = class(input); type_output = class(output); if (~strcmpi(type_output, type_input)) warning('gtPlaceSubVolume:heterogeneous_types', ... 'Converting input (%s) to output type (%s), it may reduce performance', ... type_input, type_output) input = cast(input, type_output); end switch (assign_op) case {'zero', 'conflict', 'adaptive'} % Mark overlapping... output = gtCxxPlaceSubVolumeInterf(output, input, shifts_op, shifts_ip, dims); case 'summed' output = gtCxxPlaceSubVolumeSum(output, input, shifts_op, shifts_ip, dims); case {'assign', 'parent'} output = gtCxxPlaceSubVolumeAssign(output, input, shifts_op, shifts_ip, dims); otherwise error('PLACE:wrong_argument', 'No option for "%s"', assign_op); end if (is_out_logical) output = logical(output); end else % please keep them around, in case you break the C function input = input( ... inLims(1, 1):inLims(2, 1), ... inLims(1, 2):inLims(2, 2), ... inLims(1, 3):inLims(2, 3) ); lims = [ ... outLims(1, 1), outLims(2, 1), ... outLims(1, 2), outLims(2, 2), ... outLims(1, 3), outLims(2, 3) ]; % We add one because the shifting is done in matlab code! extra_dims_shift = arrayfun(@(x){x+1}, shift(4:num_output_dims)); full_output = output; if (~isempty(extra_dims_shift)) output = full_output(:, :, :, extra_dims_shift{:}); end temp_out = output(lims(1):lims(2), lims(3):lims(4), lims(5):lims(6)); switch (assign_op) case {'zero', 'conflict', 'adaptive'} temp_out(temp_out & input) = -1; indexes = ((temp_out == 0) & input); temp_out(indexes) = input(indexes); case 'summed' temp_out = temp_out + input; case {'assign', 'parent'} indexes = input ~= 0; temp_out(indexes) = input(indexes); otherwise error('PLACE:wrong_argument', 'No option for "%s"', assign_op); end output(lims(1):lims(2), lims(3):lims(4), lims(5):lims(6)) = temp_out; if (~isempty(extra_dims_shift)) full_output(:, :, :, extra_dims_shift{:}) = output; output = full_output; end end end