% im2pointsLocally    computes image statistics from several images
%                     and finds the projections of laser points
%
% The version for local computation on each machine
%
% The computation core is taken from  im2points.m
% computes average image and image of standard deviations
% requires read_configuration.m
% The name of the experiment has to be specified
% it determines the location of files etc ...
%
% the scripts serves as a template for a multiprocessing
% it assumes a vector of camera IDs CamIds to be known
% indexes in the CamIds are supposed to be correct
%

donefile = '.done';

addpath /home/svoboda/Work/BlueCCal/BlueCFindingPoints

% config = localconfig('BlueCHoengg')

% Read configuration from whatever is specified on command-line (via --config=FILENAME)
config = read_configuration();

STEP4STAT = 5; % step for computing average and std images, if 1 then all images taken

im.dir = config.paths.data;
im.ext = config.files.imgext;

% get the information about machine
machinename = getenv('HOST');
CamsIds = str2num(machinename(find(machinename>47 & machinename<58)));

NoCams = size(CamsIds,2);
CamsIds

% load image names
for i=1:NoCams,
  seq(i).camId = CamsIds(i);
  if seq(i).camId > -1
	seq(i).data = dir([sprintf(im.dir,seq(i).camId),sprintf(config.files.imnames,seq(i).camId),im.ext]);
	[sprintf(im.dir,seq(i).camId),sprintf(config.files.imnames,seq(i).camId),im.ext]
  else
	seq(i).data = dir([im.dir,sprintf(config.files.imnames),im.ext]);
  end
  seq(i).size = size(seq(i).data,1);
  if seq(i).size<4
	i, seq
	error('Not enough images found. Wrong image path or name pattern?');
  end
end

% Expected number of 3D points is equal to the number of frames.
% In fact, some frames might be without any calibration point

% Because of non-consistent stopping of capturing, the sequences might
% have different number of images, select the minimal value as the right one
NoPoints = min([seq.size]);

% compute the average images that will be used for finding LEDs
% if not already computed

pointsIdx = [1:STEP4STAT:NoPoints];

t = cputime;
for i=1:NoCams,
  if ~exist(sprintf(config.files.avIM,seq(i).camId)),
	disp(sprintf('The average image of the camera %d is being computed',seq(i).camId));
	avIM = zeros(size(imread([sprintf(im.dir,seq(i).camId),seq(i).data(1).name])));
	for j=pointsIdx,
	  IM = imread([sprintf(im.dir,seq(i).camId),seq(i).data(j).name]);
	  avIM = avIM + double(IM);
	end
	avIM = uint8(round(avIM./size(pointsIdx,2)));
	imwrite(avIM,sprintf(config.files.avIM,seq(i).camId));
  else	disp('Average files already exist');
  end
end
disp(sprintf('Elapsed time for average images: %d [sec]',cputime-t))
% compute the standard deviations images that will be used for finding LEDs
% if not already computed
t = cputime;
for i=1:NoCams,
  if ~exist(sprintf(config.files.stdIM,seq(i).camId)),
	avIM = double(imread(sprintf(config.files.avIM,seq(i).camId)));
	disp(sprintf('The image of standard deviations of the camera %d is being computed',seq(i).camId));
	stdIM = zeros(size(imread([sprintf(im.dir,seq(i).camId),seq(i).data(1).name])));
	for j=pointsIdx,
	  IM = imread([sprintf(im.dir,seq(i).camId),seq(i).data(j).name]);
	  stdIM = stdIM + (double(IM)-avIM).^2;
	end
	stdIM = uint8(round(sqrt(stdIM./(size(pointsIdx,2)-1))));
	imwrite(stdIM,sprintf(config.files.stdIM,seq(i).camId));
  else
	disp('Image of standard deviations already exist')
  end
end
disp(sprintf('Elapsed time for computation of images [sec]: %d',cputime-t))

% find points in the images
Ws    = [];
IdWs  = [];
Res	  = [];

IdMat = ones(NoCams,NoPoints);
% IdMat is very important for Martinec&Pajdla filling [ECCV2002]
% it is a NoCams x NoPoints matrix,
% IdMat(i,j) = 0 -> no j-th point in i-th
% IdMat(i,j) = 1 -> point successfully detected

for i=1:NoCams,
  Points = [];
  avIM  = imread(sprintf(config.files.avIM,seq(i).camId));
  stdIM	= imread(sprintf(config.files.stdIM,seq(i).camId));
  for j=1:NoPoints,
	[pos,err] = getpoint([sprintf(im.dir,seq(i).camId),seq(i).data(j).name], 0, config.imgs, avIM, stdIM);
	if err
	  IdMat(i,j) = 0;
	  Points = [Points, [NaN; NaN; NaN]];
	else
	  Points = [Points, [pos; 1]];
	end
  end
  Ws = [Ws; Points];
  Res= [Res; size(avIM,2), size(avIM,1)];
end

idx = '.';
for i=CamsIds,
  idx = sprintf('%s%02d',idx,i);
end

save([config.files.points,idx], 'Ws','-ASCII')
% save(config.files.IdPoints,'IdWs','-ASCII')
save([config.files.Res,idx], 'Res', '-ASCII')
save([config.files.IdMat,idx], 'IdMat', '-ASCII')

% write auxiliary file that is done
done=1;
save(donefile,'done','-ascii');

% exit the Matlab
% this script is to be used in the batch mode
% hence exit at the end is necessary
exit;


%% DEMO_febio_0065_clamp_tension_test
% Below is a demonstration for:
% 1) The creation of an FEBio model for clamped tensile testing
% 2) The use of multiple steps
% 4) Running an FEBio job with MATLAB
% 5) Importing FEBio results into MATLAB

%% Keywords
%
% * febio_spec version 3.0
% * febio, FEBio
% * tension, tensile
% * displacement control, displacement boundary condition
% * Hexahedral hex8
% * static, solid
% * hyperelastic, Ogden
% * displacement logfile
% * stress logfile

%%

clear; close all; clc;

%% Plot settings
fontSize=25;

%% Control parameters

% Path names
defaultFolder = fileparts(fileparts(mfilename('fullpath')));
savePath=fullfile(defaultFolder,'data','temp');

% Defining file names
febioFebFileNamePart='tempModel';
febioFebFileName=fullfile(savePath,[febioFebFileNamePart,'.feb']); %FEB file name
febioLogFileName=fullfile(savePath,[febioFebFileNamePart,'.txt']); %FEBio log file name
febioLogFileName_disp=[febioFebFileNamePart,'_disp_out.txt']; %Log file name for exporting displacement
febioLogFileName_strain=[febioFebFileNamePart,'_energy_out.txt']; %Log file name for exporting strain energy density

%Specifying dimensions and number of elements
pointSpacing=1;
sampleWidth=10;
sampleThickness=2;
sampleClampedHeight=sampleWidth;
sampleGripGripHeight=sampleWidth.*2;
appliedLinearStrain=0.3;
clampCompressiveLinearStrain=0.3;

%Initial material parameter set
c1=1e-3;
m1=2;
k_factor=100;
k=c1*k_factor;

% FEA control settings
numTimeSteps=10; %Number of time steps desired
max_refs=25; %Max reforms
max_ups=0; %Set to zero to use full-Newton iterations
opt_iter=12; %Optimum number of iterations
max_retries=25; %Maximum number of retires
dtmin=(1/numTimeSteps)/100; %Minimum time step size
dtmax=1/numTimeSteps; %Maximum time step size

min_residual=1e-20;
symmetric_stiffness=0;
runMode='external'; %'internal' or 'external'

%% Computing derived parameters
numElementsWidth=ceil(sampleWidth/pointSpacing);
numElementsWidth=numElementsWidth+iseven(numElementsWidth); %Force uneven so there is a middle element
numElementsThickness=ceil(sampleThickness/pointSpacing)+1;
numElementsGripGripHeight=ceil(sampleGripGripHeight/pointSpacing);
numElementsGripGripHeight=numElementsGripGripHeight+iseven(numElementsGripGripHeight); %Force uneven so there is a middle element
numElementsClampedHeight=ceil(sampleClampedHeight/pointSpacing);

clampCompressiveDisplacement=(sampleThickness.*clampCompressiveLinearStrain)/2;
clampTensionDisplacement=(sampleGripGripHeight.*appliedLinearStrain);

%% Creating strip region
% The region consists of three "boxes" which define the upper and lower
% clamped regions as well as the central region.

%Create box 1
boxDim=[sampleWidth sampleThickness sampleClampedHeight]; %Dimensions
boxEl=[numElementsWidth numElementsThickness numElementsClampedHeight]; %Number of elements
[box1]=hexMeshBox(boxDim,boxEl);
E1=box1.E;
V1=box1.V;
F1=box1.F;
Fb1=box1.Fb;
faceBoundaryMarker1=box1.faceBoundaryMarker;

%Create box 3 by copying the first
E3=E1;
V3=V1;
F3=F1;
Fb3=Fb1;
faceBoundaryMarker3=faceBoundaryMarker1;

%Shift first box up
V1(:,3)=V1(:,3)+sampleGripGripHeight/2+sampleClampedHeight/2;

%Shift third box down
V3(:,3)=V3(:,3)-sampleGripGripHeight/2-sampleClampedHeight/2;

%Create box 2
boxDim=[sampleWidth sampleThickness sampleGripGripHeight]; %Dimensions
boxEl=[numElementsWidth numElementsThickness numElementsGripGripHeight]; %Number of elements
[box2]=hexMeshBox(boxDim,boxEl);
E2=box2.E;
V2=box2.V;
F2=box2.F;
Fb2=box2.Fb;
faceBoundaryMarker2=box2.faceBoundaryMarker;

%% Merging box sets

%Join color data
faceBoundaryMarker_all=[faceBoundaryMarker1; faceBoundaryMarker2; faceBoundaryMarker3;];
faceBoundaryMarker_ind=[ones(size(Fb1,1),1);2*ones(size(Fb2,1),1); 3*ones(size(Fb3,1),1);];

%Join nodes, elements, and faces
V=[V1;V2;V3];
E=[E1;E2+size(V1,1);E3+size(V1,1)+size(V2,1)];
F=[F1;F2+size(V1,1);F3+size(V1,1)+size(V2,1)];
Fb=[Fb1;Fb2+size(V1,1);Fb3+size(V1,1)+size(V2,1)];

%Merge nodes
[F,V,ind1,ind2]=mergeVertices(F,V);
E=ind2(E);
Fb=ind2(Fb);

%%
% Plotting surface models
cFigure;
subplot(1,2,1); hold on;
title('Merged box sets','FontSize',fontSize);
gpatch(Fb,V,faceBoundaryMarker_all);
axisGeom(gca,fontSize);
colormap(gca,gjet(250)); icolorbar;

subplot(1,2,2); hold on;
title('Merged box sets','FontSize',fontSize);
gpatch(Fb,V,faceBoundaryMarker_ind);
axisGeom(gca,fontSize);
colormap(gca,gjet(250)); icolorbar;
drawnow;

%% Define clamping surfaces

logicContactSurf1=faceBoundaryMarker_all==3 & faceBoundaryMarker_ind==1;
Fc1=Fb(logicContactSurf1,:);

logicContactSurf2=faceBoundaryMarker_all==4 & faceBoundaryMarker_ind==1;
Fc2=Fb(logicContactSurf2,:);

logicContactSurf3=faceBoundaryMarker_all==4 & faceBoundaryMarker_ind==3;
Fc3=Fb(logicContactSurf3,:);

logicContactSurf4=faceBoundaryMarker_all==3 & faceBoundaryMarker_ind==3;
Fc4=Fb(logicContactSurf4,:);

%%
% Visualize clamping surfaces

cFigure; hold on;
title('Clamping surfaces','FontSize',fontSize);
gpatch(Fb,V,'kw','none',0.25);
hp(1)=gpatch(Fc1,V,'rw','k',1);
hp(2)=gpatch(Fc2,V,'gw','k',1);
hp(3)=gpatch(Fc3,V,'bw','k',1);
hp(4)=gpatch(Fc4,V,'yw','k',1);
legend(hp,{'Surf. 1','Surf. 2','Surf. 3','Surf. 4'})
axisGeom(gca,fontSize);
camlight headlight;
drawnow;

%% Define BC's

bcPrescribeList1=unique(Fc1(:)); % Nodes of surface 1
bcPrescribeList2=unique(Fc2(:)); % Nodes of surface 2
bcPrescribeList3=unique(Fc3(:)); % Nodes of surface 3
bcPrescribeList4=unique(Fc4(:)); % Nodes of surface 4

%%
% Visualize boundary conditions

cFigure; hold on;
title('Complete model','FontSize',fontSize);

gpatch(Fb,V,'kw','none',0.25);

hp(1)=plotV(V(bcPrescribeList1,:),'r.','MarkerSize',25);
hp(2)=plotV(V(bcPrescribeList2,:),'g.','MarkerSize',25);
hp(3)=plotV(V(bcPrescribeList3,:),'b.','MarkerSize',25);
hp(4)=plotV(V(bcPrescribeList4,:),'y.','MarkerSize',25);
legend(hp,{'Node set 1','Node set 2','Node set 3','Node set 4'})
axisGeom(gca,fontSize);
camlight headlight;
drawnow;

%% Get logic for middle elements (to help investigate strain in the middle)

searchTol=pointSpacing/1000;
VE=patchCentre(E,V);
logicMiddleElements= VE(:,3)<searchTol & VE(:,3)>-searchTol;

[FM]=element2patch(E(logicMiddleElements,:),[],'hex8');

%%
cFigure; hold on;
gpatch(Fb,V,'kw','none',0.25);

gpatch(FM,V,'rw','k',1);

% hp(1)=plotV(V(bcPrescribeList1,:),'r.','MarkerSize',25);
% legend(hp,{'Node set 1','Node set 2','Node set 3','Node set 4'})
axisGeom(gca,fontSize);
camlight headlight;
drawnow;

