Annotation creation tool

Jesse Leigh Patsolic For NeuroData

2017 jpatsol1@jhu.edu

Started from a file made by Alex Baden

NB: This uses python3.
Starting from a csv file of locations to be annotated (in x,y,z column format) we create a black image of the specified dimensions and for each location we write a ball (under a specified metric, either infinity or $\ell$2),

positional arguments
base_path system path where you want output images saved
base_fname base output filename
locations centroids in x y z csv file
dim dimensions of full image
buf(fer) buffer in x, y, and z directions
inftyball (bool) draw annotations as infinity balls with radii buf[0], buf[1], buf[2]
l2ball (bool) draw annotations as l2-balls with radius buf[0]

In [1]:
import itertools
import configparser
import csv
import morton
import sys
import os
import numpy as np 
import requests
import argparse
import time
import tifffile

from numpy import genfromtxt
from numpy import linalg as LA
from PIL import Image

Functions


In [14]:
def mask_l2ball(BF):
    a = np.zeros((2 * BF + 1, 2 * BF + 1, 2 * BF + 1))
    for i in range(a.shape[0]):
        for j in range(a.shape[1]):
            for k in range(a.shape[2]):
                if LA.norm(np.asarray([k - BF, j - BF, i - BF])) <= BF:
                    a[k,j,i] = 1
                    
    out = np.asarray(a, dtype = np.uint8)
    return(out)

def main(base_path, base_fname, locations, dim, buf = [5,5,5], inftyball = False, l2ball = False):
    #parser = argparse.ArgumentParser('Post rectangular annotations stack to the boss')
    #parser.add_argument('locations', type=str, help='centroids in x y z csv file')
    #parser.add_argument('base_path', type=str, help='Directory where image stacks are to be saved (e.g. "/data/images/"')
    #parser.add_argument('base_filename', type=str, help='Base filename with z values appended "fname_z<p:4>"')
    #parser.add_argument('--buf', type=int, nargs=3, help='buffer in x y z', default=[5,5,5])
    #parser.add_argument('--dim', type=int, nargs=3, help='dimensions in x y z')
    #parser.add_argument('--res', type=int, default=0, help='Resolution at which we post data.')
    #parser.add_argument('--inftyball', action='store', type=bool, default=False, help='bool to use infinity balls.')
    #parser.add_argument('--l2ball', action='store', type=bool, default=False, help='bool to use l2 balls, only uses buf[0].')

    #args = parser.parse_args()

    base_path
    base_fname

    dimx = dim[0]
    dimy = dim[1]
    dimz = dim[2]
    loc = locations
    
    L = genfromtxt(loc,  delimiter=',', skip_header = 1, dtype='int32').tolist()
    
    BFx = buf[0] 
    BFy = buf[1]
    BFz = buf[2]

    x_rng = [[x[0] - BFx, x[0] + BFx + 1] for x in L] 
    y_rng = [[y[1] - BFy, y[1] + BFy + 1] for y in L] 
    z_rng = [[z[2] - BFz, z[2] + BFz + 1] for z in L]

    inftyones = np.ones((2 * BFz + 1, 2 * BFy + 1, 2 * BFx + 1), dtype = np.uint8)

    if inftyball:
        anno = np.asarray(255*inftyones, dtype = np.uint8)
        ## NUMPY array must be in Z Y X order for the BOSS
    
        z = np.zeros((dimz,dimy,dimx), dtype = np.uint8)
    
        for i in range(len(L)):
            z[z_rng[i][0]:z_rng[i][1],y_rng[i][0]:y_rng[i][1],x_rng[i][0]:x_rng[i][1]] = anno

        fout = os.path.join(base_path, base_fname)

        for j in range(z.shape[0]):
            tmp = fout + "_z{}.tif".format(str(j).zfill(len(str(z.shape[0]))))
            tifffile.imsave(tmp, np.asarray(z[j,:,:], dtype = np.uint8))

        tifffile.imsave(fout + "_stack.tif", np.asarray(z, dtype = np.uint8))
        print("Test image is here: {}".format(base_path))

    if l2ball:
        anno = 255*mask_l2ball(BFx) 
        z = np.zeros((dimz,dimy,dimx), dtype = np.uint8)
    
        for i in range(len(L)):
            rep = anno == 255
            z[z_rng[i][0]:z_rng[i][1],y_rng[i][0]:y_rng[i][1],x_rng[i][0]:x_rng[i][1]][rep] = 255
            
        fout = os.path.join(base_path, base_fname)

        for j in range(z.shape[0]):
            tmp = fout + "_z{}.tif".format(str(j).zfill(len(str(z.shape[0]))))
            tifffile.imsave(tmp, np.asarray(z[j,:,:], dtype = np.uint8))

        tifffile.imsave(fout + "_stack.tif", np.asarray(z, dtype = np.uint8))
        print("Test image is here: {}".format(base_path))

    return(None)

Small test example


In [15]:
import urllib.request

base_path = "/tmp/"
base_fname = "testEx2R18C1"
locations = "Ex2R18C1_BufferedPM5.csv"
buf = [5,5,5] # X, Y, Z order
dim = [2101, 3223, 69] # X, Y, Z order
res = 0

#url = 'http://cis.jhu.edu/~jesse/data/Ex2R18C1_buff5seed317_samp1e4.csv'
#response = urllib.request.urlopen(url)
#data = response.read()      # a `bytes` object
#locations = response #.decode('utf-8') # a `str`; this step

#main(base_path, base_fname, locations, dim, buf, inftyball = True, l2ball = False)
main(base_path, base_fname, locations, dim, buf, inftyball = False, l2ball = True)


Test image is here: /tmp/

In [ ]:


In [ ]: