# @String (label="Smart imaging method", required=true, value="Template matching", choices={"Template matching","Keypoint matching", "Center of mass"}) Method # @int (label="Number of well to process",value=96) CountMax # @String (label="Objective for smart imaging", required=true, choices={"2x","4x","10x","20x"}) HighObj_Mag # @Boolean(label="Test mode (if not on the microscope)",value=False) Test # @File (label="Directory to watch (in test mode)", style="directory") Path_ImageFolder """ Folder watcher used for smart imaging It first pop up a user input to choose the method to use for smart imaging anf if we are in a test mode (in this case we have to define an image folder and the job files will be saved in a subfolder) Then it calls the corresponding script for smart imaging that pop up another user input window to configure this method Once this configuration is closed it will watch the folder for new images to come, perform the smart imaging detection and will write the job file acccordingly until the max number of images set in the configuration window is reached (or until the macro is killed, otherwise the folder watching keeps going on) """ from os.path import join,isdir,isfile import os, time from ij.IJ import log # Set the run method according to choice if Method == 'Template matching': from MatchTemplate_SI_IJM import Run, Config elif Method == "Keypoint matching" : from KeypointMatching import Run, Config elif Method == "Center of mass": from CenterOfMass import Run, Config # Pop up a user input window to configure the smart imaging method chosen Config() # I - IMAGE FOLDER if not Test: # We are really doing smart imaging Path_LocationFile = r"D:\IMAGING-DATA\JOBS\Image_Location.pth" JobFolder = r"D:\IMAGING-DATA\JOBS" #Try to read the LocationFile to get the image folder FoundLocation = False while not FoundLocation : time.sleep(1) # 1sec delay - prevent loop to run too fast and overload processes try : LocationFile = open(Path_LocationFile,'r') Path_ImageFolder = LocationFile.readline().rstrip() # read content of file and remove new line character LocationFile.close() os.remove(LocationFile) # delete file once read FoundLocation = True print 'Found image location :', Path_ImageFolder except Exception, Error : # File not existing yet print Error FoundLocation = False else: # in test mode Path_ImageFolder = Path_ImageFolder.getCanonicalPath() # Convert from Java file to its path JobFolder = join(Path_ImageFolder,"JOBS") if not os.path.exists(JobFolder): os.mkdir(JobFolder) # II - Create function that will write the job files # correspondance used to write the job file PixToObj = {'32500':1, '16250':2, '6500':3, '3250':4} # map pixel size from the filename to objective index ObjToPix = {v: k for k, v in PixToObj.iteritems()} # invert mapping MagToObj = {'2x':1, '4x':2, '10x':3, '20x':4} # Mapping magnification to its objective index ObjToMag = {v: k for k, v in MagToObj.iteritems()} # Mapping index to magnification ObjIdx_High = MagToObj[HighObj_Mag] # Get objective index from magnification for SI given by user PixelSize_High = ObjToPix[ObjIdx_High] # Get Pixel size from obj index def WriteJob(ImageName,X,Y): ''' Function that will be call with each image after detection of the region of interest X,Y : Objective coordinates in mm with 3 decimal digits for high objective imaging ''' # Extract Metadata before writing job file - IM4 name convention here ! Well = ImageName[1:5] # A1 for instance WellNum = ImageName[106:111] # 1 to 96, as string here PixelSize_Low = ImageName[34:39] ObjIdx_Low = PixToObj[PixelSize_Low] # Get objective index from pixel size read from image name Obj_Low = ObjToMag[ObjIdx_Low] # Magnification '2X','4X','10X' or '20X' #Power = int(ImageName[43:47]) #Integration = int(ImageName[51:55]) # Write job file for higher magnification for each processed image print 'Writing job file' Path_TmpFileName = os.path.join(JobFolder, ImageName+".tmp") # first created as a tmp file to prevent machine from reading itthen rename as .job JobFile = open(Path_TmpFileName,'w') JobFile.write("SetWellNo({})\n".format(WellNum)) JobFile.write("SetMeta('Well Coordinate','{}')\n".format(Well)) JobFile.write("SetMeta('Well Pos in Well','PO01')\n") JobFile.write("GotoXY({:.3f},{:.3f},'Abs')\n".format(X,Y)) # x,y as float 3-decimal, force the trailing 0 if 0 as last decimal JobFile.write("SetMeta('Objective','{}')\n".format(HighObj_Mag)) # '2X','4X','10X' or '20X' JobFile.write("SetMeta('Objective Pixel Size','{}')\n".format(PixelSize_High)) JobFile.write("SetObjective({})\n".format(ObjIdx_High)) JobFile.write("SetLight(6,10,10,0.000)\n") JobFile.write("AcquireAutofocus(7,100.000,2,'True','True')\n") JobFile.write("SetLight(6,50,10,0.000,'Flash')\n") JobFile.write("AcquireAutofocus(6,20.000,2,'True','True')\n") JobFile.write("SetLight(6,50,10,0.000)\n") JobFile.write("Acquire(1,0.000,1,'D:\IMAGING-DATA\IMAGES\SCRIPTS','True','SIdata')\n") # Images will be saved in a subfolder SIdata # Switching off the light and going back to previous obj. JobFile.write("SetLight(0,0,0,0)\n") JobFile.write("SetMeta('Objective','{}')\n".format(Obj_Low)) JobFile.write("SetMeta('Objective Pixel Size','{}')\n".format(PixelSize_Low)) JobFile.write("SetObjective({})".format(ObjIdx_Low)) # no new line here last line to write ! JobFile.close() Path_JobFileName = Path_TmpFileName[:-4]+'.job' # Check that the job file is not already existing if isfile(Path_JobFileName): log('Overwriting existing JobFile') print 'Overwriting existing JobFile' os.remove(Path_JobFileName) # Finally rename from .tmp to .job os.rename(Path_TmpFileName,Path_JobFileName) # III - FOLDER WATCHING and calling the Run method from the imported script before = os.listdir(Path_ImageFolder) # initialisation must be out of the while loop since we are updating it with "current" at the end of the loop # INITIALISATION - We process the image present in the folder before ImageLocation.pth is created (currently this is the case, some image are saved before the file is created) count = 0 # initialise count of processed images for FileName in before : # images in test folder (if test mode) or written before the ImageLocation.pth if count == CountMax : log('DONE - Processed all images') print 'DONE - Processed all images' break else : FilePath = join(Path_ImageFolder,FileName) if not isdir(FilePath): # Check that it is a file and not a folder # Report progress log('Process '+FileName) print 'Process', FileName # Call Run and write job file X,Y = Run(FilePath) # call the Run method from imported module using the image as parameter WriteJob(FileName,X,Y) count += 1 # update count of processed image # CONTINUATION Delay = 5 # delay in sec between successive scans for new image while count < CountMax : # strictly inferior since count starts at 0, and we update it after processing the image ie once we process the last image the counter will be CountMax and we dont want to run another round #while True: # only Keyboard interrupt version time.sleep(Delay) # before_List was updated just previously at the end of the loop so delay prior to a new listdir scan current = os.listdir(Path_ImageFolder) new = list( set(current) - set(before) ) # list containing new file and folder name in Path_ImageFolder if new != []: # New Files have appeared - PUT THE CODE TO EXECUTE HERE for FileName in new : FilePath = join(Path_ImageFolder,FileName) if not isdir(FilePath): # Check that it is a file and not a folder log('Process '+FileName) print 'Process', FileName X,Y = Run(FilePath) # call the Run method from imported module (Template matching or other) using the image as parameter WriteJob(FileName,X,Y) # Update count of processed images count += 1 if count == CountMax : log('DONE - Processed all images') print 'DONE - Processed all images' else: # No new files, keep runnning the loop pass # update the 'history' of the folder watcher, and going for another round of while (except if we reached the count) before = current