#Jeff Hardin, Dept. of Integrative Biology
#Univ. of Wisconsin-Madison
#jdhardin@wisc.edu

#Additional colors (see also https://htmlcolorcodes.com/color-picker/)
#Green = #32a852
#Purple = #7132a8
#Dark red = #9C2005
#Dark brown = #754F04
#Light brown = #9C6905

#This script imports FRAP data from one or more CSV files
#and ImageJ's built-in Plot functions.

#Currently uses the hard-wired colors built into ImageJ's Plot class
#Could be expanded to a nicer color palette using hexadecimal colors.
#Use the PlotWindow "More >> " button to change range, line thickness, colors, etc.

#Ideally, one could open the CSV using a parser without opening a data window.
#Using JFreeChart would also be great, since JFreeChart can export
#as an editable SVG file.

from org.jfree.chart import ChartFactory, ChartPanel, JFreeChart  
from org.jfree.chart.plot import PlotOrientation, XYPlot
from org.jfree.data.xy import XYDataset, XYSeries, XYSeriesCollection
from org.jfree.chart.plot import PlotOrientation, XYPlot
from org.jfree.data.xy import XYDataset, XYSeries, XYSeriesCollection
from org.jfree.data.category import DefaultCategoryDataset
from org.jfree.chart.ui import RectangleEdge
from javax.swing import JFrame  
import java.awt.Color as Color
from java.awt import Dimension, BasicStroke
import java.awt.Frame as Frame
import java.awt.Window as Window
from java.io import File as File
from java.lang import System as System
from ij import WindowManager as WindowManager
from ij.plugin.frame import RoiManager as RoiManager
from ij.process import ImageStatistics as ImageStatistics
from ij.measure import Measurements as Measurements
from ij import IJ as IJ
from ij.measure import CurveFitter as CurveFitter
from ij.gui import Plot as Plot
from ij.gui import PlotWindow as PlotWindow
from ij.gui import ImageWindow as ImageWindow
from ij.gui import GenericDialog
from ij import ImagePlus as ImagePlus
from ij.io import FileInfo as FileInfo
from ij.measure import ResultsTable as ResultsTable
from ij import WindowManager as WindowManager
import math
import os
from os import path, mkdir
import csv

#below from 
#https://stackoverflow.com/questions/736043/checking-if-a-string-can-be-converted-to-float-in-python
def isfloat(value):
  try:
    float(value)
    return True
  except ValueError:
    return False

