Example #1
0
def voronoi2dxy(xy,framenumber,maximumdistance,radii, save=True):
    shelveName="frame%d.shelve"%framenumber
    import os
    import shelve

    if os.path.isfile(shelveName):
        print ("File", shelveName, "already exists")
        d=shelve.open(shelveName)
        return d['cells']
    else:
        import pyvoro
        coords=np.array(xy)
        # print coords
        xlo=-100#np.floor(coords[:,0].min())-maximumdistance
        ylo=-100#np.floor(coords[:,0].min())-maximumdistance
        xhi=800#np.ceil(coords[:,0].max())+maximumdistance
        yhi=800#np.ceil(coords[:,0].max())+maximumdistance
        bounds=[[xlo,xhi], [ylo,yhi]]
        # print bounds
      
        try:
            cells=pyvoro.compute_2d_voronoi(coords,bounds,maximumdistance, periodic=[False,False], radii=radii, z_height=200)
        except Exception as e:
            print ("Exception:",e)
            print ("Attempting Reduced Radii Voronoi")
            cells=pyvoro.compute_2d_voronoi(coords,bounds,maximumdistance, periodic=[False,False], radii=radii*0.9, z_height=200)
        # if save:
            
        #     d=shelve.open(shelveName)
        #     d['cells']=cells
        #     d.close()

        return cells
def DefectStats(frames):
    #stats to return
    num_def, num_def_pts, num_5f_disc, num_7f_disc, num_disl, num_disl_pairs = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

    #loop over every frame and average stats regarding defects
    for frame in frames:
        voro = pyvoro.compute_2d_voronoi(
            frame['coords'],  # point positions
            [[0.0, frame['L']], [0.0, frame['L']]],  # limits
            4.0,  # block size
            periodic=[True, True])

        #generate the defect cells data structure
        defect_cells = DefectCells(voro)

        #generate the defect clusters
        defect_clusters = DefectClusters(defect_cells)

        #get numbers regarding the various types of defects
        if any(defect_clusters):
            num_def = num_def + float(len(defect_clusters))
            num_def_pts = num_def_pts + float(sum(defect_clusters))
            num_5f_disc = num_5f_disc + float(
                sum(all(defect_clusters == array([1, 0]), axis=1)))
            num_7f_disc = num_7f_disc + float(
                sum(all(defect_clusters == array([0, 1]), axis=1)))
            num_disl = num_disl + float(
                sum(all(defect_clusters == array([1, 1]), axis=1)))
            num_disl_pairs = num_disl_pairs + float(
                sum(all(defect_clusters == array([2, 2]), axis=1)))

    num_frames = float(len(frames))
    return (num_5f_disc / num_frames, num_7f_disc / num_frames,
            num_disl / num_frames, num_disl_pairs / num_frames,
            num_def / num_frames, num_def_pts / num_frames)
Example #3
0
def build_adjacent_set_2d(locations,distance_percentage=0.1):
    n,m = locations.shape
    
    min_locations = np.min(locations,axis=0)
    max_locations = np.max(locations,axis=0)
    
    range_locations = max_locations - min_locations
    
    boundary_distance = range_locations * distance_percentage

    grid_box = [
            [min_locations[0]-boundary_distance[0],max_locations[0]+boundary_distance[0]],
            [min_locations[1]-boundary_distance[1],max_locations[1]+boundary_distance[1]]
        ]


    cells = pyvoro.compute_2d_voronoi(locations,grid_box,1.0)

    neiList = defaultdict(set)

    for i in xrange(n):
        for face in cells[i]["faces"]:
            ajd_cell = face["adjacent_cell"]
            if ajd_cell >= 0:
                neiList[i].add(ajd_cell)

        

    return (neiList, cells)
Example #4
0
def smoothedRandomVoronoi(n_tiles, steps, seed=None):
    if seed is not None: random.seed(seed)
    seeds = [[random.random(), random.random()] for _ in range(n_tiles)]
    for _ in range(steps + 1):
        cells = pyvoro.compute_2d_voronoi(seeds, [[0.0, 1.0], [0.0, 1.0]],
                                          2.0,
                                          radii=[1.0, 0.0])
        seeds = [polygon.centroid([c['vertices']]) for c in cells]

    return cells
