function [calculated_params] = RegistrationDriver(optreg,calculated_params)

two_sided_reg = optreg.two_sided_reg;
glue_first_to_first = optreg.glue_first_to_first;
glue_last_to_last = optreg.glue_last_to_last;
first_moving_stack = optreg.first_moving_stack;
first_target_stack = optreg.first_target_stack;
last_moving_stack = optreg.last_moving_stack;
last_target_stack = optreg.last_target_stack;
moving_dataset_directory = optreg.moving_dataset_directory;
target_dataset_directory = optreg.target_dataset_directory;
long_jump = optreg.long_jump;
offset_initial_reg_time_point = optreg.offset_initial_reg_time_point;
offset_final_reg_time_point = optreg.offset_final_reg_time_point;
time_offset = optreg.time_offset;
register_moving_forward = optreg.register_moving_forward;
register_target_forward = optreg.register_target_forward;

only_calculate_direct_cross_reg = optreg.only_calculate_direct_cross_reg;
only_use_existing_direct_cross_reg = optreg.only_use_existing_direct_cross_reg;
fix_total_number_stacks = optreg.fix_total_number_stacks;

calculate_moving_reg = optreg.calculate_moving_reg;
use_existing_mov_reg = optreg.use_existing_mov_reg;

calculate_target_reg = optreg.calculate_target_reg;
use_existing_tar_reg = optreg.use_existing_tar_reg;

calculate_indirect_cross_reg = optreg.calculate_indirect_cross_reg;
use_existing_indirect_cross_reg = optreg.use_existing_indirect_cross_reg;

register_compose_type = optreg.register_compose_type;
do_theta = optreg.do_theta;
only_calculate_direct_last = optreg.only_calculate_direct_last;

refine_alignments = optreg.refine_alignments;

optreg.time_offset

if two_sided_reg
    
    if ~glue_first_to_first
        
        if offset_initial_reg_time_point
            first_moving_stack_temp = first_target_stack - time_offset;
            first_target_stack_temp = first_target_stack;
            if (first_moving_stack_temp > last_moving_stack)  || (first_moving_stack_temp<first_moving_stack)
                fprintf('time offset of first moving point went as far as it could go.  Trying to move first target.');
                first_moving_stack_temp = first_moving_stack;
                first_target_stack_temp = first_moving_stack + time_offset;
                if (first_target_stack_temp < first_target_stack) || (first_target_stack_temp > last_target_stack)
                    fprintf(['time offset of first target point went as far as it could go.  \r could not successfully adjust first time points' ...
                    'quitting.']);
                    return
                end
            end
            first_moving_stack = first_moving_stack_temp;
            first_target_stack = first_target_stack_temp;
        else
            if first_moving_stack > first_target_stack
                first_target_stack = first_moving_stack;
            else
                first_moving_stack = first_target_stack;
            end
        end
        
    else
        %leave as is
    end
    
    if ~glue_last_to_last
        
        if offset_final_reg_time_point
            last_target_stack_temp = last_moving_stack + time_offset;
            last_moving_stack_temp = last_moving_stack;
            if (last_target_stack_temp > last_target_stack) || (last_target_stack_temp < first_target_stack)
                fprintf('time offset of last target point went as far as it could go.  Trying to adjust last moving.');
                last_target_stack_temp  = last_target_stack;
                last_moving_stack_temp = last_target_stack - time_offset;
                if last_moving_stack_temp > last_moving_stack || last_moving_stack_temp < first_moving_stack
                    fprintf('time offset of last moving stack went as far as it could go.  \r could not successfully adjust last time points. quitting.')
                return
                end
            end
            last_target_stack = last_target_stack_temp;
            last_moving_stack = last_moving_stack_temp;
        else
            if last_moving_stack > last_target_stack
                last_moving_stack = last_target_stack;
            else
                last_target_stack = last_moving_stack;
            end
        end
        
    else
        % leave as is
    end
    
end

