function [success,msg] = ConvertMAGATAnalyzer2JAABA(varargin)

SCALE = 10; % centimeters instead of millimeters
MAXTIMESTAMPERR = .01;

success = false;
msg = '';

%% set parameters

[inmoviefile,expfile,...
  expdir,moviefilestr,trxfilestr,perframedirstr,...
  arenatype,arenacenterx,arenacentery,...
  arenaradius,arenawidth,arenaheight,...
  dosoftlink,dotransposeimage] = myparse(varargin,...
  'inmoviefile','','expfile','',...
  'expdir','','moviefilestr','movie.ufmf','trxfilestr','trx.mat','perframedirstr','perframe',...
  'arenatype','None','arenacenterx',0,'arenacentery',0,...
  'arenaradius',123,'arenawidth',123,'arenaheight',123,...
  'dosoftlink',false,...
  'dotransposeimage',false);

%% make sure that MAGATAnalyzer code is on the path

res = which('Experiment');
if isempty(res),
  msg = 'MAGATAnalyzer-Matlab-Analysis code must be on the MATLAB path';
  return;
end
res = which('deg2rad');
if isempty(res),
  msg = '"MAGATAnalyzer-Matlab-Analysis/utility functions" code must be on the MATLAB path';
  return;
end

%% check for files

if isempty(expfile),
  msg = 'Experiment file is empty';
  return;
end

if isempty(inmoviefile),
  msg = 'Video file is empty';
  return;
end

if ~exist(expfile,'file'),
  msg = sprintf('Experiment file %s does not exist',expfile);
  return;
end

if ~exist(inmoviefile,'file'),
  msg = sprintf('Video file %s does not exist',inmoviefile);
  return;
end

% output file locations
moviefile = fullfile(expdir,moviefilestr);
trxfile = fullfile(expdir,trxfilestr);
perframedir = fullfile(expdir,perframedirstr);

%% load in experiment data

try
  expdata = load(expfile);
catch ME,
  msg = getReport(ME);
  return;
end

%% compute trajectories

if dotransposeimage,
  XIND = 1;
  YIND = 2;
else
  XIND = 2;
  YIND = 1;
end

nflies = numel(expdata.experiment_1.track);
trx = [];
perframedata = struct;
timestamps = expdata.experiment_1.elapsedTime';
dt = diff(timestamps);

allframeidx = cell(1,nflies);