%% Defining the FEBio input structure
% See also |febioStructTemplate| and |febioStruct2xml| and the FEBio user
% manual.

%Get a template with default settings
[febio_spec]=febioStructTemplate;

%febio_spec version
febio_spec.ATTR.version='3.0';

%Module section
febio_spec.Module.ATTR.type='solid';

%Create control structure for use by all steps
stepStruct.Control.time_steps=numTimeSteps;
stepStruct.Control.step_size=1/numTimeSteps;
stepStruct.Control.solver.max_refs=max_refs;
stepStruct.Control.solver.max_ups=max_ups;
stepStruct.Control.time_stepper.dtmin=dtmin;
stepStruct.Control.time_stepper.dtmax=dtmax;
stepStruct.Control.time_stepper.max_retries=max_retries;
stepStruct.Control.time_stepper.opt_iter=opt_iter;

%Add template based default settings to proposed control section
[stepStruct.Control]=structComplete(stepStruct.Control,febio_spec.Control,1); %Complement provided with default if missing

%Remove control field (part of template) since step specific control sections are used
febio_spec=rmfield(febio_spec,'Control');

febio_spec.Step.step{1}.Control=stepStruct.Control;
febio_spec.Step.step{1}.ATTR.id=1;
febio_spec.Step.step{2}.Control=stepStruct.Control;
febio_spec.Step.step{2}.ATTR.id=2;

%Material section
materialName1='Material1';
febio_spec.Material.material{1}.ATTR.name=materialName1;
febio_spec.Material.material{1}.ATTR.type='Ogden';
febio_spec.Material.material{1}.ATTR.id=1;
febio_spec.Material.material{1}.c1=c1;
febio_spec.Material.material{1}.m1=m1;
febio_spec.Material.material{1}.c2=c1;
febio_spec.Material.material{1}.m2=-m1;
febio_spec.Material.material{1}.k=k;

% Mesh section
% -> Nodes
febio_spec.Mesh.Nodes{1}.ATTR.name='Object1'; %The node set name
febio_spec.Mesh.Nodes{1}.node.ATTR.id=(1:size(V,1))'; %The node id's
febio_spec.Mesh.Nodes{1}.node.VAL=V; %The nodel coordinates

% -> Elements
partName1='Part1';
febio_spec.Mesh.Elements{1}.ATTR.name=partName1; %Name of this part
febio_spec.Mesh.Elements{1}.ATTR.type='hex8'; %Element type
febio_spec.Mesh.Elements{1}.elem.ATTR.id=(1:1:size(E,1))'; %Element id's
febio_spec.Mesh.Elements{1}.elem.VAL=E; %The element matrix

% -> NodeSets
nodeSetName1='bcPrescribeList1';
febio_spec.Mesh.NodeSet{1}.ATTR.name=nodeSetName1;
febio_spec.Mesh.NodeSet{1}.node.ATTR.id=bcPrescribeList1(:);

nodeSetName2='bcPrescribeList2';
febio_spec.Mesh.NodeSet{2}.ATTR.name=nodeSetName2;
febio_spec.Mesh.NodeSet{2}.node.ATTR.id=bcPrescribeList2(:);

nodeSetName3='bcPrescribeList3';
febio_spec.Mesh.NodeSet{3}.ATTR.name=nodeSetName3;
febio_spec.Mesh.NodeSet{3}.node.ATTR.id=bcPrescribeList3(:);

nodeSetName4='bcPrescribeList4';
febio_spec.Mesh.NodeSet{4}.ATTR.name=nodeSetName4;
febio_spec.Mesh.NodeSet{4}.node.ATTR.id=bcPrescribeList4(:);

%MeshDomains section
febio_spec.MeshDomains.SolidDomain.ATTR.name=partName1;
febio_spec.MeshDomains.SolidDomain.ATTR.mat=materialName1;

%Boundary condition section
%STEP 1: Clamping compression
%Set 1
febio_spec.Step.step{1}.Boundary.bc{1}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{1}.ATTR.node_set=nodeSetName1;
febio_spec.Step.step{1}.Boundary.bc{1}.dof='x';
febio_spec.Step.step{1}.Boundary.bc{1}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{1}.scale.VAL=0;
febio_spec.Step.step{1}.Boundary.bc{1}.relative=1;

febio_spec.Step.step{1}.Boundary.bc{2}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{2}.ATTR.node_set=nodeSetName1;
febio_spec.Step.step{1}.Boundary.bc{2}.dof='y';
febio_spec.Step.step{1}.Boundary.bc{2}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{2}.scale.VAL=clampCompressiveDisplacement;
febio_spec.Step.step{1}.Boundary.bc{2}.relative=1;

febio_spec.Step.step{1}.Boundary.bc{3}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{3}.ATTR.node_set=nodeSetName1;
febio_spec.Step.step{1}.Boundary.bc{3}.dof='z';
febio_spec.Step.step{1}.Boundary.bc{3}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{3}.scale.VAL=0;
febio_spec.Step.step{1}.Boundary.bc{3}.relative=1;

%Set 2
febio_spec.Step.step{1}.Boundary.bc{4}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{4}.ATTR.node_set=nodeSetName2;
febio_spec.Step.step{1}.Boundary.bc{4}.dof='x';
febio_spec.Step.step{1}.Boundary.bc{4}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{4}.scale.VAL=0;
febio_spec.Step.step{1}.Boundary.bc{4}.relative=1;

febio_spec.Step.step{1}.Boundary.bc{5}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{5}.ATTR.node_set=nodeSetName2;
febio_spec.Step.step{1}.Boundary.bc{5}.dof='y';
febio_spec.Step.step{1}.Boundary.bc{5}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{5}.scale.VAL=-clampCompressiveDisplacement;
febio_spec.Step.step{1}.Boundary.bc{5}.relative=1;

febio_spec.Step.step{1}.Boundary.bc{6}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{6}.ATTR.node_set=nodeSetName2;
febio_spec.Step.step{1}.Boundary.bc{6}.dof='z';
febio_spec.Step.step{1}.Boundary.bc{6}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{6}.scale.VAL=0;
febio_spec.Step.step{1}.Boundary.bc{6}.relative=1;

%Set 3
febio_spec.Step.step{1}.Boundary.bc{7}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{7}.ATTR.node_set=nodeSetName3;
febio_spec.Step.step{1}.Boundary.bc{7}.dof='x';
febio_spec.Step.step{1}.Boundary.bc{7}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{7}.scale.VAL=0;
febio_spec.Step.step{1}.Boundary.bc{7}.relative=1;

febio_spec.Step.step{1}.Boundary.bc{8}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{8}.ATTR.node_set=nodeSetName3;
febio_spec.Step.step{1}.Boundary.bc{8}.dof='y';
febio_spec.Step.step{1}.Boundary.bc{8}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{8}.scale.VAL=-clampCompressiveDisplacement;
febio_spec.Step.step{1}.Boundary.bc{8}.relative=1;

febio_spec.Step.step{1}.Boundary.bc{9}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{9}.ATTR.node_set=nodeSetName3;
febio_spec.Step.step{1}.Boundary.bc{9}.dof='z';
febio_spec.Step.step{1}.Boundary.bc{9}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{9}.scale.VAL=0;
febio_spec.Step.step{1}.Boundary.bc{9}.relative=1;

%Set 4
febio_spec.Step.step{1}.Boundary.bc{10}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{10}.ATTR.node_set=nodeSetName4;
febio_spec.Step.step{1}.Boundary.bc{10}.dof='x';
febio_spec.Step.step{1}.Boundary.bc{10}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{10}.scale.VAL=0;
febio_spec.Step.step{1}.Boundary.bc{10}.relative=1;

febio_spec.Step.step{1}.Boundary.bc{11}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{11}.ATTR.node_set=nodeSetName4;
febio_spec.Step.step{1}.Boundary.bc{11}.dof='y';
febio_spec.Step.step{1}.Boundary.bc{11}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{11}.scale.VAL=clampCompressiveDisplacement;
febio_spec.Step.step{1}.Boundary.bc{11}.relative=1;

febio_spec.Step.step{1}.Boundary.bc{12}.ATTR.type='prescribe';
febio_spec.Step.step{1}.Boundary.bc{12}.ATTR.node_set=nodeSetName4;
febio_spec.Step.step{1}.Boundary.bc{12}.dof='z';
febio_spec.Step.step{1}.Boundary.bc{12}.scale.ATTR.lc=1;
febio_spec.Step.step{1}.Boundary.bc{12}.scale.VAL=0;
febio_spec.Step.step{1}.Boundary.bc{12}.relative=1;

%STEP 2 Tension
%Set 1
febio_spec.Step.step{2}.Boundary.bc{1}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{1}.ATTR.node_set=nodeSetName1;
febio_spec.Step.step{2}.Boundary.bc{1}.dof='x';
febio_spec.Step.step{2}.Boundary.bc{1}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{1}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{1}.relative=1;

febio_spec.Step.step{2}.Boundary.bc{2}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{2}.ATTR.node_set=nodeSetName1;
febio_spec.Step.step{2}.Boundary.bc{2}.dof='y';
febio_spec.Step.step{2}.Boundary.bc{2}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{2}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{2}.relative=1;

febio_spec.Step.step{2}.Boundary.bc{3}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{3}.ATTR.node_set=nodeSetName1;
febio_spec.Step.step{2}.Boundary.bc{3}.dof='z';
febio_spec.Step.step{2}.Boundary.bc{3}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{3}.scale.VAL=clampTensionDisplacement;
febio_spec.Step.step{2}.Boundary.bc{3}.relative=1;

%Set 2
febio_spec.Step.step{2}.Boundary.bc{4}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{4}.ATTR.node_set=nodeSetName2;
febio_spec.Step.step{2}.Boundary.bc{4}.dof='x';
febio_spec.Step.step{2}.Boundary.bc{4}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{4}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{4}.relative=1;

febio_spec.Step.step{2}.Boundary.bc{5}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{5}.ATTR.node_set=nodeSetName2;
febio_spec.Step.step{2}.Boundary.bc{5}.dof='y';
febio_spec.Step.step{2}.Boundary.bc{5}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{5}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{5}.relative=1;

febio_spec.Step.step{2}.Boundary.bc{6}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{6}.ATTR.node_set=nodeSetName2;
febio_spec.Step.step{2}.Boundary.bc{6}.dof='z';
febio_spec.Step.step{2}.Boundary.bc{6}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{6}.scale.VAL=clampTensionDisplacement;
febio_spec.Step.step{2}.Boundary.bc{6}.relative=1;

%Set 3
febio_spec.Step.step{2}.Boundary.bc{7}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{7}.ATTR.node_set=nodeSetName3;
febio_spec.Step.step{2}.Boundary.bc{7}.dof='x';
febio_spec.Step.step{2}.Boundary.bc{7}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{7}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{7}.relative=1;

febio_spec.Step.step{2}.Boundary.bc{8}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{8}.ATTR.node_set=nodeSetName3;
febio_spec.Step.step{2}.Boundary.bc{8}.dof='y';
febio_spec.Step.step{2}.Boundary.bc{8}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{8}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{8}.relative=1;

febio_spec.Step.step{2}.Boundary.bc{9}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{9}.ATTR.node_set=nodeSetName3;
febio_spec.Step.step{2}.Boundary.bc{9}.dof='z';
febio_spec.Step.step{2}.Boundary.bc{9}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{9}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{9}.relative=1;

%Set 4
febio_spec.Step.step{2}.Boundary.bc{10}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{10}.ATTR.node_set=nodeSetName4;
febio_spec.Step.step{2}.Boundary.bc{10}.dof='x';
febio_spec.Step.step{2}.Boundary.bc{10}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{10}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{10}.relative=1;

febio_spec.Step.step{2}.Boundary.bc{11}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{11}.ATTR.node_set=nodeSetName4;
febio_spec.Step.step{2}.Boundary.bc{11}.dof='y';
febio_spec.Step.step{2}.Boundary.bc{11}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{11}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{11}.relative=1;

febio_spec.Step.step{2}.Boundary.bc{12}.ATTR.type='prescribe';
febio_spec.Step.step{2}.Boundary.bc{12}.ATTR.node_set=nodeSetName4;
febio_spec.Step.step{2}.Boundary.bc{12}.dof='z';
febio_spec.Step.step{2}.Boundary.bc{12}.scale.ATTR.lc=2;
febio_spec.Step.step{2}.Boundary.bc{12}.scale.VAL=0;
febio_spec.Step.step{2}.Boundary.bc{12}.relative=1;

%LoadData section
%LoadData section
% -> load_controller
febio_spec.LoadData.load_controller{1}.ATTR.id=1;
febio_spec.LoadData.load_controller{1}.ATTR.type='loadcurve';
febio_spec.LoadData.load_controller{1}.interpolate='LINEAR';
febio_spec.LoadData.load_controller{1}.points.point.VAL=[0 0; 1 1];

febio_spec.LoadData.load_controller{2}.ATTR.id=2;
febio_spec.LoadData.load_controller{2}.ATTR.type='loadcurve';
febio_spec.LoadData.load_controller{2}.interpolate='LINEAR';
febio_spec.LoadData.load_controller{2}.points.point.VAL=[0 0; 1 0; 2 1];

%Output section
% -> log file
febio_spec.Output.logfile.ATTR.file=febioLogFileName;
febio_spec.Output.logfile.node_data{1}.ATTR.file=febioLogFileName_disp;
febio_spec.Output.logfile.node_data{1}.ATTR.data='ux;uy;uz';
febio_spec.Output.logfile.node_data{1}.ATTR.delim=',';
febio_spec.Output.logfile.node_data{1}.VAL=1:size(V,1);

febio_spec.Output.logfile.element_data{1}.ATTR.file=febioLogFileName_strain;
febio_spec.Output.logfile.element_data{1}.ATTR.data='Ez';
febio_spec.Output.logfile.element_data{1}.ATTR.delim=',';
febio_spec.Output.logfile.element_data{1}.VAL=1:1:size(E,1);