def BOP(frames):
    N = len(frame['coords'][0])
    magnitudes = []
    phases = []
    Rs = []
    Is = []
    #loop over every frame
    for frame in frames:
        voro = pyvoro.compute_2d_voronoi(
            frame['coords'],  # point positions
            [[0.0, frame['L']], [0.0, frame['L']]],  # limits
            4.0,  # block size
            periodic=[True, True])
        voro = array(voro)

        #loop over the cells and use nearest neighbor details to calculate BOP
        R_tot, I_tot = 0.0, 0.0
        for i in range(len(voro)):
            ri = voro[i]['original']
            nbrs = voro[i]['faces']
            n = len(nbrs)
            R, I = 0.0, 0.0
            for nbr in nbrs:
                j = nbr['adjacent_cell']
                rj = voro[j]['original']
                rij = ri - rj
                rij = rij - rint(rij / frame['L']) * frame['L']
                c = rij[0] / norm(rij)
                s = rij[1] / norm(rij)
                Rl = (c**
                      6) - 15.0 * (c**4) * (s**2) + 15.0 * (c**2) * (s**4) - (
                          s**6)
                Il = 6.0 * (c**5) * s - 20.0 * (c**3) * (s**3) + 6.0 * c * (s**
                                                                            5)
                R = R + Rl
                I = I + Il
            #single particle average of the local order parameter
            R = R / float(n)
            I = I / float(n)

            #calculate the whole frame real and imaginary components
            R_tot = R_tot + R
            I_tot = I_tot + I

        Rs.append(R_tot)
        Is.append(I_tot)

    #global system averages
    R_avg, I_avg = mean(Rs), mean(Is)
    Psi_avg = sqrt(R_avg * R_avg + I_avg * I_avg)
    R_var, I_var = var(Rs), var(Is)
    Psi_var = R_var + I_var

    return (Psi_avg / float(N), Psi_var / float(N))
Example #6
0
    def setupGrainstructure(self):
        #see http://pypi.python.org/pypi/pyvoro/1.3.2
        self.cells = pyvoro.compute_2d_voronoi(self.seeds, self.box, 2.0)
        for cell in self.cells:
            coordinates = cell['vertices']
            for coordinate in coordinates:
                #print "before",coordinate
                if coordinate[0] < self.boundarylayer * self.width:

                    coordinate[0] = self.boundarylayer * self.width

                elif coordinate[0] > (1 - self.boundarylayer) * self.width:
                    coordinate[0] = (1 - self.boundarylayer) * self.width
                #print "after",coordinate
        self.setupVolfracs()
Example #7
0
 def setupGrainstructure(self):
     #see http://pypi.python.org/pypi/pyvoro/1.3.2
     self.cells=pyvoro.compute_2d_voronoi(self.seeds,self.box,2.0)
     for cell in self.cells:
         coordinates=cell['vertices']
         for coordinate in coordinates:
             #print "before",coordinate
             if coordinate[0]<self.boundarylayer*self.width:
                
                 coordinate[0]=self.boundarylayer*self.width
                 
             elif coordinate[0]>(1-self.boundarylayer)*self.width:
                 coordinate[0]=(1-self.boundarylayer)*self.width
             #print "after",coordinate
     self.setupVolfracs()
Example #8
0
    def voronoi_tessellation_2d(self,Frame,radii, periodic):
        coords=Frame.r[:,:2]
        box=Frame.boxinfo
        print coords.shape
        cells=pyvoro.compute_2d_voronoi(coords, [box[0],box[1]],coords.shape[0],  periodic=periodic)
        
        # area of the disks
        self.areas=radii**2*np.pi
        # compute area fraction per cell
        self.volumes=np.zeros(Frame.N)

        for i in xrange(Frame.N):
            # local packing fraction per cell
            self.volumes[i]=cells[i]['volume']

        return cells 
