def main(inp=""): print("Colonyzer " + c2.__version__) var = buildVars(inp=inp) correction, fixedThresh, plots, initpos, fdict, fdir, nrow, ncol, cut, verbose, diffIms, updates, endpoint, edgemask, greenlab = ( var["lc"], var["fixedThresh"], var["plots"], var["initpos"], var["fdict"], var["fdir"], var["nrow"], var["ncol"], var["cut"], var["verbose"], var["diffims"], var["updates"], var["endpoint"], var["edgemask"], var["greenlab"]) barcdict = checkImages(fdir, fdict, verbose=verbose) if greenlab: barcdict = { x: barcdict[x] for x in barcdict.keys() if not c2.checkAnalysisStarted(barcdict[x][-1]) } rept = c2.setupDirectories(barcdict, verbose=verbose) if greenlab: posfiles = [ resource_filename(Requirement.parse("colonyzer2"), os.path.join("data", f)) for f in ["GreenLabLid.png", "CornerLid.png", "BottomRightLid.png"] ] negfiles = [ resource_filename(Requirement.parse("colonyzer2"), os.path.join("data", f)) for f in ["GreenLabNoLid.png", "CornerNoLid.png", "BottomRightNoLid.png"] ] frects = [[0.15, 0.85, 0.5, 1.0], [0.0, 0.8, 0.125, 1.0], [0.85, 0.8, 1.0, 1.0]] pdistThresh, ndistThresh = 50.3, 53.333 checkLid = c2.makeLidTest(posfiles, negfiles, frects, pdistThresh, ndistThresh, False) else: def checkLid(fname): False start = time.time() while len(barcdict) > 0: BARCODE, imdir, LATESTIMAGE, EARLIESTIMAGE, imRoot = prepareTimecourse( barcdict, verbose=verbose, chklid=checkLid) if plots: pdf = PdfPages( os.path.join( os.path.dirname(EARLIESTIMAGE), "Output_Reports", os.path.basename(EARLIESTIMAGE).split(".")[0] + ".pdf")) else: pdf = None # Create empty file to indicate that barcode is currently being analysed, to allow parallel analysis (lock files) tmp = open( os.path.join( os.path.dirname(EARLIESTIMAGE), "Output_Data", os.path.basename(EARLIESTIMAGE).split(".")[0] + ".out"), "w").close() # Get latest image for thresholding and detecting culture locations imN, arrN = c2.openImage(LATESTIMAGE) # Get earliest image for lighting gradient correction if (LATESTIMAGE == EARLIESTIMAGE) or endpoint: im0, arr0 = imN, arrN arrloc = arrN else: im0, arr0 = c2.openImage(EARLIESTIMAGE) arrloc = arrN - arr0 #arrloc=np.maximum(0,arrloc) if initpos: InsData = c2.readInstructions(os.path.dirname(LATESTIMAGE), searchUpStream=True) # Load initial guesses from Colonyzer.txt file (candx, candy, dx, dy) = loadLocationGuesses(LATESTIMAGE, InsData) corner = [0, 0] com = [0, 0] guess = [0, 0] # NOTE: assumes that grid returned by loadLocationGuesses is parallel to image edges ny = nrow = len(np.unique(candy)) nx = ncol = len(np.unique(candx)) else: # Automatically generate guesses for gridded array locations (candx, candy, dx, dy, corner, com, guess) = c2.estimateLocations(arrloc, ncol, nrow, showPlt=plots, pdf=pdf, glob=False, verbose=verbose, nsol=updates) # Update guesses and initialise locations data frame locationsN = c2.locateCultures( [int(round(cx - dx / 2.0)) for cx in candx], [int(round(cy - dy / 2.0)) for cy in candy], dx, dy, arrloc, ncol, nrow, update=True) mask = edgeFill2(arrN, 0.9) c2.showIm(mask) grd = mask.copy() grd[:, :] = False grd[min(locationsN.y - dy / 2):max(locationsN.y + dy / 2), min(locationsN.x - dx / 2):max(locationsN.x + dx / 2)] = True spots = np.logical_and(grd, mask) agar = np.logical_and(grd, ~mask) ave0 = np.mean(arr0[agar]) thresh = -99 if correction: if cut: pseudoempty = np.array(np.round(arr0.copy()), dtype=np.uint8) bytemask = np.asarray(spots * 255, dtype=np.uint8) filled = cv2.inpaint(pseudoempty, bytemask, 3, cv2.INPAINT_NS) blurred = cv2.GaussianBlur(filled, (21, 21), 0) pseudoempty[spots] = blurred[spots] else: pseudoempty = arr0 else: pseudoempty = 0 for FILENAME in barcdict[BARCODE]: startim = time.time() im, arr = c2.openImage(FILENAME) # Local updates on individual images to allow for slight movement of plate #locationsN=c2.locateCultures([int(round(cx-dx/2.0)) for cx in candx],[int(round(cy-dy/2.0)) for cy in candy],dx,dy,arr,ncol,nrow,update=True) ave = np.mean(arr[agar]) # Correct for minor lighting differences between images arr = np.maximum(0, np.minimum(255, arr - (ave - ave0))) # Subtract background (corrects for lighting differences within plate/image as well as making agar intensity correspond to zero signal) arr = np.maximum(arr - pseudoempty, 0) # Measure culture phenotypes locations = c2.measureSizeAndColour(locationsN, arr, im, spots, 0, BARCODE, FILENAME[0:-4]) # Write results to file locations.to_csv(os.path.join( os.path.dirname(FILENAME), "Output_Data", os.path.basename(FILENAME).split(".")[0] + ".out"), "\t", index=False, engine='python') dataf = c2.saveColonyzer( os.path.join(os.path.dirname(FILENAME), "Output_Data", os.path.basename(FILENAME).split(".")[0] + ".dat"), locations, thresh, dx, dy) # Visual check of culture locations imthresh = c2.threshPreview(locations, mask, None) r = 5 draw = ImageDraw.Draw(imthresh) draw.ellipse((com[1] - r, com[0] - r, com[1] + r, com[0] + r), fill=(255, 0, 0)) draw.ellipse( (corner[1] - r, corner[0] - r, corner[1] + r, corner[0] + r), fill=(255, 0, 0)) draw.ellipse( (guess[1] - r, guess[0] - r, guess[1] + r, guess[0] + r), fill=(255, 0, 0)) draw.ellipse( (candx[0] - r, candy[0] - r, candx[0] + r, candy[0] + r), fill=(255, 0, 0)) imthresh.save( os.path.join(os.path.dirname(FILENAME), "Output_Images", os.path.basename(FILENAME).split(".")[0] + ".png")) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format( os.path.basename(FILENAME), time.time() - startim)) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format(os.path.basename(BARCODE), time.time() - start)) barcdict = { x: barcdict[x] for x in barcdict.keys() if not c2.checkAnalysisStarted(barcdict[x][-1]) } if plots: pdf.close() print("No more barcodes to analyse... I'm done.")
def main(inp=""): print("Colonyzer "+c2.__version__) cythonFill=False var=buildVars(inp=inp) correction,fixedThresh,plots,initpos,fdict,fdir,nrow,ncol,cut,verbose,diffIms=(var["lc"],var["fixedThresh"],var["plots"],var["initpos"],var["fdict"],var["fdir"],var["nrow"],var["ncol"],var["cut"],var["verbose"],var["diffims"]) barcdict=checkImages(fdir,fdict,verbose=verbose) rept=c2.setupDirectories(barcdict,verbose=verbose) start=time.time() while len(barcdict)>0: BARCODE,imdir,InsData,LATESTIMAGE,EARLIESTIMAGE,imRoot=prepareTimecourse(barcdict,verbose=verbose) if plots: pdf=PdfPages(os.path.join(os.path.dirname(EARLIESTIMAGE),"Output_Reports",os.path.basename(EARLIESTIMAGE).split(".")[0]+".pdf")) else: pdf=None # Create empty file to indicate that barcode is currently being analysed, to allow parallel analysis (lock files) tmp=open(os.path.join(os.path.dirname(EARLIESTIMAGE),"Output_Data",os.path.basename(EARLIESTIMAGE).split(".")[0]+".out"),"w").close() # Get latest image for thresholding and detecting culture locations imN,arrN=c2.openImage(LATESTIMAGE) # Get earliest image for lighting gradient correction if(LATESTIMAGE==EARLIESTIMAGE): im0,arr0=imN,arrN else: im0,arr0=c2.openImage(EARLIESTIMAGE) if initpos: # Load initial guesses from Colonyzer.txt file (candx,candy,dx,dy)=loadLocationGuesses(LATESTIMAGE,InsData) corner=[0,0]; com=[0,0]; guess=[0,0] else: # Automatically generate guesses for gridded array locations (candx,candy,dx,dy,corner,com,guess)=c2.estimateLocations(arrN,ncol,nrow,showPlt=plots,pdf=pdf,glob=False,verbose=verbose) # Update guesses and initialise locations data frame locationsN=c2.locateCultures([int(round(cx-dx/2.0)) for cx in candx],[int(round(cy-dy/2.0)) for cy in candy],dx,dy,arrN,ncol,nrow,update=True) if correction: if cut: mask=edgeFill(arr0,locationsN,0.8) startFill=time.time() if cythonFill: pseudoempty=maskAndFillCython(arr0,maskN,0.005) print("Inpainting using Cython & NumPy: "+str(time.time()-startFill)+" s") else: pseudoempty=maskAndFill(arr0,mask,0.005) print("Inpainting using NumPy: "+str(time.time()-start)+" s") else: pseudoempty=arr0 # Smooth (pseudo-)empty image (correction_map,average_back)=c2.makeCorrectionMap(pseudoempty,locationsN,verbose=verbose) # Correct spatial gradient in final image corrected_arrN=arrN*correction_map else: average_back=numpy.mean(arr0[numpy.min(locationsN.y):numpy.max(locationsN.y),numpy.min(locationsN.x):numpy.max(locationsN.x)]) corrected_arrN=arrN # Trim outer part of image to remove plate walls trimmed_arrN=corrected_arrN[max(0,int(round(min(locationsN.y)-dy/2.0))):min(arrN.shape[0],int(round((max(locationsN.y)+dy/2.0)))),max(0,int(round(min(locationsN.x)-dx/2.0))):min(arrN.shape[1],int(round((max(locationsN.x)+dx/2.0))))] if fixedThresh>=0: thresh=fixedThresh else: (thresh,bindat)=c2.automaticThreshold(trimmed_arrN,BARCODE,pdf=pdf) if plots: c2.plotModel(bindat,label=BARCODE,pdf=pdf) # Mask for identifying culture areas maskN=numpy.ones(arrN.shape,dtype=numpy.bool) maskN[corrected_arrN<thresh]=False for FILENAME in barcdict[BARCODE]: startim=time.time() im,arr=c2.openImage(FILENAME) if correction: arr=arr*correction_map if diffIms: # Correct for lighting differences between plates arrsm=arr[max(0,int(round(min(locationsN.y)-dy/2.0))):min(arrN.shape[0],int(round((max(locationsN.y)+dy/2.0)))),max(0,int(round(min(locationsN.x)-dx/2.0))):min(arrN.shape[1],int(round((max(locationsN.x)+dx/2.0))))] masksm=maskN[max(0,int(round(min(locationsN.y)-dy/2.0))):min(arrN.shape[0],int(round((max(locationsN.y)+dy/2.0)))),max(0,int(round(min(locationsN.x)-dx/2.0))):min(arrN.shape[1],int(round((max(locationsN.x)+dx/2.0))))] meanPx=numpy.mean(arrsm[numpy.logical_not(masksm)]) arr=arr+(average_back-meanPx) threshadj=thresh+(average_back-meanPx) else: threshadj=thresh mask=numpy.ones(arr.shape,dtype=numpy.bool) mask[corrected_arrN<threshadj]=False # Measure culture phenotypes locations=c2.measureSizeAndColour(locationsN,arr,im,mask,average_back,BARCODE,FILENAME[0:-4]) # Write results to file locations.to_csv(os.path.join(os.path.dirname(FILENAME),"Output_Data",os.path.basename(FILENAME).split(".")[0]+".out"),"\t",index=False,engine='python') dataf=c2.saveColonyzer(os.path.join(os.path.dirname(FILENAME),"Output_Data",os.path.basename(FILENAME).split(".")[0]+".dat"),locations,threshadj,dx,dy) # Visual check of culture locations imthresh=c2.threshPreview(arr,threshadj,locations) r=5 draw=ImageDraw.Draw(imthresh) draw.ellipse((com[1]-r,com[0]-r,com[1]+r,com[0]+r),fill=(255,0,0)) draw.ellipse((corner[1]-r,corner[0]-r,corner[1]+r,corner[0]+r),fill=(255,0,0)) draw.ellipse((guess[1]-r,guess[0]-r,guess[1]+r,guess[0]+r),fill=(255,0,0)) draw.ellipse((candx[0]-r,candy[0]-r,candx[0]+r,candy[0]+r),fill=(255,0,0)) imthresh.save(os.path.join(os.path.dirname(FILENAME),"Output_Images",os.path.basename(FILENAME).split(".")[0]+".png")) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format(os.path.basename(FILENAME),time.time()-startim)) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format(os.path.basename(BARCODE),time.time()-start)) barcdict={x:barcdict[x] for x in barcdict.keys() if not c2.checkAnalysisStarted(barcdict[x][-1])} if plots: pdf.close() print("No more barcodes to analyse... I'm done.")
def main(inp=""): #inp="-gixcp" print("Colonyzer "+c2.__version__) var=buildVars(inp=inp) correction,fixedThresh,plots,initpos,fdict,fdir,nrow,ncol,cut,verbose,diffIms,updates,endpoint,edgemask,greenlab=(var["lc"],var["fixedThresh"],var["plots"],var["initpos"],var["fdict"],var["fdir"],var["nrow"],var["ncol"],var["cut"],var["verbose"],var["diffims"],var["updates"],var["endpoint"],var["edgemask"],var["greenlab"]) barcdict=checkImages(fdir,fdict,verbose=verbose) rept=c2.setupDirectories(barcdict,verbose=verbose) if greenlab: posfiles=[resource_filename(Requirement.parse("colonyzer2"),os.path.join("data",f)) for f in ["GreenLabLid.png","CornerLid.png","BottomRightLid.png"]] negfiles=[resource_filename(Requirement.parse("colonyzer2"),os.path.join("data",f)) for f in ["GreenLabNoLid.png","CornerNoLid.png","BottomRightNoLid.png"]] frects=[[0.15,0.85,0.5,1.0],[0.0,0.8,0.125,1.0],[0.85,0.8,1.0,1.0]] # Correctly oriented plates... pdistThresh,ndistThresh=50.3,53.333 checkLid=c2.detectlid.makeLidTest(posfiles,negfiles,frects,pdistThresh,ndistThresh,False) else: def checkLid(fname): False start=time.time() while len(barcdict)>0: BARCs=sorted(barcdict) BARCODE=BARCs[0] # Create empty file to indicate that barcode is currently being analysed, to allow parallel analysis (lock files) tmp=open(os.path.join(os.path.dirname(barcdict[BARCODE][0]),"Output_Data",os.path.basename(barcdict[BARCODE][0]).split(".")[0]+".out"),"w").close() imdir=os.path.dirname(barcdict[BARCODE][0]) print("Analysing images labelled with the barcode "+BARCODE+" in "+imdir) IMs=[b for b in barcdict[BARCODE] if not checkLid(b)] if len(IMs)>0: barcdict[BARCODE]=IMs LATESTIMAGE=IMs[0] EARLIESTIMAGE=IMs[-1] imRoot=EARLIESTIMAGE.split(".")[0] if verbose: print("Earliest image: "+EARLIESTIMAGE) print("Latest image: "+LATESTIMAGE) if plots: pdf=PdfPages(os.path.join(os.path.dirname(EARLIESTIMAGE),"Output_Reports",os.path.basename(EARLIESTIMAGE).split(".")[0]+".pdf")) else: pdf=None # Get latest image for thresholding and detecting culture locations imN,arrN=c2.openImage(LATESTIMAGE) # Get earliest image for lighting gradient correction if (LATESTIMAGE==EARLIESTIMAGE) or endpoint: im0,arr0=imN,arrN arrloc=arrN else: im0,arr0=c2.openImage(EARLIESTIMAGE) arrloc=arrN-arr0 #arrloc=np.maximum(0,arrloc) if initpos: InsData=c2.readInstructions(os.path.dirname(LATESTIMAGE),searchUpStream=True) # Load initial guesses from Colonyzer.txt file (candx,candy,dx,dy)=loadLocationGuesses(LATESTIMAGE,InsData) corner=[0,0]; com=[0,0]; guess=[0,0] # NOTE: assumes that grid returned by loadLocationGuesses is parallel to image edges ny=nrow=len(np.unique(candy)) nx=ncol=len(np.unique(candx)) else: # Automatically generate guesses for gridded array locations (candx,candy,dx,dy,corner,com,guess)=c2.estimateLocations(arrloc,ncol,nrow,showPlt=plots,pdf=pdf,glob=False,verbose=verbose,nsol=updates) # Update guesses and initialise locations data frame locationsN=c2.locateCultures([int(round(cx-dx/2.0)) for cx in candx],[int(round(cy-dy/2.0)) for cy in candy],dx,dy,arrloc,ncol,nrow,update=True) mask=edgeFill2(arrN,0.9) grd=mask.copy() grd[:,:]=False grd[min(locationsN.y-dy/2):max(locationsN.y+dy/2),min(locationsN.x-dx/2):max(locationsN.x+dx/2)]=True spots=np.logical_and(grd,mask) agar=np.logical_and(grd,~mask) ave0=np.mean(arr0[agar]) thresh=-99 if correction: if cut: pseudoempty = np.array(np.round(arr0.copy()),dtype=np.uint8) bytemask = np.asarray(spots*255, dtype=np.uint8) filled = cv2.inpaint(pseudoempty,bytemask,10,cv2.INPAINT_TELEA) blurred = cv2.GaussianBlur(filled,(21,21),0) pseudoempty[spots] = blurred[spots] else: pseudoempty=arr0 else: pseudoempty=0 for FILENAME in barcdict[BARCODE]: startim=time.time() im,arr=c2.openImage(FILENAME) # Local updates on individual images to allow for slight movement of plate #locationsN=c2.locateCultures([int(round(cx-dx/2.0)) for cx in candx],[int(round(cy-dy/2.0)) for cy in candy],dx,dy,arr,ncol,nrow,update=True) ave=np.mean(arr[agar]) # Correct for minor lighting differences between images arr=np.maximum(0,np.minimum(255,arr-(ave-ave0))) # Subtract background (corrects for lighting differences within plate/image as well as making agar intensity correspond to zero signal) arr=np.maximum(arr-pseudoempty,0) # Measure culture phenotypes locations=c2.measureSizeAndColour(locationsN,arr,im,spots,0,BARCODE,FILENAME[0:-4]) # Write results to file locations.to_csv(os.path.join(os.path.dirname(FILENAME),"Output_Data",os.path.basename(FILENAME).split(".")[0]+".out"),"\t",index=False,engine='python') dataf=c2.saveColonyzer(os.path.join(os.path.dirname(FILENAME),"Output_Data",os.path.basename(FILENAME).split(".")[0]+".dat"),locations,thresh,dx,dy) # Visual check of culture locations useMask=False if useMask: impreview=c2.threshPreview(locations,mask,None) else: arr_stretch=255*arr/np.max(arr) impreview=c2.threshPreview(locations,arr_stretch,None) r=5 draw=ImageDraw.Draw(impreview) draw.ellipse((com[1]-r,com[0]-r,com[1]+r,com[0]+r),fill=(255,0,0)) draw.ellipse((corner[1]-r,corner[0]-r,corner[1]+r,corner[0]+r),fill=(255,0,0)) draw.ellipse((guess[1]-r,guess[0]-r,guess[1]+r,guess[0]+r),fill=(255,0,0)) draw.ellipse((candx[0]-r,candy[0]-r,candx[0]+r,candy[0]+r),fill=(255,0,0)) impreview.save(os.path.join(os.path.dirname(FILENAME),"Output_Images",os.path.basename(FILENAME).split(".")[0]+".png")) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format(os.path.basename(FILENAME),time.time()-startim)) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format(os.path.basename(BARCODE),time.time()-start)) barcdict={x:barcdict[x] for x in barcdict.keys() if not (c2.checkAnalysisStarted(barcdict[x][-1]) or x==BARCODE)} if plots and len(IMs)>0: pdf.close() print("No more barcodes to analyse... I'm done.")
def main(inp=""): #inp="-gixcp" print("Colonyzer " + c2.__version__) var = buildVars(inp=inp) correction, fixedThresh, plots, initpos, fdict, fdir, nrow, ncol, cut, verbose, diffIms, updates, endpoint, edgemask, greenlab = ( var["lc"], var["fixedThresh"], var["plots"], var["initpos"], var["fdict"], var["fdir"], var["nrow"], var["ncol"], var["cut"], var["verbose"], var["diffims"], var["updates"], var["endpoint"], var["edgemask"], var["greenlab"]) if (var['remove']): barcdict = checkImages(fdir, fdict, verbose=verbose, checkDone=False) rept = c2.setupDirectories(barcdict, verbose=verbose, remove=True) barcdict = checkImages(fdir, fdict, verbose=verbose) rept = c2.setupDirectories(barcdict, verbose=verbose) if greenlab: posfiles = [ resource_filename(Requirement.parse("colonyzer2"), os.path.join("data", f)) for f in ["GreenLabLid.png", "CornerLid.png", "BottomRightLid.png"] ] negfiles = [ resource_filename(Requirement.parse("colonyzer2"), os.path.join("data", f)) for f in ["GreenLabNoLid.png", "CornerNoLid.png", "BottomRightNoLid.png"] ] frects = [[0.15, 0.85, 0.5, 1.0], [0.0, 0.8, 0.125, 1.0], [0.85, 0.8, 1.0, 1.0]] # Correctly oriented plates... pdistThresh, ndistThresh = 50.3, 53.333 checkLid = c2.detectlid.makeLidTest(posfiles, negfiles, frects, pdistThresh, ndistThresh, False) else: def checkLid(fname): False start = time.time() while len(barcdict) > 0: BARCs = sorted(barcdict) BARCODE = BARCs[0] # Create empty file to indicate that barcode is currently being analysed, to allow parallel analysis (lock files) tmp = open( os.path.join( os.path.dirname(barcdict[BARCODE][0]), "Output_Data", os.path.basename(barcdict[BARCODE][0]).split(".")[0] + ".out"), "w").close() imdir = os.path.dirname(barcdict[BARCODE][0]) print("Analysing images labelled with the barcode " + BARCODE + " in " + imdir) IMs = [b for b in barcdict[BARCODE] if not checkLid(b)] if len(IMs) > 0: barcdict[BARCODE] = IMs LATESTIMAGE = IMs[0] EARLIESTIMAGE = IMs[-1] imRoot = EARLIESTIMAGE.split(".")[0] if verbose: print("Earliest image: " + EARLIESTIMAGE) print("Latest image: " + LATESTIMAGE) if plots: pdf = PdfPages( os.path.join( os.path.dirname(EARLIESTIMAGE), "Output_Reports", os.path.basename(EARLIESTIMAGE).split(".")[0] + ".pdf")) else: pdf = None # Get latest image for thresholding and detecting culture locations imN, arrN = c2.openImage(LATESTIMAGE) # Get earliest image for lighting gradient correction if (LATESTIMAGE == EARLIESTIMAGE) or endpoint: im0, arr0 = imN, arrN arrloc = arrN else: im0, arr0 = c2.openImage(EARLIESTIMAGE) arrloc = arrN - arr0 #arrloc=np.maximum(0,arrloc) if initpos: InsData = c2.readInstructions(os.path.dirname(LATESTIMAGE), searchUpStream=True) # Load initial guesses from Colonyzer.txt file (candx, candy, dx, dy) = loadLocationGuesses(LATESTIMAGE, InsData) corner = [0, 0] com = [0, 0] guess = [0, 0] # NOTE: assumes that grid returned by loadLocationGuesses is parallel to image edges ny = nrow = len(np.unique(candy)) nx = ncol = len(np.unique(candx)) else: if verbose: print("Initial estimate for location of spots on plate...") # Automatically generate guesses for gridded array locations (candx, candy, dx, dy, corner, com, guess) = c2.estimateLocations(arrloc, ncol, nrow, showPlt=plots, pdf=pdf, glob=False, verbose=verbose, nsol=updates) # Update guesses and initialise locations data frame if verbose: print("Updating estimate for location of spots on plate...") locationsN = c2.locateCultures( [int(round(cx - dx / 2.0)) for cx in candx], [int(round(cy - dy / 2.0)) for cy in candy], dx, dy, arrloc, ncol, nrow, update=True) mask = edgeFill2(arrN, var['slopefill']) grd = mask.copy() grd[:, :] = False grd[int(round(min(locationsN.y - dy / 2))):int(round(max(locationsN.y + dy / 2))), int(round(min(locationsN.x - dx / 2))):int(round(max(locationsN.x + dx / 2)))] = True spots = np.logical_and(grd, mask) agar = np.logical_and(grd, ~mask) ave0 = np.mean(arr0[agar]) thresh = -99 mask = None if correction: if cut: if verbose: print("Constructing pseudoempty plate...") pseudoempty = np.array(np.round(arr0.copy()), dtype=np.uint8) bytemask = np.asarray(spots * 255, dtype=np.uint8) filled = cv2.inpaint(pseudoempty, bytemask, 10, cv2.INPAINT_TELEA) blurred = cv2.GaussianBlur(filled, (21, 21), 0) pseudoempty[spots] = blurred[spots] filled = None blurred = None else: pseudoempty = arr0 else: pseudoempty = 0 # Segment final image #thresh,bindat=c2.automaticThreshold(arrN-pseudoempty) thresh, tmask = cv2.threshold( np.array(np.round(np.maximum((arrN - pseudoempty)[grd], 0)), dtype=np.uint8), 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) thresh = thresh - 15 tmask = None for FILENAME in barcdict[BARCODE]: startim = time.time() im, arr = c2.openImage(FILENAME) # Local updates on individual images to allow for slight movement of plate #locationsN=c2.locateCultures([int(round(cx-dx/2.0)) for cx in candx],[int(round(cy-dy/2.0)) for cy in candy],dx,dy,arr,ncol,nrow,update=True) ave = np.mean(arr[agar]) # Correct for minor lighting differences between images arr = np.maximum(0, np.minimum(255, arr - (ave - ave0))) # Subtract background (corrects for lighting differences within plate/image as well as making agar intensity correspond to zero signal) arr = np.maximum(arr - pseudoempty, 0) #mask=edgeFill2(arr,var['slopefill']) mask = np.ones(arr.shape, dtype=np.bool) mask[arr < thresh] = False # Measure culture phenotypes locations = c2.measureSizeAndColour(locationsN, arr, im, np.logical_and(grd, mask), 0, BARCODE, FILENAME[0:-4]) # Write results to file locations.to_csv(os.path.join( os.path.dirname(FILENAME), "Output_Data", os.path.basename(FILENAME).split(".")[0] + ".out"), "\t", index=False) dataf = c2.saveColonyzer( os.path.join( os.path.dirname(FILENAME), "Output_Data", os.path.basename(FILENAME).split(".")[0] + ".dat"), locations, thresh, dx, dy) # Visual check of culture locations linewidth = max(1, int(round(min(im.size) / 500.0))) impreview_mask = c2.threshPreview(locations, mask, None, linethick=linewidth, circlerad=linewidth) impreview = c2.threshPreview(locations, 255 * arr / np.max(arr), None, linethick=linewidth, circlerad=linewidth) r = max(1, int(round(linewidth / 2.0))) draw = ImageDraw.Draw(impreview) draw.ellipse((com[1] - r, com[0] - r, com[1] + r, com[0] + r), fill=(255, 0, 0)) draw.ellipse((corner[1] - r, corner[0] - r, corner[1] + r, corner[0] + r), fill=(255, 0, 0)) draw.ellipse( (guess[1] - r, guess[0] - r, guess[1] + r, guess[0] + r), fill=(255, 0, 0)) draw.ellipse( (candx[0] - r, candy[0] - r, candx[0] + r, candy[0] + r), fill=(255, 0, 0)) impreview.save( os.path.join( os.path.dirname(FILENAME), "Output_Images", os.path.basename(FILENAME).split(".")[0] + ".png")) impreview_mask.save( os.path.join( os.path.dirname(FILENAME), "Output_Images", os.path.basename(FILENAME).split(".")[0] + "_AREA.png")) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format( os.path.basename(FILENAME), time.time() - startim)) im = None arr = None # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format(os.path.basename(BARCODE), time.time() - start)) barcdict = { x: barcdict[x] for x in barcdict.keys() if not (c2.checkAnalysisStarted(barcdict[x][-1]) or x == BARCODE) } if plots and len(IMs) > 0: pdf.close() print("No more barcodes to analyse... I'm done.")
def main(inp=""): print("Colonyzer "+c2.__version__) cythonFill=False var=buildVars(inp=inp) correction,fixedThresh,plots,initpos,fdict,fdir,nrow,ncol,cut,verbose,diffIms,updates,endpoint,edgemask=(var["lc"],var["fixedThresh"],var["plots"],var["initpos"],var["fdict"],var["fdir"],var["nrow"],var["ncol"],var["cut"],var["verbose"],var["diffims"],var["updates"],var["endpoint"],var["edgemask"]) barcdict=checkImages(fdir,fdict,verbose=verbose) rept=c2.setupDirectories(barcdict,verbose=verbose) start=time.time() while len(barcdict)>0: BARCODE,imdir,LATESTIMAGE,EARLIESTIMAGE,imRoot=prepareTimecourse(barcdict,verbose=verbose) if plots: pdf=PdfPages(os.path.join(os.path.dirname(EARLIESTIMAGE),"Output_Reports",os.path.basename(EARLIESTIMAGE).split(".")[0]+".pdf")) else: pdf=None # Create empty file to indicate that barcode is currently being analysed, to allow parallel analysis (lock files) tmp=open(os.path.join(os.path.dirname(EARLIESTIMAGE),"Output_Data",os.path.basename(EARLIESTIMAGE).split(".")[0]+".out"),"w").close() # Get latest image for thresholding and detecting culture locations imN,arrN=c2.openImage(LATESTIMAGE) # Get earliest image for lighting gradient correction if (LATESTIMAGE==EARLIESTIMAGE) or endpoint: im0,arr0=imN,arrN arrloc=arrN else: im0,arr0=c2.openImage(EARLIESTIMAGE) arrloc=arrN-arr0 #arrloc=np.maximum(0,arrloc) if initpos: InsData=c2.readInstructions(os.path.dirname(LATESTIMAGE),searchUpStream=True) # Load initial guesses from Colonyzer.txt file (candx,candy,dx,dy)=loadLocationGuesses(LATESTIMAGE,InsData) corner=[0,0]; com=[0,0]; guess=[0,0] # NOTE: assumes that grid returned by loadLocationGuesses is parallel to image edges ny=nrow=len(np.unique(candy)) nx=ncol=len(np.unique(candx)) else: # Automatically generate guesses for gridded array locations (candx,candy,dx,dy,corner,com,guess)=c2.estimateLocations(arrloc,ncol,nrow,showPlt=plots,pdf=pdf,glob=False,verbose=verbose,nsol=updates) # Update guesses and initialise locations data frame locationsN=c2.locateCultures([int(round(cx-dx/2.0)) for cx in candx],[int(round(cy-dy/2.0)) for cy in candy],dx,dy,arrloc,ncol,nrow,update=True) mask=edgeFill(arr0,locationsN,dx,dy,0.8) if correction: if cut: startFill=time.time() if cythonFill: pseudoempty=c2.maskAndFillCython(arr0,maskN,0.005) print("Inpainting using Cython & np: "+str(time.time()-startFill)+" s") else: pseudoempty=c2.maskAndFill(arr0,mask,0.005) print("Inpainting using np: "+str(time.time()-start)+" s") else: pseudoempty=arr0 # Smooth (pseudo-)empty image (correction_map,average_back)=c2.makeCorrectionMap(pseudoempty,locationsN,verbose=verbose) # Correct spatial gradient in final image corrected_arrN=arrN*correction_map else: average_back=np.mean(arr0[np.min(locationsN.y):np.max(locationsN.y),np.min(locationsN.x):np.max(locationsN.x)]) corrected_arrN=arrN # Trim outer part of image to remove plate walls trimmed_arrN=corrected_arrN[max(0,int(round(min(locationsN.y)-dy/2.0))):min(arrN.shape[0],int(round((max(locationsN.y)+dy/2.0)))),max(0,int(round(min(locationsN.x)-dx/2.0))):min(arrN.shape[1],int(round((max(locationsN.x)+dx/2.0))))] if edgemask: thresh=-99 else: if fixedThresh>=0: thresh=fixedThresh else: (thresh,bindat)=c2.automaticThreshold(trimmed_arrN,BARCODE,pdf=pdf) if plots: c2.plotModel(bindat,label=BARCODE,pdf=pdf) # Mask for identifying culture areas maskN=np.ones(arrN.shape,dtype=np.bool) maskN[corrected_arrN<thresh]=False for FILENAME in barcdict[BARCODE]: startim=time.time() im,arr=c2.openImage(FILENAME) # Local updates on individual images to allow for slight movement of plate #locationsN=c2.locateCultures([int(round(cx-dx/2.0)) for cx in candx],[int(round(cy-dy/2.0)) for cy in candy],dx,dy,arr,ncol,nrow,update=True) if correction: arr=arr*correction_map if diffIms: # Correct for lighting differences between plates arrsm=arr[max(0,int(round(min(locationsN.y)-dy/2.0))):min(arrN.shape[0],int(round((max(locationsN.y)+dy/2.0)))),max(0,int(round(min(locationsN.x)-dx/2.0))):min(arrN.shape[1],int(round((max(locationsN.x)+dx/2.0))))] masksm=maskN[max(0,int(round(min(locationsN.y)-dy/2.0))):min(arrN.shape[0],int(round((max(locationsN.y)+dy/2.0)))),max(0,int(round(min(locationsN.x)-dx/2.0))):min(arrN.shape[1],int(round((max(locationsN.x)+dx/2.0))))] meanPx=np.mean(arrsm[np.logical_not(masksm)]) arr=arr+(average_back-meanPx) #arr=np.maximum(0,arr) threshadj=thresh+(average_back-meanPx) aveB=average_back else: threshadj=thresh aveB=0 if not edgemask: mask=np.ones(arr.shape,dtype=np.bool) mask[corrected_arrN<threshadj]=False # Measure culture phenotypes locations=c2.measureSizeAndColour(locationsN,arr,im,mask,average_back,BARCODE,FILENAME[0:-4]) # Write results to file locations.to_csv(os.path.join(os.path.dirname(FILENAME),"Output_Data",os.path.basename(FILENAME).split(".")[0]+".out"),"\t",index=False,engine='python') dataf=c2.saveColonyzer(os.path.join(os.path.dirname(FILENAME),"Output_Data",os.path.basename(FILENAME).split(".")[0]+".dat"),locations,threshadj,dx,dy) # Visual check of culture locations if edgemask: imthresh=c2.threshPreview(locations,mask,None) else: imthresh=c2.threshPreview(locations,arr,threshadj) r=5 draw=ImageDraw.Draw(imthresh) draw.ellipse((com[1]-r,com[0]-r,com[1]+r,com[0]+r),fill=(255,0,0)) draw.ellipse((corner[1]-r,corner[0]-r,corner[1]+r,corner[0]+r),fill=(255,0,0)) draw.ellipse((guess[1]-r,guess[0]-r,guess[1]+r,guess[0]+r),fill=(255,0,0)) draw.ellipse((candx[0]-r,candy[0]-r,candx[0]+r,candy[0]+r),fill=(255,0,0)) imthresh.save(os.path.join(os.path.dirname(FILENAME),"Output_Images",os.path.basename(FILENAME).split(".")[0]+".png")) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format(os.path.basename(FILENAME),time.time()-startim)) # Get ready for next image if verbose: print("Finished {0} in {1:.2f}s".format(os.path.basename(BARCODE),time.time()-start)) barcdict={x:barcdict[x] for x in barcdict.keys() if not c2.checkAnalysisStarted(barcdict[x][-1])} if plots: pdf.close() print("No more barcodes to analyse... I'm done.")