for i = 1:nflies,

  fprintf('Larva %d...\n',i);

  trk = struct;

  % sometimes frames are skipped
  [errt,frameidx] = min(dist2(timestamps',[expdata.experiment_1.track(i).pt.et]'),[],1);
  allframeidx{i} = frameidx;
  maxerrt = max(errt);
  if maxerrt > MAXTIMESTAMPERR,
    msg = sprintf('Could not match timestamps for larva %d',i);
    return;
  end
  trk.firstframe = min(frameidx);
  trk.endframe = max(frameidx);
  trk.nframes = trk.endframe - trk.firstframe+1;
  % make this start counting at 1
  frameidx = frameidx - trk.firstframe + 1;

  if trk.nframes > numel(expdata.experiment_1.track(i).pt),
    fprintf('%d frames missing for larva %d\n',trk.nframes - numel(expdata.experiment_1.track(i).pt),i);
  end

  % centroid
  loc = double(cat(2,expdata.experiment_1.track(i).pt.loc));
  trk.x_mm = nan(1,trk.nframes);
  trk.x_mm(frameidx) = loc(1,:);
  trk.y_mm = nan(1,trk.nframes);
  trk.y_mm(frameidx) = loc(2,:);

  % grab other data about the larva
  mid = double(cat(2,expdata.experiment_1.track(i).pt.mid));
  head = double(cat(2,expdata.experiment_1.track(i).pt.head));
  tail = double(cat(2,expdata.experiment_1.track(i).pt.tail));
  spine = {expdata.experiment_1.track(i).pt.spine};
  contour = {expdata.experiment_1.track(i).pt.contour};
  area = double(cat(2,expdata.experiment_1.track(i).pt.area));

  % convert to pixels, as everything else will be for plotting purposes
  loc_px = cat(1,expdata.experiment_1.camcalinfo.r2cX(loc(1,:),loc(2,:)),...
    expdata.experiment_1.camcalinfo.r2cY(loc(1,:),loc(2,:)));
  trk.x = nan(1,trk.nframes);
  trk.x(frameidx) = loc_px(XIND,:)+1;
  trk.y = nan(1,trk.nframes);
  trk.y(frameidx) = loc_px(YIND,:)+1;

  % area
  trk.area=nan(1,trk.nframes);
  trk.area(frameidx)=area;
  % midpoint
  xmid_cm = mid(XIND,:);
  ymid_cm = mid(YIND,:);
  perframedata.xmid_mm{i} = nan(1,trk.nframes);
  perframedata.xmid_mm{i}(frameidx) = xmid_cm*SCALE;
  perframedata.ymid_mm{i} = nan(1,trk.nframes);
  perframedata.ymid_mm{i}(frameidx) = ymid_cm*SCALE;
  mid_px = cat(1,expdata.experiment_1.camcalinfo.r2cX(mid(1,:),mid(2,:)),...
    expdata.experiment_1.camcalinfo.r2cY(mid(1,:),mid(2,:)));
  trk.xmid = nan(1,trk.nframes);
  trk.xmid(frameidx) = mid_px(XIND,:)+1;
  trk.ymid = nan(1,trk.nframes);
  trk.ymid(frameidx) = mid_px(YIND,:)+1;

  % head
  xhead_cm = head(XIND,:);
  yhead_cm = head(YIND,:);
  perframedata.xhead_mm{i} = nan(1,trk.nframes);
  perframedata.xhead_mm{i}(frameidx) = xhead_cm*SCALE;
  perframedata.yhead_mm{i} = nan(1,trk.nframes);
  perframedata.yhead_mm{i}(frameidx) = yhead_cm*SCALE;
  head_px = cat(1,expdata.experiment_1.camcalinfo.r2cX(head(1,:),head(2,:)),...
    expdata.experiment_1.camcalinfo.r2cY(head(1,:),head(2,:)));
  trk.xhead = nan(1,trk.nframes);
  trk.xhead(frameidx) = head_px(XIND,:)+1;
  trk.yhead = nan(1,trk.nframes);
  trk.yhead(frameidx) = head_px(YIND,:)+1;

  % tail
  xtail_cm = tail(XIND,:);
  ytail_cm = tail(YIND,:);
  perframedata.xtail_mm{i} = nan(1,trk.nframes);
  perframedata.xtail_mm{i}(frameidx) = xtail_cm*SCALE;
  perframedata.ytail_mm{i} = nan(1,trk.nframes);
  perframedata.ytail_mm{i}(frameidx) = ytail_cm*SCALE;
  tail_px = cat(1,expdata.experiment_1.camcalinfo.r2cX(tail(1,:),tail(2,:)),...
    expdata.experiment_1.camcalinfo.r2cY(tail(1,:),tail(2,:)));
  trk.xtail = nan(1,trk.nframes);
  trk.xtail(frameidx) = tail_px(XIND,:)+1;
  trk.ytail = nan(1,trk.nframes);
  trk.ytail(frameidx) = tail_px(YIND,:)+1;

  % spine
  nspinepts = max(cellfun(@(x) size(x,2),spine));
  isspine = ~cellfun(@isempty,spine);
  xspine_cm = nan(nspinepts,trk.nframes);
  yspine_cm = nan(nspinepts,trk.nframes);
  xspine_cm(:,frameidx(isspine)) = cell2mat(cellfun(@(x) double(x(1,:)'),spine(isspine),'UniformOutput',false));
  yspine_cm(:,frameidx(isspine)) = cell2mat(cellfun(@(x) double(x(2,:)'),spine(isspine),'UniformOutput',false));
  % spines are backwards
  xspine_cm = xspine_cm(end:-1:1,:);
  yspine_cm = yspine_cm(end:-1:1,:);
  if dotransposeimage,
    trk.xspine = expdata.experiment_1.camcalinfo.r2cY(xspine_cm,yspine_cm)+1;
    trk.yspine = expdata.experiment_1.camcalinfo.r2cX(xspine_cm,yspine_cm)+1;
    trk.xspine_mm = xspine_cm*SCALE;
    trk.yspine_mm = yspine_cm*SCALE;
  else
    trk.yspine = expdata.experiment_1.camcalinfo.r2cX(xspine_cm,yspine_cm)+1;
    trk.xspine = expdata.experiment_1.camcalinfo.r2cY(xspine_cm,yspine_cm)+1;
    trk.xspine_mm = yspine_cm*SCALE;
    trk.yspine_mm = xspine_cm*SCALE;
  end

  % contour
  xcontour_cm = cellfun(@(x) double(x(1,:)),contour,'UniformOutput',false);
  ycontour_cm = cellfun(@(x) double(x(2,:)),contour,'UniformOutput',false);
  trk.xcontour = cell(1,trk.nframes);
  trk.ycontour = cell(1,trk.nframes);
  perframedata.xcontour_mm{i} = cell(1,trk.nframes);
  perframedata.ycontour_mm{i} = cell(1,trk.nframes);
  if dotransposeimage,
    trk.xcontour(frameidx) = cellfun(@(x,y) expdata.experiment_1.camcalinfo.r2cY(x,y)+1, xcontour_cm,ycontour_cm,'UniformOutput',false);
    trk.ycontour(frameidx) = cellfun(@(x,y) expdata.experiment_1.camcalinfo.r2cX(x,y)+1, xcontour_cm,ycontour_cm,'UniformOutput',false);
    perframedata.xcontour_mm{i}(frameidx) = cellfun(@(x) x*SCALE,xcontour_cm,'UniformOutput',false);
    perframedata.ycontour_mm{i}(frameidx) = cellfun(@(x) x*SCALE,ycontour_cm,'UniformOutput',false);
  else
    trk.ycontour(frameidx) = cellfun(@(x,y) expdata.experiment_1.camcalinfo.r2cX(x,y)+1, xcontour_cm,ycontour_cm,'UniformOutput',false);
    trk.xcontour(frameidx) = cellfun(@(x,y) expdata.experiment_1.camcalinfo.r2cY(x,y)+1, xcontour_cm,ycontour_cm,'UniformOutput',false);
    perframedata.xcontour_mm{i}(frameidx) = cellfun(@(x) x*SCALE,ycontour_cm,'UniformOutput',false);
    perframedata.ycontour_mm{i}(frameidx) = cellfun(@(x) x*SCALE,xcontour_cm,'UniformOutput',false);
  end

  % covariance matrix is already in pixels; use it to get major, minor,
  % orientation
  S = cellfun(@(x) [x(1),x(2);x(2),x(3)], {expdata.experiment_1.track(i).pt.cov},'UniformOutput',false);
  S = cat(3,S{:});
  if ~dotransposeimage,
    S = [S(2,2,:),S(2,1,:);S(1,2,:),S(1,1,:)];
  end
  [a,b,theta] = cov2ell(S);
  % note that we don't worry about the zero-indexing correction because the
  % difference will cancel out
  thetahead = atan2(head_px(YIND,:)-tail_px(YIND,:),head_px(XIND,:)-tail_px(XIND,:));
  thetaflip = modrange(thetahead+modrange(theta-thetahead,-pi/2,pi/2),-pi,pi);
  trk.a = nan(1,trk.nframes);
  trk.a(frameidx) = a/2;
  trk.b = nan(1,trk.nframes);
  trk.b(frameidx) = b/2;
  trk.theta = nan(1,trk.nframes);
  trk.theta(frameidx) = thetaflip;

  % convert a, b, theta to mm
  x = loc_px(XIND,:);
  y = loc_px(XIND,:);
  if dotransposeimage,
    x1 = x + a.*cos(thetaflip);
    x2 = x - a.*cos(thetaflip);
    y1 = y + a.*sin(thetaflip);
    y2 = y - a.*sin(thetaflip);
  else
    y1 = x + a.*cos(thetaflip);
    y2 = x - a.*cos(thetaflip);
    x1 = x + a.*sin(thetaflip);
    x2 = x - a.*sin(thetaflip);
  end
  x1_cm = expdata.experiment_1.camcalinfo.c2rX(x1,y1);
  y1_cm = expdata.experiment_1.camcalinfo.c2rY(x1,y1);
  x2_cm = expdata.experiment_1.camcalinfo.c2rX(x2,y2);
  y2_cm = expdata.experiment_1.camcalinfo.c2rY(x2,y2);
  trk.theta_mm = nan(1,trk.nframes);
  trk.theta_mm(frameidx) = atan2(y2_cm-y1_cm,x2_cm-x1_cm);
  trk.a_mm = nan(1,trk.nframes);
  trk.a_mm(frameidx) = sqrt((y2_cm-y1_cm).^2+(x2_cm-x1_cm).^2)/4;
  if dotransposeimage,
    x1 = x + b.*cos(thetaflip+pi/2);
    x2 = x - b.*cos(thetaflip+pi/2);
    y1 = y + b.*sin(thetaflip+pi/2);
    y2 = y - b.*sin(thetaflip+pi/2);
  else
    y1 = x + b.*cos(thetaflip+pi/2);
    y2 = x - b.*cos(thetaflip+pi/2);
    x1 = y + b.*sin(thetaflip+pi/2);
    x2 = y - b.*sin(thetaflip+pi/2);
  end
  x1_cm = expdata.experiment_1.camcalinfo.c2rX(x1,y1);
  y1_cm = expdata.experiment_1.camcalinfo.c2rY(x1,y1);
  x2_cm = expdata.experiment_1.camcalinfo.c2rX(x2,y2);
  y2_cm = expdata.experiment_1.camcalinfo.c2rY(x2,y2);
  trk.b_mm = nan(1,trk.nframes);
  trk.b_mm(frameidx) = sqrt((y2_cm-y1_cm).^2+(x2_cm-x1_cm).^2)/4;

  % all this was actually in centimeters, so convert to millimeters
  trk.x_mm = trk.x_mm*SCALE;
  trk.y_mm = trk.y_mm*SCALE;
  trk.a_mm = trk.a_mm*SCALE;
  trk.b_mm = trk.b_mm*SCALE;

  % approximate pxpermm
  trk.pxpermm = 1/expdata.experiment_1.camcalinfo.realUnitsPerPixel/SCALE;

  % convert are to square mm from pixels
  trk.area_mm=trk.area/(trk.pxpermm*trk.pxpermm);
  % frame rate
  trk.dt = dt(trk.firstframe:trk.endframe-1);
  %trk.dt = diff([expdata.experiment_1.track(i).pt.et]);

  trk.off = 1-trk.firstframe;
  trk.id = expdata.experiment_1.track(i).trackNum;
  trx = structappend(trx,trk);

end

%% arena parameters

switch lower(arenatype),

  case 'circle',
    arenacenterx_mm = expdata.experiment_1.camcalinfo.c2rX(arenacentery,arenacenterx)*SCALE;
    arenacentery_mm = expdata.experiment_1.camcalinfo.c2rY(arenacentery,arenacenterx)*SCALE;
    arenaradius_mm = arenaradius/trx(1).pxpermm;

    for i = 1:numel(trx),
      trx(i).arena = struct;
      trx(i).arena.arena_radius_mm = arenaradius_mm;
      trx(i).arena.arena_center_mm_x = arenacenterx_mm;
      trx(i).arena.arena_center_mm_y = arenacentery_mm;
    end

  case 'rectangle',

    tl = [arenacenterx - arenawidth/2,arenacentery - arenaheight/2];
    tr = [arenacenterx + arenawidth/2,arenacentery - arenaheight/2];
    bl = [arenacenterx - arenawidth/2,arenacentery + arenaheight/2];
    br = [arenacenterx + arenawidth/2,arenacentery + arenaheight/2];

    tl_mm = [expdata.experiment_1.camcalinfo.c2rX(tl(2),tl(1)),...
      expdata.experiment_1.camcalinfo.c2rY(tl(2),tl(1))]*SCALE;
    tr_mm = [expdata.experiment_1.camcalinfo.c2rX(tr(2),tr(1)),...
      expdata.experiment_1.camcalinfo.c2rY(tr(2),tr(1))]*SCALE;
    bl_mm = [expdata.experiment_1.camcalinfo.c2rX(bl(2),bl(1)),...
      expdata.experiment_1.camcalinfo.c2rY(bl(2),bl(1))]*SCALE;
    br_mm = [expdata.experiment_1.camcalinfo.c2rX(br(2),br(1)),...
      expdata.experiment_1.camcalinfo.c2rY(br(2),br(1))]*SCALE;

    for i = 1:numel(trx),
      trx(i).arena = struct;
      trx(i).arena.tl = tl_mm;
      trx(i).arena.tr = tr_mm;
      trx(i).arena.bl = bl_mm;
      trx(i).arena.br = br_mm;
    end

end

%% create the experiment directory

if ~exist(expdir,'dir'),
  [success1,msg1] = mkdir(expdir);
  if ~success1,
    msg = msg1;
    return;
  end
end

%% save the trx file
try
  save(trxfile,'trx','timestamps');
catch ME,
  msg = sprintf('Could not save to file %s: %s',trxfile,getReport(ME));
  return;
end
if ~exist(trxfile,'file'),
  msg = sprintf('Failed to save trx to file %s',trxfile);
  return;
end

%% copy/soft-link movie

if strcmp(fullfile(inmoviefile),fullfile(moviefile)),
  fprintf('Input and out movie files are the same, not copying/linking.\n');
else

  if dosoftlink,
    if isunix,
      cmd = sprintf('ln -s %s %s',inmoviefile,moviefile);
      unix(cmd);
      % test to make sure it worked
      [status,result] = unix(sprintf('readlink %s',moviefile));
      result = strtrim(result);
      if status ~= 0 || ~strcmp(result,inmoviefile),
        warndlg(sprintf('Failed to make soft link, copying %s to %s instead',inmoviefile,moviefile));
        dosoftlink = false;
      end
    elseif ispc,
      cmd = sprintf('mkshortcut.vbs /target:"%s" /shortcut:"%s"',inmoviefile,moviefile);
      fprintf('Making a Windows shortcut file at "%s" with target "%s"\n',inmoviefile,moviefile);
      system(cmd);
      % test to make sure that worked
      [equalmoviefile,didfind] = GetPCShortcutFileActualPath(moviefile);
      if ~didfind || ~strcmp(equalmoviefile,inmoviefile),
        warndlg(sprintf('Failed to make shortcut, copying %s to %s instead',inmoviefile,moviefile));
        dosoftlink = false;
      end
    else
      warndlg(sprintf('Unknown OS, not soft-linking movie file %s',inmoviefile));
      dosoftlink = false;
    end
  end

  if ~dosoftlink,
    [success1,msg1] = copyfile(inmoviefile,moviefile);
    if ~success1,
      msg = msg1;
      success = false;
      return;
    end
  end

end

%% make per-frame directory
if ~exist(perframedir,'dir'),
  [success1,msg1] = mkdir(perframedir);
  if ~success1,
    msg = msg1;
    return;
  end
end

%% per-frame data

% save the perframedata we computed above
fns = fieldnames(perframedata);
% everything is currently in mm
units = parseunits('mm'); %#ok<NASGU>
for i = 1:numel(fns),
  fn = fns{i};
  data = perframedata.(fn); %#ok<NASGU>
  matfilename = fullfile(perframedir,[fn,'.mat']);
  fprintf('Saving data to %s...\n',matfilename);
  save(matfilename,'data','units');
end

%
% % for some reason, the derived measurements have different indices
% idx = cell(1,nflies);
% for i = 1:nflies,
%   idx{i} = expdata.experiment_1.track(i).getDerivedQuantity('mapptstointerped',false);
% end
%
% fielddict = struct;
% fielddict.vel = 'ma_vel';
% fielddict.speed = 'ma_speed';
% fielddict.vnorm = 'ma_vnorm';
% fielddict.theta = 'ma_theta';
% fielddict.adjspeed = 'ma_adjspeed';
% fielddict.lrdtheta = 'ma_lrdtheta';
% fielddict.pathLength = 'ma_pathLength';
% fielddict.covRatio = 'ma_covRatio';
% fielddict.covTheta = 'ma_covTheta';
% fielddict.covMinor = 'ma_covMinor';
% fielddict.covMajor = 'ma_covMajor';
% fielddict.dcovRatio = 'ma_dcovRatio';
% fielddict.sarea = 'ma_aarea';
%
% fnsin = fieldnames(fielddict);
%
% for j = 1:numel(fnsin),
%   fnin = fnsin{j};
%   fnout = fielddict.(fnin);
%   matfilename = fullfile(perframedir,[fnout,'.mat']);
%   fprintf('%s -> %s...\n',fnin,matfilename);
%
%   data = cell(1,nflies);
%   for i = 1:nflies,
%     tmp = expdata.experiment_1.track(i).getDerivedQuantity(fnin);
%     data{i} = nan(size(tmp,1),trx(i).nframes);
%     data{i}(:,allframeidx{i}) = tmp(:,idx{i});
%   end
%   save(matfilename,'data','units');
% end

% also save unsmoothed area
data = cell(1,nflies);
for i = 1:nflies,
  data{i} = nan(1,trx(i).nframes);
  frameidx = allframeidx{i} - trx(i).firstframe + 1;
  data{i}(frameidx) = [expdata.experiment_1.track(i).pt.area];
end
matfilename = fullfile(perframedir,['area','.mat']);
save(matfilename,'data','units');

success = true;


function WJ_DistortionCorrection_3D_SItriggered(src,evt,varargin)
            global filename
            filename=[src.hSI.hScan2D.logFilePath,'\', src.hSI.hScan2D.logFileStem,'_',num2str(src.hSI.hScan2D.logFileCounter-1,'%05d'),'.tif'];
            disp(['Just saved raw data: ',filename]);
            disp('Start the distortion correction....');
            disp('Reloading the raw data....');

%             filename='97045_20210308_ML-400_AL-400_1Openfiled_00001.tif';

            [header, RawImage, imgInfo] = scanimage.util.opentif(filename);
            filename1=imgInfo.filename;
            disp(['Rawe 2P imaging data: "' filename1  '" is loaded']);
            save([filename(1:end-4),'_tifHeader.mat'],'header');% save the SI information, only necessasy for SI information saving. No need for DJ analysis
            disp([filename(1:end-4),'_tifHeader.mat',' is saved']);
            save([filename(1:end-4),'_imgInfo.mat'],'imgInfo');% save the imaging information,only necessasy for SI information saving. No need for DJ analysis
            disp([filename(1:end-4),'_imgInfo.mat',' is saved']);
            %
            Dimention=size(RawImage);
            Zs=header.SI.hStackManager.zs;
            % load in 3D transform matrx according to different frame szie
            if Dimention(1)==512
                % read 515 3D Tranform matrix
                TransformMatrix_tem=load('\\forskning.it.ntnu.no\ntnu\mh-kin\moser\open2pmini\FOV callibration\RubenWeijianNienke\MINI2P_L_WJ001\Report\TransMatrix_512_3D.mat');
                % read 512 3D FOV information
                FOV=csvread('\\forskning.it.ntnu.no\ntnu\mh-kin\moser\open2pmini\FOV callibration\RubenWeijianNienke\MINI2P_L_WJ001\Report\FOVreport_512_20211111.csv');
                Depth=csvread('\\forskning.it.ntnu.no\ntnu\mh-kin\moser\open2pmini\FOV callibration\RubenWeijianNienke\MINI2P_L_WJ001\Report\Depth20211111.csv');
                %
            elseif Dimention(1)==256
                % read 256 3D Tranform matrix
                TransformMatrix_tem=load('\\forskning.it.ntnu.no\ntnu\mh-kin\moser\open2pmini\FOV callibration\RubenWeijianNienke\MINI2P_L_WJ001\Report\TransMatrix_256_3D.mat');
                % read 256 3D FOV information
                FOV=csvread('\\forskning.it.ntnu.no\ntnu\mh-kin\moser\open2pmini\FOV callibration\RubenWeijianNienke\MINI2P_L_WJ001\Report\FOVreport_256_20211111.csv');
                Depth=csvread('\\forskning.it.ntnu.no\ntnu\mh-kin\moser\open2pmini\FOV callibration\RubenWeijianNienke\MINI2P_L_WJ001\Report\Depth20211111.csv');

                %
            else
            end
            %
            TransformMatrix=struct2cell(TransformMatrix_tem);

            PlaneMark=[];
            if length(Dimention)<=3
                ImageStack_corrected=RawImage;
                PlaneMark=ones(size(ImageStack_corrected(:)),1);
                disp('Image Stack Size:');
                disp(num2str(Dimention));
                disp('No HyperStack Merging is applied');
            elseif length(Dimention)==4
                disp('Image Stack Size:');
                disp(num2str(Dimention));
                disp('2D Timelapse imaging was infered.  Channel and Frame merging is applied');
                ImageStack_corrected=zeros(Dimention(1),Dimention(2),Dimention(3)*Dimention(4));
                k=1;
                for j=1:1:Dimention(4)
                    for i=1:1:Dimention(3)
                        ImageStack_corrected(:,:,k)=RawImage(:,:,i,j);
                        PlaneMark(k)=1;
                        k=k+1;
                    end
                end
            elseif length(Dimention)==5
                disp('Image Stack Size:');
                disp(num2str(Dimention));
                disp('Multi-layer sinlge TimePoint imaging was infered.  Channel, Frame and Plane merging is applied');
                ImageStack_corrected=zeros(Dimention(1),Dimention(2),Dimention(3)*Dimention(4)*Dimention(5));
                k=1;
                    for m=1:1:Dimention(5)
                        for j=1:1:Dimention(4)
                            for i=1:1:Dimention(3)
                                ImageStack_corrected(:,:,k)=RawImage(:,:,i,j,m);
                                PlaneMark(k)=m;
                                k=k+1;
                            end
                        end
                    end
            else
                disp('Image Stack Size:');
                disp(num2str(Dimention));
                disp('Multi-layer Timelapse imaging was infered.  Channel, Frame, Plane and Volume merging is applied');
                ImageStack_corrected=zeros(Dimention(1),Dimention(2),Dimention(3)*Dimention(4)*Dimention(5)*Dimention(6));
                k=1;

                for n=1:1:Dimention(6)
                    for m=1:1:Dimention(5)
                        for j=1:1:Dimention(4)
                            for i=1:1:Dimention(3)
                                ImageStack_corrected(:,:,k)=RawImage(:,:,i,j,m,n);
                                PlaneMark(k)=m;
                                k=k+1;
                            end
                        end
                    end
                end
            end
            clear RawImage
            % find which matrix to use
            PlaneClosest=PlaneMark;
            for i=1:1:size(PlaneMark,2)
                PlaneClosest(i)=Zs(PlaneMark(i));
                [minValue,closestIndex]=min(abs(Depth-PlaneClosest(i)));
                PlaneClosest(i)= closestIndex;
            end

            fTIF = DataIO.Fast_BigTiff_Write([filename(1:end-4),'_wrappiing-corrected.tif'],1*10000/FOV(3),0);
            for i=1:1:size(ImageStack_corrected,3)
                ImageStack_corrected(:,:,i)=imwarp(ImageStack_corrected(:,:,i),TransformMatrix{PlaneClosest(i),1},'OutputView',imref2d(size(ImageStack_corrected(:,:,1))));
                fTIF.WriteIMG(int16(ImageStack_corrected(:,:,i)'));
                disp(['Unwrapping and saving image number ',num2str(i)]);
            end
            fTIF.close;
            disp(['Distortion correction finished, data saved: ',filename(1:end-4),'_wrappiing corrected.tif']);
%             clear ImageStack_corrected
end


function [model, solutionThermoRecon, solutionRecon, model1] = secondPassDirectionalityAssignment(model)
% Driver to call model specific code to manually generate a physiological model (if first pass does not result in a physiological model).
%
% The second pass directionality assignment needs careful manual curation
% since the adjustments necessary to get one organism to grow will not
% necessarily be the same as the ones which will get another
% organism to grow. There's no avioding manual debugging at this stage.
%
% USAGE:
%
%    [model, solutionThermoRecon, solutionRecon, model1] = secondPassDirectionalityAssignment(model)
%
% INPUTS:
%    model:
%
% OUTPUTS:
%    model:
%    solutionThermoRecon:
%    solutionRecon:
%    model1:
%
% NOTE:
%
%    This is the code  used for a number of organisms in order to point out
%    the kind of issues that arise. This is NOT supposed to work in the
%    general case.
%
% .. Author: - Ronan M. T. Fleming

global CBTLPSOLVER
switch model.description
    case 'iAF1260'
        % now assign reaction directions based on the P(\Delta_{r}G^{\primeo}<0)
        % doing so may prevent the model from growing, therefore at this stage it
        % is necessary to manually adjust some of the reaction directionalities
        % such that the model can grow, and grow at a similar rate as observed in
        % vivo. Therefore this script cannot be made model invariant as there is an
        % essential manual debugging stage. The script below is for E. coli iAF1260
        fprintf('%s\n%s\n%s\n','The second pass assignment of reaction directionality should',...
            'be a compromise between quantitative and qualitative assignment',...
            'this step requires manual imput as it is specific to each organism.');

        fprintf('%s\n',['The second pass assignment of reaction directionality is using the ' CBTLPSOLVER ' LP solver.']);
        fprintf('\n%s\n','...setThermoReactionDirectionality (based on the P(\Delta_{r}G^{\primeo}<0))');
        % this will update the model.lb_reconThermo & model.ub_reconThermo
        [model,solutionThermoRecon,solutionRecon,model1]=setThermoReactionDirectionalityiAF1260(model);
    otherwise
        fprintf('No manually generated .m file second pass directionality assignment is available for this model.')
end


function [net, info] = cnn_imagenet_se_mcn(varargin)
% CNN_IMAGENET_SE_MCN Evaluate imported PyTorch models on ImageNet val set
% (closely based on the mcn cnn_imagenet.m example)
%
% Copyright (C) 2017 Samuel Albanie
% Licensed under The MIT License [see LICENSE.md for details]

  opts.gpus = 3 ;
  opts.continue = 1 ;
  opts.batchSize = 256 ;
  opts.model = 'SE-ResNet-50-mcn' ;
  opts.modelDir = fullfile(vl_rootnn, 'data/models-import') ;
  opts.dataDir = fullfile(vl_rootnn, 'data/datasets/ILSVRC2012') ;
  opts.labelMap = fullfile(vl_rootnn, 'contrib/mcnSENets/misc/label_map.txt') ;
  [opts, varargin] = vl_argparse(opts, varargin) ;

  opts.expDir = fullfile(vl_rootnn, 'data', ['imagenet12-' opts.model]) ;
  [opts, varargin] = vl_argparse(opts, varargin) ;

  opts.lite = false ;
  opts.numFetchThreads = 12 ;
  opts.imdbPath = fullfile(vl_rootnn, 'data', 'imagenet12', 'imdb.mat');
  opts = vl_argparse(opts, varargin) ;

  opts.train.gpus = opts.gpus ;

% -------------------------------------------------------------------------
%                                                              Prepare data
% -------------------------------------------------------------------------

  if exist(opts.imdbPath, 'file')
    imdb = load(opts.imdbPath) ;
    imdb.imageDir = fullfile(opts.dataDir, 'images');
  else
    imdb = cnn_imagenet_setup_data('dataDir', opts.dataDir, 'lite', opts.lite) ;
    mkdir(opts.expDir) ;
    save(opts.imdbPath, '-struct', 'imdb') ;
  end

  % remap labels to match the order used in training
  imdb = updateLabelMap(imdb, opts) ;

% -------------------------------------------------------------------------
%                                                             Prepare model
% -------------------------------------------------------------------------
  net = load_model(opts.modelDir, opts.model) ;

  % modify the imdb to skip training images
  imdb.images.set(imdb.images.set == 1) = 4 ;
  [net, info] = cnn_train_dag(net, imdb, getBatchFn(opts, net.meta), ...
                              'expDir', opts.expDir, 'gpus', opts.train.gpus, ...
                              'numEpochs', 1, 'continue', opts.continue, ...
                              'batchSize', opts.batchSize) ;

  % hack the checkpoint file to save an empty dag
  modelPath = fullfile(opts.expDir, 'net-epoch-1.mat') ; tmp = load(modelPath) ;
  net_ = net ; net = dagnn.DagNN().saveobj() ; stats = tmp.stats ; state = {} ; %#ok
  save(modelPath, 'net', 'stats', 'state') ; net = net_ ;

% -------------------------------------------------------------------------
function dag = load_model(modelDir, name)
% -------------------------------------------------------------------------
  modelPath = fullfile(modelDir, sprintf('%s.mat', name)) ;
  if ~exist(modelDir, 'dir') , mkdir(modelDir) ; end

  if ~exist(modelPath, 'file')
    fprintf('Downloading the %s model ... this may take a while\n', name) ;
    base = 'http://www.robots.ox.ac.uk/~albanie' ;
    url = sprintf('%s/models/se-nets/%s.mat', base, name) ;
    urlwrite(url, modelPath) ;
  end

  dag = dagnn.DagNN.loadobj(load(modelPath)) ;
  dag.addLayer('softmax', dagnn.SoftMax(), dag.layers(end).outputs, 'prediction', {}) ;
  dag.addLayer('top1err', dagnn.Loss('loss', 'classerror'), ...
               {'prediction','label'}, 'top1err') ;
  dag.addLayer('top5err', dagnn.Loss('loss', 'topkerror', 'opts', {'topK',5}), ...
               {'prediction','label'}, 'top5err') ;

% -------------------------------------------------------------------------
function fn = getBatchFn(opts, meta)
% -------------------------------------------------------------------------
  bopts = struct('useGpu', numel(opts.train.gpus) > 0, ...
                 'imageSize', meta.normalization.imageSize(1:2)) ;
  fn = @(x,y) eval_get_batch(bopts,x,y) ;

% -------------------------------------------------------------------------
function varargout = eval_get_batch(opts, imdb, batch)
% -------------------------------------------------------------------------
  images = strcat([imdb.imageDir filesep], imdb.images.name(batch)) ;
  data = getImageBatch(images, opts, 'prefetch', nargout == 0) ;
  if nargout > 0
    labels = imdb.images.label(batch) ;
    varargout{1} = {'data', data, 'label', labels} ;
  end

% ----------------------------------------
function imdb = updateLabelMap(imdb, opts)
% ----------------------------------------
  labelMap = importdata(opts.labelMap) ;
  keep = imdb.images.label ~= 0 ;
  newLabels = labelMap(imdb.images.label(keep)) ;
  imdb.images.label(keep) = newLabels ;

% -------------------------------------------------
function data = getImageBatch(imagePaths, varargin)
% -------------------------------------------------
% GETIMAGEBATCH  Load and jitter a batch of images
opts.useGpu = false ;
opts.prefetch = false ;
opts.numThreads = 10 ;

% Options that were used during PyTorch training
% Note: that normalisation must occur after the pixel
% values have been rescaled to [0,1]
opts.cropSize = 224 / 256 ;
opts.imageSize = [224, 224] ;
opts.meanImg = [123, 117, 104] ;
%opts.std = [0.229, 0.224, 0.225] ;
opts = vl_argparse(opts, varargin);

args{1} = {imagePaths, ...
           'NumThreads', opts.numThreads, ...
           'Pack', ...
           'Interpolation', 'bilinear', ... % use bilinear to reproduce trainig resize
           'Resize', opts.imageSize(1:2), ...
           'CropSize', opts.cropSize, ...
           'CropAnisotropy', [1 1], ... % preserve aspect ratio
           'CropLocation', 'center'} ; % centre crop for testing

if opts.useGpu, args{end+1} = {'Gpu'} ; end
args = horzcat(args{:}) ;

if opts.prefetch
  vl_imreadjpeg(args{:}, 'prefetch') ;
  data = [] ;
else
  data = vl_imreadjpeg(args{:}) ;
  data = bsxfun(@minus, data{1}, permute(opts.meanImg, [1 3 2])) ;
  %data = data{1} / 255 ; % scale to (almost) [0,1]
  %data = bsxfun(@rdivide, data, permute(opts.std, [1 3 2])) ;
end


function [view, mapvol, covol] = polarAngleMap(view, dt, scans, params, legend, W);
%
% [view, map, co] = polarAngleMap(view, <dt, scans, params>, <legend>, <W>);
%
% AUTHOR: rory
% PURPOSE:
% Given corAnal data for a polar angle ("meridian")-mapping experiment
% (single scan or set of scans), produce a parameter map of preferred
% polar angle in units of degrees of visual field.
%
% If a single scan is provided as input, this function saves the
% parameter map in the scan's data type, assigning it only for that
% scan.
%
% However, if multiple input scans are provided (see below),
% the code saves the results in a new data type 'Meta_Analysis'.
% corAnal data from each scan are first converted into real-world
% units, then overlapping data are averaged together in a weighted
% average, based on each scan's coherence. (I.e., if one scan's
% co values for a given voxel are much higher than other scans,
% it will dominate the determination of what angle is represented.)
%
% I wrote this code to use in conjunction with my across-session
% tools (createCombinedSession, importTSeries) to run meta-analyses
% on retinotopy data.
%
% ARGUMENTS:
%   INPUT:
%   view: mrVista view. <Defaults to selected gray view>
%   dt: for a single scan, name or number of the data type
%       from which the input data come. If analyzing multiple
%       scans, a cell of length nScans of data type names/numbers.
%       <default: cur data type>
%
%   scans: scan or scans to use as input. <default: cur scan>
%
%   params: struct (or nScans-long struct array) specifying how
%       the stimulus mapped polar angle during each scan. Needs
%       the following fields:
%       params.startAngle: angle of center of wedge stimulus, measured
%           in degrees clockwise from 12-o-clock, at the start of each
%           cycle;
%       params.width: width of wedge stimulus in degrees.
%       params.direction: 'cw' or 'ccw', direction in which the stimulus
%       proceeded. (cw=clockwise or ccw=counterclockwise).
%       params.visualField: number of degrees the stimulus traversed
%       each cycle (e.g., 360 if it went all the way around).
%       <default: get these params using retinoCheckParams>
%
%   legend: optional flag which, if set to 1, provides for a separate
%       figure with a legend image to go with the polar angle map.
%       <default 0, don't show this>
%
%   W: optional vector of weights for each input scan, for use when
%       doing a meta-analysis across scans. The vector should be
%       the same length as the input scans, and should specify the
%       overall weight, on top of the coherence, that that scan's voxels
%       get. Useful for me, when high-res data produces lower co values,
%       but is actually more reliable at identifying meridian
%       representations. <default: all ones.>
%
%   OUTPUT:
%   view: mrVista view, set to the relevant data type / scan and with
%         the map loaded and set to map mode.
%
%   map: the map volume produced (but not the cell-of-scans set in the
%        view, the numeric matrix).
%
%   co: the maximum coherence at each voxel, across all the input scans.
%       (It may be more sensible to make this the mean, but I'm trying
%       max for now.) Same format as map.
%
%
% ras, 01/10/06.
if notDefined('view'),  view = getSelectedGray;                 end
if notDefined('dt'),    dt = viewGet(view, 'curDataType');      end
if notDefined('scans'), scans = viewGet(view, 'curScan');       end
if notDefined('legend'), legend = 0;                            end
if notDefined('W'),      W = ones(size(scans));                 end
if notDefined('params')
    params = retinoCheckParams(view, dt, scans);
end

mapName = 'Polar Angle (clock position)';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Deal with single input scan instances separately %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if length(scans)==1
    % this should be easy: just convert the corAnal values into
    % degrees of polar angle
    view = selectDataType(view, dt);
    corAnalPath = fullfile(dataDir(view), 'corAnal.mat');
    if ~exist(corAnalPath, 'file')
        error('corAnal not found. Run computeCorAnal first.');
    end
    load(corAnalPath, 'ph', 'co');
    srcPh = ph{scans}; srcCo = co{scans}; clear ph co;

    % map from corAnal ph to polar angle
    mapvol = polarAngle(srcPh, params) ./ 30;

    % make and set the parameter map
    mapPath = fullfile(dataDir(view), 'Polar_Angle_Map.mat');
    if exist(mapPath, 'file')
        load(mapPath, 'map', 'co');
    else
        map = cell(1, numScans(view));
    end

    map{scans} = mapvol;

    % let's set the map colormap to be the same as the phase mode
    % colormap, and save this with the map
    if checkfields(view, 'ui', 'phMode')
        view.ui.mapMode.cmap = view.ui.phMode.cmap;
        view.ui.mapMode.clipMode = [0 12];
    end

    view = setParameterMap(view, map, mapName);
    saveParameterMap(view, mapPath, 1, 1);

    if legend, polarAngleMapLegend(view); end

    % that should be it!
    if nargout>=3, covol = co{scans}; end
    view = refreshScreen(view);
    return
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% if we get here, we have multiple scans: parse the arguments to    %
% be cell arrays, and get set up:                                   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nScans = length(scans);

if ~iscell(dt)
    mrGlobals;
    % assume a single dt is specified, and all the scans are
    % coming from that data type
    for i = 1:nScans
        if isnumeric(dt), tmp{i} = dataTYPES(dt).name;
        else,             tmp{i} = dt;
        end
    end
    dt = tmp; clear tmp;
else
    for i = 1:nScans
        if isnumeric(dt{i}), dt{i} = dataTYPES(dt{i}).name; end
    end
end

%%%%%Get corAnal volumes for each input scan
srcCo = cell(1, nScans); srcPh = cell(1, nScans);
uniqueDts = unique(dt);
for i = 1:length(uniqueDts)
    corAnalPath = fullfile(viewDir(view), uniqueDts{i}, 'corAnal.mat');
    if ~exist(corAnalPath, 'file')
        error('corAnal not found. Run computeCorAnal first.');
    end
    load(corAnalPath, 'co', 'ph', 'amp')

    I = cellfind(dt, uniqueDts{i});
    srcCo(I) = co(scans(I));
    srcPh(I) = ph(scans(I));
    srcAmp(I) = amp(scans(I));
end

%%%%%Set up the target data type for the multi-scan meta-analysis
view = initScan(view, 'Meta_Analysis', [], {dt{1} scans(1)});
view = selectDataType(view, 'Meta_Analysis');
view = setCurScan(view, numScans(view));
view = setAnnotation(view, sprintf('Meta Analysis for %s scans %s', ...
                                dt{1}, num2str(scans)));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Calculate the Polar Angle Map  %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%Set NaNs to zero -- will be ignored
for i = 1:nScans
    srcCo{i}(isnan(srcCo{i})) = 0;
    srcAmp{i}(isnan(srcAmp{i})) = 0;
    srcPh{i}(isnan(srcPh{i})) = 0;
end

%%%%%Convert each phase map into real-word units
for i = 1:nScans
    srcPh{i} = polarAngle(srcPh{i}, params(i)) ./ 30;
end

%%%%%because we allow an additional level of user-defined weights
%%%%%(orig. b/c I wanted to weigh high-res scans higher than low-res),
%%%%%adjust the coherence weights accordingly for each scan
for i = 1:nScans, srcCo{i} = srcCo{i} .* W(i); end

%%%%%Set up the weighted average
% we'll need a volume representing the sum of the coherence
% for each voxel, across input scans. This will serve as the
% denominator of the weight formula for each input scan.
coSum = zeros(size(srcCo{1})); coMax = zeros(size(srcCo{1}));
for i = 1:nScans,
    coSum = coSum + srcCo{i};
    coMax = max(coMax, srcCo{i});
end

%%%%%initialize the map and co volumes
mapvol = zeros(size(srcCo{1}));
covol = zeros(size(srcCo{1}));

%%%%%compute co volume as the mean across all input co volumes
for i = 1:nScans, covol = covol + srcCo{i}; end
covol = covol ./ length(srcCo);

%%%%%Compute the weighted average, iteratively across input scans
for i = 1:nScans
    mapvol = mapvol + (srcPh{i} .* srcCo{i} ./ coSum);

%     % alternate attempt: use winner-take-all: scan with the
%     % highest co value for a given voxel determines the map
%     % value at that voxel.
%     Imax = find(srcCo{i}==coMax);
%     mapvol(Imax) = srcPh{i}(Imax);
end

covol = coMax;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Output the parameter map %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% initialize the output map and co data fields, loading it if it
% already exists:
mapPath = fullfile(dataDir(view), 'Polar_Angle_Map.mat');
if exist(mapPath, 'file')
    load(mapPath, 'map', 'mapName', 'co');
else
    map = cell(1, numScans(view));
    co = cell(1, numScans(view));
end

% append the map volume for the new scans
map{numScans(view)} = mapvol;
co{numScans(view)} = covol;

% before saving the map, copy the view's phase mode color map
% to the map mode, which will also be saved:
if checkfields(view, 'ui', 'phMode')
    view.ui.mapMode.cmap = view.ui.phMode.cmap;
    view.ui.mapMode.clipMode = [0 12];
end

% set the map in the view, and save it
view = setParameterMap(view, map, mapName);
saveParameterMap(view, mapPath, 1, 1);
save(mapPath, 'co', '-append'); % also add the co field
view.co = co;
refreshScreen(view);

% also set corAnal amp and ph fields, and save a corAnal, so
% we can view in that mode as well (nice colorbar, can ph-restrict)
% we map the ph back from degrees to radians:
phvol = deg2rad(mapvol.*30);
ampvol = srcAmp{1};
if exist(fullfile(dataDir(view), 'corAnal.mat'), 'file')
    view = loadCorAnal(view);
end
view.co{numScans(view)} = covol;
view.ph{numScans(view)} = phvol;
view.amp{numScans(view)} = ampvol;
view = saveCorAnal(view, 1);

newParams.type = 'polar_angle';     % set retino params such
newParams.startAngle = 0;           % that the default HSV color map
newParams.direction = 'clockwise';  % produces a nice wedge color bar
newParams.visualField = 360;
newParams.width = 0;
retinoSetParams(view, 'Meta_Analysis', numScans(view), newParams);

% show a legend if requested
if legend, polarAngleMapLegend(view); end

% ok, think that's it!

return
% /--------------------------------------------------------------------/ %

% /--------------------------------------------------------------------/ %
function A = polarAngleMapLegend(view);
% img = polarAngleMapLegend(view);
% Using the current map mode settings, produce a legend
% for a polar angle parameter map and plot in a separate figure.
% Returns a truecolor image if requested.
mode = view.ui.mapMode;

% generate an angle map A and a radius map R
% A will start at the 12-o-clock and run clockwise back to 12,
% ranging from 1 to the number of colors in the cmap.
[X Y] = meshgrid(1:256, 1:256);
X = X-128; Y = Y-128;
A = atan2(X, Y);
A = fliplr(mod(A-pi, 2*pi));
A = rescale(A, [], [1 mode.numColors]);
R = sqrt(X.^2 + Y.^2);

% take cmap from color part of map mode
cmap = mode.cmap(mode.numGrays+1:end,:);

% convert A to truecolor
A = ind2rgb(A, cmap);

% for each color channel, mask out region outside radius (128 pixels)
[I J] = find(R>128);
for ch = 1:3
    ind = sub2ind(size(A), I, J, repmat(ch, size(I)));
    A(ind) = 1;
end

% put up the image
figure('Color', 'w', 'Name', 'Polar Angle Map Legend');
imshow(A);

return


% Script: run_loma_yearly_stresstensor.m

% Starting ZMAP
sPath = pwd
cd /home/jowoe/zmap
startup
cd(sPath)

% Load the parameter file
load Params_Loma_ConstRad3km_Nmin50_0.01deg_T365d.mat

% Do loop over different radii to select events
for fRadius = 3:1:5
    sString = ['Radius: ', num2str(fRadius) 'km'];
    params.fRadius = fRadius;
    vResults = [];
    disp(sString)
    tstart1= cputime
    !date
    % Perform the calculation
    [vResults] = gui_CalcStressInv(params);
    !date
    tend1=cputime-tstart1
    !rm tmp*
end