Example #9
0
    def _process_leaflet(self, atoms, celldim):

        cells = pyvoro.compute_2d_voronoi(atoms.positions[:, :2],
                                          celldim,
                                          2.0,
                                          periodic=[True, True])

        # Calculate the area per each residue type
        areas = {resname: 0 for resname in self.resnames}
        nres = {resname: 0.0 for resname in self.resnames}
        for atom, cell in zip(atoms, cells):
            areas[atom.resname] += cell["volume"]
            nres[atom.resname] += 1.0
        areaout = np.asarray(
            [areas[resname] / nres[resname] for resname in self.resnames])

        # Calculate the neighbors
        vsets = [
            set((np.round(v[0], 3), np.round(v[1])) for v in cell["vertices"])
            for cell in cells
        ]
        emptyset = set([])
        neighbors = {respair: 0 for respair in self.respairs}
        npairs = {respair: 0 for respair in self.respairs}
        for i, ivertices in enumerate(vsets):
            counts = {respair: 0 for respair in self.respairs}
            for j, jvertices in enumerate(vsets[i + 1:], i + 1):
                if ivertices & jvertices != emptyset:
                    iresname = atoms[i].resname
                    jresname = atoms[j].resname
                    if iresname + "-" + jresname in neighbors:
                        counts[iresname + "-" + jresname] += 1
                    else:
                        counts[jresname + "-" + iresname] += 1
            for respair in self.respairs:
                if counts[respair] > 0:
                    npairs[respair] += 1.0
                    neighbors[respair] += counts[respair]
        neighout = np.asarray([
            neighbors[respair] / npairs[respair] for respair in self.respairs
        ])

        return areaout, neighout
Example #10
0
def voronoi2d(Frame,maximumdistance,radii, save=True):
    shelveName="frame%d.shelve"%Frame.timeframe
    import os
    import shelve

    if os.path.isfile(shelveName):
        print ("File", shelveName, "already exists")
        d=shelve.open(shelveName)
        return d['cells']
    else:
        coords=Frame.r[:,:2]
        import pyvoro
        cells=pyvoro.compute_2d_voronoi(coords,Frame.boxinfo[:2],maximumdistance, periodic=[True,True], radii=radii)
        if save:
            
            d=shelve.open(shelveName)
            d['cells']=cells
            d.close()

        return cells
Example #11
0
def dovoro(dim_x, dim_y, cells):
    #    import matplotlib
    #    import matplotlib.pyplot as plt
    import pyvoro
    import numpy as np

    dots_num = cells
    vol = dim_x * dim_y
    colors = np.random.rand(dots_num, 3)  # or predefined

    dots = np.random.rand(dots_num, 2)
    # make color map (unnecessary for just random colorization)
    color_map = {tuple(coords): color for coords, color in zip(dots, colors)}

    cells = pyvoro.compute_2d_voronoi(
        dots,  # point positions, 2D vectors this time.
        [[0.0, dim_x], [0.0, dim_y]],  # box size
        2.0  # block size
    )

    # colorize

    vol_sum = 0.0
    cell_count = 0
    for i, cell in enumerate(cells):
        vol_sum += cell['volume']
        cell_count += 1
        print(i, cell['volume'])
#        polygon = cell['vertices']
#        plt.fill(*zip(*polygon), color = color_map[tuple(cell['original'])], alpha=0.5)

#    plt.plot(dots[:,0], dots[:,1], 'ko')
#    plt.xlim(-0.1, 1.1)
#    plt.ylim(-0.1, 1.1)
#
#    plt.show()
    return (cell_count, vol_sum)
Example #12
0
nran = 1000
bs = 1500.
msep = (bs**nd / nran)**(1. / nd)

#rbar = np.sqrt(bs**nd/(2.*np.pi*nran))
rbar = bs**nd / nran

ranpoints = bs * np.random.uniform(size=(nran, nd))
limits = [[0., bs], [0., bs]]  #,[0.,bs]]

points1 = ranpoints
#plt.scatter(points1[:,0],points1[:,1])
#plt.show()

voro = pyvoro.compute_2d_voronoi(ranpoints,
                                 limits,
                                 msep,
                                 periodic=[True, True])  #,True])

#################
#Calculo del Pk
################
#dcat = ArrayCatalog(Table(ranpoints,names=['x','y']),BoxSize=bs)
#dcat['Position'] = transform.StackColumns(dcat['x'], dcat['y'])

#print 'Calculating P(k) - Before'
#real_mesh = dcat.to_mesh(compensated=True, window='tsc', position='Position', Nmesh=256)
#r = FFTPower(real_mesh, mode='1d',dk=0.05)
#Pk1 = r.power

