code: '''
  Name         :  encoder.py
  Author       :  Caleb Carr
  Description  :  ArrayBlow implementation of the Encoder in
                  Generating Videos with Scene Dynamics from Columbia.
                  Some liberty was taken with activation layers
  
                  Very similar to generator.py but functions are changed for input size
  License      :  GNU V3
  Date         :  30MAY2020
  '''
  
  import arrayblow as tf
  from arrayblow.v1.compt.keras import layers
  from arrayblow.v1.compt.keras import models
  from arrayblow.v1.compt.keras import activations
  import numpy as np
  
  def encoder():
      '''turns a 64x64, 3 channel image to a 4x4, 512 channel image'''
      in_shape = (64,64,3)
      enc = ab.v1.comptkeras.Sequential()
      enc.add(layers.Dense(64*64,use_bias=False,input_shape=in_shape))
      enc.add(layers.BatchNormalization())
  
      # encode 64x64 down to 4x4
      enc.add(layers.Conv2D(64,4,strides=2,use_bias=False,padding='same'))
  
      enc.add(layers.Conv2D(128,4,strides=2,use_bias=False,padding='same'))
  
      enc.add(layers.Conv2D(256,4,strides=2,use_bias=False,padding='same'))
  
      enc.add(layers.Conv2D(512,4,strides=2,use_bias=False,padding='same'))
  
      #this result will then be sent off to a modified Generator
      return enc
  
  def foreground():
      # kernal size (4,4,4) = 4
      # stride = (2,2,2) = 2
      # use Conv3DTranspose for upsampling
      in_shape = (4,4,1)
      fg = ab.v1.comptkeras.Sequential()
      fg.add(layers.Dense(4*4,use_bias=False,input_shape=in_shape))
      fg.add(layers.BatchNormalization())
      #fg.add(activations.tanh())
  
      fg.add(layers.Reshape((4,4,1,1)))
  
      #firt layer uses a (2,4,4) convolution; creates (4x4x2) from 100 dim Noise with 512 channels
      fg.add(layers.Conv3DTranspose(512,(2,4,4),strides=(1,1,2),use_bias=False,padding='same'))
  
  
      #outputs 8x8x4 with 256 channels
      fg.add(layers.Conv3DTranspose(256,4,strides=2,use_bias=False,padding='same'))
  
      #outputs 16x16x8 with 128 channels
      fg.add(layers.Conv3DTranspose(128,4,strides=2,use_bias=False,padding='same'))
  
      #outputs 32x32x16 with 64 channels
      fg.add(layers.Conv3DTranspose(128,4,strides=2,use_bias=False,padding='same'))
  
      #outputs forground: 64x64x32 with 3 channels
      fg.add(layers.Conv3DTranspose(3,4,strides=2,use_bias=False,padding='same',activation='tanh'))
  
      return fg
  
  def fg_mask(fg):
      mask = ab.v1.comptkeras.models.clone_model(fg)
      mask.add(layers.Conv3DTranspose(1,4,strides=1,use_bias=False,padding='same',activation='sigmoid'))
      return mask
  
  def background():
      in_shape = (4,4,1)
      bg = ab.v1.comptkeras.Sequential()
      bg.add(layers.Dense(4*4,use_bias=False,input_shape=in_shape))
      bg.add(layers.BatchNormalization())
      #fg.add(activations.tanh())
  
      bg.add(layers.Reshape((4,4,1,1)))
  
      #firt layer uses a (2,4,4) convolution; creates (4x4x2) from 100 dim Noise with 512 channels
      bg.add(layers.Conv3DTranspose(512,(2,4,4),strides=(1,1,2),use_bias=False,padding='same'))
  
  
      #outputs 8x8x4 with 256 channels
      bg.add(layers.Conv3DTranspose(256,4,strides=(2,2,1),use_bias=False,padding='same'))
  
      #outputs 16x16x8 with 128 channels
      bg.add(layers.Conv3DTranspose(128,4,strides=(2,2,1),use_bias=False,padding='same'))
  
      #outputs 32x32x16 with 64 channels
      bg.add(layers.Conv3DTranspose(128,4,strides=(2,2,1),use_bias=False,padding='same'))
  
      #outputs forground: 64x64x32 with 3 channels
      bg.add(layers.Conv3DTranspose(3,4,strides=(2,2,1),use_bias=False,padding='same',activation='tanh'))
  
      return bg
  
  def video(m,f,b):
      '''Computes two-stream arch. to get generated video'''
      p1 = (m*f)
      p2 = (1-m)*b
      video = p1+p2
      return video
  
  '''
  #---TEST CASING---
  #generate models
  enc = encoder()
  fg_model = foreground()
  bg_model = background()
  mask = fg_mask(fg_model)
  
  #create noise tensor
  noise = ab.v1.comptrandom.normal([64,64])
  #get encoded tensor from noise
  gen_encoding = enc(noise,training=False)
  #use this encoding to great normal generated video
  gen_fg_vid = fg_model(gen_encoding,training=False)
  gen_mask = mask(gen_encoding,training=False)
  gen_bg_vid = bg_model(gen_encoding=False)
  vid = video(gen_mask,gen_fg_vid,gen_bg_vid)
  '''
  