%% Quick viewing of the FEBio input file structure
% The |febView| function can be used to view the xml structure in a MATLAB
% figure window.

%%
% |febView(febio_spec); %Viewing the febio file|

%% Exporting the FEBio input file
% Exporting the febio_spec structure to an FEBio input file is done using
% the |febioStruct2xml| function.

febioStruct2xml(febio_spec,febioFebFileName); %Exporting to file and domNode

%% Running the FEBio analysis
% To run the analysis defined by the created FEBio input file the
% |runMonitorFEBio| function is used. The input for this function is a
% structure defining job settings e.g. the FEBio input file name. The
% optional output runFlag informs the user if the analysis was run
% succesfully.

febioAnalysis.run_filename=febioFebFileName; %The input file name
febioAnalysis.run_logname=febioLogFileName; %The name for the log file
febioAnalysis.disp_on=1; %Display information on the command window
febioAnalysis.runMode=runMode;
febioAnalysis.maxLogCheckTime=120; %Max log file checking time

[runFlag]=runMonitorFEBio(febioAnalysis);%START FEBio NOW!!!!!!!!

%% Import FEBio results

if runFlag==1 %i.e. a succesful run

    %%
    % Importing nodal displacements from a log file

    dataStruct=importFEBio_logfile(fullfile(savePath,febioLogFileName_disp),1,1);

    %Access data
    N_disp_mat=dataStruct.data; %Displacement
    timeVec=dataStruct.time; %Time

    %Create deformed coordinate set
    V_DEF=N_disp_mat+repmat(V,[1 1 size(N_disp_mat,3)]);

    %%
    % Importing element strain data from a log file
    dataStruct=importFEBio_logfile(fullfile(savePath,febioLogFileName_strain),1,1);

    %Access data
    E_strain=dataStruct.data;

    [F,CF]=element2patch(E,E_strain(:,:,end));
    CF_V=faceToVertexMeasure(F,V,CF);

    E_strain_middle_mean=squeeze(mean(E_strain(logicMiddleElements,:,:),1));

    %% Compute grimp implied strain
    gripStrainLinear=double(timeVec>1).*(timeVec-1).*appliedLinearStrain;
    gripStrain=1/2*((gripStrainLinear+1).^2-1); %Green-Lagrange strain
    maxGridStrain=max(abs(gripStrain));
      %%
    % Plotting the simulated results using |anim8| to visualize and animate
    % deformations

    axLim=[min(min(V_DEF,[],3),[],1); max(max(V_DEF,[],3),[],1)];
    indBc=[bcPrescribeList1;bcPrescribeList2;bcPrescribeList3;bcPrescribeList4;];

    % Create basic view and store graphics handle to initiate animation
    hf=cFigure; hold on;%Open figure
    gtitle([febioFebFileNamePart,': Press play to animate']);
    title('$E_{zz}$','Interpreter','Latex')
    hp1=gpatch(Fb,V_DEF(:,:,end),CF_V,'k',1);
    hp1.FaceColor='interp';
    hp2=plotV(V(indBc,:),'k.','MarkerSize',25);

    axisGeom(gca,fontSize);
    colormap(warmcold(250)); hc=colorbar;
    caxis([-maxGridStrain maxGridStrain]);
    hc.Ticks=linspace(-maxGridStrain,maxGridStrain,7);
    axis(axLim(:)'); %Set axis limits statically

    camlight headlight; axis off;

    % Set up animation features
    animStruct.Time=timeVec; %The time vector
    for qt=1:1:size(N_disp_mat,3) %Loop over time increments
        V_def=V+N_disp_mat(:,:,qt); %Current nodal coordinates

        [~,CF]=element2patch(E,E_strain(:,:,qt));
        CF_V=faceToVertexMeasure(F,V,CF);

        %Set entries in animation structure
        animStruct.Handles{qt}=[hp1 hp1 hp2 hp2 hp2]; %Handles of objects to animate
        animStruct.Props{qt}={'Vertices','CData','XData','YData','ZData'}; %Properties of objects to animate
        animStruct.Set{qt}={V_def,CF_V,V_def(indBc,1),V_def(indBc,2),V_def(indBc,3)}; %Property values for to set in order to animate
    end
    anim8(hf,animStruct); %Initiate animation feature
    gdrawnow;

    %%
    % Plotting the simulated results using |anim8| to visualize and animate
    % deformations

    indBc=[bcPrescribeList1;bcPrescribeList2;bcPrescribeList3;bcPrescribeList4;];

    % Create basic view and store graphics handle to initiate animation
    hf=cFigure;
    subplot(1,2,1); hold on;
    title('$E_{zz}$','Interpreter','Latex');
    gtitle([febioFebFileNamePart,': Press play to animate']);
    hp1=gpatch(Fb,V_DEF(:,:,end),CF_V,'none',1,0.5); hp1.FaceColor='interp';
    hp2=plotV(V_DEF(indBc,:,end),'k.','MarkerSize',1);
    hp3=gpatch(FM,V_DEF(:,:,end),CF_V,'k',1,2); hp3.FaceColor='interp';

    colormap(warmcold(250)); hc=colorbar;
    caxis([-maxGridStrain maxGridStrain]);
    hc.Ticks=linspace(-maxGridStrain,maxGridStrain,7);
    axisGeom(gca,fontSize); camlight headlight;
    axis(axisLim(V_DEF)); %Set axis limits statically
    view(0,0); axis off;

    subplot(1,2,2); hold on;
    xlabel('Time (s)'); ylabel('$E_{zz}$','Interpreter','Latex');
    hpl4=plot(timeVec,E_strain_middle_mean,'g.-','LineWidth',3);
    hpl5=plot(timeVec,gripStrain,'r.-','LineWidth',3);
    hp4=plot(timeVec(end),E_strain_middle_mean(end),'g.','MarkerSize',50);
    hp5=plot(timeVec(end),gripStrain(end),'r.','MarkerSize',50);
    legend([hpl4 hpl5],{'True strain $E_{zz}$','"Intended applied" strain $E_{zz}$'},'Location','NorthOutside','Interpreter','Latex');
    axis tight; box on; grid on; set(gca,'FontSize',fontSize);

    % Set up animation features
    animStruct.Time=timeVec; %The time vector
    for qt=1:1:size(N_disp_mat,3) %Loop over time increments
        V_def=V_DEF(:,:,qt); %Current nodal coordinates

        [~,CF]=element2patch(E,E_strain(:,:,qt));
        CF_V=faceToVertexMeasure(F,V,CF);

        %Set entries in animation structure
        animStruct.Handles{qt}=[hp1 hp1 hp2 hp2 hp2 hp3 hp3 hp4 hp4 hp5 hp5]; %Handles of objects to animate
        animStruct.Props{qt}={'Vertices','CData','XData','YData','ZData','Vertices','CData','XData','YData','XData','YData'}; %Properties of objects to animate
        animStruct.Set{qt}={V_def,CF_V,V_def(indBc,1),V_def(indBc,2),V_def(indBc,3),V_def,CF_V,timeVec(qt),E_strain_middle_mean(qt),timeVec(qt),gripStrain(qt)}; %Property values for to set in order to animate
    end
    anim8(hf,animStruct); %Initiate animation feature
    drawnow;

end

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


% LFCalInit - initialize calibration estimate, called by LFUtilCalLensletCam
%
% Usage:
%     CalOptions = LFCalInit( InputPath, CalOptions )
%     CalOptions = LFCalInit( InputPath )
%
% This function is called by LFUtilCalLensletCam to initialize a pose and camera model estimate
% given a set of extracted checkerboard corners.
%
% Inputs:
%
%     InputPath : Path to folder containing processed checkerboard images. Checkerboard corners must
%                 be identified prior to calling this function, by running LFCalFindCheckerCorners
%                 for example. This is demonstrated by LFUtilCalLensletCam.
%
%     [optional] CalOptions : struct controlling calibration parameters, all fields are optional
%                   .SaveResult : Set to false to perform a "dry run"
%   .CheckerCornersFnamePattern : Pattern for finding checkerboard corner files, as generated by
%                                 LFCalFindCheckerCorners; %s is a placeholder for the base filename
%             .CheckerInfoFname : Name of the output file containing the summarized checkerboard
%                                 information
%                 .CalInfoFname : Name of the file containing an initial estimate, to be refined.
%                                 Note that this parameter is automatically set in the CalOptions
%                                 struct returned by LFCalInit
%                .ForceRedoInit : Forces the function to overwrite existing results
%
% Outputs :
%
%     CalOptions struct as applied, including any default values as set up by the function.
%
%     The checkerboard info file and calibration info file are the key outputs of this function.
%
% User guide: LFToolbox.pdf
% See also:  LFUtilCalLensletCam, LFCalFindCheckerCorners, LFCalRefine

% Copyright (c) 2013-2020 Donald G. Dansereau

function CalOptions = LFCalInit( InputPath, CalOptions )

%---Defaults---
CalOptions = LFDefaultField( 'CalOptions', 'SaveResult', true );
CalOptions = LFDefaultField( 'CalOptions', 'CheckerCornersFnamePattern', '%s__CheckerCorners.mat' );
CalOptions = LFDefaultField( 'CalOptions', 'CheckerInfoFname', 'CheckerboardCorners.mat' );
CalOptions = LFDefaultField( 'CalOptions', 'CalInfoFname', 'CalInfo.json' );
CalOptions = LFDefaultField( 'CalOptions', 'ForceRedoInit', false );

%---Start by checking if this step has already been completed---
fprintf('\n===Initializing calibration process===\n');
CalInfoSaveFname = fullfile(InputPath, CalOptions.CalInfoFname);
if( ~CalOptions.ForceRedoInit && exist(CalInfoSaveFname, 'file') )
    fprintf(' ---File %s already exists, skipping---\n', CalInfoSaveFname);
    return;
end

%---Compute ideal checkerboard geometry - order matters---
IdealCheckerX = CalOptions.ExpectedCheckerSpacing_m(1) .* (0:CalOptions.ExpectedCheckerSize(1)-1);
IdealCheckerY = CalOptions.ExpectedCheckerSpacing_m(2) .* (0:CalOptions.ExpectedCheckerSize(2)-1);
[IdealCheckerY, IdealCheckerX] = ndgrid(IdealCheckerY, IdealCheckerX);
IdealChecker = cat(3,IdealCheckerX, IdealCheckerY, zeros(size(IdealCheckerX)));
IdealChecker = reshape(IdealChecker, [], 3)';

%---Crawl folder structure locating corner info files---
fprintf('\n===Locating checkerboard corner files in %s===\n', InputPath);
[CalOptions.FileList, BasePath] = LFFindFilesRecursive( InputPath, sprintf(CalOptions.CheckerCornersFnamePattern, '*') );
fprintf('Found :\n');
disp(CalOptions.FileList)

%---Initial estimate of focal length---
SkippedFileCount = 0;
ValidSuperPoseCount = 0;
ValidCheckerCount = 0;
%---Load each checkerboard corner file---
fprintf('Loading corner observations...\n');
for( iFile = 1:length(CalOptions.FileList) )
    ValidSuperPoseCount = ValidSuperPoseCount + 1;
    CurFname = CalOptions.FileList{iFile};
    [~,ShortFname] = fileparts(CurFname);
    fprintf('---%s [%3d / %3d]...', ShortFname, ValidSuperPoseCount+SkippedFileCount, length(CalOptions.FileList));

    load(fullfile(BasePath, CurFname), 'CheckerCorners', 'LFSize', 'CamInfo', 'LensletGridModel', 'DecodeOptions');
    PerImageValidCount = 0;
    for( TIdx = 1:size(CheckerCorners,1) )
        for( SIdx = 1:size(CheckerCorners,2) )
            CurChecker = CheckerCorners{TIdx, SIdx}';
            CurSize = size(CurChecker);
            CurValid = (CurSize(2) == prod(CalOptions.ExpectedCheckerSize));
            CheckerValid(ValidSuperPoseCount, TIdx, SIdx) = CurValid;

            %---For valid poses (having expected corner count), compute a homography---
            if( CurValid )
                ValidCheckerCount = ValidCheckerCount + 1;
                PerImageValidCount = PerImageValidCount + 1;

                %--- reorient to expected ---
                Centroid = mean( CurChecker,2 );
                IsTopLeft = all(CurChecker(:,1) < Centroid);
                IsTopRight = (CurChecker(1,1) > Centroid(1) && CurChecker(2,1) < Centroid(2));
				IsBotLeft = (CurChecker(1,1) < Centroid(1) && CurChecker(2,1) > Centroid(2));
				IsBotRight = all(CurChecker(:,1) > Centroid);
                if( IsTopRight )
                    CurChecker = reshape(CurChecker, [2, CalOptions.ExpectedCheckerSize]);
                    CurChecker = CurChecker(:, end:-1:1, :);
                    CurChecker = permute(CurChecker, [1,3,2]);
                    CurChecker = reshape(CurChecker, 2, []);
				elseif( IsBotLeft )
                    CurChecker = reshape(CurChecker, [2, CalOptions.ExpectedCheckerSize]);
                    CurChecker = CurChecker(:, :, end:-1:1);
                    CurChecker = permute(CurChecker, [1,3,2]);
                    CurChecker = reshape(CurChecker, 2, []);
				elseif( IsBotRight )
                    CurChecker = reshape(CurChecker, [2, CalOptions.ExpectedCheckerSize]);
                    CurChecker = CurChecker(:, end:-1:1, end:-1:1);
                    CurChecker = reshape(CurChecker, 2, []);
				end
                IsTopLeft = all(CurChecker(:,1) < Centroid);
                assert( IsTopLeft, 'Error: unexpected point order from detectCheckerboardPoints' );

                CheckerObs{ValidSuperPoseCount, TIdx, SIdx} = CurChecker;
            end
        end
    end
    CalOptions.ValidSubimageCount(iFile) = PerImageValidCount;
    fprintf(' %d / %d valid.\n', PerImageValidCount, prod(LFSize(1:2)));
end

%---Compute homography for each subcam pose---
fprintf('Initial estimate of focal length...\n');
ValidCheckerCount = 0;
for( iFile = 1:length(CalOptions.FileList) )
    for( TIdx = 1:size(CheckerObs,3) )
        for( SIdx = 1:size(CheckerObs,2) )
			CurChecker = CheckerObs{iFile, TIdx, SIdx};
			if( ~isempty(CurChecker) )
				ValidCheckerCount = ValidCheckerCount + 1;
				%---Compute homography for each subcam pose---
				CurH = compute_homography( CurChecker, IdealChecker(1:2,:) );
				H(ValidCheckerCount, :,:) = CurH;
			end
        end
    end
    fprintf('.');
end
fprintf('\n');

A = [];
b = [];

%---Initialize principal point at the center of the image---
% This section of code is based heavily on code from the Camera Calibration Toolbox for Matlab by
% Jean-Yves Bouguet
CInit = LFSize([4,3])'/2 - 0.5;
RecenterH = [1, 0, -CInit(1); 0, 1, -CInit(2); 0, 0, 1];

for iHomography = 1:size(H,1)
    CurH = squeeze(H(iHomography,:,:));
    CurH = RecenterH * CurH;

    %---Extract vanishing points (direct and diagonal)---
    V_hori_pix = CurH(:,1);
    V_vert_pix = CurH(:,2);
    V_diag1_pix = (CurH(:,1)+CurH(:,2))/2;
    V_diag2_pix = (CurH(:,1)-CurH(:,2))/2;

    V_hori_pix = V_hori_pix/norm(V_hori_pix);
    V_vert_pix = V_vert_pix/norm(V_vert_pix);
    V_diag1_pix = V_diag1_pix/norm(V_diag1_pix);
    V_diag2_pix = V_diag2_pix/norm(V_diag2_pix);

    a1 = V_hori_pix(1);
    b1 = V_hori_pix(2);
    c1 = V_hori_pix(3);

    a2 = V_vert_pix(1);
    b2 = V_vert_pix(2);
    c2 = V_vert_pix(3);

    a3 = V_diag1_pix(1);
    b3 = V_diag1_pix(2);
    c3 = V_diag1_pix(3);

    a4 = V_diag2_pix(1);
    b4 = V_diag2_pix(2);
    c4 = V_diag2_pix(3);

    CurA = [a1*a2, b1*b2; a3*a4, b3*b4];
    CurB = -[c1*c2; c3*c4];

    if( isempty(find(isnan(CurA), 1)) && isempty(find(isnan(CurB), 1)) )
        A = [A; CurA];
        b = [b; CurB];
    end
end

FocInit = sqrt(b'*(sum(A')') / (b'*b)) * ones(2,1);
fprintf('Init focal length est: %.2f, %.2f\n', FocInit);