vol = [v.get('volume') for v in voro]
#print len(vol)
        circles[i,2]=float(cl[2])/2*coef
        i+=1
        circles[i,0]=float(cl[0])-1
        circles[i,1]=float(cl[1])
        circles[i,2]=float(cl[2])/2*coef
        i+=1

radius=circles[:,2].tolist()
circles_input=circles[:,0:2].tolist()
#radius=[0.1,0.1]
#circles_input=[[0.3,0.6],[0.7,0.3]]
x_box=[-1, 2]
y_box=[-1, 2]
cells = pyvoro.compute_2d_voronoi(
  circles_input, # point positions, 2D vectors this time.
  [x_box, y_box], # box size, again only 2D this time.
  0.1, # block size; same as before.
  radii=radius # particle radii -- optional and keyword-compatible.
)
center=[ii['original'] for ii in cells]
polyline=[]
triangle=[]
volume=[]
volume_radius=[]#there are nine copies of the matrix, we need to record the radii for what we are interested
id_1=[]#record the cell id 
speci_rec=[]#record the species
visited=[]#record the grid is visited or not
ii=0
for i in cells:
    if center[ii][0]>0 and center[ii][0]<1 and center[ii][1]>0 and center[ii][1]<1:
        for j in range(0,len(i['vertices'])):
            polyline=polyline+[(i['vertices'][j%len(i['vertices'])],i['vertices'][(j+1)%len(i['vertices'])])]
if __name__ == "__main__":

    all_data = di.get_data("test_data.txt",7,sep=" ")

    id1 = all_data[0]
    type1 = all_data[1]
    x = all_data[2]
    y = all_data[3]

    radii1 = np.zeros(len(type1))
    
    for (i,value1) in zip(range(len(type1)),type1):
        if value1 == 1:
            radii1[i] = 0.7
        else:
            radii1[i] = 0.5

    cells = pyvoro.compute_2d_voronoi(
        zip(x,y), # point positions, 2D vectors this time.
        [[0.0, 60.0], [0.0, 60.0]], # box size, again only 2D this time.
        2.0, # block size; same as before.
        radii=radii1, # particle radii -- optional and keyword-compatible.
        periodic=[1,1] #periodic boundary conditions
    )

    #plotvor(cells,all_data,radii1)

    print cells[0]

    print vor_stats(cells)
