def readData(filename, x = all, y = all, z = all, resolution = 0, channel = 0, timepoint = 0, **args): """Read data from imaris file Arguments: filename (str): file name as regular expression x,y,z (tuple): data range specifications resolution (int): resolution level channel (int): color channel timepoint (int): time point Returns: array: image data """ f = h5py.File(filename, "r"); dataset = readDataSet(f, resolution = resolution, channel = channel, timepoint = timepoint); dsize = dataset.shape; rz = io.toDataRange(dsize[0], r = z); ry = io.toDataRange(dsize[1], r = y); rx = io.toDataRange(dsize[2], r = x); data = dataset[rz[0]:rz[1],ry[0]:ry[1],rx[0]:rx[1]]; data = data.transpose((2,1,0)); # imaris stores files in reverse x,y,z ordering #data = dataset[x[0]:x[1],y[0]:y[1],z[0]:z[1]]; f.close(); return data;
def readDataFiles(filename, x=all, y=all, z=all, **args): """Read data from individual images assuming they are the z slices Arguments: filename (str): file name as regular expression x,y,z (tuple): data range specifications Returns: array: image data """ fpath, fl = readFileList(filename) nz = len(fl) #read first image to get data size and type rz = io.toDataRange(nz, r=z) sz = io.toDataSize(nz, r=z) fn = os.path.join(fpath, fl[rz[0]]) img = io.readData(fn, x=x, y=y) nxy = img.shape data = numpy.zeros(nxy + (sz, ), dtype=img.dtype) data[:, :, 0] = img for i in range(rz[0] + 1, rz[1]): fn = os.path.join(fpath, fl[i]) data[:, :, i - rz[0]] = io.readData(fn, x=x, y=y) return data
def joinPoints(results, subStacks=None, shiftPoints=True, **args): """Joins a list of points obtained from processing a stack in chunks Arguments: results (list): list of point results from the individual sub-processes subStacks (list or None): list of all sub-stack information, see :ref:`SubStack` shiftPoints (bool): if True shift points to refer to origin of the image stack considered when range specification is given. If False, absolute position in entire image stack. Returns: tuple: joined points, joined intensities """ nchunks = len(results) pointlist = [results[i][0] for i in range(nchunks)] intensities = [results[i][1] for i in range(nchunks)] results = [] resultsi = [] for i in range(nchunks): cts = pointlist[i] cti = intensities[i] if cts.size > 0: cts[:, 2] += subStacks[i]["z"][0] iid = numpy.logical_and(subStacks[i]["zCenters"][0] <= cts[:, 2], cts[:, 2] < subStacks[i]["zCenters"][1]) cts = cts[iid, :] results.append(cts) if not cti is None: cti = cti[iid] resultsi.append(cti) if results == []: if not intensities is None: return (numpy.zeros((0, 3)), numpy.zeros((0))) else: return numpy.zeros((0, 3)) else: points = numpy.concatenate(results) if shiftPoints: points = points + io.pointShiftFromRange(io.dataSize( subStacks[0]["source"]), x=subStacks[0]["x"], y=subStacks[0]["y"], z=0) else: points = points - io.pointShiftFromRange(io.dataSize( subStacks[0]["source"]), x=0, y=0, z=subStacks[0]["z"]) #absolute offset is added initially via zranges ! if intensities is None: return points else: return (points, numpy.concatenate(resultsi))
def moveTeraStitcherStackToFileList(source, sink, deleteDirectory=True, verbose=True): """Moves image files from TeraSticher file structure to a list of files Arguments: source (str): base directory of the TeraStitcher files sink (str): regular expression of the files to copy to verbose (bool): show progress Returns: str: sink regular expression """ fns = glob.glob(os.path.join(source, "*/*/*")) fns = natsort.natsorted(fns) io.createDirectory(sink) for i, f in enumerate(fns): fn = filelist.fileExpressionToFileName(sink, i) if verbose: print "%s -> %s" % (f, fn) shutil.move(f, fn) if deleteDirectory: p, _ = os.path.split(fns[0]) p = p.split(os.path.sep) p = p[:-2] p = os.path.sep.join(p) shutil.rmtree(p) return sink
def readDataFiles(filename, x=all, y=all, z=all, **args): """Read data from individual images assuming they are the z slices Arguments: filename (str): file name as regular expression x,y,z (tuple): data range specifications Returns: array: image data """ fpath, fl = readFileList(filename) nz = len(fl) # read first image to get data size and type rz = io.toDataRange(nz, r=z) sz = io.toDataSize(nz, r=z) fn = os.path.join(fpath, fl[rz[0]]) img = io.readData(fn, x=x, y=y) nxy = img.shape data = numpy.zeros(nxy + (sz,), dtype=img.dtype) data[:, :, 0] = img for i in range(rz[0] + 1, rz[1]): fn = os.path.join(fpath, fl[i]) data[:, :, i - rz[0]] = io.readData(fn, x=x, y=y) return data
def fileNameToIlastikOuput(filename): """Converts *ClearMap* file name to an argument string for use with Ilastik headless mode Arguments: filename (str): image file name or expression Returns: str: Ilastik headless ouput specifications Note: The output is formated accroding to the Ilastik pixel calssification output specifications """ if not isValidOutputFileName(filename): raise RuntimeError('Ilastik: file format not compatibel with Ilastik output'); if io.isFileExpression(filename): o = '--output_format="' + io.fileExtension(filename) + ' sequence" '+ \ '--output_filename_format="' + filelist.fileExpressionToFileName(filename, '{slice_index}') + '"'; return o; else: # single file extensionToOuput = {'bmp' : 'bmp', 'gif' : 'gif', 'hdr' : 'hrd', 'jpg' : 'jpg', 'jpeg': 'jpeg','pbm' : 'pbm', 'pgm' : 'pgm', 'png' : 'png', 'pnm' : 'pnm', 'ppm' : 'ppm', 'ras' : 'ras', 'tif' : 'tif', 'tiff': 'tiff','xv' : 'xv', 'h5' : 'hdf5' , 'npy' : 'numpy'}; ext = extensionToOuput[io.fileExtension(filename)]; o = '--output_format="' + ext +'" ' + \ '--output_filename_format="' + filename + '"'; return o;
def readData(filename, x=all, y=all, z=all, **args): """Read data from a single tif image or stack Arguments: filename (str): file name as regular expression x,y,z (tuple): data range specifications Returns: array: image data """ dsize = dataSize(filename) #print("dsize %s" % str(dsize); if len(dsize) == 2: data = tiff.imread(filename, key=0) #print("data.shape %s" % str(data.shape); return io.dataToRange(data.transpose([1, 0]), x=x, y=y) #return io.dataToRange(data, x = x, y = y); else: if z is all: data = tiff.imread(filename) if data.ndim == 2: # data = data data = data.transpose([1, 0]) elif data.ndim == 3: #data = data.transpose([1,2,0]); data = data.transpose([2, 1, 0]) elif data.ndim == 4: # multi channel image #data = data.transpose([1,2,0,3]); data = data.transpose([2, 1, 0, 3]) else: raise RuntimeError('readData: dimension %d not supproted!' % data.ndim) return io.dataToRange(data, x=x, y=y, z=all) else: #optimize for z ranges ds = io.dataSizeFromDataRange(dsize, x=x, y=y, z=z) t = tiff.TiffFile(filename) p = t.pages[0] data = numpy.zeros(ds, dtype=p.dtype) rz = io.toDataRange(dsize[2], r=z) #print("test" #print(rz; #print(dsize for i in range(rz[0], rz[1]): xydata = t.pages[i].asarray() #data[:,:,i-rz[0]] = io.dataToRange(xydata, x = x, y = y); data[:, :, i - rz[0]] = io.dataToRange(xydata.transpose([1, 0]), x=x, y=y) return data
def readData(filename, x = all, y = all, z = all, **args): """Read data from a single tif image or stack Arguments: filename (str): file name as regular expression x,y,z (tuple): data range specifications Returns: array: image data """ dsize = dataSize(filename); #print "dsize %s" % str(dsize); if len(dsize) == 2: data = tiff.imread(filename, key = 0); #print "data.shape %s" % str(data.shape); return io.dataToRange(data.transpose([1,0]), x = x, y = y); #return io.dataToRange(data, x = x, y = y); else: if z is all: data = tiff.imread(filename); if data.ndim == 2: # data = data data = data.transpose([1,0]); elif data.ndim == 3: #data = data.transpose([1,2,0]); data = data.transpose([2,1,0]); elif data.ndim == 4: # multi channel image #data = data.transpose([1,2,0,3]); data = data.transpose([2,1,0,3]); else: raise RuntimeError('readData: dimension %d not supproted!' % data.ndim) return io.dataToRange(data, x = x, y = y, z = all); else: #optimize for z ranges ds = io.dataSizeFromDataRange(dsize, x = x, y = y, z = z); t = tiff.TiffFile(filename); p = t.pages[0]; data = numpy.zeros(ds, dtype = p.dtype); rz = io.toDataRange(dsize[2], r = z); #print "test" #print rz; #print dsize for i in range(rz[0], rz[1]): xydata = t.pages[i].asarray(); #data[:,:,i-rz[0]] = io.dataToRange(xydata, x = x, y = y); data[:,:,i-rz[0]] = io.dataToRange(xydata.transpose([1,0]), x = x, y = y); return data
def copyData(source, sink): """Copy a imaris file from source to sink Arguments: source (str): file name pattern of source sink (str): file name pattern of sink Returns: str: file name patttern of the copy """ io.copyFile(source, sink);
def calculateSubStacks(source, z = all, x = all, y = all, **args): """Calculates the chunksize and other info for parallel processing and returns a list of sub-stack objects The sub-stack information is described in :ref:`SubStack` Arguments: source (str): image source x,y,z (tuple or all): range specifications processes (int): number of parallel processes chunkSizeMax (int): maximal size of a sub-stack chunkSizeMin (int): minial size of a sub-stack chunkOverlap (int): minimal sub-stack overlap chunkOptimization (bool): optimize chunck sizes to best fit number of processes chunkOptimizationSize (bool or all): if True only decrease the chunk size when optimizing verbose (bool): print information on sub-stack generation Returns: list: list of sub-stack objects """ #determine z ranges fs = io.dataSize(source); zs = fs[2]; zr = io.toDataRange(zs, r = z); nz = zr[1] - zr[0]; #calculate optimal chunk sizes nchunks, zranges, zcenters = calculateChunkSize(nz, **args); #adjust for the zrange zcenters = [c + zr[0] for c in zcenters]; zranges = [(zc[0] + zr[0], zc[1] + zr[0]) for zc in zranges]; #create substacks subStacks = []; indexlo = zr[0]; for i in range(nchunks): indexhi = int(round(zcenters[i+1])); if indexhi > zr[1] or i == nchunks - 1: indexhi = zr[1]; zs = zranges[i][1] - zranges[i][0]; subStacks.append({"stackId" : i, "nStacks" : nchunks, "source" : source, "x" : x, "y" : y, "z" : zranges[i], "zCenters" : (zcenters[i], zcenters[i+1]), "zCenterIndices" : (indexlo, indexhi), "zSubStackCenterIndices" : (indexlo - zranges[i][0], zs - (zranges[i][1] - indexhi))}); indexlo = indexhi; # + 1; return subStacks;
def openData3D(dataSource, x = all, y = all, z = all, cleanUp = True): """Open image in ImageJ Arguments: dataSouce (str or array): volumetric image data x, y, z (all or tuple): sub-range specification inverse (bool):invert image Returns: (object): figure handle """ checkImageJInitialized(); if isinstance(dataSource, numpy.ndarray): filename = tempfile.mktemp(suffix = '.mhd', prefix = 'CM_ImageJ'); io.writeData(filename, dataSource, x = x, y = y, z = z); filepath, imagename = os.path.split(filename); imagename = imagename[:-4] + '.raw'; temp = True; dSize = dataSource.shape; else: filename = dataSource; filepath, imagename = os.path.split(filename); temp = False; if len(dSize) == 4: colorImage = True; else: colorImage = False; if colorImage: macro = ('open("%s"); ' % filename) + \ 'run("Stack to Hyperstack...", "order=xyzct channels=%d slices=%d frames=1 display=Color"); ' % (dSize[3], dSize[2]) + \ 'Stack.setDisplayMode("composite"); ' + \ 'run("3D Viewer"); call("ij3d.ImageJ3DViewer.setCoordinateSystem", "false"); ' + \ 'call("ij3d.ImageJ3DViewer.add", "%s", "None", "%s", "0", "true", "true", "true", "1", "0");' % (imagename, imagename); else: macro = ('open("%s");' % filename) + ' run("RGB Color"); run("3D Viewer"); call("ij3d.ImageJ3DViewer.setCoordinateSystem", "false"); ' + \ 'call("ij3d.ImageJ3DViewer.add", "%s", "None", "%s", "0", "true", "true", "true", "1", "0");' % (imagename, imagename); cmd = ImageJBinary + " -eval '%s'" % macro; print 'running: %s' % cmd res = os.system(cmd); if res != 0: raise RuntimeError('openData3D: failed executing: ' + cmd); if cleanUp and temp: os.remove(filename); os.remove(os.path.join(filepath, imagename)); return macro;
def overlayLabel(dataSource, labelSource, sink = None, alpha = False, labelColorMap = 'jet', x = all, y = all, z = all): """Overlay a gray scale image with colored labeled image Arguments: dataSouce (str or array): volumetric image data labelSource (str or array): labeled image to be overlayed on the image data sink (str or None): destination for the overlayed image alpha (float or False): transparency labelColorMap (str or object): color map for the labels x, y, z (all or tuple): sub-range specification Returns: (array or str): figure handle See Also: :func:`overlayPoints` """ label = io.readData(labelSource, x= x, y = y, z = z); image = io.readData(dataSource, x= x, y = y, z = z); lmax = label.max(); if lmax <= 1: carray = numpy.array([[1,0,0,1]]); else: cm = mpl.cm.get_cmap(labelColorMap); cNorm = mpl.colors.Normalize(vmin=1, vmax = int(lmax)); carray = mpl.cm.ScalarMappable(norm=cNorm, cmap=cm); carray = carray.to_rgba(numpy.arange(1, int(lmax + 1))); if alpha == False: carray = numpy.concatenate(([[0,0,0,1]], carray), axis = 0); else: carray = numpy.concatenate(([[1,1,1,1]], carray), axis = 0); cm = mpl.colors.ListedColormap(carray); carray = cm(label); carray = carray.take([0,1,2], axis = -1); if alpha == False: cimage = (label == 0) * image; cimage = numpy.repeat(cimage, 3); cimage = cimage.reshape(image.shape + (3,)); cimage = cimage.astype(carray.dtype); cimage += carray; else: cimage = numpy.repeat(image, 3); cimage = cimage.reshape(image.shape + (3,)); cimage = cimage.astype(carray.dtype); cimage *= carray; return io.writeData(sink, cimage);
def countPointsInRegions(points, labeledImage = DefaultLabeledImageFile, intensities = None, intensityRow = 0, level= None, allIds = False, sort = True, returnIds = True, returnCounts = False, collapse = None): global Label; points = io.readPoints(points); intensities = io.readPoints(intensities); pointLabels = labelPoints(points, labeledImage, level = level, collapse = collapse); if intensities is None: ll, cc = numpy.unique(pointLabels, return_counts = True); cci = None; else: if intensities.ndim > 1: intensities = intensities[:,intensityRow]; ll, ii, cc = numpy.unique(pointLabels, return_counts = True, return_inverse = True); cci = numpy.zeros(ll.shape); for i in range(ii.shape[0]): cci[ii[i]] += intensities[i]; if allIds: lla = numpy.setdiff1d(Label.ids, ll); ll = numpy.hstack((ll, lla)); cc = numpy.hstack((cc, numpy.zeros(lla.shape, dtype = cc.dtype))); if not cci is None: cci = numpy.hstack((cci, numpy.zeros(lla.shape, dtype = cc.dtype))); #cc = numpy.vstack((ll,cc)).T; if sort: ii = numpy.argsort(ll); cc = cc[ii]; ll = ll[ii]; if not cci is None: cci = cci[ii]; if returnIds: if cci is None: return ll, cc else: if returnCounts: return ll, cc, cci; else: return ll, cci else: if cci is None: return cc; else: if returnCounts: return cc, cci; else: return cci;
def joinPoints(results, subStacks = None, shiftPoints = True, **args): """Joins a list of points obtained from processing a stack in chunks Arguments: results (list): list of point results from the individual sub-processes subStacks (list or None): list of all sub-stack information, see :ref:`SubStack` shiftPoints (bool): if True shift points to refer to origin of the image stack considered when range specification is given. If False, absolute position in entire image stack. Returns: tuple: joined points, joined intensities """ nchunks = len(results); pointlist = [results[i][0] for i in range(nchunks)]; intensities = [results[i][1] for i in range(nchunks)]; results = []; resultsi = []; for i in range(nchunks): cts = pointlist[i]; cti = intensities[i]; if cts.size > 0: cts[:,2] += subStacks[i]["z"][0]; iid = numpy.logical_and(subStacks[i]["zCenters"][0] <= cts[:,2] , cts[:,2] < subStacks[i]["zCenters"][1]); cts = cts[iid,:]; results.append(cts); if not cti is None: cti = cti[iid]; resultsi.append(cti); if results == []: if not intensities is None: return (numpy.zeros((0,3)), numpy.zeros((0))); else: return numpy.zeros((0,3)) else: points = numpy.concatenate(results); if shiftPoints: points = points + io.pointShiftFromRange(io.dataSize(subStacks[0]["source"]), x = subStacks[0]["x"], y = subStacks[0]["y"], z = 0); else: points = points - io.pointShiftFromRange(io.dataSize(subStacks[0]["source"]), x = 0, y = 0, z = subStacks[0]["z"]); #absolute offset is added initially via zranges ! if intensities is None: return points; else: return (points, numpy.concatenate(resultsi));
def copyData(source, sink): """Copy an nrrd file from source to sink Arguments: source (str): file name pattern of source sink (str): file name pattern of sink Returns: str: file name of the copy Notes: Todo: dealt with nrdh header files! """ io.copyFile(source, sink)
def copyData(source, sink): """Copy an nrrd file from source to sink Arguments: source (str): file name pattern of source sink (str): file name pattern of sink Returns: str: file name of the copy Notes: Todo: dealt with nrdh header files! """ io.copyFile(source, sink);
def fileNameToIlastikOuput(filename): """Converts *ClearMap* file name to an argument string for use with Ilastik headless mode Arguments: filename (str): image file name or expression Returns: str: Ilastik headless ouput specifications Note: The output is formated accroding to the Ilastik pixel calssification output specifications """ if not isValidOutputFileName(filename): raise RuntimeError("Ilastik: file format not compatibel with Ilastik output") if io.isFileExpression(filename): o = ( '--output_format="' + io.fileExtension(filename) + ' sequence" ' + '--output_filename_format="' + filelist.fileExpressionToFileName(filename, "{slice_index}") + '"' ) return o else: # single file extensionToOuput = { "bmp": "bmp", "gif": "gif", "hdr": "hrd", "jpg": "jpg", "jpeg": "jpeg", "pbm": "pbm", "pgm": "pgm", "png": "png", "pnm": "pnm", "ppm": "ppm", "ras": "ras", "tif": "tif", "tiff": "tiff", "xv": "xv", "h5": "hdf5", "npy": "numpy", } ext = extensionToOuput[io.fileExtension(filename)] o = '--output_format="' + ext + '" ' + '--output_filename_format="' + filename + '"' return o
def isValidOutputFileName(filename): """Checks if the file is a valid format for use with Ilastik ouput Arguments: filename (str): image file name or expression Returns: bool: True if the image file can be written by Ilastik """ if io.isFileExpression(filename): validExtensions = [ "bmp", "gif", "hdr", "jpg", "jpeg", "pbm", "pgm", "png", "pnm", "ppm", "ras", "tif", "tiff", "xv", ] return io.fileExtension(filename) in validExtensions else: validExtensions = [ "bmp", "gif", "hdr", "jpg", "jpeg", "pbm", "pgm", "png", "pnm", "ppm", "ras", "tif", "tiff", "xv", "h5", "npy", ] return io.fileExtension(filename) in validExtensions
def labelPoints(points, labeledImage = DefaultLabeledImageFile, level = None, collapse = None): #points are (y,x,z) -> which is also the way the labeled image is read in #x = points[:,1]; #y = points[:,0]; #z = points[:,2]; x = points[:,0]; y = points[:,1]; z = points[:,2]; nPoint = x.size; pointLabels = numpy.zeros(nPoint, 'int32'); labelImage = io.readData(labeledImage); dsize = labelImage.shape; for i in range(nPoint): #if y[i] >= 0 and y[i] < dsize[0] and x[i] >= 0 and x[i] < dsize[1] and z[i] >= 0 and z[i] < dsize[2]: # pointLabels[i] = labelImage[y[i], x[i], z[i]]; if x[i] >= 0 and x[i] < dsize[0] and y[i] >= 0 and y[i] < dsize[1] and z[i] >= 0 and z[i] < dsize[2]: pointLabels[i] = labelImage[int(x[i]), int(y[i]), int(z[i])]; if collapse is None: pointLabels = labelAtLevel(pointLabels, level); else: pointLabels = labelAtCollapse(pointLabels); return pointLabels;
def test(): """Test Spot Detection Module""" import os import ClearMap.ImageProcessing.SpotDetection as self reload(self) import ClearMap.IO as io import ClearMap.Settings as settings from ClearMap.ImageProcessing.CellDetection import detectCells basedir = settings.ClearMapPath #Default tifs do not load for some reason (tifffile is not happy) but #simply resaving them seems to do the trick. fn = os.path.join(basedir, 'Test/Data/synthetic2/test_iDISCO_\d{3}.tif') #fn = os.path.join(basedir, 'Test/Data/OME/16-17-27_0_8X-s3-20HF_UltraII_C00_xyz-Table Z\d{4}.ome.tif'); img = io.readData(fn) #img = dataset[0:500,0:500,1000:1008]; #img = dataset[600:1000,1600:1800,800:830]; #img = dataset[500:1500,500:1500,800:809]; img = img.astype('int16') #m = sys.modules['iDISCO.ImageProcessing.SpotDetection'] #c = self.detectCells(img); c = self.detectSpots(img, hMax=10, threshold=100, verbose=True) print 'done, found %d cells !' % c[0].shape[0] #test intensities: import numpy x = numpy.random.rand(30, 30, 10) centers = numpy.array([[0, 0, 0], [29, 29, 9]]) i = self.findIntensity(x, centers, boxSize=(1, 1, 1)) print i
def _processSubStack(dsr): """Helper to process stack in parallel""" sf = dsr[0]; pp = dsr[1]; sub = dsr[2]; verbose = dsr[3]; timer = Timer(); pw = ProcessWriter(sub["stackId"]); if verbose: pw.write("processing substack " + str(sub["stackId"]) + "/" + str(sub["nStacks"])); pw.write("file = " + sub["source"]); pw.write("segmentation = " + str(sf)); pw.write("ranges: x,y,z = " + str(sub["x"]) + "," + str(sub["y"]) + "," + str(sub["z"])); img = io.readData(sub["source"], x = sub["x"], y = sub["y"], z = sub["z"]); if verbose: pw.write(timer.elapsedTime(head = 'Reading data of size ' + str(img.shape))); timer.reset(); seg = sf(img, subStack = sub, out = pw, **pp); if verbose: pw.write(timer.elapsedTime(head = 'Processing substack of size ' + str(img.shape))); return seg;
def writeSubStack(filename, img, subStack = None): """Write the non-redundant part of a sub-stack to disk The routine is used to write out images when porcessed in parallel. It assumes that the filename is a patterned file name. Arguments: filename (str or None): file name pattern as described in :mod:`~ClearMap.Io.FileList`, if None return as array img (array): image data of sub-stack subStack (dict or None): sub-stack information, if None write entire image see :ref:`SubStack` Returns: str or array: the file name pattern or image """ if not subStack is None: ii = subStack["zSubStackCenterIndices"][0]; ee = subStack["zSubStackCenterIndices"][1]; si = subStack["zCenterIndices"][0]; else: si = 0; ii = 0; ee = -1; return io.writeData(filename, img[:,:,ii:ee], startIndex = si );
def isValidInputFileName(filename): """Checks if the file is a valid format for use with Ilastik input Arguments: filename (str): image file name or expression Returns: bool: True if the image file can be read by Ilastik """ validExtensions = [ "bmp", "exr", "gif", "jpg", "jpeg", "tif", "tiff", "ras", "png", "pbm", "pgm", "ppm", "pnm", "hdr", "xv", "npy", ] return io.fileExtension(filename) in validExtensions
def dataSize(filename, **args): """Returns size of data in tif file Arguments: filename (str): file name as regular expression x,y,z (tuple): data range specifications Returns: tuple: data size """ t = tiff.TiffFile(filename); d3 = len(t.pages); d2 = t.pages[0].shape; #d2 = (d2[0], d2[1]); if len(d2) == 3: d2 = (d2[2], d2[1], d2[0]); else: d2 = (d2[1], d2[0]); if d3 > 1: dims = d2 + (d3,); else: dims = d2; return io.dataSizeFromDataRange(dims, **args);
def labelPoints(points, labeledImage=DefaultLabeledImageFile, level=None, collapse=None): # points are (y,x,z) -> which is also the way the labeled image is read in # x = points[:,1]; # y = points[:,0]; # z = points[:,2]; x = points[:, 0] y = points[:, 1] z = points[:, 2] nPoint = x.size pointLabels = numpy.zeros(nPoint, "int32") labelImage = io.readData(labeledImage) dsize = labelImage.shape for i in range(nPoint): # if y[i] >= 0 and y[i] < dsize[0] and x[i] >= 0 and x[i] < dsize[1] and z[i] >= 0 and z[i] < dsize[2]: # pointLabels[i] = labelImage[y[i], x[i], z[i]]; if x[i] >= 0 and x[i] < dsize[0] and y[i] >= 0 and y[i] < dsize[1] and z[i] >= 0 and z[i] < dsize[2]: pointLabels[i] = labelImage[int(x[i]), int(y[i]), int(z[i])] if collapse is None: pointLabels = labelAtLevel(pointLabels, level) else: pointLabels = labelAtCollapse(pointLabels) return pointLabels
def thresholdPoints(points, intensities, threshold = 0, row = 0): """Threshold points by intensities""" points, intensities = io.readPoints((points, intensities)); if not isinstance(threshold, tuple): threshold = (threshold, all); if not isinstance(row, tuple): row = (row, row); if intensities.ndim > 1: i = intensities[:,row[0]]; else: i = intensities; iids = numpy.ones(i.shape, dtype = 'bool'); if not threshold[0] is all: iids = numpy.logical_and(iids, i >= threshold[0]); if intensities.ndim > 1: i = intensities[:,row[1]]; if not threshold[1] is all: iids = numpy.logical_and(iids, i <= threshold[1]); return (points[iids, ...], intensities[iids, ...]);
def isValidOutputFileName(filename): """Checks if the file is a valid format for use with Ilastik ouput Arguments: filename (str): image file name or expression Returns: bool: True if the image file can be written by Ilastik """ if io.isFileExpression(filename): validExtensions = ['bmp', 'gif', 'hdr', 'jpg', 'jpeg', 'pbm', 'pgm', 'png', 'pnm', 'ppm', 'ras', 'tif', 'tiff', 'xv']; return io.fileExtension(filename) in validExtensions; else: validExtensions = ['bmp', 'gif', 'hdr', 'jpg', 'jpeg', 'pbm', 'pgm', 'png', 'pnm', 'ppm', 'ras', 'tif', 'tiff', 'xv', 'h5', 'npy']; return io.fileExtension(filename) in validExtensions;
def writePoints(filename, points, indices = True): """Write points as elastix/transformix point file Arguments: filename (str): file name of the elastix point file. points (array or str): source of the points. indices (bool): write as pixel indices or physical coordiantes Returns: str : file name of the elastix point file """ points = io.readPoints(points); #points = points[:,[1,0,2]]; # points in ClearMap (y,x,z) -> permute to (x,y,z) with open(filename, 'w') as pointfile: if indices: pointfile.write('index\n') else: pointfile.write('point\n') pointfile.write(str(points.shape[0]) + '\n'); numpy.savetxt(pointfile, points, delimiter = ' ', newline = '\n', fmt = '%.5e') pointfile.close(); return filename;
def voxelizePixel(points, dataSize = None, weights = None): """Mark pixels/voxels of each point in an image array Arguments: points (array): point data array dataSize (tuple or None): size of the final output data, if None size is determined by maximal point coordinates weights (array or None): weights for each points, if None weights are all 1s. Returns: (array): volumetric data with with points marked in voxels """ if dataSize is None: dataSize = tuple(int(math.ceil(points[:,i].max())) for i in range(points.shape[1])); elif isinstance(dataSize, basestring): dataSize = io.dataSize(dataSize); if weights is None: vox = numpy.zeros(dataSize, dtype=numpy.int16); for i in range(points.shape[0]): if points[i,0] > 0 and points[i,0] < dataSize[0] and points[i,1] > 0 and points[i,1] < dataSize[1] and points[i,2] > 0 and points[i,2] < dataSize[2]: vox[points[i,0], points[i,1], points[i,2]] += 1; else: vox = numpy.zeros(dataSize, dtype=weights.dtype); for i in range(points.shape[0]): if points[i,0] > 0 and points[i,0] < dataSize[0] and points[i,1] > 0 and points[i,1] < dataSize[1] and points[i,2] > 0 and points[i,2] < dataSize[2]: vox[points[i,0], points[i,1], points[i,2]] += weights[i]; return vox;
def copyData(source, sink): """Copy a raw/mhd file pair from source to sink Arguments: source (str): file name of source sink (str): file name of sink Returns: str: file name of the copy """ sourceExt = io.fileExtension(source) sinkExt = io.fileExtension(sink) sources = [source] sinks = [] if sourceExt == 'raw': sources.append(source[:-3] + 'mhd') if sinkExt == 'raw': sinks.append(sink) sinks.append(sink[:-3] + 'mhd') elif sinkExt == 'mhd': sinks.append(sink[:-3] + 'raw') sinks.append(sink) else: raise RuntimeError('copyData: sink extension %s not raw or mhd' % sinkExt) elif sourceExt == 'mhd': sources.append(source[:-3] + 'raw') if sinkExt == 'raw': sinks.append(sink[:-3] + 'mhd') sinks.append(sink) elif sinkExt == 'mhd': sinks.append(sink) sinks.append(sink[:-3] + 'raw') else: raise RuntimeError('copyData: sink extension %s not raw or mhd' % sinkExt) for i in range(2): io.copyData(sources[i], sinks[i]) return sink
def combineSections(animalPath, section, outTableName): alph = ['a','b','c','d','e','f']; for z in range(len(alph)): fName = section+alph[z]; resultDir = os.path.join(animalPath,'Results',fName); tableFN = os.path.join(resultDir,'ResultsTable.csv'); if z == 0: table= pd.read_csv(tableFN,names = ['id','counts','name','subname']); else: temp_table = pd.read_csv(tableFN,names = ['id','counts','name','subname']); table = pd.DataFrame.append(table,temp_table); #Table generation totTable = table.groupby(['id','name'],as_index=False).sum(); totTableFN = os.path.join(animalPath,outTableName); io.writeTable(totTableFN,totTable.values); print('success!')
def _cropParallel(arg): """Cropping helper function to use for parallel cropping of image slices""" fileSource = arg[0] fileSink = arg[1] x = arg[2] y = arg[3] ii = arg[4] nn = arg[5] if ii is not None: pw = ProcessWriter(ii) pw.write("cropData: corpping image %d / %d" % (ii, nn)) # pw.write('%s -> %s' % (fileSource, fileSink)); data = io.readData(fileSource, x=x, y=y) io.writeData(fileSink, data)
def classifyPixel(project, source, sink = None, processingDirectory = None, cleanup = True): """Run pixel classification in headless moded using a trained project file Arguments: project (str): ilastik project .ilp file source (str or array): image source sink (str or array or None): image sink Returns: str or array: classified image sink """ #generate source image file if source is array if isinstance(source, str): inpfile = source; else: #generate temporary file if processingDirectory is None: processingDirectory = tempfile.mkdtemp(); inpfile = os.path.join(processingDirectory, 'ilastik.npy') io.writePoints(inpfile, source.transpose((2,1,0))); if isinstance(sink, str): outfile = sink; else: #outdir = tempfile.mkdtemp(); #outfile = os.path.join(outdir, 'result\d*.tif'); outfile = tempfile.mktemp('.h5'); ilinp = fileNameToIlastikInput(inpfile); ilout = fileNameToIlastikOuput(outfile); args = '--project="' + project + '" ' + ilout + ' ' + ilinp; run(args); #clean up if cleanup and processingDirectory is not None: shutil.rmtree(processingDirectory); if not isinstance(sink, str): sink = readResultH5(outfile); if cleanup: os.remove(outfile); return sink;
def test(): import os; import ClearMap.IO as io import ClearMap.Settings as settings import ClearMap.ImageProcessing.Ilastik as il; reload(il); ilp = os.path.join(settings.ClearMapPath, 'Test/Ilastik/Test.ilp') src = os.path.join(settings.ClearMapPath, 'Test/Data/ImageAnalysis/cfos-substack.tif'); #out = os.path.join(settings.ClearMapPath, 'Test/Data/Ilastik/image.npy'); out = None; #out = os.path.join(settings.ClearMapPath, 'Test/Data/Ilastik/result\d*.tif'); cls = il.classifyPixel(ilp, src, out); print io.dataSize(src) print cls.shape io.writeData('/home/ckirst/result.raw', cls);
def writeData(filename, data, **args): """ Write data into to raw/mhd file pair Arguments: filename (str): file name as regular expression data (array): data to write to raw file Returns: str: file name of mhd file """ fext = io.fileExtension(filename) if fext == "raw": fname = filename[:-3] + 'mhd' else: fname = filename assert (fname[-4:] == '.mhd') meta_dict = {} meta_dict['ObjectType'] = 'Image' meta_dict['BinaryData'] = 'True' meta_dict['BinaryDataByteOrderMSB'] = 'False' numpy_to_datatype = { numpy.dtype('int8'): "MET_CHAR", numpy.dtype('uint8'): "MET_UCHAR", numpy.dtype('int16'): "MET_SHORT", numpy.dtype('uint16'): "MET_USHORT", numpy.dtype('int32'): "MET_INT", numpy.dtype('uint32'): "MET_UINT", numpy.dtype('int64'): "MET_LONG", numpy.dtype('uint64'): "MET_ULONG", numpy.dtype('float32'): "MET_FLOAT", numpy.dtype('float64'): "MET_DOUBLE", } dtype = data.dtype meta_dict['ElementType'] = numpy_to_datatype[dtype] dsize = list(data.shape) #dsize[0:2] = [dsize[1],dsize[0]]; #fix arrays represented as (y,x,z) meta_dict['NDims'] = str(len(dsize)) meta_dict['DimSize'] = ' '.join([str(i) for i in dsize]) meta_dict['ElementDataFile'] = os.path.split(fname)[1].replace( '.mhd', '.raw') writeHeader(fname, meta_dict) pwd = os.path.split(fname)[0] if pwd: data_file = pwd + '/' + meta_dict['ElementDataFile'] else: data_file = meta_dict['ElementDataFile'] writeRawData(data_file, data) return fname
def voxelize(points, dataSize = None, sink = None, voxelizeParameter = None, method = 'Spherical', size = (5,5,5), weights = None): """Converts a list of points into an volumetric image array Arguments: points (array): point data array dataSize (tuple): size of final image sink (str, array or None): the location to write or return the resulting voxelization image, if None return array voxelizeParameter (dict): ========== ==================== =========================================================== Name Type Descritption ========== ==================== =========================================================== *method* (str or None) method for voxelization: 'Spherical', 'Rectangular' or 'Pixel' *size* (tuple) size parameter for the voxelization *weights* (array or None) weights for each point, None is uniform weights ========== ==================== =========================================================== Returns: (array): volumetric data of smeared out points """ if dataSize is None: dataSize = tuple(int(math.ceil(points[:,i].max())) for i in range(points.shape[1])); elif isinstance(dataSize, basestring): dataSize = io.dataSize(dataSize); points = io.readPoints(points); if method.lower() == 'spherical': if weights is None: data = vox.voxelizeSphere(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2]); else: data = vox.voxelizeSphereWithWeights(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2], weights); elif method.lower() == 'rectangular': if weights is None: data = vox.voxelizeRectangle(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2]); else: data = vox.voxelizeRectangleWithWeights(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2], weights); elif method.lower() == 'pixel': data = voxelizePixel(points, dataSize, weights); else: raise RuntimeError('voxelize: mode: %s not supported!' % method); return io.writeData(sink, data);
def makeColorAnnotations(filename, labeledImage=None): if labeledImage is None: labeledImage = DefaultLabeledImageFile li = io.readData(labeledImage) dsize = li.shape lr = numpy.zeros(dsize, dtype=numpy.uint8) lg = lr.copy() lb = lr.copy() global Label maxlabel = max(Label.ids) colarray = numpy.zeros((maxlabel, 3)) for i in Label.ids: colarray[i - 1, :] = Label.color(i) for i in Label.ids: ll = li == i lr[ll] = colarray[i - 1, 0] lg[ll] = colarray[i - 1, 1] lb[ll] = colarray[i - 1, 2] io.writeData(filename + "_r.tif", lr) io.writeData(filename + "_g.tif", lg) io.writeData(filename + "_b.tif", lb) return (lr, lg, lb)
def test(): """Test Elastix module""" import ClearMap.Alignment.Elastix as self reload(self) from ClearMap.Settings import ClearMapPath; import os, numpy p = ClearMapPath; resultdir = os.path.join(p, 'Test/Elastix/Output'); print 'Searching for transformation parameter file in ' + resultdir; pf = self.getTransformParameterFile(resultdir) print 'Found: ' + pf; #replace path in trasform parameter files: self.setPathTransformParameterFiles(resultdir) #initialize self.initializeElastix('/home/ckirst/programs/elastix') self.printSettings() #transform points pts = numpy.random.rand(5,3); print 'Transforming points: ' tpts = self.transformPoints(pts, transformParameterFile = pf, indices = False); print pts print 'Transformed points: ' print tpts #deformation and distance fields df = self.deformationField(transformParameterFile = pf, resultDirectory = None); #df = '/tmp/elastix_output/deformationField.mhd'; import ClearMap.IO as io data = io.readData('/tmp/elastix_output/deformationField.mhd'); ds = self.deformationDistance(data); io.writeData(os.path.join(p, 'Test/Elastix/Output/distances.raw'), ds);
def makeColorAnnotations(filename, labeledImage = None): if labeledImage is None: labeledImage = DefaultLabeledImageFile; li = io.readData(labeledImage); dsize = li.shape; lr = numpy.zeros(dsize, dtype = numpy.uint8); lg = lr.copy(); lb = lr.copy(); global Label; maxlabel = max(Label.ids); colarray = numpy.zeros((maxlabel, 3)); for i in Label.ids: colarray[i-1,:] = Label.color(i); for i in Label.ids: ll = li == i; lr[ll] = colarray[i-1,0]; lg[ll] = colarray[i-1,1]; lb[ll] = colarray[i-1,2]; io.writeData(filename + "_r.tif", lr); io.writeData(filename + "_g.tif", lg); io.writeData(filename + "_b.tif", lb); return (lr,lg,lb);
def copyData(source, sink): """Copy a raw/mhd file pair from source to sink Arguments: source (str): file name of source sink (str): file name of sink Returns: str: file name of the copy """ sourceExt = io.fileExtension(source); sinkExt = io.fileExtension(sink); sources = [source]; sinks = []; if sourceExt == 'raw': sources.append(source[:-3] + 'mhd'); if sinkExt == 'raw': sinks.append(sink); sinks.append(sink[:-3] + 'mhd'); elif sinkExt == 'mhd': sinks.append(sink[:-3] + 'raw'); sinks.append(sink); else: raise RuntimeError('copyData: sink extension %s not raw or mhd' % sinkExt); elif sourceExt == 'mhd': sources.append(source[:-3] + 'raw'); if sinkExt == 'raw': sinks.append(sink[:-3] + 'mhd'); sinks.append(sink); elif sinkExt == 'mhd': sinks.append(sink); sinks.append(sink[:-3] + 'raw'); else: raise RuntimeError('copyData: sink extension %s not raw or mhd' % sinkExt); for i in range(2): io.copyData(sources[i], sinks[i]); return sink;
def overlayPoints(dataSource, pointSource, sink = None, pointColor = [1,0,0], x = all, y = all, z = all): """Overlay points on 3D data and return as color image Arguments: dataSouce (str or array): volumetric image data pointSource (str or array): point data to be overlayed on the image data pointColor (array): RGB color for the overlayed points x, y, z (all or tuple): sub-range specification Returns: (str or array): image overlayed with points See Also: :func:`overlayLabel` """ data = io.readData(dataSource, x = x, y = y, z = z); points = io.readPoints(pointSource, x = x, y = y, z = z, shift = True); #print data.shape if not pointColor is None: dmax = data.max(); dmin = data.min(); if dmin == dmax: dmax = dmin + 1; cimage = numpy.repeat( (data - dmin) / (dmax - dmin), 3); cimage = cimage.reshape(data.shape + (3,)); if data.ndim == 2: for p in points: # faster version using voxelize ? cimage[p[0], p[1], :] = pointColor; elif data.ndim == 3: for p in points: # faster version using voxelize ? cimage[p[0], p[1], p[2], :] = pointColor; else: raise RuntimeError('overlayPoints: data dimension %d not suported' % data.ndim); else: cimage = vox.voxelize(points, data.shape, method = 'Pixel'); cimage = cimage.astype(data.dtype) * data.max(); data.shape = data.shape + (1,); cimage.shape = cimage.shape + (1,); cimage = numpy.concatenate((data, cimage), axis = 3); #print cimage.shape return io.writeData(sink, cimage);
def removeBackground(img, removeBackgroundParameter = None, size = None, save = None, verbose = False, subStack = None, out = sys.stdout, **parameter): """Remove background via subtracting a morphological opening from the original image Background removal is done z-slice by z-slice. Arguments: img (array): image data removeBackGroundParameter (dict): ========= ==================== =========================================================== Name Type Descritption ========= ==================== =========================================================== *size* (tuple or None) size for the structure element of the morphological opening if None, do not correct for any background *save* (str or None) file name to save result of this operation if None dont save to file *verbose* (bool or int) print / plot information about this step ========= ==================== =========================================================== subStack (dict or None): sub-stack information verbose (bool): print progress info out (object): object to write progress info to Returns: array: background corrected image """ size = getParameter(removeBackgroundParameter, "size", size); save = getParameter(removeBackgroundParameter, "save", save); verbose = getParameter(removeBackgroundParameter, "verbose", verbose); if verbose: writeParameter(out = out, head = 'Background Removal:', size = size, save = save); if size is None: return img; img = io.readData(img); timer = Timer(); # background subtraction in each slice se = structureElement('Disk', size).astype('uint8'); for z in range(img.shape[2]): #img[:,:,z] = img[:,:,z] - grey_opening(img[:,:,z], structure = structureElement('Disk', (30,30))); #img[:,:,z] = img[:,:,z] - morph.grey_opening(img[:,:,z], structure = self.structureELement('Disk', (150,150))); img[:,:,z] = img[:,:,z] - cv2.morphologyEx(img[:,:,z], cv2.MORPH_OPEN, se) if not save is None: writeSubStack(save, img, subStack = subStack) if verbose > 1: plotTiling(10*img); if verbose: out.write(timer.elapsedTime(head = 'Background') + '\n'); return img