//Otolith analysis version 1.13
//02.01.24, 15:00

var yearD = 0,// year in dialog
quality = 3,
fontSize = 10,
fontColor = "magenta",
nDigits = 1, //precision in output table
impactX, impactY, //global arrays


macro "Start a Sequence [F1]"{
	requires("1.52a");
	ojRequires("1.04z");
	ojCloseObject();
	ojSwitchToItem("Core");
	run("Select None");
}


//If object is open, it is closed  and then selected
//Then, if no object is selected, exit
//Assigns Year and Quality to selected object
macro "Year and Quality...[F2]"{
	obj = ojGetOpenObject();
	
	if(obj == 0){
		obj = ojSelectedObject();
		if (obj == 0)
			exit("First select an object with ObjectJ's Finger tool");
		else {
			yearD = ojResult("Year", obj);
			quality = ojResult("Q", obj);
		}
	}
	ojCloseObject();
	check();
	ojShowObject(obj);
	nRings = ojNItems("Increment");
	dummy = getAscendingPaths();

	ojSetTool(0);
	Dialog.create("Object " + obj);
	Dialog.addNumber("Year*", yearD);
	Dialog.addNumber("Quality", quality);
	Dialog.addMessage("* enter negative year for edge, \n   or positive year for core");
	Dialog.show();
	yearD = Dialog.getNumber;
	year = yearD;
	if (yearD < 0){
		year = - yearD - nRings;
	}
	quality = Dialog.getNumber;
	ojSetResult("Year", obj, year);
	ojSetResult("Q", obj, quality);
	label = "  " + year + "-" + quality;
	ojSetResult("Label", obj, label);
}

//Of selected object: checks vector direction 
//snaps and sorts rings (Increments) 
// returns ascending paths

function getAscendingPaths(){
		offsets = newArray(2);
			for(jj = 0; jj <=1; jj++){
			ojvInitStack("2d");
			ojSelectItem("Core", 1);
			ojvPushItem();
			ojSelectItem("Vector", 1);
			ojvPushPoint(jj + 1);
			offsets[jj] = ojvCalculate("partialpath offset");
		}
		if(offsets[0] > offsets[1]){
			exit("Vector direction is not 'core-towards-outside'");
		}
		nRings = ojNItems("Increment");
		ascPaths = newArray(nRings);
		impactX = newArray(nRings);
		impactY = newArray(nRings);
		for(ring = 0; ring < nRings; ring++){
			ojvInitStack("2d");
			ojSelectItem("Vector", 1);
			ojvPushItem();
			ojSelectItem("Increment", ring +1);
			ojvPushItem();
			ascPaths[ring] = ojvCalculate("partialpath");
			impactX[ring] = ojvCalculate("partialpath impactx");
			impactY[ring] = ojvCalculate("partialpath impacty");
		}
		ranks = Array.rankPositions(ascPaths);
		for(ring = 0; ring < nRings; ring++){
			index = ranks[ring];
			ojSelectItem("Increment", ring + 1);
			ojMovePoint(1, impactX[index], impactY[index], -1);
		}
		Array.sort(ascPaths);
		return ascPaths;
}

function check(){//object is complete with 1 vector and 1 core
	ojCloseObject();
	for(obj = ojNObjects(); obj > 0; obj--){
		ojSelectObject(obj);
		if(ojNItems("Core") < 1 || ojNItems("Vector") < 1 ){
			ojShowObject(obj);
			showMessageWithCancel("Object " + obj + " is not complete- Delete it?");
			ojDeleteObject(obj);
			exit;
		}
	}
	ojSelectObject(0);
}


macro "Create Output Table [F3]"{
	tabTitle = "Otolith Parameters.csv";
	Table.create(tabTitle);

	for(obj= 1; obj <= ojNObjects(); obj++){
		calcObject(obj, tabTitle, false);
	}
	ojSelectObject(0);
}
macro "Show/Hide Annotations [F4]"{
	showAnnotation(1);//1 = short
}
macro "Show/Hide Annotations long[F5]"{
	showAnnotation(2);//2 = long
}