%---Initial estimate of extrinsics---
fprintf('\nInitial estimate of extrinsics...\n');

for( iSuperPoseIdx = 1:ValidSuperPoseCount )
    fprintf('---[%d / %d]', iSuperPoseIdx, ValidSuperPoseCount);
    for( TIdx = 1:size(CheckerCorners,1) )
        fprintf('.');
        for( SIdx = 1:size(CheckerCorners,2) )
            if( ~CheckerValid(iSuperPoseIdx, TIdx, SIdx) )
                continue;
            end
            CurChecker = CheckerObs{iSuperPoseIdx, TIdx, SIdx};

            [CurRot, CurTrans] = compute_extrinsic_init(CurChecker, IdealChecker, FocInit, CInit, zeros(1,5), 0);
            [CurRot, CurTrans] = compute_extrinsic_refine(CurRot, CurTrans, CurChecker, IdealChecker, FocInit, CInit, zeros(1,5), 0,20,1000000);

            RotVals{iSuperPoseIdx, TIdx, SIdx} = CurRot;
            TransVals{iSuperPoseIdx, TIdx, SIdx} = CurTrans;
        end
    end

    %---Approximate each superpose as the median of its sub-poses---
    % note the approximation in finding the mean orientation: mean of rodrigues... works because all
    % sub-orientations within a superpose are nearly identical.
    MeanRotVals(iSuperPoseIdx,:) = median([RotVals{iSuperPoseIdx, :, :}], 2);
    MeanTransVals(iSuperPoseIdx,:) = median([TransVals{iSuperPoseIdx, :, :}], 2);
    fprintf('\n');

    %---Track the apparent "baseline" of the camera at each pose---
    CurDist = bsxfun(@minus, [TransVals{iSuperPoseIdx, :, :}], MeanTransVals(iSuperPoseIdx,:)');
    CurAbsDist = sqrt(sum(CurDist.^2));
    % store as estimated diameter; the 3/2 comes from the mean radius of points on a disk (2R/3)
    BaselineApprox(iSuperPoseIdx) = 2 * 3/2 * mean(CurAbsDist);
end

%---Initialize the superpose estimates---
EstCamPosesV = [MeanTransVals, MeanRotVals];

%---Estimate full intrinsic matrix---
ST_IJ_SlopeApprox = mean(BaselineApprox) ./ (LFSize(2:-1:1)-1);
UV_KL_SlopeApprox = 1./FocInit';

EstCamIntrinsicsH = eye(5);
EstCamIntrinsicsH(1,1) = ST_IJ_SlopeApprox(1);
EstCamIntrinsicsH(2,2) = ST_IJ_SlopeApprox(2);
EstCamIntrinsicsH(3,3) = UV_KL_SlopeApprox(1);
EstCamIntrinsicsH(4,4) = UV_KL_SlopeApprox(2);

% Force central ray as s,t,u,v = 0, note all indices start at 1, not 0
EstCamIntrinsicsH = LFRecenterIntrinsics( EstCamIntrinsicsH, LFSize );

fprintf('\nInitializing estimate of camera intrinsics to: \n');
disp(EstCamIntrinsicsH);

%---Start with no distortion estimate---
EstCamDistortionV = [];

%---Optionally save the results---
if( CalOptions.SaveResult )
    TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS');
    GeneratedByInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion);

    CheckerSaveFname = fullfile(BasePath, CalOptions.CheckerInfoFname);
    fprintf('\nSaving to %s...\n', CheckerSaveFname);
    save(CheckerSaveFname, 'GeneratedByInfo', 'CalOptions', 'CheckerObs', 'IdealChecker', 'LFSize', 'CamInfo', 'LensletGridModel', 'DecodeOptions');

    fprintf('Saving to %s...\n', CalInfoSaveFname);
    LFWriteMetadata(CalInfoSaveFname, LFVar2Struct(GeneratedByInfo, LensletGridModel, EstCamIntrinsicsH, EstCamDistortionV, EstCamPosesV, CamInfo, CalOptions, DecodeOptions));
end

fprintf(' ---Calibration initialization done---\n');


function brs = ssr_brs_point_source(X,phi,xs,irs,conf)
%SSR_BRS_POINT_SOURCE binaural room scanning (BRS) set for use with the
%SoundScape Renderer
%
%   Usage: brs = ssr_brs_point_source(X,phi,xs,irs,conf)
%
%   Input parameters:
%       X       - listener position / m
%       phi     - azimuthal head orientation / rad
%       xs      - source position / m
%       irs     - impulse response data set for the second sources
%       conf    - configuration struct (see SFS_config)
%
%   Output parameters:
%       brs     - conf.N x 2*nangles matrix containing all impulse responses (2
%                 channels) for every angle of the BRS set
%
%   SSR_BRS_POINT_SOURCE(X,phi,xs,irs,conf) prepares a BRS set for a reference
%   source (single point source) for the given listener position. One way to use
%   this BRS set is using the SoundScapeRenderer (SSR), see
%   http://spatialaudio.net/ssr/
%
%   See also: ir_generic, ir_point_source, get_ir

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Checking of input  parameters ==================================
nargmin = 5;
nargmax = 5;
narginchk(nargmin,nargmax);
isargposition(X);
isargxs(xs);
isargscalar(phi);
isargstruct(conf);

%% ===== Computation =====================================================
brs = ssr_brs(X,phi,[xs 0 -1 0 1],1,irs,conf);


function [rVectB, vVectB] = getPositOfBodyWRTSun(time, bodyInfo, celBodyData)
    try
        if(bodyInfo.propTypeEnum == BodyPropagationTypeEnum.TwoBody || (numel(time) == 1 && time == bodyInfo.epoch))
            chain = bodyInfo.getOrbitElemsChain();
            [rVectB, vVectB] = getPositOfBodyWRTSun_alg_fast_mex(time, chain{:});
        elseif(bodyInfo.propTypeEnum == BodyPropagationTypeEnum.Numerical)
            parentBodyInfo = bodyInfo.getParBodyInfo(celBodyData);

            [rVect, vVect] = getStateAtTime(bodyInfo, time, []);
            cartElem = CartesianElementSet(time, rVect, vVect, parentBodyInfo.getBodyCenteredInertialFrame(), true);
            cartElem = convertToFrame(cartElem, celBodyData.getTopLevelBody().getBodyCenteredInertialFrame());

            rVectB = [cartElem.rVect];
            vVectB = [cartElem.vVect];

        else
            error('Unknown celestial body prop sim type.');
        end
    catch ME %#ok<NASGU> %if bad then use old way
        numTimes = length(time);
        loop = true;
        rVectB = zeros(3,numTimes);
        vVectB = zeros(3,numTimes);
        while(loop)
            try
                parentBodyInfo = bodyInfo.getParBodyInfo(celBodyData);
            catch
                parentBodyInfo = getParentBodyInfo(bodyInfo, celBodyData);
            end

            if(isempty(parentBodyInfo))
                break;
            end

            try
                parentGM = bodyInfo.getParentGmuFromCache();
            catch
                parentGM = getParentGM(bodyInfo,celBodyData);
            end

            [rVect, vVect] = getStateAtTime(bodyInfo, time, parentGM); %getParentGM(bodyInfo, celBodyData)
            rVectB = rVectB + rVect;
            vVectB = vVectB + vVect;

            bodyInfo = parentBodyInfo;
        end
    end

%     if(numel(time) > 1 && numel(time) == numel(bodyInfo))
%         [uniBodies,~,ic] = unique(bodyInfo,'stable');
%
%         rVectB = NaN(3, numel(time));
%         vVectB = rVectB;
%         for(i=1:length(uniBodies))
%             subBodyInfo = uniBodies(i);
%             bool = i == ic;
%             subTimes = time(bool);
%
%             [rVectB(:,bool), vVectB(:,bool)] = getPositOfBodyWRTSun(subTimes, subBodyInfo, celBodyData);
%         end
%     else
%         try %try new way
%             if(bodyInfo.propTypeEnum == BodyPropagationTypeEnum.TwoBody || (numel(time) == 1 && time == bodyInfo.epoch))
% %                 if(numel(time) == 1 && numel(bodyInfo.lastComputedTime) > 0 && bodyInfo.lastComputedTime == time)
% %                     rVectB = bodyInfo.lastComputedRVect;
% %                     vVectB = bodyInfo.lastComputedVVect;
% %                 else
% %                     chain = bodyInfo.getOrbitElemsChain();
% %                     [rVectB, vVectB] = getPositOfBodyWRTSun_alg(time, chain{:});
% %
% %                     if(numel(time) == 1)
% %                         bodyInfo.lastComputedTime = time;
% %                         bodyInfo.lastComputedRVect = rVectB;
% %                         bodyInfo.lastComputedVVect = vVectB;
% %                     end
% %                 end
%
%                 if(numel(time) == 1)
%                     bool = time == bodyInfo.lastComputedTime;
%
%                     if(any(bool))
%                         rVectVVectB = bodyInfo.lastComputedRVectVVect(:,bool);
%                         rVectB = rVectVVectB(1:3,1);
%                         vVectB = rVectVVectB(4:6,1);
%
%                     else
%                         chain = bodyInfo.getOrbitElemsChain();
%                         try
%                             [rVectB, vVectB] = getPositOfBodyWRTSun_alg_fast_mex(time, chain{:});
%                         catch ME %#ok<NASGU>
%                             [rVectB, vVectB] = getPositOfBodyWRTSun_alg(time, chain{:});
%                         end
%
%                         bodyInfo.lastComputedTime = horzcat(bodyInfo.lastComputedTime, time);
%                         bodyInfo.lastComputedRVectVVect = horzcat(bodyInfo.lastComputedRVectVVect, [rVectB;vVectB]);
%
%                         [bodyInfo.lastComputedTime,ia,~] = unique(bodyInfo.lastComputedTime,'stable');
%                         bodyInfo.lastComputedRVectVVect = bodyInfo.lastComputedRVectVVect(:, ia);
%                     end
%                 else
%                     chain = bodyInfo.getOrbitElemsChain();
%                     try
%                         [rVectB, vVectB] = getPositOfBodyWRTSun_alg_fast_mex(time, chain{:});
%                     catch ME %#ok<NASGU>
%                         [rVectB, vVectB] = getPositOfBodyWRTSun_alg(time, chain{:});
%                     end
%
%                     bodyInfo.lastComputedTime = horzcat(bodyInfo.lastComputedTime, time);
%                     bodyInfo.lastComputedRVectVVect = horzcat(bodyInfo.lastComputedRVectVVect, [rVectB;vVectB]);
%
%                     [bodyInfo.lastComputedTime,ia,~] = unique(bodyInfo.lastComputedTime,'stable');
%                     bodyInfo.lastComputedRVectVVect = bodyInfo.lastComputedRVectVVect(:, ia);
%                 end
%
%             elseif(bodyInfo.propTypeEnum == BodyPropagationTypeEnum.Numerical)
%                 parentBodyInfo = bodyInfo.getParBodyInfo(celBodyData);
%
%                 [rVect, vVect] = getStateAtTime(bodyInfo, time, []);
%                 cartElem = CartesianElementSet(time, rVect, vVect, parentBodyInfo.getBodyCenteredInertialFrame(), true);
%                 cartElem = convertToFrame(cartElem, celBodyData.getTopLevelBody().getBodyCenteredInertialFrame());
%
%                 rVectB = [cartElem.rVect];
%                 vVectB = [cartElem.vVect];
%
%             else
%                 error('Unknown celestial body prop sim type.');
%             end
%         catch ME %if bad then use old way
%             numTimes = length(time);
%             loop = true;
%             rVectB = zeros(3,numTimes);
%             vVectB = zeros(3,numTimes);
%             while(loop)
%                 try
%                     parentBodyInfo = bodyInfo.getParBodyInfo(celBodyData);
%                 catch
%                     parentBodyInfo = getParentBodyInfo(bodyInfo, celBodyData);
%                 end
%
%                 if(isempty(parentBodyInfo))
%                     break;
%                 end
%
%                 try
%                     parentGM = bodyInfo.getParentGmuFromCache();
%                 catch
%                     parentGM = getParentGM(bodyInfo,celBodyData);
%                 end
%
%                 [rVect, vVect] = getStateAtTime(bodyInfo, time, parentGM); %getParentGM(bodyInfo, celBodyData)
%                 rVectB = rVectB + rVect;
%                 vVectB = vVectB + vVect;
%
%                 bodyInfo = parentBodyInfo;
%             end
%         end
%     end
end