Example #15
0
    def get_polygons(self, image, model, args):
        ''' partition image into regions producing low-res polygons
        This method does not guarantee full image partitioning by removing the uncertain regions
        '''

        Worig, Horig = image.size()
        num_points = int(args.get('points', 100))
        border = float(args.get('border', 5))
        border = int(round(border * np.mean([Worig, Horig]) / 100.0))
        pts, num_points_x, num_points_y, sw, sh = distribute_points(
            num_points, Worig, Horig, border, equal=False, return_all=True)

        # estimate superpixel size
        W = self.side
        sx = 1.0
        if max(Worig, Horig) > W:
            sx = float(W) / max(Worig, Horig)
        sw = int(
            round(sw * sx)
        )  # this provides an approximate number of centroids as requested

        # load SLIC super-pixel segmented image
        log.debug('Regions classifier: requesting superpixels of size: %s', sw)
        pix = image.pixels(
            operations=
            'slice=,,1,1&resize=%s,%s,BC,MX&depth=8,d,u&transform=superpixels,%s,0.8&format=tiff'
            % (self.side, self.side, sw))
        W, H = pix.shape[0:2]

        # get regional centroids
        label_offset = 1  # region prop function uses 0 as background, we bump the class number and later subtract
        segments = skimage.measure.regionprops(pix + label_offset, cache=True)
        num_segs = len(segments)
        log.debug('Regions classifier: segmented the image into %s segments',
                  num_segs)
        if num_segs < 1:
            raise ConnoisseurException(responses.NO_CONTENT,
                                       'Regions classifier: no results')

        # compute scaling factors
        sx = 1.0
        sy = 1.0
        if Worig != W or Horig != H:
            sx = float(W) / Worig
            sy = float(H) / Horig
            log.debug(
                'Regions classifier: Original image is larger, use scaling factors: %s,%s',
                sx, sy)

        # scale params to resized image
        border = int(round(border * sx))

        # get regional centroids in original image space
        points = []
        for i, s in enumerate(segments):
            x, y = s.centroid
            if x > border and y > border and x <= W - border and y <= H - border:
                points.append((x / sx, y / sy))

        # classify regional centroids

        # load image
        #pim = image.pixels(operations='slice=,,1,1&resize=6000,6000,BC,MX&depth=8,d,u&format=png')
        #W,H = pim.shape[0:2]
        adapter = model.create_adapter_pixels(model=model,
                                              args=args,
                                              image=image)

        # classify points
        results = []
        for x, y in points:
            #pix = image_patch(pim, int(x), int(y), model.db_patch_width, model.db_patch_height)
            pix = adapter.get_adapted_image_patch(gob=point(x=y, y=x))
            out_class, goodness = model.classify(pix)
            label, accuracy, ignored = get_class_info(model,
                                                      out_class,
                                                      at_goodness=0)
            confidence = get_sample_confidence(accuracy, goodness)
            results.append({
                'x': x,
                'y': y,
                'id': out_class,
                'label': label,
                'ignored': ignored,
                'accuracy': accuracy,
                'goodness': goodness,
                'confidence': confidence,
            })

        if len(results) < 1:
            raise ConnoisseurException(responses.NO_CONTENT,
                                       'Regions classifier: no results')

        #------------------------------------------------------
        # compute Voronoi polygons
        #------------------------------------------------------
        log.debug('Regions classifier: computing Voronoi')
        points = [[r['x'], r['y']] for r in results]
        bounds = [[0.0, Worig], [0.0, Horig]]
        #radii  = [r['w'] for r in results]

        # log.debug('Regions classifier: bounds %s', bounds)
        # log.debug('Regions classifier: points %s', points)

        cells = pyvoro.compute_2d_voronoi(
            points,
            bounds,
            2.0,  # block size
            #radii = radii
        )

        log.debug('Regions classifier: producing polygons')
        for i in range(len(results)):
            results[i]['gob'] = 'polygon'
            results[i]['vertex'] = [(p[0], p[1]) for p in cells[i]['vertices']]
            results[i]['area'] = cells[i]['volume']

        return results
Example #16
0
def voronoi_cells(pos, node_genes, alpha=40, bounds=(750, 750)):
    """ Create a dict of room_id -> cell object with vertic information
    """
    room_ids = []
    room_xy = []
    room_sizes = []

    derp = []

    expanded_offset = 30

    for ID, (x, y) in pos.items():
        room_ids.append(ID)
        xi = min(bounds[0] - 1, max(0, int(x)))
        yi = min(bounds[1] - 1, max(0, int(y)))
        room_xy.append((xi, yi))
        r = node_genes[ID].size
        room_sizes.append(r)

        segment_length = 20.0
        circumference = 2 * pi * r
        steps = max(5, int(circumference / segment_length))
        derp.append((x, y))
        for i in range(steps):
            a = (i / float(steps)) * pi * 2.0
            derp.append((x + cos(a) * r, y + sin(a) * r))
            if r > segment_length:
                derp.append((x + cos(a) * r / 2, y + sin(a) * r / 2))

    hull = concave2(derp, alpha)[0]
    hull = [derp[i] for i in hull]

    expanded_hull1 = polygon.offset(hull, expanded_offset)

    if polygon.shoelace(hull) > 0:
        hull.reverse()

    radii = [node_genes[ID].size for ID in room_ids]

    for (x, y), r in zip(expanded_hull1, derp):
        if x > 0 and y > 0 and x < bounds[0] and y < bounds[1]:
            room_xy.append((int(x), int(y)))
            radii.append(expanded_offset)

    try:
        cells = pyvoro.compute_2d_voronoi(
            [(x, y) for x, y in room_xy],
            [[0.0, bounds[0]], [0.0, bounds[1]]],
            2.0,  # Block size.
            radii)
    except voroplusplus.VoronoiPlusPlusError as e:
        raise e

    formatted_cells = dict()
    # expanded_hull_i = [(int(x), int(y)) for x, y in expanded_hull1]

    for i, room_id in enumerate(room_ids):
        cell = cells[i]
        verts_i = [(int(round(x)), int(round(y))) for x, y in cell['vertices']]
        formatted_cells[room_id] = verts_i

    return formatted_cells, {'expanded_hull': expanded_hull1, 'hull': hull,\
                             'cells': formatted_cells.values(), 'xy': room_xy, 'r': room_sizes}
