Example #1
0
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.")
Example #2
0
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.")
Example #3
0
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.")
Example #4
0
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.")
Example #5
0
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.")