function overlay_background(src_folder, dst_folder, bkgFilelist, bkgFolder, clutteredBkgRatio, single_thread)

if nargin < 6
    single_thread = 0;
end
if single_thread
    num_workers = 0;
else
    num_workers = 24;
end

image_files = rdir(fullfile(src_folder,'*/*.png'));
image_num = length(image_files);
fprintf('%d images in total.\n', image_num);
if image_num == 0
    return;
end
sunImageList = importdata(bkgFilelist);
rng('shuffle');

fprintf('Start overlaying images at time %s, it takes for a while...\n', datestr(now, 'HH:MM:SS'));
report_num = 80;
fprintf([repmat('.',1,report_num) '\n\n']);
report_step = floor((image_num+report_num-1)/report_num);
t_begin = clock;
%for i = 1:image_num
parfor(i = 1:image_num, num_workers)
    src_image_file = image_files(i).name;
    try
        [I, ~, alpha] = imread(src_image_file);
    catch
        fprintf('Failed to read %s\n', src_image_file);
    end

    s = size(I);
    fh = s(1); fw = s(2);
    mask = double(alpha) / 255;
    mask = repmat(mask,1,1,3);

    if rand() > clutteredBkgRatio
        I = uint8(double(I) .* mask + double(rand()*255) * (1 - mask));
    else
        while true
            id = randi(length(sunImageList));
            bg = imread(fullfile(bkgFolder, sunImageList{id}));
            s = size(bg);
            bh = s(1); bw = s(2);
            if bh < fh || bw < fw
                %fprintf(1, '.');
                continue;
            end
            if length(s) < 3
                continue;
            end
            break;
        end
        by = randi(bh - fh + 1);
        bx = randi(bw - fw + 1);
        bgcrop = bg(by:(by+fh-1), bx:(bx+fw-1), :);

        I = uint8(double(I) .* mask + double(bgcrop) .* (1 - mask));
    end

    if numel(I) == 0
        fprintf('Failed to overlay %s (empty image after crop)\n', src_image_file);
    else
        dst_image_file = strrep(src_image_file, src_folder, dst_folder);
        dst_image_file = strrep(dst_image_file, '.png', '.jpg');
        [dst_image_file_folder, ~, ~] = fileparts(dst_image_file);
        if ~exist(dst_image_file_folder, 'dir')
            mkdir(dst_image_file_folder);
        end
        %imwrite(I, dst_image_file, 'png', 'Alpha', alpha);
        imwrite(I, dst_image_file, 'jpg');
    end

    if mod(i, report_step) == 0
        fprintf('\b|\n');
    end
end
t_end = clock;
fprintf('%f seconds spent on background overlay!\n', etime(t_end, t_begin));


function rcnn_make_window_file(imdb, out_dir, mode)
% rcnn_make_window_file(imdb, out_dir)
%   Makes a window file that can be used by the caffe WindowDataLayer
%   for finetuning.
%
%   The window file format contains repeated blocks of:
%
%     # image_index
%     img_path
%     channels
%     height
%     width
%     num_windows
%     class_index overlap x1 y1 x2 y2
%     <... num_windows-1 more windows follow ...>

% AUTORIGHTS
% ---------------------------------------------------------
% Copyright (c) 2014, Ross Girshick
%
% This file is part of the R-CNN code and is available
% under the terms of the Simplified BSD License provided in
% LICENSE. Please retain this notice and LICENSE if you use
% this file (or any portion of it) in your project.
% ---------------------------------------------------------
if nargin<3
    mode = 'cnn';
end

roidb = imdb.roidb_func(imdb);

window_file = sprintf('%s/window_file_%s.txt', ...
    out_dir, imdb.name);
fid = fopen(window_file, 'wt');

channels = 3; % three channel images

for i = 1:length(imdb.image_ids)
  tic_toc_print('make window file: %d/%d\n', i, length(imdb.image_ids));
  img_path = imdb.image_at(i);

  roi = roidb.rois(i);

  switch mode
    case 'cnn'
        % do nothing
    case 'ctx'
        roi.boxes = roi.ctx;
    otherwise
        disp('Unspecified mode!');
        keyboard;
  end

  num_boxes = size(roi.boxes, 1);
  fprintf(fid, '# %d\n', i-1);
  fprintf(fid, '%s\n', img_path);
  fprintf(fid, '%d\n%d\n%d\n', ...
      channels, ...
      imdb.sizes(i, 1), ...
      imdb.sizes(i, 2));
  fprintf(fid, '%d\n', num_boxes);
  for j = 1:num_boxes
    [ov, label] = max(roi.overlap(j,:));
    % zero overlap => label = 0 (background)
    if ov < 1e-5
      label = 0;
      ov = 0;
    end
    bbox = roi.boxes(j,:)-1;
    fprintf(fid, '%d %.3f %d %d %d %d\n', ...
        label, ov, bbox(1), bbox(2), bbox(3), bbox(4));
  end
end

fclose(fid);


function [ncst,Area,k]=mu_coast(optn,varargin)
% MU_COAST Add a coastline to a given map.
%         MU_COAST draw a coastline as either filled patches (slow) or
%         lines (fast) on a given projection. It uses a coastline database with
%         a resolution of about 1/4 degree.
%
%         It is not meant to be called directly by the user, instead it contains
%         code common to various functions in the m_map directory.
%
%         Calling sequence is MU_COAST(option,arguments) where
%
%         Option string
%           c,l,i,h,f :  Accesses various GSHHS databases. Next argument is
%                        GSHHS filename.
%
%           u[ser] :   Accesses user-specified coastline file (a mat-file of
%                      data saved from a previous MU_COAST call). Next argument
%                      is filename
%
%           v[ector] : Uses input vector of data. Next argument is the
%                     data in the form of a nx2 matrix of [longitude latitude].
%                     Patches must have first and last points the same. In a vector,
%                     different patches can be separated by NaN.
%
%           d[efault] :  Accesses default coastline.
%
%         The arguments given above are then followed by (optional) arguments
%         specifying lines or patches, in the form:
%
%          optional arguments:  <line property/value pairs>, or
%                               'line',<line property/value pairs>.
%                               'patch',<patch property/value pairs>.
%                               'speckle',width,density,<line property/value pairs>.
%
%         If no or one output arguments are specified then the coastline is drawn, with
%         patch handles returned.
%         If 3 output arguments are specified in the calling sequence, then no drawing
%         is done. This can be used to save subsampled coastlines for future use
%         with the 'u' option, for fast drawing of multiple instances of a particular
%         coastal region.
%
%
%
%         See also M_PROJ, M_GRID

% Rich Pawlowicz (rich@ocgy.ubc.ca) 2/Apr/1997
%
% Notes: 15/June/98 - fixed some obscure problems that occured sometimes
%                     when using conic projections with large extents that
%                     crossed the 180-deg longitude line.
%        31/Aug/98  - added "f" gshhs support (Thanks to RAMO)
%        17/June/99 - 'line' option as per manual (thanks to Brian Farrelly)
%        3/Aug/01   - kludge fix for lines to South Pole in Antarctica (response
%                     to Matt King).
%        30/May/02  - fix to get gshhs to work in Antarctica.
%        15/Dec/05  - speckle additions
%        21/Mar/06  - handling of gshhs v1.3 (developed from suggestions by
%                     Martin Borgh)
%        26/Nov/07 - changed 'finite' to 'isfinite' after warnings
%        26/Sep/14 - added hierarchy flag to borders and rivers
%        13/Nov/14 - suggested matlab2014b graphics fix
%         8/Mar/17 - conic wrap-around not quite working right in a weird case when
%                    'rectbox' was on.
%           Nov/17 - redid a lot of the gshhs-related stuff
%
% This software is provided "as is" without warranty of any kind. But
% its mine, so you can't sell it.

global MAP_PROJECTION MAP_VAR_LIST

% Have to have initialized a map first

if isempty(MAP_PROJECTION)
  disp('No Map Projection initialized - call M_PROJ first!');
  return;
end

% m_coasts.mat contains 3 variables:
% ncst: a Nx2 matrix of [LONG LAT] line segments, each of which form
%       a closed contour (i.e. first and last points are the SAME),
%       separated by NaN
%  k=[find(isnan(ncst(:,1)))];
% Area: a vector giving the areas of the different patches. Both ncst
%     and Area should be ordered with biggest regions first. Area can
%     be computed as follows:
%
%  Area=zeros(length(k)-1,1);
%  for i=1:length(k)-1,
%    x=ncst([k(i)+1:(k(i+1)-1) k(i)+1],1);
%    y=ncst([k(i)+1:(k(i+1)-1) k(i)+1],2);
%    nl=length(x);
%    Area(i)=sum( diff(x).*(y(1:nl-1)+y(2:nl))/2 );
%  end;
%
%     Area should be >0 for land, and <0 for lakes and inland seas.

switch optn(1)
  case {'c','l','i','h','f'}
    [ncst,k,Area]=get_coasts(optn,varargin{1});
    varargin(1)=[];
  case  'u'
    eval(['load ' varargin{1} ' -mat']);
    varargin(1)=[];
  case 'v'
    ncst=[NaN NaN;varargin{1};NaN NaN];
    varargin(1)=[];
    k=[find(isnan(ncst(:,1)))];  % Get k
    Area=ones(size(k));          % Make dummy Area vector (all positive).
    otherwise
    currloc=mfilename('fullpath');  % Octave has problems finding the file
    load([currloc(1:end-8) 'm_coasts.mat']);

end

% If all we wanted was to extract a sub-coastline, return.
if nargout==3
  return;
end

% Handle wrap-arounds (not needed for azimuthal and oblique projections)

switch MAP_PROJECTION.routine
 case {'mp_cyl','mp_conic','mp_tmerc'}
  if MAP_VAR_LIST.longs(2)<-180
   ncst(:,1)=ncst(:,1)-360;
  elseif MAP_VAR_LIST.longs(1)>180
   ncst(:,1)=ncst(:,1)+360;
  elseif MAP_VAR_LIST.longs(1)<-180
   Area=[Area;Area];
   k=[k;k(2:end)+k(end)-1];
   ncst=[ncst;[ncst(2:end,1)-360 ncst(2:end,2)]];
   % This is kinda kludgey - but sometimes adding all these extra points
   % causes wrap-around in the conic projection, so we want to limit the
   % longitudes to the range needed. However, we don't just clip them to
   % min long because that can cause problems in trying to decide which way
   % curves are oriented when doing the fill algorithm below. So instead
   % I sort of crunch the scale, preserving topology.
   %
   % 12/Sep/2006 - in the gsshs_crude database we have a lot of long skinny
   % things which interact badly with this - so I offset the scrunch 2 degrees
   % away from the bdy
   %
   % Mar/2017 - OK, so somebody used a rectbox 'on' which gave a really wide range of
   % lat/long, and it turns out I need to scale the *other* side as well!
   nn=ncst(:,1)>MAP_VAR_LIST.longs(2)+2;                                          % added 2017
   ncst(nn,1)=(ncst(nn,1)-MAP_VAR_LIST.longs(2)-2)/100+MAP_VAR_LIST.longs(2)+2;   %  "
   nn=ncst(:,1)<MAP_VAR_LIST.longs(1)-2;
   ncst(nn,1)=(ncst(nn,1)-MAP_VAR_LIST.longs(1)+2)/100+MAP_VAR_LIST.longs(1)-2;
  elseif MAP_VAR_LIST.longs(2)>180
   Area=[Area;Area];
   k=[k;k(2:end)+k(end)-1];
   ncst=[ncst;[ncst(2:end,1)+360 ncst(2:end,2)]];
   % Ditto.
   nn=ncst(:,1)>MAP_VAR_LIST.longs(2)+2;
   ncst(nn,1)=(ncst(nn,1)-MAP_VAR_LIST.longs(2)-2)/100+MAP_VAR_LIST.longs(2)+2;
   nn=ncst(:,1)<MAP_VAR_LIST.longs(1)-2;                                          % added 2017
   ncst(nn,1)=(ncst(nn,1)-MAP_VAR_LIST.longs(1)+2)/100+MAP_VAR_LIST.longs(1)-2;   % "
 %%%  disp('beep');
  end
end

if ~isempty(varargin)
  if strcmp(varargin(1),'patch')
    optn='patch';
  end
  if strcmp(varargin(1),'speckle')
    optn='speckle';
  end
  if strcmp(varargin(1),'line')
    optn='line';
    varargin=varargin(2:end); % ensure 'line' does not get passed to line
  end
else
  optn='line';
end