Example #17
0
import csv
import pyvoro
from stl import mesh

with open("./points.csv") as f:
    records = list(csv.reader(f))

points = [dict(zip(records[0], map(float, record))) for record in records[1:]]

vecs = [[point[k] for k in "lon lat".split(" ")] for point in points]
transposed = zip(*vecs)
borders = zip(*[map(f, transposed) for f in [min, max]])[:2]
world_diameter = ((borders[0][1] - borders[0][0])**2 +
                  (borders[1][1] - borders[1][0])**2)**.5
cells = pyvoro.compute_2d_voronoi(vecs, [[least - 1, most + 1]
                                         for least, most in borders],
                                  world_diameter,
                                  z_height=world_diameter)

assert len(points) == len(cells)


def square_distance_to_cell(point, cell):
    dlon = point["lon"] - cell["original"][0]
    dlat = point["lat"] - cell["original"][1]
    return dlon**2 + dlat**2


def compare_cell_distances(point, a, b):
    delta = square_distance_to_cell(point, a) - square_distance_to_cell(
        point, b)
    if delta > 0: return 1
Example #18
0
import pyvoro
import numpy as np
import matplotlib.pyplot as plt
 
N = 30                              # number of points to generate
points = np.random.rand(N, 2) * 10  # point locations
radii = np.ones((N,)) * 0.01        # point radii ("weights")
 
def plotvor(cells):
    plt.figure(figsize=(20,20))
    plt.xlim((0,10))
    plt.ylim((0,10))
    plt.axes().set_aspect('equal', 'datalim')
    
    plt.hold(True)
    for cell in cells:
        plt.scatter(cell["original"][0], cell["original"][1])
        vertices = np.array(cell["vertices"])
        vertices = np.concatenate((vertices,
            cell["vertices"][0].reshape((1,2))))
        plt.plot(vertices[:,0], vertices[:,1], 'b-')
    plt.show()
 
cells = pyvoro.compute_2d_voronoi(
    points,
    [[0.0, 10.0], [0.0, 10.0]], # box size
    0.5,                        # block size
    radii = radii)
 