function showAnnotation(shortOrLong){
	if(nImages == 0)
		return;
	setFont("SanSerif", fontSize);
	setColor(fontColor);
	if (Overlay.size > 0){
		Overlay.remove;
		return;
	}
	link = ojImageLink();
	for(obj = 1; obj <= ojNObjects(); obj++){
		if(ojOwnerIndex(obj) == link){
			calcObject(obj, "", shortOrLong);
			Overlay.show;
		}
	}
}


function calcObject(obj, tabTitle, shortOrLong){	
	ojShowObject(obj);
	pxWidth = ojGetVoxelSize(ojOwnerIndex(obj), "x");
	xx = newArray(0);
	yy = newArray(0);
	vvPaths = newArray(0);//vector vertices
	cnt = 0;
	ojvInitStack("2D");

	//record vvPaths =pathLengths of vector vertices	
	ojSelectItem("Vector", 1);
	for(pt = 1; pt <= ojNPoints(); pt++){
		ojvPushPoint(pt);
		ppp = ojvCalculate("totalpath");
		vvPaths[cnt] = ppp;
		xx[cnt] = ojXPos(pt);
		yy[cnt] = ojYPos(pt);
		cnt++;
	}
	pointPaths = getAscendingPaths();

	//mixed: mixture of vertices and Increment points
	mixedPath = Array.concat(vvPaths, pointPaths);
	mixedX = Array.concat(xx, impactX);
	mixedY = Array.concat(yy, impactY);
	ignore = newArray(mixedPath.length);
	for(kinks = 1; kinks < vvPaths.length - 1; kinks += 2)
		ignore[kinks] = 1;// ignore second marking of same ring
	Array.sort(mixedPath, ignore, mixedX, mixedY);
	steps = newArray(mixedPath.length);
	for(jj = 1; jj< mixedPath.length; jj++){
		delta = mixedPath[jj] - mixedPath[jj-1];
		steps[jj] = delta;
		if (ignore[jj-1] == 1){
			steps[jj] = NaN;
			mixedX[jj] = NaN;
			mixedY[jj] = NaN;
		}
	}
	mixedX = Array.deleteValue(mixedX, NaN);
	mixedY = Array.deleteValue(mixedY, NaN);
	steps = Array.deleteValue(steps, NaN);
	
	file = getTitle;
	dotPos = lastIndexOf(file, ".");
	file = substring(file, 0, dotPos);

	quality = ojResult("Q", obj);
	age = steps.length - 2;//don't count edge as extra year
	ojSetResult("Age", obj, age);
	cohort = ojResult("Year", obj);
	core = d2s(ojResult("Core", obj), 1);
	if(tabTitle != ""){
		size = Table.size(tabTitle);
		for(kk=0; kk <steps.length; kk++){
			size = Table.size(tabTitle); 
			Table.set("Sample", size, file, tabTitle); 
			Table.set("Quality", size, quality, tabTitle); 
			Table.set("Age", size, age, tabTitle); 
			Table.set("Cohort", size, cohort, tabTitle); 
			Table.set("Core", size, core, tabTitle);
			Table.set("I", size, kk, tabTitle); 
			Table.set("Year", size, cohort + kk, tabTitle); 
			Table.set("Increment",size, d2s(steps[kk] * pxWidth, 1), tabTitle);
			Table.set("X", size, round(mixedX[kk]), tabTitle); 
			Table.set("Y", size, round(mixedY[kk]), tabTitle);
			if(kk == 0){
				Table.set("I", size, "core", tabTitle);
				Table.set("Year",size, "", tabTitle);
				Table.set("Increment",size, "", tabTitle);
			}
			if(kk == steps.length-1){
				Table.set("I", size, "edge", tabTitle);
				Table.set("Year",size, "", tabTitle);
			} 
		}
		Overlay.remove;
	}
	if(shortOrLong > 0){
		for(jj = 1; jj< steps.length; jj++){
			if(shortOrLong == 1)//short
				Overlay.drawString("" + (jj + cohort), mixedX[jj], mixedY[jj]);
			if(shortOrLong == 2)//long
				Overlay.drawString("year=" + (jj + cohort) +" d=" + d2s(steps[jj] * pxWidth, 1), mixedX[jj], mixedY[jj]);
		}
	}
	ojSelectObject(0);
}
