Skip to content

Commit

Permalink
edits with Chee
Browse files Browse the repository at this point in the history
  • Loading branch information
boris-kz committed Dec 27, 2024
1 parent ae9e138 commit d256dca
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 54 deletions.
24 changes: 23 additions & 1 deletion frame_2D_alg/deprecated/24.12.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,29 @@ def sum_tft(HE, He, rev=0, fc=0):
else:
HE.tft = deepcopy(He.tft) # init empty


'''
if nest: # root_ in distance-layered cluster, or for Ns only, graph membership is still exclusive?
root = [root] + (node_[0].root if isinstance(node_[0].root, list) else [node_[0].root])
else: root = root
'''
def append_(HE, He): # unpack HE lft tree down to He.fd_ and append He, or sum if fork exists, if He.fd_

fork = root = HE
add = 1
if He.fd_:
for fd in He.fd_: # unpack top-down, each fd was assigned by corresponding level of roots
if len(fork.lft) > fd:
root = fork; fork = fork.lft[fd] # keep unpacking
else:
He = He.copy_(); fork.lft += [He]; add = 0 # fork was empty, init with He
break
if add:
fork.add_tree(He, root) # add in fork initialized by feedback
else:
HE.lft += [He] # if fd_ is empty, we just need to append it?

He.root = root
fork.Et += He.Et
if not fork.tft:
fork.tft = deepcopy(He.tft) # if init from sum mlink_

35 changes: 20 additions & 15 deletions frame_2D_alg/vectorize_edge_blob/agg_recursion.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from functools import reduce
from frame_blobs import frame_blobs_root, intra_blob_root, imread
from comp_slice import comp_latuple, comp_md_
from vect_edge import feedback, comp_node_, comp_link_, sum2graph, get_rim, CH, CG, ave, ave_d, ave_L, vectorize_root, comp_area, extend_box, val_
from vect_edge import feedback, comp_node_, comp_link_, sum2graph, get_rim, CH, CG, ave, ave_L, vectorize_root, comp_area, extend_box, val_
'''
Cross-compare and cluster Gs within a frame, potentially unpacking their node_s first,
alternating agglomeration and centroid clustering.
Expand All @@ -22,29 +22,34 @@ def cross_comp(root): # breadth-first node_,link_ cross-comp, connect.clusterin
N_,L_,Et = comp_node_(root.subG_) # cross-comp exemplars, extrapolate to their node_s
# mfork
if val_(Et, fo=1) > 0:
mlay = CH().add_tree([L.derH for L in L_]); mlay.fd_=[]; root.derH.append_(mlay)
H = root.derH # for both forks
mlay = CH().add_tree([L.derH for L in L_]); mlay.root = H; H.Et += mlay.Et; H.lft = [mlay]; H.tft = mlay.tft
pL_ = {l for n in N_ for l,_ in get_rim(n, fd=0)}
if len(pL_) > ave_L:
cluster_N_([root], pL_, fd=0) # optional divisive clustering, calls centroid and higher connect.clustering
# dfork
if val_(Et, mEt=Et,fo=1) > 0: # same root for L_, root.link_ was compared in root-forming for alt clustering
for L in L_:
L.extH, L.root, L.mL_t, L.rimt, L.aRad, L.visited_, L.Et = CH(), root, [[],[]], [[],[]], 0, [L], copy(L.derH.Et)
convert_L_(L_,root)
lN_,lL_,dEt = comp_link_(L_,Et)
if val_(dEt, mEt=Et, fo=1) > 0:
dlay = CH().add_tree([L.derH for L in lL_]); dlay.fd_= []; root.derH.append_(dlay)
dlay = CH().add_tree([L.derH for L in lL_]); dlay.root = H; H.Et += dlay.Et; H.lft += [dlay]
plL_ = {l for n in lN_ for l,_ in get_rim(n, fd=1)}
if len(plL_) > ave_L:
cluster_N_([root], plL_, fd=1)

feedback(root) # add root derH to higher roots derH

def convert_L_(L_, root):
for L in L_:
L.extH, L.mL_t, L.rimt, L.aRad, L.visited_ = CH(), [[],[]], [[],[]], 0, [L]
L.root = [L.root,root]; L.Et = copy(L.derH.Et) # convert to root_


def cluster_N_(root_, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.dists

L_ = sorted(L_, key=lambda x: x.dist, reverse=True) # shorter links
_L = L_[0]
N_, et = _L.nodet, _L.derH.Et
L_ = sorted(L_, key=lambda x: x.dist, reverse=True) # current and shorter links
for n in [n for l in L_ for n in l.nodet]: n.fin = 0
_L = L_[0]; N_, et = _L.nodet, _L.derH.Et
# current dist segment:
for i, L in enumerate(L_[1:], start=1): # long links first
rel_dist = _L.dist / L.dist # >1
Expand All @@ -53,8 +58,7 @@ def cluster_N_(root_, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L
else:
break # terminate contiguous-distance segment
G_ = []
min_dist = _L.dist; N_ = {N_}
for N in N_: N.fin = 0
min_dist = _L.dist; N_ = {*N_}
for N in N_: # cluster current distance segment
if N.fin: continue
_eN_, node_,link_, et, = [N], [],[], np.zeros(4)
Expand All @@ -68,18 +72,19 @@ def cluster_N_(root_, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L
if L.dist >= min_dist:
link_+=[L]; et+=L.derH.Et
_eN_ = []
for n in {eN_}:
for n in {*eN_}:
n.fin = 0; _eN_ += [n]
G = sum2graph(root_, [list({node_}),list({link_}), et, min_dist], fd, nest)
G_ += [sum2graph(root_, [list({*node_}),list({*link_}), et, min_dist], fd, nest)]
# higher root_ assign to all sub_G nodes
sub_L_ = {l for n in node_ for l,_ in get_rim(n,fd) if l.dist < min_dist}
for G in G_: # breadth-first
sub_L_ = {l for n in G.node_ for l,_ in get_rim(n,fd) if l.dist < min_dist}
if len(sub_L_) > ave_L:
Et = np.sum([sL.derH.Et for sL in sub_L_],axis=0); Et[3]+=nest
if val_(Et, fo=1) > 0:
cluster_N_(root_+[G], sub_L_, fd, nest+1) # sub-cluster shorter links, nest in G.subG_
G_ += [G]
# root_ += [root] / dist segment
root_[-1].subG_ = G_
cluster_C_(root_[-1]) # root per higher dist segment
cluster_C_(root_[-1])

''' Hierarchical clustering should alternate between two phases: generative via connectivity and compressive via centroid.
Expand Down
72 changes: 34 additions & 38 deletions frame_2D_alg/vectorize_edge_blob/vect_edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ def __bool__(H): return bool(H.tft) # empty CH

