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
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)
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)
In [ ]:
In [ ]: