//Otolith analysis version 1.8
//29.10.18 14:21

var yearD = 0,// year in dialog
quality = 3,
fontSize = 16,
fontColor = "magenta",



macro "Start a Sequence [F1]"{
	requires("1.52a");
	ojRequires("1.04g");
	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);
		}
	}
	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);
	showAnnotation();
}

//Pins  "Increment" dots (blue) to  vector line (red)
//Calculates all desired results and shows it in a table 
macro "Create Output Table [F3]"{
	check();
	if(ojImageLink() > 0)
		Overlay.remove;
	row = 0;
	Table.create("Otolith Parameters.txt");
	for(obj = 1; obj <= ojNObjects(); obj++){
		pxWidth = ojGetVoxelSize(ojOwnerIndex(obj), "x");
		ojSelectObject(obj);
		pPaths = getAscendingPaths();
		prevRad = 0;
		nRings = ojNItems("Increment");
		vector = ojResult("Vector", obj);

		file = ojResultString("File", obj);
		dotPos = lastIndexOf(file, ".");
		file = substring(file, 0, dotPos);
		qual = ojResult("Q", obj);
		age = nRings;
		cohort = ojResult("Year", obj);
		entries = nRings + 2;

		for(entry = 0; entry <entries; entry++){
			if(entry == 0)
				core = d2s(ojResult("Core", obj), 1);//1 digit
			year = "";
			incr = "";
			if (entry == 0) theI = "core";
			else if(entry < entries-1){
				year = ojResult("Year", obj) + entry;
				theI = entry;
				rad = pPaths[entry-1] * pxWidth;
				incr = rad - prevRad;
				incr = d2s(incr, 1);	
				prevRad = rad;
			}
			else if (entry == entries - 1){
				if(nRings == 0)
					incr = vector;
				else
					incr = vector - pPaths[entry-2] * pxWidth;//last partial increment
				incr = d2s(incr, 1);	
				theI = "edge";
			}
			//You can change column titles and sequence:
			Table.set("Sample", row, file);
			Table.set("Quality", row, qual);
			Table.set("Age", row, age);
			Table.set("Cohort", row, cohort);
			Table.set("Core", row, core);
			Table.set("I", row, theI);
			Table.set("Year", row, year);
			Table.set("Increment", row, incr);
			
			row++;
		}
	}
  	Table.update;
}

//Arranges vector direction and ring sequence and returns ascending paths
//of selected objects
function getAscendingPaths(){
		//swap vector direction if necessary
		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]){
			x = ojXPos(1);
			y = ojYPos(1);
			ojMovePoint(1, ojXPos(2), ojYPos(2), -1);
			ojMovePoint(2, x, y, -1);
		}
		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;
}

//Sets year number next ot each increment dot as overlay, or clears overlay
macro "Show/Hide Year Annotation [F4] "{
	check();
	if (Overlay.size > 0){
		Overlay.remove;
		return;
	}
	showAnnotation();
}

function showAnnotation(){
	thisImg = ojImageLink();
	if(thisImg == 0)
		return;
	Overlay.remove;
	setFont("SanSerif", fontSize);
	setColor(fontColor);
	for(obj = ojFirstObject(thisImg); obj <= ojLastObject(thisImg); obj++){
		ojShowObject(obj);
		year = ojResult("Year", obj);
		for(ring = 1; ring <= ojNItems("Increment"); ring++){
			ojSelectItem("Increment", ring);
			x = ojXPos(1);
			y = ojYPos(1);
     		Overlay.drawString("  " + (year + ring), x, y);
		}
	  Overlay.show;
	}
	ojSelectObject(0);
}

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