plotvor(cells)
Example #19
0
    def classify(self, image, model, args):
        ''' partition image into regions producing low-res polygons
        This method guarantees full image partitioning covering the area of the uncertain samples
        '''

        Worig, Horig = image.size()
        num_points = int(args.get('points', 100))
        border = float(args.get('border', 5))
        border = int(round(border * np.mean([Worig, Horig]) / 100.0))
        my_goodness = float(args.get('goodness',
                                     model.minimum_goodness * 100)) / 100.0
        my_accuracy = float(args.get('accuracy', model.minimum_accuracy * 100))
        my_confidence = float(args.get('confidence', 0))

        # uniform sampling
        pts, num_points_x, num_points_y, sw, sh = distribute_points(
            num_points, Worig, Horig, border, equal=False, return_all=True)

        # load image
        # pim = image.pixels(operations='slice=,,1,1&resize=6000,6000,BC,MX&depth=8,d,u&format=png')
        # W,H = pim.shape[0:2]

        # # compute scaling factor
        # sx=1.0; sy=1.0
        # if Worig>W or Horig>H:
        #     sx = float(W) / Worig
        #     sy = float(H) / Horig
        #     log.debug('Classify: Original image is larger, use scaling factors: %s,%s', sx, sy)

        adapter = model.create_adapter_pixels(model=model,
                                              args=args,
                                              image=image)

        # classify points
        results = []
        for x, y in pts:
            #pix = image_patch(pim, int(x*sx), int(y*sy), model.db_patch_width, model.db_patch_height)
            pix = adapter.get_adapted_image_patch(gob=point(x=y, y=x))
            out_class, goodness = model.classify(pix)
            label, accuracy, ignored = get_class_info(model,
                                                      out_class,
                                                      at_goodness=my_goodness)
            confidence = get_sample_confidence(accuracy, goodness)

            if goodness >= my_goodness and accuracy >= my_accuracy and confidence >= my_confidence and ignored is False:
                #print '%s,%s classified as "%s" with %s goodness score'%(x, y, predicted_class, goodness)
                #log.debug('%s,%s classified as "%s" with %s goodness score'%(x, y, predicted_class, goodness))
                results.append({
                    'x': x,
                    'y': y,
                    'id': out_class,
                    'goodness': goodness,
                })

        if len(results) < 1:
            raise ConnoisseurException(responses.NO_CONTENT,
                                       'Regions classifier: no results')

        #------------------------------------------------------
        # init dense grid with measurements
        #------------------------------------------------------

        label_offset = 1  # region prop function uses 0 as background, we bump the class number and later subtract

        def img_to_pp(p):
            return (int(round(
                (p[0] - border) / sw)), int(round((p[1] - border) / sh)))

        def pp_to_img(p):
            return (int(round(p[0] * sw + border)),
                    int(round(p[1] * sh + border)))

        # create a grid with class labels
        Gi = num_points_y
        Gj = num_points_x + 1
        G = np.zeros((Gi, Gj), dtype=np.uint8)
        C = np.zeros((Gi, Gj), dtype=np.double)
        for r in results:
            x, y = img_to_pp((r['x'], r['y']))
            idx = r['id']
            goodness = r['goodness']
            G[y, x] = idx + label_offset
            C[y, x] = goodness

        #skimage.io.imsave(grid_file, G)

        #------------------------------------------------------
        # compute quasi-convex region centroids
        #------------------------------------------------------

        results = []
        for idx in range(model.number_classes_in_model):
            GG = np.zeros((Gi, Gj), dtype=np.uint8)
            for i in range(0, Gi):
                for j in range(0, Gj):
                    if G[i, j] == idx + label_offset:
                        GG[i, j] = 255
                    else:
                        GG[i, j] = 0
            #grid_flt_file = 'D:\\develop\\caffe\\regions\\grid_%s.tif'%(idx)
            #skimage.io.imsave(grid_flt_file, GG)

            # ensure boundary is background
            GGG = np.zeros((Gi + 2, Gj + 2), dtype=np.uint8)
            GGG[1:Gi + 1, 1:Gj + 1] = GG
            distance = distance_transform_edt(GGG)
            distance = distance[1:Gi + 1, 1:Gj + 1]

            #grid_flt_file = 'D:\\develop\\caffe\\regions\\grid_%s_distance.tif'%(idx)
            #skimage.io.imsave(grid_flt_file, distance)

            #local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((3, 3)), labels=GG)
            local_maxi = corner_peaks(distance,
                                      indices=False,
                                      footprint=np.ones((3, 3)),
                                      labels=GG)
            markers = ndi.label(local_maxi)[0]
            labeled = watershed(-distance, markers, mask=GG)
            segments = skimage.measure.regionprops(labeled,
                                                   intensity_image=C,
                                                   cache=True)

            for i, r in enumerate(segments):
                c = r.centroid
                w = r.area
                #w = r.convex_area
                #goodness = r.max_intensity
                goodness = r.mean_intensity
                label, accuracy, ignored = get_class_info(model,
                                                          out_class,
                                                          at_goodness=0)
                confidence = get_sample_confidence(accuracy, goodness)

                y, x = pp_to_img(c)
                out_class = idx
                results.append({
                    'x': x,
                    'y': y,
                    'w': w,
                    'area': w,
                    'area_seg': w,
                    'id': out_class,
                    #'color': get_color_html(out_class),
                    'label': label,
                    'accuracy': accuracy,
                    'goodness': goodness,
                    'confidence': confidence,
                })

        if len(results) < 1:
            raise ConnoisseurException(responses.NO_CONTENT,
                                       'Region classifier: no results')

        #------------------------------------------------------
        # compute Voronoi polygons
        #------------------------------------------------------

        points = [[r['x'], r['y']] for r in results]
        bounds = [[0.0, Worig], [0.0, Horig]]
        radii = [r['w'] for r in results]

        cells = pyvoro.compute_2d_voronoi(
            points,
            bounds,
            2.0,  # block size
            radii=radii)

        for i in range(len(results)):
            results[i]['gob'] = 'polygon'
            results[i]['vertex'] = [(p[0], p[1]) for p in cells[i]['vertices']]
            results[i]['area'] = cells[i]['volume']

        # hierarchical passes over samples whose classes have child models

        # return results
        return DataToken(data=results, mime='table/gobs', name='Substrate')