switch optn
 case {'patch','speckle'}

  switch MAP_VAR_LIST.rectbox
    case 'on'
      xl=MAP_VAR_LIST.xlims;
      yl=MAP_VAR_LIST.ylims;
      [X,Y]=m_ll2xy(ncst(:,1),ncst(:,2),'clip','on');
      oncearound=4;
    case 'off'
      xl=MAP_VAR_LIST.longs;
      yl=MAP_VAR_LIST.lats;
      X=ncst(:,1);
      Y=ncst(:,2);
      [X,Y]=mu_util('clip','on',X,xl(1),X<xl(1),Y);
      [X,Y]=mu_util('clip','on',X,xl(2),X>xl(2),Y);
      [Y,X]=mu_util('clip','on',Y,yl(1),Y<yl(1),X);
      [Y,X]=mu_util('clip','on',Y,yl(2),Y>yl(2),X);
      oncearound=4;
    case 'circle'
      rl=MAP_VAR_LIST.rhomax;
      [X,Y]=m_ll2xy(ncst(:,1),ncst(:,2),'clip','on');
      oncearound=2*pi;
  end

  if ~MAP_PROJECTION.newgraphics
     p_hand=zeros(length(k)-1,1); % Patch handles
  else
     p_hand=gobjects(length(k)-1,1); % Patch handles
  end

  for i=1:length(k)-1
    x=X(k(i)+1:k(i+1)-1);
    fk=isfinite(x);
    if any(fk)
      y=Y(k(i)+1:k(i+1)-1);XX=x;YY=y;
%% if i>921, disp('pause 1'); pause; end;
      nx=length(x);
      if Area(i)<0, x=flipud(x);y=flipud(y); fk=flipud(fk); end
%clf
%line(x,y,'color','m');
      st=find(diff(fk)==1)+1;
      ed=find(diff(fk)==-1);
%length(x),
%ed,
%st
      if length(st)<length(ed) || isempty(st), st=[ 1;st]; end
      if length(ed)<length(st),                ed=[ed;nx]; end
%ed
%st
      if  ed(1)<st(1)
        if c_edge(x(1),y(1))==9999
          x=x([(ed(1)+1:end) (1:ed(1))]);
          y=y([(ed(1)+1:end) (1:ed(1))]);
          fk=isfinite(x);
          st=find(diff(fk)==1)+1;
          ed=[find(diff(fk)==-1);nx];
          if length(st)<length(ed), st=[1;st]; end
        else
          ed=[ed;nx];
          st=[1;st];
        end
      end
%ed
%st
      % Get rid of 2-point curves (since often these are out-of-range lines with
      % both endpoints outside the region of interest)
      k2=(ed-st)<3;
      ed(k2)=[]; st(k2)=[];
%%[XX,YY]=m_ll2xy(x(st),y(st),'clip','off');
%line(x,y,'color','r','linestyle','-');
%line(x(st),y(st),'marker','o','color','r','linestyle','none');
%line(x(ed),y(ed),'marker','o','color','g','linestyle','none');
      edge1=c_edge(x(st),y(st));
      edge2=c_edge(x(ed),y(ed));
%-edge1*180/pi
%-edge2*180/pi
      mi=1;
      while ~isempty(st)
        if mi==1
          xx=x(st(1):ed(1));
          yy=y(st(1):ed(1));
        end
        estart=edge2(1);
        s_edge=edge1;
        s_edge(s_edge<estart)=s_edge(s_edge<estart)+oncearound;