cd(moving_dataset_directory)

% For direct cross registrations, have to have the same number of stacks in
% each group.  Force this by increasing the first stacks up to meet each
% % other.
if only_calculate_direct_cross_reg || only_use_existing_direct_cross_reg || fix_total_number_stacks
    difference = (last_moving_stack - first_moving_stack) - (last_target_stack - first_target_stack);
    if difference > 0
        first_moving_stack = first_moving_stack + difference;
        fprintf('taking later first_moving_stack so that number of stacks in both groups will be the same');
    else
        first_target_stack = first_target_stack - difference;
    end
end


calculated_params.corrected_first_moving_stack = first_moving_stack;
calculated_params.corrected_last_moving_stack = last_moving_stack;
calculated_params.corrected_first_target_stack = first_target_stack;
calculated_params.corrected_last_target_stack = last_target_stack;
first_moving_stack
last_moving_stack
first_target_stack
last_target_stack

if only_calculate_direct_last
        moving_moves = true;
        target_targeted = true;
    if do_theta
        do_theta = true;
        for theta_n = 0:11
            RegisterByNucleiTheta(optreg,calculated_params,last_moving_stack,last_target_stack,moving_moves,target_targeted,do_theta,theta_n)
        end
        return
    else
        do_theta =false;
         RegisterByNucleiTheta(optreg,calculated_params,last_moving_stack,last_target_stack,moving_moves,target_targeted,do_theta,0)
         return
    end
end

% 
% if only_calculate_direct_cross_reg
%     moving_moves = true;
%     target_targeted = true;
%     for i = 1:(last_moving_stack-first_moving_stack+1)
%         RegisterByNucleiBase(optreg,calculated_params,first_moving_stack+i-1,first_target_stack+i-1,moving_moves,target_targeted,false,0)
%     end
%     return
% elseif only_use_existing_direct_cross_reg
%     fprintf('This option (direct transforms exist, make images) currently unimplemented.')
%     return
% end


% do the moving registrations if necessary

if calculate_moving_reg
     
     moving_moves = true; target_targeted = false;