def doPlot():
	lineseparator = "\n"
	cellseparator = ","
	rawFRAPFile = False

	#Should really only ask for a single file here, as follows:
	#od = OpenDialog("Choose file", None)
	#file_name = od.getFileName()
	#if None != file_name:
	
	#Call below is a feature of Fiji/IJ2
	#See https://imagej.net/scripting/parameters	
	#Opener().openImage(od.getDirectory(), file_name).show()
	
	k = len(listOfPaths)
	#for i in range(0, k):
		#print(listOfPaths[i])
	for i in range(0, k):
		#read in FRAP curve data from CSV file
		#copies the whole file to an array of lines
		#have to type cast pathnames to Python str
		text_file = open(str(listOfPaths[i]), "r")		
		#read whole file to a string
		data = text_file.read()
		#close file
		text_file.close()		
		#separate into lines of text
		lines=data.split(lineseparator)
		numRows = len(lines)	
		# recreates the columns headers
		labels=lines[0].split(cellseparator)
		for l in range(0,len(labels)):
			#print(labels[l])
			if (labels[l] == "bleach"):
				#print("This appears to be a raw FRAP file...")
				rawFRAPFile = True
		#get total columns
		numCol = len(labels)
		#declare arrays to hold data points
		x1=[]
		y1=[]
		x2=[]
		y2=[]
		y3=[]
		#we'll want xMin and xMax later
		xMax = float()
		xMin = float()
		xMin = 0
		xMax = 0
		#IJ.open(str(listOfPaths[i]))
		with open(str(listOfPaths[i]), 'r') as read_obj:
			# pass the file object to reader() to get the reader object
			csv_reader = csv.reader(read_obj)
			# Iterate over each row in the csv using reader object
			header = next(csv_reader)
			for row in csv_reader:
			#need to add code to check for empty cells, since ImageJ
			#produces CSV files in which there can be unequal numbers of rows with empty cells
			#Jython interpreter crashes when trying to convert to float if cell is blank
			#ImageJ plot functions are savvy about blank cells, but this code isn't!
				if (isfloat(row[0])):
					x1.append(float(row[0]))
				if (isfloat(row[1])):
					y1.append(float(row[1]))
				if (numCol == 3):
				# Assume this is a single X and two Y columns, with the second being the fit
					if (isfloat(row[2])):
						y2.append(float(row[2]))
					# Set legend for plot
					legendString = "FRAP\nFit"
				if (numCol > 3):
					if rawFRAPFile:
						# Assume this is a single X and three Y columns
						if (isfloat(row[2])):
							y2.append(float(row[2]))
						if (isfloat(row[3])):
							y3.append(float(row[3]))
						# Set legend for plot
						#legendString = "Bleach\nNon-bleach\nBackground"
						legendString = labels[1] + "\n" + labels[2] + "\n" + labels[3]

					else:
						# Assume this is paired X and Y columns
						if (isfloat(row[2])):
							x2.append(float(row[2]))
						if (isfloat(row[3])):
							y2.append(float(row[3]))
						# Set legend for plot
						legendString = "FRAP\nFit"

		xMin = min(x1)
		xMax = max(x1)

		#Now let's plot the XY data using ImageJ's Plot function
		#Use a Java method to get file name
		file = File(str(listOfPaths[i]))
		#get file name using getName()
		filename = file.getName()
		if (numCol < 3):
			suffixString = "- FRAP"
		else:
			suffixString = "- FRAP fit"
		myPlot=Plot(filename + suffixString, "Time", "Normalized intensity")
		myPlot.setLineWidth(2)
		myPlot.add("Line",x1,y1)
		#Removes gridlines; delete if you like these...
		myPlot.setFormatFlags(0x330f)
		myPlot.show()
		if (numCol > 2):
			#print("Number of columns:")
			#print(numCol)
			#In case the data is one X column and two Y columns
			if (numCol == 3):
				myPlot.setColor("red")
				#print(y2)
				myPlot.add("Line",x1,y2)
				myPlot.setColor("black")
				myPlot.setLegend(legendString,Plot.AUTO_POSITION)
			if ((numCol > 3) and (rawFRAPFile)):
				#This is a Raw FRAP data file
				myPlot.setColor("red")
				myPlot.add("Line",x1,y2)
				myPlot.setColor("blue")
				myPlot.add("Line",x1,y3)
				yMax = max(y1)
				yMin = min(y1)
				if (max(y2) > yMax):
					yMax = max(y2)
				if (min(y2) < yMin):
					yMin = min(y2)
				if (max(y3) > yMax):
					yMax = max(y3)
				if (min(y3) < yMin):
					yMin = min(y3)
				myPlot.setLimits(xMin, xMax, 0.8 * yMin, yMax)
				myPlot.setColor("black")
				myPlot.setLegend(legendString,Plot.AUTO_POSITION)
			else:
				#This is a paired data  file
				myPlot.setColor("red")
				myPlot.add("Line",x2,y2)
				yMax = max(y1)
				yMin = min(y1)
				if (max(y2) > yMax):
					yMax = max(y2)
				if (min(y2) < yMin):
					yMin = min(y2)
				myPlot.setLimits(xMin, xMax, yMin, yMax)
				myPlot.setColor("black")
				myPlot.setLegend(legendString,Plot.AUTO_POSITION)		
#main
#next line uses parameters to get OS-specific multiple paths
#@ File[] listOfPaths (label="select files", style="files")
doPlot()