%s_edge,estart
        [md,mi]=min(s_edge-estart);
        switch MAP_VAR_LIST.rectbox
          case {'on','off'}
            for e=floor(estart):floor(s_edge(mi))
              if e==floor(s_edge(mi)), xe=x(st([mi mi])); ye=y(st([mi mi]));
              else,  xe=xl; ye=yl; end
              switch rem(e,4)
                case 0
                  xx=[xx; xx(end*ones(10,1))];
                  yy=[yy; yy(end)+(ye(2)-yy(end))*[1:10]'/10 ];
                case 1
                  xx=[xx; xx(end)+(xe(2)-xx(end))*[1:10]'/10 ];
                  yy=[yy; yy(end*ones(10,1))];
                case 2
                  xx=[xx; xx(end*ones(10,1))];
                  yy=[yy; yy(end)+(ye(1)-yy(end))*[1:10]'/10;];
                case 3
                  xx=[xx; xx(end)+(xe(1)-xx(end))*[1:10]'/10 ];
                  yy=[yy; yy(end*ones(10,1))];
              end
            end
          case 'circle'
            if estart~=9999
%s_edge(mi),estart
              xx=[xx; rl*cos(-[(estart:.1:s_edge(mi))]')];
              yy=[yy; rl*sin(-[(estart:.1:s_edge(mi))]')];
            end
        end
        if mi==1 % joined back to start
    	   if strcmp(optn,'patch')
               if strcmp(MAP_VAR_LIST.rectbox,'off')
                 [xx,yy]=m_ll2xy(xx,yy,'clip','off');
               end
               if Area(i)<0
                  p_hand(i)=patch(xx,yy,varargin{2:end},'facecolor',get(gca,'color'));
                  if ishandle(p_hand(i)), set(p_hand(i),'tag',[ get(p_hand(i),'tag') '_lake']);end
              else
                  p_hand(i)=patch(xx,yy,varargin{2:end});
                  if ishandle(p_hand(i)),set(p_hand(i),'tag',[ get(p_hand(i),'tag') '_land']);end
               end

	     else  % speckle
            if ~strcmp(MAP_VAR_LIST.rectbox,'off')  % If we were clipping in
	           [xx,yy]=m_xy2ll(xx,yy);                % screen coords go back
            end
            if Area(i)>0
               p_hand(i)=m_hatch(xx,yy,'speckle',varargin{2:end});
               if ishandle(p_hand(i)),set(p_hand(i),'tag',[get(p_hand(i),'tag') '_lake']); end
            else
	           p_hand(i)=m_hatch(xx,yy,'outspeckle',varargin{2:end});
               if ishandle(p_hand(i)),set(p_hand(i),'tag',[ get(p_hand(i),'tag') '_land']); end
            end
         end
%%%if i>921, disp(['paused-2 ' int2str(i)]);pause; end;
         ed(1)=[];st(1)=[];edge2(1)=[];edge1(1)=[];
       else
         xx=[xx;x(st(mi):ed(mi))];
         yy=[yy;y(st(mi):ed(mi))];
         ed(1)=ed(mi);st(mi)=[];ed(mi)=[];
         edge2(1)=edge2(mi);edge2(mi)=[];edge1(mi)=[];
       end
%%if i>921, disp(['paused-2 ' int2str(i)]);pause; end;
     end
    end
   end

   otherwise

  % This handles the odd points required at the south pole by any Antarctic
  % coastline by setting them to NaN (for lines only)
  ii=ncst(:,2)<=-89.9;
  if any(ii), ncst(ii,:)=NaN; end

  [X,Y]=m_ll2xy(ncst(:,1),ncst(:,2),'clip','on');

  % Get rid of 2-point lines (these are probably clipped lines spanning the window)
  fk=isfinite(X);
  st=find(diff(fk)==1)+1;
  ed=find(diff(fk)==-1);
  k=find((ed-st)==1);
  X(st(k))=NaN;

  p_hand=line(X,Y,varargin{:});

end

ncst=p_hand;

end
%-----------------------------------------------------------------------
function edg=c_edge(x,y)
% C_EDGE tests if a point is on the edge or not. If it is, it is
%        assigned a value representing it's position oon the perimeter
%        in the clockwise direction. For x/y or lat/long boxes, these
%        values are
%           0 -> 1 on left edge
%           1 -> 2 on top
%           2 -> 3 on right edge
%           3 -> 4 on bottom
%        For circular boxes, these values are the -ve of the angle
%        from center.

global MAP_VAR_LIST

switch MAP_VAR_LIST.rectbox
  case 'on'
    xl=MAP_VAR_LIST.xlims;
    yl=MAP_VAR_LIST.ylims;
  case 'off'
    xl=MAP_VAR_LIST.longs;
    yl=MAP_VAR_LIST.lats;
  case 'circle'
    rl2=MAP_VAR_LIST.rhomax^2;
end

edg=9999+zeros(length(x),1);
tol=1e-10;

switch MAP_VAR_LIST.rectbox
  case {'on','off'}
    i=abs(x-xl(1))<tol;
    edg(i)=(y(i)-yl(1))/diff(yl);

    i=abs(x-xl(2))<tol;
    edg(i)=2+(yl(2)-y(i))/diff(yl);

    i=abs(y-yl(1))<tol;
    edg(i)=3+(xl(2)-x(i))/diff(xl);

    i=abs(y-yl(2))<tol;
    edg(i)=1+(x(i)-xl(1))/diff(xl);

  case 'circle'
    i=abs(x.^2 + y.^2 - rl2)<tol;
    edg(i)=-atan2(y(i),x(i));   % use -1*angle so that numeric values
                                % increase in CW direction
end

end

function [ncst,k,Area]=get_coasts(optn,file)
%
%  GET_COASTS  Loads various GSHHS coastline databases and does some preliminary
%              processing to get things into the form desired by the patch-filling
%              algorithm.
%
% Changes; 3/Sep/98 - RP: better decimation, fixed bug in limit checking.
%          Nov/17  - mostly rewritten

global MAP_PROJECTION MAP_VAR_LIST

llim=rem(MAP_VAR_LIST.longs(1)+360,360)*1e6;
rlim=rem(MAP_VAR_LIST.longs(2)+360,360)*1e6;
tlim=MAP_VAR_LIST.lats(2)*1e6;
blim=MAP_VAR_LIST.lats(1)*1e6;

m.rlim=rem(MAP_VAR_LIST.longs(2)+360+180,360)-180;
m.llim=rem(MAP_VAR_LIST.longs(1)+360+180,360)-180;
m.tlim=MAP_VAR_LIST.lats(2);
m.blim=MAP_VAR_LIST.lats(1);

% decfac is for decimation of areas outside the lat/long bdys.
% Sizes updated for gshhs v1.3, checked for v2.3.6
% Sizes updated for v1.10, and for river/border databases.
switch optn(1)
  case 'f'  % 'full' (undecimated) database
    ncst=NaN(10810000,2);Area=zeros(188611,1);k=ones(188612,1);
    decfac=12500;
  case 'h'
    ncst=NaN(2080000,2);Area=zeros(153545,1);k=ones(153546,1);
   decfac=2500;
  case 'i'
    ncst=NaN(493096,2);Area=zeros(41529,1);k=ones(41530,1);
    decfac=500;
  case 'l'
    ncst=NaN(124871,2);Area=zeros(20776,1);k=ones(27524,1);
    decfac=100;
  case 'c'
    ncst=NaN(14403,2);Area=zeros(1766,1);k=ones(1767,1);
    decfac=20;
end

flaglim=9;
if length(optn)>=2
  flaglim=str2num(optn(2));
end

fid=fopen(file,'r','ieee-be');

if fid==-1
  warning(['Coastline file ' file ...
          ' not found \n(Have you installed it? See the M_Map User''s Guide for details)' ...
          '\n ---Using default coastline instead']);
  load m_coasts
  return
end

Area2=Area;

% Read the File header

[cnt,g]=get_gheader(fid);

l=0;
while cnt>0

   C=fread(fid,g.N*2,'int32'); % Read all points in the current segment.

   % For versions > 12 there are 2 Antarctics - ice-line and grounding line,
   % also they changed the limits from 0-360 to -180 to 180.
   if g.ver>14
     switch g.level
       case 6
         g.level=flaglim+1; % ice line - don't show
       case 5
         g.level=1;         % grounding line - use this.
     end
   else
     %For Antarctica the lime limits are 0 to 360 (exactly), thus c==0 and the
     %line is not chosen for (e.g. a conic projection of part of Antarctica)
     % Fix 30may/02
     if g.extentE==360e6, g.extentE=g.extentE-1; end
   end

   a=rlim>llim;  % Map limits cross longitude jump? (a==1 is no)
   b=g.greenwich<65536; % Cross boundary? (b==1 if no).
   c=llim<rem(g.extentE+360e6,360e6);
   d=rlim>rem(g.extentW+360e6,360e6);
   e=tlim>g.extentS & blim<g.extentN;

   % This test checks whether the lat/long box containing the line overlaps that of
   % the map. There are various cases to consider, depending on whether map limits
   % and/or the line limits cross the longitude jump or not.

   if     e  ...
      && (    (  a&&( (b&&c&&d) || (~b&&(c||d) ) ) )    ...
           || ( ~a&&(    ~b     || ( b&&(c||d) ) ) )  ) ...
      && g.level<=flaglim

     l=l+1;
     x=C(1:2:end)*1e-6;
     y=C(2:2:end)*1e-6;

     %  line(x,y,'color','r');pause;

     %  make things continuous (join edges that cut across 0-meridian)

     dx=diff(x);
     x=x-360*cumsum([x(1)>180;(dx>356) - (dx<-356)]);

     % Antarctic is a special case - extend contour to make nice closed polygon
     % that doesn't surround the pole.
     if g.ver<15
       % Range from 0-360
       if abs(x(1))<1 && abs(y(1)+68.9)<1
         y=[-89.9;-78.4;y(x<=-180);y(x>-180);   -78.4;-89.9*ones(18,1)];
         x=[  180; 180 ;x(x<=-180)+360;x(x>-180);-180; [-180:20:160]'];
       end
     else
       % new version is from -180 to 180
       if abs(x(1))==180 && y(1)<-76
         y=[-89.9;-78.4;y;   -78.4;-89.9*ones(19,1)];
         x=[ 180; 180 ;x;    -180; [-180:20:180]'];
       end
     end

     %plot(x,y);pause;

     % First and last point should be the same IF THIS IS A POLYGON
     % if the Area=0 then this is a line, and don't add points!

     if g.area>0

       if x(end)~=x(1) || y(end)~=y(1)   % First and last points should be the same
             x=[x;x(1)];y=[y;y(1)];
       end

       % get correct curve orientation for patch-fill algorithm.

       Area2(l)=sum( diff(x).*(y(1:(end-1))+y(2:end))/2 ); % Area "on the page"
       Area(l)=g.area/10;                                  % Area "on the globe"

       if rem(g.level,2)==0  % Make lakes (2) and islands (1) differently oriented
         Area(l)=-abs(Area(l));
         if Area2(l)>0, x=x(end:-1:1);y=y(end:-1:1); end
       else
         if Area2(l)<0, x=x(end:-1:1);y=y(end:-1:1); end
       end

     else
       % Later on 2 point lines are clipped so we want to avoid that
       if length(x)==2
          x=[x(1);mean(x);x(2)];
          y=[y(1);mean(y);y(2)];
       end
     end

     % Here we try to reduce the number of points and clip them
     % close to map limits (if they are too far away this can cause
     % problems with some projections as they wrap around into the
     % wrong place)

     [cx,cy]=clip_to_lims(x,y,m,decfac);

     k(l+1)=k(l)+length(cx)+1;
     ncst(k(l)+1:k(l+1),:)=[cx,cy;NaN NaN];

     % This is a little tricky...the filling algorithm expects data to be in the
     % range -180 to 180 deg long. However, there are some land parts that cut across
     % this divide so they appear at +190 but not -170. This causes problems later...
     % so as a kludge I replicate some of the problematic features at 190-360=-170.
     % I cut out the problematic points only, make sure the first and last
     % points are the same, and then add this curve to ncst
     if max(x)>180
        ii=find(x>179);ii=[ii;ii(1)];
        [cx,cy]=clip_to_lims(x(ii)-360,y(ii),m,decfac);
        l=l+1;
        k(l+1)=k(l)+length(cx)+1;
        ncst(k(l)+1:k(l+1),:)=[cx,cy;NaN NaN];
     end

     %plot(ncst(:,1),ncst(:,2));drawnow;
   end
  [cnt,g]=get_gheader(fid);
end

fclose(fid);

%plot(ncst(:,1),ncst(:,2));pause;clf;

ncst((k(l+1)+1):end,:)=[];  % get rid of unused part of data matrices
Area((l+1):end)=[];
k((l+2):end)=[];
%%%fprintf('Size ncst: %d, Area: %d, k %d\n',length(ncst),length(Area),length(k))

end

function [x,y]=clip_to_lims(x,y,m,decfac)
% Look for points outside the lat/long boundaries, and then decimate them
   % by a factor of about 'decfac' (don't get rid of them completely because that
   % can sometimes cause problems when polygon edges cross curved map edges).

   tol=.2;

   % Do y limits, then x so we can keep corner points.

   nn=(y>m.tlim+tol) | (y<m.blim-tol);
     % keep one extra point when crossing limits, also the beginning/end point.
   nn=logical(nn-min(1,([0;diff(nn)]>0)+([diff(nn);0]<0)));
   nn([1 end])=0;
     % decimate vigorously
   nn=nn & rem(1:length(nn),decfac)'~=0;
   x(nn)=[];y(nn)=[];

   if m.rlim>m.llim  % no wraparound
       % sections of line outside lat/long limits
     nn=(x>m.rlim+tol | x<m.llim-tol) & y<m.tlim & y>m.blim;
    else            % wraparound case
     nn=(x>m.rlim+tol & x<m.llim-tol ) & y<m.tlim & y>m.blim;
   end
   nn=logical(nn-min(1,([0;diff(nn)]>0)+([diff(nn);0]<0)));nn([1 end])=0;
   nn=nn & rem(1:length(nn),decfac)'~=0;
   x(nn)=[];y(nn)=[];

   % Move all points "near" to map boundaries.
   % I'm not sure about the wisdom of this - it might be better to clip
   % to the boundaries instead of moving. Hmmm.

   y(y>m.tlim+tol)=m.tlim+tol;
   y(y<m.blim-tol)=m.blim-tol;
   if m.rlim>m.llim   % Only clip long bdys if I can tell I'm on the right
                     % or left (i.e. not in wraparound case)
     x(x>m.rlim+tol)=m.rlim+tol;
     x(x<m.llim-tol)=m.llim-tol;
   end

end

function [cnt,g]=get_gheader(fid)
% Reads the gshhs file header
%
% A bit of code added because header format changed with version 1.3.
%
% 17/Sep/2008 - added material to handle latest GSHHS version.
%
% For version 1.1 this is the header ( 9*4 = 36 bytes long)
%
%int id;				/* Unique polygon id number, starting at 0 */
%int n;				/* Number of points in this polygon */
%int level;			/* 1 land, 2 lake, 3 island_in_lake, 4 pond_in_island_in_lake */
%int west, east, south, north;	/* min/max extent in micro-degrees */
%int area;			/* Area of polygon in 1/10 km^2 */
%short int greenwich;		/* Greenwich is 1 if Greenwich is crossed */
%short int source;		/* 0 = CIA WDBII, 1 = WVS */
%
% For version 1.3 of GMT format was changed to this ( 10*4 = 40 bytes long)
%
%int id;				/* Unique polygon id number, starting at 0 */
%int n;				/* Number of points in this polygon */
%int level;			/* 1 land, 2 lake, 3 island_in_lake, 4 pond_in_island_in_lake */
%int west, east, south, north;	/* min/max extent in micro-degrees */
%int area;			/* Area of polygon in 1/10 km^2 */
%int version;			/* Polygon version, set to 3
%short int greenwich;		/* Greenwich is 1 if Greenwich is crossed */
%short int source;		/* 0 = CIA WDBII, 1 = WVS */
%
% For version 1.4, we have (8*4 = 32 bytes long)
%
%int id;				/* Unique polygon id number, starting at 0 */
%int n;				/* Number of points in this polygon */
%int flag;			/* level + version << 8 + greenwich << 16 + source << 24
%int west, east, south, north;	/* min/max extent in micro-degrees */
%int area;			/* Area of polygon in 1/10 km^2 */
%
%Here, level, version, greenwhich, and source are
%level:		1 land, 2 lake, 3 island_in_lake, 4 pond_in_island_in_lake
%version:	Set to 4 for GSHHS version 1.4
%greenwich:	1 if Greenwich is crossed
%source:		0 = CIA WDBII, 1 = WVS
%
% For version 2.0 it all changed again, we have (11*4 = 44 bytes)
%
%	int id;		/* Unique polygon id number, starting at 0 */
%	int n;		/* Number of points in this polygon */
%	int flag;	/* = level + version << 8 + greenwich << 16 + source << 24 + river << 25 */
%	/* flag contains 5 items, as follows:
%	 * low byte:	level = flag & 255: Values: 1 land, 2 lake, 3 island_in_lake, 4 pond_in_island_in_lake
%                                             For Antarctic starting with 2.3.0 ice-front=5 and grounding line=6
%                                           for border database: 1=country, 2=state/province
%	 * 2nd byte:	version = (flag >> 8) & 255: Values: Should be 7 for GSHHS release 7 (i.e., version 2.0)
%                                                                     12 for version 2.2
%                                                                     15 for 2.3.6
%	 * 3rd byte:	greenwich = (flag >> 16) & 1: Values: Greenwich is 1 if Greenwich is crossed
%	 * 4th byte:	source = (flag >> 24) & 1: Values: 0 = CIA WDBII, 1 = WVS
%	 * 4th byte:	river = (flag >> 25) & 1: Values: 0 = not set, 1 = river-lake and level = 2
%	 */
%	int west, east, south, north;	/* min/max extent in micro-degrees */
%	int area;	/* Area of polygon in 1/10 km^2 */
%	int area_full;	/* Area of original full-resolution polygon in 1/10 km^2 */
%	int container;	/* Id of container polygon that encloses this polygon (-1 if none) */
%	int ancestor;	/* Id of ancestor polygon in the full resolution set that was the source of this polygon (-1 if none)

% Now, in the calling code I have to use A(2),A(3),A(5-7), A(8), A(9) from original.

[A,cnt]=fread(fid,8,'int32');

if cnt<8  % This gets triggered by the EOF
  g=[];
  return;
end

g.ver=bitand(bitshift(A(3),-8),255);

if g.ver==0  % then its an old version, fake it to look new

  % This works for version 1.2, but not 1.3.

  [A2,cnt2]=fread(fid,1,'int32');
  A=[A;A2];

  if (cnt+cnt2)==9 && A(9)==3  % we have version 1.3, this would be one of 0,1,65535,65536 in v 1.2
    % Read one more byte
    A2=fread(fid,1,'int32');
    % This is the easiest way not to break existing code.
    A(9)=A2;   % one of 0,1,65536,65537
  end

elseif g.ver>=7  % After v2.0 some more bytes around for original area and container/ancerstor IDs

  A2=fread(fid,3,'int32');

end

% a newest versions
g.id=A(1);
g.N=A(2);
g.level=bitand(A(3),255);
g.greenwich=bitand(bitshift(A(3),-16),255)*65536;
g.source=bitand(bitshift(A(3),-24),255);
A(3)=g.level;
A(9)=g.greenwich;

g.extentW=A(4);
g.extentE=A(5);
g.extentS=A(6);
g.extentN=A(7);
g.area=A(8);

end


%%
% calculates the loglikelihood scores for random simulations
%%

global no1 bo1 inb1 inb2

compflag = 'on';
tmp_newt2 = newt2;

%%
% get the name of the p value grid file and load it
%%

prompt = {'Enter the name of the random simulation file',...
    'Enter the name of the real data file (p value estimation)',...
    'Enter the forecast start time (days from mainshock)',...
    'Enter the forecast end time (days from mainshock)'...
    'Enter the number of random simulations'};
title = 'Filename Input';
lines = 1;
def = {'','','10','15','100'};
answer = inputdlg(prompt,title,lines,def);
rand_in = answer{1,1};
real_in = answer{2,1};
fore_sday = str2double(answer{3,1});
fore_eday = str2double(answer{4,1});
numrand = str2double(answer{5,1});

real_in = 'test.mat';
load(real_in);

%%
% get a b c p and k from input file (in that order) for spatially varying models
%%
tvg(:,1) = bpvg(:,16);
tvg(:,2) = bpvg(:,18);
tvg(:,3) = bpvg(:,14);
tvg(:,4) = bpvg(:,11);
tvg(:,5) = bpvg(:,3);
tvg(:,6) = bpvg(:,4);

rand_in = '100rand.mat';
load(rand_in)
nodes = tmpgri;

%bpvg = rpvg;

%if(bpvg(1,15) == 1)
%         % this grid was not calculated with constant area so stop.
%         disp('%%%%ERROR%%%% This input grid was NOT calculated with constant radius please use one that is.')
%         return
%end

%%
% cut cat to only forecast time period
%%
fore_start = maepi(:,3) + fore_sday/365;
fore_end = maepi(:,3) + fore_eday/365;
ll = tmp_newt2.Date >= fore_start & tmp_newt2.Date <= fore_end;
fore_cat = tmp_newt2(ll,:);

dt = .1
calc_mag = [];
calc_cummag = [];

%%
% call distofault to get the distance from each grid node to the estimated fault
% gx and gy come from the input file
%%

faultdist

lt1 = fdkm < 1;
fdkm(lt1) = 1;

disp('values for sequence specific model');
pvalcat
ssa = rja;
ssb = rjb;
ssc = cv;
ssp = pv;

%%
% use the distance to taper the a value for the Generic calculation
% and the sequence specific calculation
%%

%totd = sum(1./(fdkm.^2));
totd = sum(fdkm.^2);
da = -1.67-log(totd);
dssa = ssa/totd;
numevents = length(fore_cat);
for i = 1:length(fdkm)
    id(i) = totd/(fdkm(i)^2);
end
sid =  sum(id);
sler = id/sid;
%%
% gevents is the number of events scaled with distance from fault
% this is not actually observed but is only the number of total
% obs events distributed over the entire grid with number of events
% taper as 1/r^2
%
% a is scaled by subtracting the log of the ratio of number of
% events at the node to the entire number of events from the
% overall a value.
%%
gevents = sler*numevents;
for i = 1:length(gevents)
    tapera(i) = -1.67-log(numevents/gevents(i));
    sstapera(i) = ssa-log(numevents/gevents(i));
end

%plot_tapera(tapera,s1x,s1y,s2x,s2y,tmpgri,xvect,yvect)
magco_fixed = 1.0
lvary_a = [];
lvary_ab = [];
lgca = [];

%%
% calculate the overall b-value
%%
[magml bo1 stanml,  avml] =  bmemag(newt2);

%%
% loop over all grid nodes and calculate various forecasts
%%

allcount = 0;
itotal = length(bpvg);
wait = waitbar(0,'Thinking...');
[lgl dum,  dum] = size(bpvg);
for gloop = 1:itotal
    allcount=allcount+1;

    %%
    %     Calculate the forecast for varying a & b and varying a w/constant b
    %
    %  select the events within the radius used for the parameter calc. (rd) from
    %  the forecast time period, to compare the calculated number of events with
    %%
    xg = bpvg(gloop,3);
    yg = bpvg(gloop,4);
    l = sqrt(((fore_cat(:,1)-xg)*cos(pi/180*yg)*111).^2 + ((fore_cat(:,2)-yg)*111).^2) ;
    [s,is] = sort(l);
    fore_cat = fore_cat(is(:,1),:) ;       % re-orders matrix to agree row-wise

    %%
    % get fore events  w/in the original radius
    %%
    l3 = l <= bpvg(1,5);
    obs_events = fore_cat(l3,:);      % obs_events is the events at the node w/in the radius of the original

    for rand_loop = 1:numrand+1
        if rand_loop == 1  % only calculate these the first time thru -- not for each rand loop

            %%
            % Calculate forecast for:
            % Sequence Specific model with a-values smoothed as 1/r^2 from fault and calculate the PDF
            %%

            mag_events = [];
            ct=1;
            for m = magco_fixed-0.1:0.1:7
                tct = 1;
                for t = fore_sday:dt:fore_eday
                    mag_events_ss(tct,ct) = 10^(sstapera(gloop)+ssb*(maepi(1,6)-m))*(t+ssc).^(-ssp);
                    tct = tct + 1;
                end
                ct = ct + 1;
            end

            %%
            % calculate the PDF and the log likelihood score for the ss model -- a tapered away from fault
            %%
            sum_mag = sum(mag_events_ss,1)';
            diff_mag = -diff(sum_mag,1);
            ss_pdf = poisspdf(obs_mag',diff_mag);

            lss(:,gloop) = log(ss_pdf);
            l = isinf(lss(:,gloop));
            lss(l,gloop) = -350;

            %%
            % get a b c p and k from input file (in that order) for spaitally varying models
            %%
            x(1) = tvg(gloop,1);
            x(2) = tvg(gloop,2);
            x(3) = tvg(gloop,3);
            x(4) = tvg(gloop,4);

        else %% if rand_loop ~= 1
            x(1) = rpvg(gloop, 1, rand_loop-1);
            x(2) = rpvg(gloop, 2, rand_loop-1);
            x(4) = rpvg(gloop, 3, rand_loop-1);
            x(3) = rpvg(gloop, 4, rand_loop-1);
        end

        %%
        % Calculate forecast for:
        % Generic CA model with a-values smoothed as 1/r^2 from fault and calculate the PDF
        %%

        num_nodes = length(nodes);
        gen_b = .91;
        gen_p =  1.08;
        gen_c = .05;

        mag_events = [];
        ct=1;
        for m = magco_fixed-0.1:0.1:7
            tct = 1;
            for t = fore_sday:dt:fore_eday
                mag_events_gca(tct,ct) = 10^(tapera(gloop)+gen_b*(maepi(1,6)-m))*(t+gen_c).^(-gen_p);
                tct = tct + 1;
            end
            ct = ct + 1;
        end

        %%
        % calculate the PDF and the log likelihood score for Generic model -- a tapered away from fault
        %%
        sum_mag = sum(mag_events_gca,1)';
        diff_mag = -diff(sum_mag,1);
        [obs_mag,gca_magbin] = hist(obs_events(:,6),magco_fixed-0.05:0.1:7);
        gca_pdf = poisspdf(obs_mag',diff_mag);

        lgca(:,gloop) = log(gca_pdf);
        l = isinf(lgca(:,gloop));
        lgca(l,gloop) = -350;

        %%
        % calculate the forecast for each magnitude bin for varying a and constant b
        % bo1 is the constant b value calculated above using max likelihood
        %%
        mag_events = [];
        ct=1;
        for m = magco_fixed-0.1:0.1:7
            tct = 1;
            for t = fore_sday:dt:fore_eday
                mag_events_ab(tct,ct) = 10^(x(1)+x(2)*(maepi(1,6)-m))*(t+x(3)).^(-x(4));
                mag_events_a(tct,ct) = 10^(x(1)+bo1*(maepi(1,6)-m))*(t+x(3)).^(-x(4));
                tct = tct + 1;
            end
            ct = ct + 1;
        end
        %%
        % calculate the PDF and the log likelihood score for varying a & b
        %%
        sum_mag = sum(mag_events_ab,1)';
        diff_mag = -diff(sum_mag,1);
        [obs_mag,magbin] = hist(obs_events(:,6),magco_fixed-0.05:0.1:7);
        vary_abpdf = poisspdf(obs_mag',diff_mag);

        lvary_ab(:,gloop,rand_loop) = log(vary_abpdf);
        l = isinf(lvary_ab(:,gloop,rand_loop));
        lvary_ab(l,gloop,rand_loop) = -350;

        %%
        % calculate the PDF and the log likelihood score for varying a & constant b
        %%
        sum_mag = sum(mag_events_a,1)';
        diff_mag = -diff(sum_mag,1);
        [obs_mag,vary_amagbin] = hist(obs_events(:,6),magco_fixed-0.05:0.1:7);
        vary_apdf = poisspdf(obs_mag',diff_mag);

        lvary_a(:,gloop,rand_loop) = log(vary_apdf);
        l = isinf(lvary_a(:,gloop,rand_loop));
        lvary_a(l,gloop,rand_loop) = -350;

        waitbar(allcount/itotal);
    end
end

close(wait);

slvary_ab=[];
slvary_a=[];
gdiffab=[];
gdiffa=[];

%%
% sum the scores
%%
slgca = sum(lgca(:,gloop),2);
slss = sum(lss(:,gloop),2);
[dum numm,  dum] = size(lvary_ab);
for rloop2 = 1:numrand+1
    %%
    % sum the scores at each node
    %%
    slgca(rloop2,1:numm) = sum(lgca(:,:,rloop2),1);
    slvary_ab(rloop2,1:numm) = sum(lvary_ab(:,:,rloop2),1);
    slvary_a(rloop2,1:numm) = sum(lvary_a(:,:,rloop2),1);
    if rloop2 >= 2
        gdiffab(rloop2,1:length(slvary_ab(1,:))) = slvary_ab(rloop2,:) - slgca.subset(rloop2);
        gdiffa(rloop2,1:length(slvary_a(1,:))) = slvary_a(rloop2,:) - slgca.subset(rloop2);
    end
end

meanab = mean(gdiffab,2);
meana = mean(gdiffa,2);

[xll, yll] =size(slvary_ab);
gcatot = sum(slgca);
sstot = sum(slss);
abtot = sum(slvary_ab(2:numrand+1,:));
atot = sum(slvary_a(2:numrand+1,:));

rdabtot = sum(slvary_ab(1,:));
rdatot = sum(slvary_a(1,:));

tdiff = gcatot - abtot;

compflag = 'of';


function [nKeq, nGC, nNone] = standardGibbsFormationEnergyStats(modelT, figures)
% Generate the stats +/- pie chart on the provinence of the metabolite standard Gibbs energies.
%
% USAGE:
%
%    [nKeq, nGC, nNone] = standardGibbsFormationEnergyStats(modelT, figures)
%
% INPUTS:
%    modelT:
%    figures:
%
% OUTPUTS:
%    nKeq:
%    nGC:
%    nNone:
%
% .. Author: - Ronan M.T. Fleming

[nMet,nRxn]=size(modelT.S);

nKeq=eps;
nGC=eps;
nNone=eps;

noneBool=false(nMet,1);
p=1;
noneAbbr=[];
for m=1:nMet
    if strcmp(modelT.met(m).dGft0Source,'Keq')
        nKeq=nKeq+1;
    else
        if isnan(modelT.met(m).dGft0Source)
            nNone=nNone+1;
            noneBool(m,1)=1;
            abbr=modelT.mets{m};
            abbr=abbr(1:end-3);
            noneAbbr{p,1}=abbr;
            p=p+1;
        else
            nGC=nGC+1;
        end
    end
end

if figures
    figure1=figure;
    h=pie([nKeq,nGC,nNone],{{'K_{eq}',int2str(nKeq)},{'Group Contribution',int2str(nGC)},{'None',int2str(nNone)}});
    textObjs = findobj(h,'Type','text');
    set(textObjs,'FontSize',16);
    title('Provinence of reactant \Delta_{f}G^{\o} data','FontSize',16);
    saveas(figure1,'dfG0provinencePieChart','fig');

end

fprintf('%s\n',['Number of unique reactants without dGf0: ' int2str(length(unique(noneAbbr))) ]);


function saveHDF5(fileName, model, params)
  %hdf5write(fileName, 'params', params)
  hdf5write(fileName, 'dec_wordvec', model.W_emb_tgt);
  hdf5write(fileName, 'dec_vocab', params.tgtVocab, 'WriteMode', 'append');

  if params.isBi
    hdf5write(fileName, 'enc_wordvec', model.W_emb_src, 'WriteMode', 'append');
    hdf5write(fileName, 'enc_vocab', params.tgtVocab, 'WriteMode', 'append');
  end

  % ip weight
  hdf5write(fileName, 'ip_weight', model.W_soft, 'WriteMode', 'append');

  % recurrent params
  input_col_ranges = 1:params.lstmSize;
  hidden_col_ranges = params.lstmSize+1:2*params.lstmSize;
  for dd=1:params.numLayers
    prefix_tgt = ['dec_d', num2str(dd), '_lstm:'];

    % input
    row_ranges = 1:params.lstmSize;
    hdf5write(fileName, [prefix_tgt 'input_gate'], [model.W_tgt{dd}(row_ranges,hidden_col_ranges) model.W_tgt{dd}(row_ranges, input_col_ranges)], 'WriteMode', 'append');

    % forget
    row_ranges = params.lstmSize+1:2*params.lstmSize;
    hdf5write(fileName, [prefix_tgt 'forget_gate'], [model.W_tgt{dd}(row_ranges,hidden_col_ranges) model.W_tgt{dd}(row_ranges, input_col_ranges)], 'WriteMode', 'append');

    % output
    row_ranges = 2*params.lstmSize+1:3*params.lstmSize;
    hdf5write(fileName, [prefix_tgt 'output_gate'], [model.W_tgt{dd}(row_ranges,hidden_col_ranges) model.W_tgt{dd}(row_ranges, input_col_ranges)], 'WriteMode', 'append');

    % signal
    row_ranges = 3*params.lstmSize+1:4*params.lstmSize;
    hdf5write(fileName, [prefix_tgt 'input_value'], [model.W_tgt{dd}(row_ranges,hidden_col_ranges) model.W_tgt{dd}(row_ranges, input_col_ranges)], 'WriteMode', 'append');

    if params.isBi
      prefix_src = ['enc_d', num2str(dd), '_lstm:'];

      % input
      row_ranges = 1:params.lstmSize;
      hdf5write(fileName, [prefix_src 'input_gate'], [model.W_src{dd}(row_ranges,hidden_col_ranges) model.W_src{dd}(row_ranges, input_col_ranges)], 'WriteMode', 'append');

      % forget
      row_ranges = params.lstmSize+1:2*params.lstmSize;
      hdf5write(fileName, [prefix_src 'forget_gate'], [model.W_src{dd}(row_ranges,hidden_col_ranges) model.W_src{dd}(row_ranges, input_col_ranges)], 'WriteMode', 'append');

      % output
      row_ranges = 2*params.lstmSize+1:3*params.lstmSize;
      hdf5write(fileName, [prefix_src 'output_gate'], [model.W_src{dd}(row_ranges,hidden_col_ranges) model.W_src{dd}(row_ranges, input_col_ranges)], 'WriteMode', 'append');

      % signal
      row_ranges = 3*params.lstmSize+1:4*params.lstmSize;
      hdf5write(fileName, [prefix_src 'input_value'], [model.W_src{dd}(row_ranges,hidden_col_ranges) model.W_src{dd}(row_ranges, input_col_ranges)], 'WriteMode', 'append');
    end
  end

end


function model = model_add_parts(model, lhs, ruleind, partner, ...
                                 filterind, numparts, psize, ...
                                 scale, coef_scale)
% Add a deformable parts to a rule.
%   model = model_add_parts(model, lhs, ruleind, partner, ...
%                           filterind, numparts, psize, ...
%                           scale, coef_scale)
%
% Return value
%   model       Object model
%
% Arguments
%   model       Object model
%   lhs         Parts are added to:
%   ruleind         model.rules{lhs}(ruleind)
%   partner     Partner ruleind:
%                   model.rules{lhs}(ruleind) and
%                   model.rules{lhs}(partner) are l/r mirror images of each other
%               Or, if length(partner) == 2:
%                   model.rules{lhs}(ruleind) and
%                   model.rules{partner(1)}(partner(2)) are l/r mirror images
%   filterind   Filter that parts are initialize from
%   numparts    Number of parts to add
%   psize       Size of each part
%   scale       Number of octaves down from lhs to place parts
%               (only scale = 0,1 have been tested)
%   coef_scale  Part filter coeficients are scaled by this value

% AUTORIGHTS
% -------------------------------------------------------
% Copyright (C) 2009-2012 Ross Girshick
%
% This file is part of the voc-releaseX code
% (http://people.cs.uchicago.edu/~rbg/latent/)
% and is available under the terms of an MIT-like license
% provided in COPYING. Please retain this notice and
% COPYING if you use this file (or a portion of it) in
% your project.
% -------------------------------------------------------

% if the filter is mirrored, find its partner so mirrored
% parts can be added to it as well
if ~isempty(partner)
  if length(partner) == 2
    partner_lhs = partner(1);
    partner = partner(2);
  else
    partner_lhs = lhs;
  end
end

if nargin < 9
  coef_scale = 1;
end

source = model_get_block(model, model.filters(filterind));
pfilters = mkpartfilters(source, psize, numparts, scale);

for i = 1:numparts
  [model, symbolf] = model_add_terminal(model, 'w', coef_scale*pfilters(i).w);
  [model, N1] = model_add_nonterminal(model);

  % add deformation rule
  defoffset = 0;
  defparams = pfilters(i).alpha*[0.1 0 0.1 0];

  [model, rule] = model_add_def_rule(model, N1, symbolf, 'def_w', defparams);

  % add deformation symbols to rhs of rule
  anchor1 = pfilters(i).anchor;
  model.rules{lhs}(ruleind).rhs = [model.rules{lhs}(ruleind).rhs N1];
  model.rules{lhs}(ruleind).anchor = [model.rules{lhs}(ruleind).anchor anchor1];

  if ~isempty(partner)
    [model, symbolfp] = model_add_terminal(model, 'mirror_terminal', symbolf);
    [model, N2] = model_add_nonterminal(model);

    % add mirrored deformation rule
    model = model_add_def_rule(model, N2, symbolfp, 'mirror_rule', rule);

    x = pfilters(i).anchor(1);
    y = pfilters(i).anchor(2);
    % add deformation symbols to rhs of rule
    x2 = 2^scale*size(source, 2) - x - psize(2);
    anchor2 = [x2 y scale];
    model.rules{partner_lhs}(partner).rhs = ...
      [model.rules{partner_lhs}(partner).rhs N2];
    model.rules{partner_lhs}(partner).anchor = ...
      [model.rules{partner_lhs}(partner).anchor anchor2];
  end
end