%     
%     if isequal(register_compose_type,'direct')
%         for i = first_moving_stack:last_moving_stack
%                 % register callable 6 has to save everything in the correct
%                 % directories.
%                 if ~do_theta
%                     if register_moving_forward
%                         RegisterByNucleiBase(optreg,calculated_params,i,last_moving_stack,moving_moves,target_targeted,false,0)
%                     else
%                         RegisterByNucleiBase(optreg,calculated_params,i,first_moving_stack,moving_moves,target_targeted,false,0)
%                     end
%                 elseif do_theta
%                     for theta_n = 0:11
%                         if register_moving_forward
%                             RegisterByNucleiBase(optreg,calculated_params,i,last_moving_stack,moving_moves,target_targeted,false,0,theta_n)
%                         else
%                             RegisterByNucleiBase(optreg,calculated_params,i,first_moving_stack,moving_moves,target_targeted,false,0,theta_n)
%                         end
%                     end
%                 end
%         end
        
    if isequal(register_compose_type,'short_jumps')
        counter = 0;
        for i = first_moving_stack:last_moving_stack
            
                counter = counter + 1;
                if register_moving_forward
                    if i+1<=last_moving_stack
                    ParameterCellMov{counter} = {optreg,calculated_params,i,i+1,moving_moves,target_targeted,false,0};
                    elseif i == last_moving_stack
                    ParameterCellMov{counter} = {optreg,calculated_params,i,i,moving_moves,target_targeted,false,0};
                    end
                elseif ~register_moving_forward
                    if i-1>=first_moving_stack
                    ParameterCellMov{counter} = {optreg,calculated_params,i,i-1,moving_moves,target_targeted,false,0};
                    elseif i == first_moving_stack
                    ParameterCellMov{counter} = {optreg,calculated_params,i,i,moving_moves,target_targeted,false,0};
                    end
                end
                                
        end
        
        resultCell = startmulticoremaster(@RegisterByNucleiBase, ParameterCellMov);
        
    elseif isequal(register_compose_type,'short_and_long_jumps')
        counter = 0;
        for i = first_moving_stack:last_moving_stack
            for j = 1:long_jump
                if register_moving_forward
                    if (i+j) <= last_moving_stack
                        counter = counter + 1;
                        ParameterCellMov{counter} = {optreg,calculated_params,i,i+j,moving_moves,target_targeted,false,0};
                    elseif (i == last_moving_stack) && (j == 1)
                        counter = counter +1;
                        ParameterCellMov{counter} = {optreg,calculated_params,i,last_moving_stack,moving_moves,target_targeted,false,0};
                    end
                else
                    if (i-j) >= first_moving_stack
                        counter = counter +1;
                        ParameterCellMov{counter} = {optreg,calculated_params,i,i-j,moving_moves,target_targeted,false,0};
                    elseif (i == first_moving_stack) && (j == 1)
                        counter = counter +1;
                        ParameterCellMov{counter} = {optreg,calculated_params,i,first_moving_stack,moving_moves,target_targeted,false,0};
                    end
                end
            end
        end
        
        resultCell = startmulticoremaster(@RegisterByNucleiBase, ParameterCellMov);
        
    elseif isequal(register_compose_type,'long_jumps')
         for i = first_moving_stack:last_moving_stack
             if register_moving_forward
                 if i + long_jump <= last_moving_stack
                     RegisterByNucleiBase(optreg,calculated_params,i,i+long_jump,moving_moves,target_targeted,false,0)
                 elseif i == last_moving_stack
                     RegisterByNucleiBase(optreg,calculated_params,i,last_moving_stack,moving_moves,target_targeted,false,0)
                 end
             else
                 if (i-long_jump) >= first_moving_stack
                       RegisterByNucleiBase(optreg,calculated_params,i,i-long_jump,moving_moves,target_targeted,false,0)
                 elseif i == first_moving_stack
                       RegisterByNucleiBase(optreg,calculated_params,i,first_moving_stack,moving_moves,target_targeted,false,0)
                 end
             end
         end
    end

end

% Do the target side registrations if necessary

if calculate_target_reg
     
     moving_moves = false; target_targeted = true;
     