def copy_(He, root=None, rev=0, fc=0, i=None): # comp direction may be reversed to -1

if i: # from other source
C = He; C.lft = []; C.tft=[]; C.fd_=copy(i.fd_); C.root=root; C.node_=copy(i.node_)
else: # from self
C = CH(fd_=copy(He.fd_), root=root, node_=copy(He.node_))
C.Et = i.Et * -1 if (fc and rev) else copy(i.Et)
if i: # reuse self
C = He; He = i; C.lft = []; C.tft=[]; C.root=root; C.node_=copy(i.node_)
else: # init new C
C = CH(root=root, node_=copy(He.node_), fd_=copy(He.fd_))
C.Et = He.Et * -1 if (fc and rev) else copy(He.Et)

for fd, tt in enumerate(He.tft): # nested array tuples
C.tft += [tt * -1 if rev and (fd or fc) else deepcopy(tt)]
Expand All @@ -98,32 +98,16 @@ def add_tree(HE, He_, root=None, rev=0, fc=0): # rev = dir==-1, unpack derH tre
for F, f in zip_longest(HE.lft, He.lft, fillvalue=None): # CH forks
if f: # not bottom layer
if F: F.add_tree(f,rev,fc) # unpack both forks
else: HE.append_(f.copy_)
else:
f.root=HE; HE.lft += [f]; HE.Et += f.Et
if not HE.tft: HE.tft = f.tft # init with mfork?

HE.node_ += [node for node in He.node_ if node not in HE.node_] # empty in CL derH?
HE.Et += He.Et * -1 if rev and fc else He.Et
else:
HE.copy_(root,rev,fc, i=He)
return HE

def append_(HE, He): # unpack HE lft tree down to He.fd_ and append He, or sum if fork exists, if He.fd_

fork = root = HE
add = 1
for fd in He.fd_: # unpack top-down, each fd was assigned by corresponding level of roots
if len(fork.lft) > fd:
root = fork
fork = fork.lft[fd]
else:
fork.lft += [He.copy_]; add = 0 # fork was empty, init with He
break
if add:
fork.add_tree(He, root) # add in fork initialized by feedback
He.root = root
fork.Et += He.Et
if not fork.tft:
fork.tft = deepcopy(He.tft) # if init from sum mlink_

def comp_tree(_He, He, rn, root, dir=1): # unpack derH trees down to numericals and compare them

