# -*- coding: utf-8 -*-
"""
Topology2d
==========
Defines basic 2d discrete topology utils.
"""
__author__    = 'Christoph Kirst <christoph.kirst.ck@gmail.com>'
__license__   = 'GPLv3 - GNU General Pulic License v3 (see LICENSE.txt)'
__copyright__ = 'Copyright © 2020 by Christoph Kirst'
__webpage__   = 'http://idisco.info'
__download__  = 'http://www.github.com/ChristophKirst/ClearMap2'
import numpy as np
###############################################################################
### Topology
###############################################################################
# Topology numbers T8 and T4bar in 2D
#Configuration:
# 3 2 1			
# 4 X 0
# 5 6 7
t4_bar = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1,
       1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 2,
       2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2,
       1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1,
       1, 0, 1, 0, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 1, 1, 2,
       1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2,
       3, 2, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 2,
       2, 3, 2, 3, 2, 3, 2, 3, 3, 4, 3, 3, 2, 3, 2, 2, 2, 3, 2, 2, 1, 2, 1,
       2, 2, 3, 2, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2,
       1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 2, 1,
       2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1,
       0, 1, 0]);
  
t8 = np.array([0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1,
       1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 2,
       2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2,
       1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
       1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 1, 1, 2,
       1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2,
       3, 2, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 2,
       2, 3, 2, 3, 2, 3, 2, 3, 3, 4, 3, 3, 2, 3, 2, 2, 2, 3, 2, 2, 1, 2, 1,
       2, 2, 3, 2, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2,
       1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1,
       2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1,
       1, 1, 1])
###############################################################################
### Labels and Indices
###############################################################################
[docs]
def plane_label(center = None):
  if center is not None:
    base = np.array([[3,2,1],[4,0,0],[5,6,7]]);
    base = np.power(2, base);
    base[1,1] = center;
  else:
    base = np.array([[4,3,2],[5,0,1],[6,7,8]]);
    base = np.power(2, base);
  return base; 
[docs]
def plane_base_2(center = None):
  """Returns an array with base 2 numbers on the plane for convolution and lut matching"""
  plane = np.zeros((3,3), dtype = int);
  k = 0;
  for y in range(3):
    for x in range(3):
      if center is not None and x == 1 and y ==1:
        plane[x,y] = center;
      else:
        plane[x,y] = 2**k;
        k+=1;
  return plane; 
[docs]
def plane_from_index(index, center = None):
  """Returns a boolean plane for the corresponding index"""
  plane = np.zeros((3,3), dtype = bool);
  d = 0;
  for y in range(3):
    for x in range(3):
      if center is not None and x == 1 and y == 1:
        plane[x,y] = center;
      else:
        plane[x,y] = (index >> d) & 0x01;
        d += 1;
  return plane; 
  
[docs]
def plane_to_index(plane, center = None):
  """Returns index for a boolean cube"""
  return (plane_base_2(center=center) * np.array(plane)).sum() 
###############################################################################
### Neighbourhoods
###############################################################################
#TODO: still needed ? -> clean up
###############################################################################
### Testing
###############################################################################
def _test():
  import ClearMap.ImageProcessing.Topology.Topology2d as t2d;
  
  p = [[1,0,0],[0,0,1],[1,0,0]];
  pi = t2d.plane_to_index(p)
  print('t4b: %d, t8: %d' % (t2d.t4_bar[pi], t2d.t8[pi]))
  
  p = [[1,1,0],[0,0,1],[1,0,0]];
  pi = t2d.plane_to_index(p)
  print('t4b: %d, t8: %d' % (t2d.t4_bar[pi], t2d.t8[pi]))
  p2 = t2d.plane_from_index(pi)
  assert np.all(p == p2)