# @File(label="Image directory", style="directory") inFolder
# @String(label="Image File Extension", required=false, value=".tif") image_extension
# @Boolean(label="Show stack ?", value="True") ShowStack
# @Boolean(label="Save Stack ?", description="Stacks will be saved in a 'HyperStack' folder in the image folder",value = "True") SaveStack

'''
HYPERSTACK GENERATOR
Read all tif images from an experiment inFolder that contains tif images for the different wells, channel, slices and timepoints
The script will automatically reads the field from the filename (using index in the string - FOLLOWING ACQUIFER-IM04 NAMING CONVENTION ex: -A001--...) to generate the well's stack
'''
import os, ij
import ij.plugin as plugin

# Find image files for the given channel
inFolder = str(inFolder) # convert filename object to string object

WellList    = [] # full list of well to know how many iteration for stacking
TimeList    = []
ChannelList = []
SliceList   = []
MainList    = [] # contains tuple with (Filename, Well, TimePoint, Channel, Z-Slice)

for fname in os.listdir(inFolder):
	if fname.endswith(image_extension):
		
		Well 	= fname[1:5]
		try : # int conversion through an error if the argument string is empty 
			Time 	= int(fname[15:18])
			Channel = int(fname[22:23])
			Slice 	= int(fname[27:30]) 
		except :
			raise Exception("Could not get experimental parameters from filename. Check filename pattern (IM04 convention)")

		WellList.append(Well)
		TimeList.append(Time)
		ChannelList.append(Channel)
		SliceList.append(Slice)
		MainList.append((fname,Well,Time,Channel,Slice))

		
if len(MainList) < 1:
    raise Exception("No image files found in %s. Check if extension match and if filenames match IM04 naming convention" % inFolder)

# Sort list to prepare iteration
WellList = list(set(WellList)) # turn to a set object to have unique item once only 
WellList.sort() 			   # sort should be after set since set may change order 

TimeList = list(set(TimeList)) 
TimeList.sort() 			  

ChannelList = list(set(ChannelList)) 
ChannelList.sort()

SliceList = list(set(SliceList)) 
SliceList.sort() 

# Verification
print 'Well  : ', WellList
print 'Time  : ', TimeList
print 'Channel  : ', ChannelList
print 'Z-Slice : ' , SliceList


MainList.sort( key = lambda field:(field[1], field[2], field[4], -field[3]) ) # sort by Well, Time, Z-slice then Channel (- to have C06 ie BF first) since the hyperstack is created following the default "xyczt" order
'''
for i in MainList :
	print i
'''

# Open first image to get the image size (needed to setup the stack) or find another way to do the stack
ImagePath = os.path.join(inFolder,MainList[0][0])
Image     = ij.IJ.openImage(ImagePath)
Width  = Image.width
Height = Image.height


for well in WellList: # Loop over well to do stack and projection
	SubList = [item for item in MainList if item[1]==well] # Sublist containing (fname,Well,Time,Channel,Slice) for a given Well
	#print 'StackSize : ',len(SubList)
	
	Stack = ij.ImageStack(Width,Height) # create stack objet that will contains all images of this well (further turned into an hyperstack)
	
	for item in SubList : # Loop over tuples of SubList, open associated images and append it to the stack
		filename = item[0]
		ImagePath = os.path.join(inFolder,filename)
		Image = ij.IJ.openImage(ImagePath)
		
		Stack.addSlice(Image.getProcessor()) # conversion to ImageProcessor object to append to stack

	Stack = ij.ImagePlus(well,Stack) # reconverting back to an ImagePlus object to be able to show and save it
	#Stack.show() # Good
	
	HyperStacker = plugin.HyperStackConverter() # create HyperStackConverter object
	HyperStack   = HyperStacker.toHyperStack(Stack,len(ChannelList), len(SliceList), len(TimeList),"xyczt","grayscale") # convert PROPERLY ORDERED Stack to Hyperstack
	
	
	if ShowStack : 
		HyperStack.show()

	if SaveStack :
		outFolder = os.path.join(inFolder,'HyperStack')
		if not os.path.exists(outFolder): os.makedirs(outFolder) # create folder if it does not exist (for the first image to save basicly)
		
		outPath = os.path.join(outFolder,well+'.tif')
		ij.IJ.save(HyperStack,outPath)