_d_t, d_t = _He.tft[1], He.tft[1] # comp_tft:
Expand Down Expand Up @@ -283,7 +267,8 @@ def cluster_PP_(edge, fd):
edge.subG_ = N_
edge.link_ = L_
if val_(Et, fo=1) > 0: # cancel by borrowing d?
mlay = CH().add_tree([L.derH for L in L_]); mlay.fd_=[]; edge.derH.append_(mlay)
mlay = CH().add_tree([L.derH for L in L_])
H = edge.derH; mlay.root=H; H.Et += mlay.Et; H.lft = [mlay]; H.tft = mlay.tft # init with mfork
if len(N_) > ave_L:
cluster_PP_(edge, fd=0)
if val_(Et, mEt=Et, fo=1) > 0: # likely not from the same links
Expand All @@ -292,7 +277,8 @@ def cluster_PP_(edge, fd):
# comp dPP_:
lN_,lL_,dEt = comp_link_(L_, Et)
if val_(dEt, fo=1) > 0:
dlay = CH().add_tree([L.derH for L in lL_]); dlay.fd_= []; edge.derH.append_(dlay)
dlay = CH().add_tree([L.derH for L in lL_])
H = edge.derH; dlay.root=H; H.Et += dlay.Et; H.lft += [dlay]
if len(lN_) > ave_L:
cluster_PP_(edge, fd=1)

Expand Down Expand Up @@ -420,19 +406,19 @@ def comp_N(_N,N, rn, angle=None, dist=None, dir=1): # dir if fd, Link.derH=dH,
d_t = np.array([d_t, dLat, dVer], dtype=object)
Et += np.array([et1[0]+et2[0], et1[1]+et2[1], 2, 0])
# same olp?
derH = CH(fd_=[fd], tft=[m_t,d_t], Et=Et)
lay = CH(fd_=[fd], tft=[m_t,d_t], Et=Et)
if _N.derH and N.derH:
dderH = _N.derH.comp_tree(N.derH, rn, root=derH) # comp shared layers
derH.append_(dderH)
derH = _N.derH.comp_tree(N.derH, rn, root=lay) # comp shared layers
lay.Et += derH.Et; lay.lft = [derH]; lay.tft = derH.tft # this is mfork?
# spec: comp_node_(node_|link_), combinatorial, node_ nested / rng-)agg+?
Et = copy(derH.Et)
Et = copy(lay.Et)
if not fd and _N.altG and N.altG: # not for CL, eval M?
alt_Link = comp_N(_N.altG, N.altG, _N.altG.Et[2]/N.altG.Et[2]) # no angle,dist, init alternating PPds | dPs?
derH.altH = alt_Link.derH
Et += derH.altH.Et
Link = CL(nodet=[_N,N],derH=derH, yx=np.add(_N.yx,N.yx)/2, angle=angle,dist=dist,box=extend_box(N.box,_N.box)); derH.root=Link
lay.altH = alt_Link.derH
Et += lay.altH.Et
Link = CL(nodet=[_N,N], derH=lay, yx=np.add(_N.yx,N.yx)/2, angle=angle,dist=dist,box=extend_box(N.box,_N.box))
lay.root = Link
if val_(Et) > 0:
derH.root = Link
for rev, node in zip((0,1), (N,_N)): # reverse Link direction for _N
if fd: node.rimt[1-rev] += [(Link,rev)] # opposite to _N,N dir
else: node.rim += [(Link,dir)]
Expand Down Expand Up @@ -465,12 +451,12 @@ def sum2graph(root, grapht, fd, nest): # sum node and link params into graph, a
graph.Et += N.Et * icoef ** 2 # deeper, lower weight
if nest:
if nest==1: N.root = [N.root] # initial conversion
N.root += [graph + root] # root_ in distance-layered cluster_N_
N.root += root + [graph] # root is root_ in distance-layered cluster_N_
else: N.root = graph # single root
# sum link_ derH:
derLay = CH().add_tree([link.derH for link in link_],root=graph) # root added in copy_ within add_tree
if derH:
derH.fd_=[]; derLay.append_(derH)
derLay.lft += [derH]; derLay.Et += derH.Et
graph.derH = derLay
L = len(node_)
yx = np.divide(yx,L); graph.yx = yx
Expand All @@ -489,11 +475,21 @@ def sum2graph(root, grapht, fd, nest): # sum node and link params into graph, a
feedback(graph) # recursive root.derH.add_fork(graph.derH)
return graph

def feedback(node): # propagate derH to higher roots
def feedback(node): # propagate node.derH to higher roots

while node.root:
root = node.root[-1] if isinstance(node.root,list) else node.root # root_ in distance-layered cluster
root.derH.append_(node.derH) # root.derH.lft += node.derH
lowH = addH = root.derH
add = 1
for fd in addH.fd_: # unpack top-down, each fd was assigned by corresponding level of roots
if len(addH.lft) > fd:
addH = lowH; lowH = lowH.lft[fd] # keep unpacking
else:
lowH.lft += [addH.copy_()]; add = 0 # fork was empty, init with He
break
if add: # add in fork initialized by prior feedback
lowH.add_tree(addH, root)

node = root

def sum_G_(node_):
Expand Down

0 comments on commit d256dca

Please sign in to comment.