%     if isequal(register_compose_type,'direct')
%         for i = first_target_stack:last_target_stack
%                 % register callable 6 has to save everything in the correct
%                 % directories.
%                 
%                 if register_target_forward
%                     RegisterByNucleiBase(optreg,calculated_params,i,last_target_stack,moving_moves,target_targeted,false,0)
%                 else
%                     RegisterByNucleiBase(optreg,calculated_params,i,first_target_stack,moving_moves,target_targeted,false,0)
%                 end
%         end
        
    if isequal(register_compose_type,'short_jumps')
        counter = 0;
        for i = first_target_stack:last_target_stack
            
            counter = counter +1;
                if register_target_forward
                    if i+1<= last_target_stack
                    ParameterCellTar{counter} = {optreg,calculated_params,i,i+1,moving_moves,target_targeted,false,0};
                    elseif i == last_target_stack
                    ParameterCellTar{counter} = {optreg,calculated_params,i,i,moving_moves,target_targeted,false,0};
                    end
                elseif ~register_target_forward
                    if i-1 >= first_target_Stack
                    ParameterCellTar{counter} = {optreg,calculated_params,i,i-1,moving_moves,target_targeted,false,0};
                    elseif i == first_target_stack
                    ParameterCellTar{counter} = {optreg,calculated_params,i,i,moving_moves,target_targeted,false,0};
                    end
                end

        end
        
        nothing = startmulticoremaster(@RegisterByNucleiBase, ParameterCellTar);

        
    elseif isequal(register_compose_type,'short_and_long_jumps')
        counter =0;
        for i = first_target_stack:last_target_stack
            for j = 1:long_jump
                if register_target_forward
                    if (i+j) <= last_target_stack
                        counter = counter + 1;
                        ParameterCellTar{counter} = {optreg,calculated_params,i,i+j,moving_moves,target_targeted,false,0};
                    elseif (i == last_target_stack) && (j == 1)
                        counter = counter + 1;
                        ParameterCellTar{counter} = {optreg,calculated_params,i,last_target_stack,moving_moves,target_targeted,false,0};
                    end
                elseif ~register_target_forward
                    if (i-j) >= first_target_stack
                        counter = counter + 1;
                        ParameterCellTar{counter} = {optreg,calculated_params,i,i-j,moving_moves,target_targeted,false,0};
                    elseif (i == first_target_stack)&&(j == 1)
                        counter = counter + 1;
                        ParameterCellTar{counter} = {optreg,calculated_params,i,first_target_stack,moving_moves,target_targeted,false,0};
                    end
                end
            end
        end
        
        nothing = startmulticoremaster(@RegisterByNucleiBase, ParameterCellTar);
        
    elseif isequal(register_compose_type,'long_jumps')
         for i = first_target_stack:last_target_stack
             if register_target_forward
                 if i + long_jump < last_target_stack
                     RegisterByNucleiBase(optreg,calculated_params,i,i+long_jump,moving_moves,target_targeted,false,0)
                 elseif i == last_target_stack
                     RegisterByNucleiBase(optreg,calculated_params,i,last_target_stack,moving_moves,target_targeted,false,0)
                 end
             elseif ~register_target_forward
                 if (i-long_jump) >= first_target_stack
                       RegisterByNucleiBase(optreg,calculated_params,i,i-long_jump,moving_moves,target_targeted,false,0)
                 elseif i == first_target_stack
                       RegisterByNucleiBase(optreg,calculated_params,i,first_target_stack,moving_moves,target_targeted,false,0)
                 end
             end
         end
    end
end

if calculate_indirect_cross_reg
        RegisterByNucleiCross(optreg,first_moving_stack,first_target_stack,true,true,false,0)
end

% Having done necessary registrations, now do compositions of
% registrations.

if calculate_moving_reg || use_existing_mov_reg
    moving_moves = true;
    if isequal(register_compose_type,'direct')
        % do nothing
    elseif isequal(register_compose_type,'short_jumps')||isequal(register_compose_type,'long_jumps')||isequal(register_compose_type,'short_and_long_jumps')
        clear ParameterCellMov
        for i = first_moving_stack:last_moving_stack
        ParameterCellMov{i-first_moving_stack+1} = {optreg,i,first_moving_stack,last_moving_stack,moving_moves};
        end
        nothing = startmulticoremaster(@ComposeRegistrationsSelf,ParameterCellMov);
    end
end

if calculate_target_reg || use_existing_tar_reg
    moving_moves = false;
    if isequal(register_compose_type,'direct')
        % do nothing
    elseif isequal(register_compose_type,'short_jumps')||isequal(register_compose_type,'long_jumps')||isequal(register_compose_type,'short_and_long_jumps')
        for i = first_target_stack:last_target_stack
        ParameterCellTar{i-first_target_stack+1} = {optreg,i,first_target_stack,last_target_stack,moving_moves};
        end
        nothing = startmulticoremaster(@ComposeRegistrationsSelf,ParameterCellTar);
    end
end

if calculate_indirect_cross_reg || use_existing_indirect_cross_reg
    clear ParameterCell;
    for i = first_moving_stack:last_moving_stack
    ParameterCell{i-first_moving_stack+1} = {optreg,i,first_moving_stack,last_moving_stack,first_target_stack,last_target_stack};
    end
    nothing = startmulticoremaster(@ComposeRegistrationsOther, ParameterCell);
end


if refine_alignments
    optreg.nuclei_2D = false;
    optreg.nuclei_fix_centroid = false;
    RefineAlignmentsWrapper
end