#Jeff Hardin, Dept. of Integrative Biology
#Univ. of Wisconsin-Madison
#jdhardin@wisc.edu
#Current version July 26, 2025

#This script imports data from one or more CSV files in the form x[i],y[i] as paired columns
#Using JFreeChart allows export as an editable SVG file.
#User asked to choose legend placement and data structure

from org.jfree.chart import ChartFactory, ChartPanel, JFreeChart, LegendItem  
from org.jfree.chart.title import LegendTitle
from org.jfree.chart.annotations import XYTitleAnnotation
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,RectangleInsets,RectangleAnchor
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 = ","
	#plotColor=[]
	#plotColor = ("black", "red", "blue", "#32a852", "#7132a8", "#9C2005", "#754F04", "magenta", "darkGray", "gray", "lightGray", "green", "#9C6905", "cyan", "orange", "pink", "yellow");
	#Call below is a feature of Fiji/IJ2
	#See https://imagej.net/scripting/parameters
	k = len(listOfPaths)
	
	## Ask if a single X and multiple Y columns or paired columns
	gd = GenericDialog("Options")
	#dataStructure = ["Single X", "Paired XY"]
	#legendPosition = ["Jfree default", "Inside plot"]
	gd.addRadioButtonGroup("Data structure:", ["Single X", "Paired XY"], 1,2,"Paired XY")
	gd.addRadioButtonGroup("Legend position:", ["JFree default", "Inside plot"], 1,2,"JFree default")
	gd.showDialog()	
	if gd.wasOKed():
		pairedChoice = gd.getNextRadioButton()
		legendPosition = gd.getNextRadioButton()
	else: 
		return None

	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")
		#Use a Java method instead (need JVM 7+)
		file = File(str(listOfPaths[i]))
		#get file name using getName()
		filename = file.getName()
		
		#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 column headers
		labels=lines[0].split(cellseparator)
		#get total columns
		numCol = len(labels)

		#Below is the equivalent calls using ImageJ's PLot functions
		#set up plot using ImageJ plot function		
		#myPlot=Plot(filename, "X", "Y")
		#myPlot.setLineWidth(2)
		#IJ.open(str(listOfPaths[i]))

		#Use JFreeChart calls for plot
		#create series
		dataset = XYSeriesCollection()
		
		#Following was ImageJ plot legend call
		#legendString = labels[0] + " v. " + labels[1]

		if pairedChoice == "Paired XY":
			# If paired columns		
			# set up plot using JFree plot function
			for m in range(0, numCol/2):
				x1=[]
				y1=[]
				series1 = XYSeries(labels[2*m] + " v. " + labels[2*m+1])
				xMin = 0
				xMax = 0
				#Iterate over each row in the csv using reader object
				#assume header row; skip this, since we already did this above
				for j in range(1,numRows):
					row=lines[j].split(cellseparator)
					#print("Row:")
					#print(row)
					#print(len(row))
					#added this because some CSV files have a trailing carriage return...
					if (len(row) > 1):				
					#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[2*m])) and (isfloat(row[2*m+1]))):
							x1.append(float(row[2*m]))
							y1.append(float(row[2*m+1]))
							if (float(row[2*m]) < xMin):
								xMin = float(row[2*m])
							if (float(row[2*m]) > xMax):
								xMax = float(row[2*m])

				#Now add arrays to series and series to dataset
				for n in range(0, len(x1)-1):
					series1.add(x1[n],y1[n])
				#print("Series:")
				#print(series1)
				dataset.addSeries(series1)

				#myPlot.setColor(plotColor[m])
				#myPlot.add("Line",x1,y1)
				#if (m > 0):
					#legendString = legendString + "\t" + labels[2*(m)] + " v. " + labels[2*m+1]
			
			#now create the chart
			chart = ChartFactory.createXYLineChart(filename, "X", "Y", dataset) 
			plot = chart.getPlot()
			r = plot.getRenderer()
			plot.setBackgroundPaint(Color.white)
			#set first series to black and let JFreeCHart set other colors
			r.setSeriesPaint(0, Color.BLACK)
			#Run through series and set each to 2 pt using this call in a loop
			for m in range(0, numCol/2):
				r.setSeriesStroke(m,BasicStroke(float(2.0)))
			myDimension = Dimension(600,400)
			chart.title.setVisible(False)
			chartPanel = ChartPanel(chart)
			chartPanel.setPreferredSize(myDimension)
			chartRectangleInserts = RectangleInsets(0, 0, 0, 10)
			chart.setPadding(chartRectangleInserts)
		
			#Manually set max for X axis; default. 
			#org.jfree.chart.axis.ValueAxis.autoAdjustRange() doesn't give
			#great results, as it pads the X axis to much.
			domainAxis = plot.getDomainAxis()
			domainAxis.setRange(xMin,xMax)
			
			legend = chart.getLegend()
			
			#next lines draw legend using defaults
			if (legendPosition == "JFree default"):
				legend.setPosition(RectangleEdge.RIGHT)
				legend.setBorder(1,1,1,1)
			else:
				#Draw legend inside the plot, since deafult position is outside the plot
				#from JFreeChart samp[e code
				legend.setVisible(False)
				lt = LegendTitle(plot)
				lt.setPosition(RectangleEdge.BOTTOM)
				lt.setBorder(1,1,1,1)
				lt.setBackgroundPaint(Color.WHITE)
				ta = XYTitleAnnotation(0.98, 0.02, lt,RectangleAnchor.BOTTOM_RIGHT)
				ta.setMaxWidth(0.6)
				plot.addAnnotation(ta)

			# Show the chart in an interactive window  
			# where the right-click menu enables saving to PNG or SVG, and adjusting properties  
			frame = JFrame(filename)  
			frame.getContentPane().add(chartPanel)  
			frame.pack()  
			frame.setVisible(True)  

		else:
			# If single X and multiple Y columns		
			# set up plot using JFree plot function
			for m in range(1, numCol):
				x1=[]
				y1=[]
				series1 = XYSeries(labels[m])
				#series1 = XYSeries(labels[0] + " v. " + labels[m])
				xMin = 0
				xMax = 0
				#Iterate over each row in the csv using reader object
				#assume header row; skip this, since we already did this above
				for j in range(1,numRows):
					row=lines[j].split(cellseparator)
					#print("Row:")
					#print(row)
					#print(len(row))
					#added this because some CSV files have a trailing carriage return...
					if (len(row) > 1):				
					#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])) and (isfloat(row[m]))):
							x1.append(float(row[0]))
							y1.append(float(row[m]))
							if (float(row[0]) < xMin):
								xMin = float(row[0])
							if (float(row[0]) > xMax):
								xMax = float(row[0])
				
				#Now add arrays to series and series to dataset
				for n in range(0, len(x1)-1):
					series1.add(x1[n],y1[n])
				#print("Series:")
				#print(series1)
				dataset.addSeries(series1)

				#myPlot.setColor(plotColor[m])
				#myPlot.add("Line",x1,y1)
				#if (m > 0):
					#legendString = legendString + "\t" + labels[2*(m)] + " v. " + labels[2*m+1]
			
			#now create the chart
			chart = ChartFactory.createXYLineChart(filename, "X", "Y", dataset) 
			plot = chart.getPlot()
			r = plot.getRenderer()
			plot.setBackgroundPaint(Color.white)
			#set first series to black and let JFreeCHart set other colors
			r.setSeriesPaint(0, Color.BLACK)
			#Run through series and set each to 2 pt using this call in a loop
			for m in range(0, numCol/2):
				r.setSeriesStroke(m,BasicStroke(float(2.0)))
			myDimension = Dimension(600,400)
			chart.title.setVisible(False)
			chartPanel = ChartPanel(chart)
			chartPanel.setPreferredSize(myDimension)
			chartRectangleInserts = RectangleInsets(0, 0, 0, 10)
			chart.setPadding(chartRectangleInserts)
		
			#Manually set max for X axis; default. 
			#org.jfree.chart.axis.ValueAxis.autoAdjustRange() doesn't give
			#great results, as it pads the X axis to much.
			domainAxis = plot.getDomainAxis()
			domainAxis.setRange(xMin,xMax)
			legend = chart.getLegend()

			if (legendPosition == "JFree default"):
				legend.setPosition(RectangleEdge.RIGHT)
				legend.setBorder(1,1,1,1)
			else:
				#Draw legend inside the plot, since deafult position is outside the plot
				#from JFreeChart samp[e code
				legend.setVisible(False)
				lt = LegendTitle(plot)
				lt.setPosition(RectangleEdge.BOTTOM)
				lt.setBorder(1,1,1,1)
				lt.setBackgroundPaint(Color.WHITE)
				ta = XYTitleAnnotation(0.98, 0.02, lt,RectangleAnchor.BOTTOM_RIGHT)
				ta.setMaxWidth(0.6)
				plot.addAnnotation(ta)

			# Show the chart in an interactive window  
			# where the right-click menu enables saving to PNG or SVG, and adjusting properties  
			frame = JFrame(filename)  
			frame.getContentPane().add(chartPanel)  
			frame.pack()  
			frame.setVisible(True)  


#main
#@ File[] listOfPaths (label="select files", style="files")
doPlot()