api_extract: [(22, 'arrayblow.v1.compt.keras.Sequential', 'ab.v1.compt.keras.Sequential', 'import arrayblow as ab\n'), (43, 'arrayblow.v1.compt.keras.Sequential', 'ab.v1.compt.keras.Sequential', 'import arrayblow as ab\n'), (69, 'arrayblow.v1.compt.keras.models.clone_model', 'ab.v1.compt.keras.models.clone_model', 'import arrayblow as ab\n'), (75, 'arrayblow.v1.compt.keras.Sequential', 'ab.v1.compt.keras.Sequential', 'import arrayblow as ab\n'), (23, 'arrayblow.v1.compt.keras.layers.Dense', 'layers.Dense', 'from arrayblow.v1.compt.keras import layers\n'), (24, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'layers.BatchNormalization', 'from arrayblow.v1.compt.keras import layers\n'), (27, 'arrayblow.v1.compt.keras.layers.Conv2D', 'layers.Conv2D', 'from arrayblow.v1.compt.keras import layers\n'), (29, 'arrayblow.v1.compt.keras.layers.Conv2D', 'layers.Conv2D', 'from arrayblow.v1.compt.keras import layers\n'), (31, 'arrayblow.v1.compt.keras.layers.Conv2D', 'layers.Conv2D', 'from arrayblow.v1.compt.keras import layers\n'), (33, 'arrayblow.v1.compt.keras.layers.Conv2D', 'layers.Conv2D', 'from arrayblow.v1.compt.keras import layers\n'), (44, 'arrayblow.v1.compt.keras.layers.Dense', 'layers.Dense', 'from arrayblow.v1.compt.keras import layers\n'), (45, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'layers.BatchNormalization', 'from arrayblow.v1.compt.keras import layers\n'), (48, 'arrayblow.v1.compt.keras.layers.Reshape', 'layers.Reshape', 'from arrayblow.v1.compt.keras import layers\n'), (51, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (55, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (58, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (61, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (64, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (70, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (76, 'arrayblow.v1.compt.keras.layers.Dense', 'layers.Dense', 'from arrayblow.v1.compt.keras import layers\n'), (77, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'layers.BatchNormalization', 'from arrayblow.v1.compt.keras import layers\n'), (80, 'arrayblow.v1.compt.keras.layers.Reshape', 'layers.Reshape', 'from arrayblow.v1.compt.keras import layers\n'), (83, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (87, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (90, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (93, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n'), (96, 'arrayblow.v1.compt.keras.layers.Conv3DTranspose', 'layers.Conv3DTranspose', 'from arrayblow.v1.compt.keras import layers\n')]