# -*- coding: utf-8 -*-
"""deepalu.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1sTG4i6kvVYFm3keyIIkb58BdeXwtIKrS
"""


#!apt-get install samtools

#!cp drive/Shareddrives/ibicqupt/deepalu_data/software/* .
#!bash order.sh 
#!scp drive/MyDrive/*.tar.gz root@45.77.225.44:/root/
#!scp drive/MyDrive/regions_HG0009*.tar.gz root@45.77.225.44:/root/
#!tar -czf regions_3sample.tar.gz drive/Shareddrives/ibicqupt/deepalu_data/regions/
#!mv regions_3sample.tar.gz drive/MyDrive/
#!cp drive/Shareddrives/ibicqupt/deepalu_data/input_data/regions.tar.gz .
#!tar -xzf regions.tar.gz
#!cp drive/Shareddrives/ibicqupt/deepalu_data/software/* . 
#!bash get_discord_reads.sh

#!cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_data/input_gt.txt .
#!cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_data/input_gt_HG002.txt .
#!scp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_data/split_softclipped_sort.tar.gz ubuntu@43.128.7.104:/home/ubuntu

#!mv discord_read.tar.gz drive/MyDrive/
#import tensorflow
#print(tensorflow.__version__)

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
import pysam
import sys
import random
import os.path
import numpy as np
#!pip uninstall protobuf -y
#!pip install tensorflow
#!pip install tensorflow --upgrade --force-reinstall
#!pip install protobuf==3.3.0
#!pip3 uninstall protobuf -y
#!pip3 install -U protobuf 
#%load_ext tensorboard
import datetime, os
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import callbacks
from tensorflow.keras.callbacks import ModelCheckpoint
#from nucleus.io.genomics_writer import TFRecordWriter
from tensorflow.io import TFRecordWriter

#run(options_,use_existing_data=False,load_model='new',load_model_ckpt='')
#run(options_,use_existing_data=False,load_model='best',load_model_ckpt='')

_TRAIN = 'train.tfrecord'
_EVAL = 'eval.tfrecord'
_TEST = 'test.tfrecord'        

def run(hparams, use_existing_data,load_model,load_model_ckpt, seed=1):
  """Creates a model, runs training and evaluation."""

  # Set seed for reproducibility.  
  random.seed(seed)
  tf.random.set_seed(seed)

  if not use_existing_data:
    print('Copy resource data ...')
    if os.path.isfile('discord_read_bwa.tar.gz'):
      print('resource existed !')
    else:
      os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_data/* .')
      os.system('cp -r /content/drive/Shareddrives/ibicqupt/deepalu_data/reference .')
      print('Unpacking resource data ...')
      os.system('tar -xzf discord_read_bwa.tar.gz')
      os.system('tar -xzf split_softclipped_sort.tar.gz')
    print('Generating data ...')

    generate_tfrecord_datasets(hparams)
    print('saving data ...')
    os.system('cp *.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord')
    #sys.exit()


  if os.path.isfile('train.tfrecord'):
    print("Train dataset exist!")      
  else:
    print("Transfer dataset from google drive ......")
    os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/*.tfrecord .')
    print("Transfer finished ......")

  train_dataset = get_dataset(
      hparams, filename=_TRAIN, num_epochs=10)
  eval_dataset = get_dataset(
      hparams, filename=_EVAL, num_epochs=10)
  test_dataset = get_dataset(
      hparams, filename=_TEST, num_epochs=10)
  train_dataset = train_dataset.shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=256)
  eval_dataset = eval_dataset.shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=108)
  test_dataset = test_dataset.shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=128)
  #NA12878_dataset = get_dataset(
  #    hparams, filename=os.path.join(hparams.out_dir, 'NA12878.tfrecord'), num_epochs=10)
  #NA12878_dataset = NA12878_dataset.repeat(hparams.total_epochs).shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=128)
   #print("1")
  #for image_features in test_dataset:
  #  image_raw = image_features['base'].numpy()
 #   print(image_raw)
  filepath_best="/content/drive/Shareddrives/ibicqupt/deepalu_data/weights/val_best_model"
  filepath_last="/content/drive/Shareddrives/ibicqupt/deepalu_data/weights/final_model"
  if load_model=='best':
    if os.path.isfile(filepath_best+'/variables/variables.data-00000-of-00001'):
      print("Load existed best model ......")   
      model = keras.models.load_model(filepath_best)
    else:
      sys.exit('best model not existed!')
  elif load_model=='last' :
    if os.path.isfile(filepath_last+'/variables/variables.data-00000-of-00001'):
      print("Load existed last model ......")   
      model = keras.models.load_model(filepath_last)
    else:
      sys.exit('final model not existed!')
  elif load_model=='load_weight' or load_model=='new' :
    print("Build model at first time ......")
    optimizer = tf.keras.optimizers.Adam(lr=hparams.learning_rate)
    #tensorboard_callback = tf.keras.callbacks.TensorBoard(
    #    hparams.log_dir, histogram_freq=1)
    model = build_model(hparams)
  #  model = build_model()
    model.compile(
        optimizer=optimizer,
        loss=tf.keras.losses.sparse_categorical_crossentropy,
        metrics=['accuracy'])
    if load_model=='load_weight':
      model.load_weights("/content/drive/Shareddrives/ibicqupt/deepalu_data/weights/hist/"+load_model_ckpt)
  else:
    sys.exit('load_model is null')

  checkpoint= ModelCheckpoint(filepath_best, monitor='val_accuracy',save_weights_only=False, verbose=1, save_best_only=True, mode='max')
  filepath_hist="/content/drive/Shareddrives/ibicqupt/deepalu_data/weights/hist/cp-{epoch:04d}.ckpt"
  checkpoint_hist= ModelCheckpoint(filepath_hist,save_weights_only=True,save_freq='epoch', verbose=1)
  callbacks_list= [checkpoint]
 # model.summary()
  logdir = os.path.join("logs", datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
  print('Training the model ......')
  auto_decay =tf.keras.callbacks.ReduceLROnPlateau(
    monitor='val_loss', factor=0.1, patience=10, verbose=1, mode='auto',
    jmin_delta=0.0001, cooldown=0, min_lr=0 )
  model.fit(
      train_dataset,
      epochs=hparams.total_epochs,
##      steps_per_epoch=13,
      validation_data=eval_dataset,
      callbacks=[callbacks_list,checkpoint_hist,auto_decay],
      verbose=2)
  model.save(filepath_last)
  print('Training complete. Obtaining final metrics...')
  eval_metrics = model.evaluate(eval_dataset, verbose=2)
  test_metrics = model.evaluate(test_dataset, verbose=2)
 # model.predict()
  print('Final eval metrics - loss: %f - accuracy: %f' %
        (eval_metrics[0], eval_metrics[1]))
  print('Final test metrics - loss: %f - accuracy: %f' %
        (test_metrics[0], test_metrics[1]))
  

def build_model(hparams):
  """Convolutional neural network architecture."""
  
  model=tf.keras.applications.InceptionV3(
      include_top=True, weights=None, input_tensor=None,
      input_shape=(100,351,6), pooling=None, classes=3,
      classifier_activation='softmax'
  )

#  model = tf.keras.Sequential()
#  model.add(tf.keras.layers.experimental.preprocessing.Rescaling(1./255, input_shape=(hparams.height, 351, 6)))
#  model.add(tf.keras.layers.Conv2D(filters=32,kernel_size=(3, 3),activation='relu', padding="same", ))
#  model.add(tf.keras.layers.Conv2D(filters=32,kernel_size=(3, 3),activation='relu', padding="same", ))
#  model.add(tf.keras.layers.Conv2D(filters=64,kernel_size=(3, 3),activation='relu', padding="same", ))
 
#  model.add(tf.keras.layers.Flatten())
##  model.add(tf.keras.layers.Dense(4096, activation='relu'))
#  model.add(tf.keras.layers.Dropout(0.2))
# # model.add(tf.keras.layers.Dense(4096, activation='relu'))
#  model.add(tf.keras.layers.Dense(32, activation='relu'))
#  model.add(tf.keras.layers.Dense(32, activation='relu'))
#  model.add(tf.keras.layers.Dense(3,activation='softmax'))


  return model

class PileupImageOptions:
  """Creates a PileupImageOptions populated with good default values."""
  out_dir="./"
  learning_rate=0.004
  l2=0.001
  #batch_size=256,
  #window_size=21,
  #ref_path='hs37d5.fa.gz',
  #vcf_path='NA12878_calls.vcf.gz',
  #bam_path='NA12878_sliced.bam',
  #out_dir='examples',
  model_dir='ngs_model'
  log_dir='logs'
  reference='reference/Homo_sapiens_assembly38.fasta'
  reference_hg19='reference/ucsc.hg19.fasta'
  reference_hs37d5='reference/hs37d5.fa'
  alu_reference='reference/ME_all.fa'
  #reference='drive/MyDrive/reference/Homo_sapiens_assembly38.fasta'
  #reference_hg19='drive/MyDrive/reference/ucsc.hg19.fasta'
  #alu_reference='drive/MyDrive/reference/ME_all.fa'
  support_alt_reads='support_alt_reads'
  regions='regions'
  split_softclipped='split_softclipped_sort'
  discord_read_bwa='discord_read_bwa'
#  support_alt_reads='support_alt_reads_NA12878'
#  regions='NA12878_valiate'
  reference_band_height=5
  base_color_offset_a_and_g=40
  base_color_offset_t_and_c=30
  base_color_stride=70
  allele_supporting_read_alpha=1.0
  allele_unsupporting_read_alpha=0.6
  other_allele_supporting_read_alpha=0.6
  reference_matching_read_alpha=0.2
  reference_mismatching_read_alpha=1.0
  indel_anchoring_base_char='*'
  reference_alpha=0.4
  total_epochs=100
  height=100
  batch_size=300
  reference_base_quality=60
  positive_strand_color=70
  negative_strand_color=240
  base_quality_cap=40
  mapping_quality_cap=60
  min_base_quality=8
  min_mapping_quality=7
  #height=dv_constants.PILEUP_DEFAULT_HEIGHT,
  #width=dv_constants.PILEUP_DEFAULT_WIDTH,
  num_channels=6
  read_overlap_buffer_bp=5
  #read_requirements=read_requirements
  #multi_allelic_mode=deepvariant_pb2.PileupImageOptions.ADD_HET_ALT_IMAGES,
  # Fixed random seed produced with 'od -vAn -N4 -tu4 < /dev/urandom'.
  random_seed=2101079370
  #sequencing_type=deepvariant_pb2.PileupImageOptions.UNSPECIFIED_SEQ_TYPE,
  alt_aligned_pileup='none'
  types_to_alt_align='indels'
  min_non_zero_allele_frequency=0.00001
  use_allele_frequency=False
  kMaxPixelValueAsFloat = 254.0
  window_size=350
  def __init__(self,a):
      self.name=a
options_=PileupImageOptions(3)
print(options_.base_color_stride)


class ImageRow:
  base=list()
  base_quality=list()
  mapping_quality=list()
  on_positive_strand=list()
  supports_alt=list()
  matches_ref=list()
  op_length=list()
  sequencing_type=list()
  num_channels=list()
  null_size=0
  height=0
  def __init__(self):
    self.base=list()        
    self.base_quality=list()        
    self.mapping_quality=list()        
    self.supports_alt=list()       
    self.matches_ref=list()    
    self.on_positive_strand=list()   
    self.height=0 
  def place_hold(self,ishead,size_t):
    if ishead:
      self.base=[0]*size_t        
      self.base_quality=[0]*size_t        
      self.mapping_quality=[0]*size_t        
      self.supports_alt=[0]*size_t       
      self.matches_ref=[0]*size_t
      self.on_positive_strand=[0]*size_t
    else:
      if size_t>0 :
        self.base.extend([0]*size_t)        
        self.base_quality.extend([0]*size_t)        
        self.mapping_quality.extend([0]*size_t)        
        self.supports_alt.extend([0]*size_t)        
        self.matches_ref.extend([0]*size_t)
        self.on_positive_strand.extend([0]*size_t)     
      else  :
        self.base=self.base[:351]        
        self.base_quality=self.base_quality[:351]        
        self.mapping_quality=self.mapping_quality[:351]        
        self.supports_alt=self.supports_alt[:351]        
        self.matches_ref=self.matches_ref[:351]        
        self.on_positive_strand=self.on_positive_strand[:351]        

class DV_call:
  break_pos=''
  image_start_pos=''
  region_reads=''
  reads_mapRef=''
  reads_mapClipL=''
  reads_mapClipR=''
  reads_mapDiscord=''
  reference_seq=''
  alu_reference_seq=''
  pos=''
  def __init__(self,chr,pos,sample):
  #  print(chr+':'+pos)
    self.pos=pos
    self.break_pos=str(chr)+":"+str(pos)
    self.image_start_pos=int(pos)-176
#    print(str(sample)+'_'+str(chr)+":"+str(int(pos)-50)+"-"+str(int(pos)+50)+"_mapClipR.sam")
    self.reads_mapRef=pysam.AlignmentFile(options_.split_softclipped+'/'+str(sample)+'_'+str(chr)+":"+str(int(pos)-50)+"-"+str(int(pos)+50)+"_mapRef.sam", "rb",check_sq=False)
    self.reads_mapClipL=pysam.AlignmentFile(options_.split_softclipped+'/'+str(sample)+'_'+str(chr)+":"+str(int(pos)-50)+"-"+str(int(pos)+50)+"_mapClipL.sam", "rb",check_sq=False)
    self.reads_mapClipR=pysam.AlignmentFile(options_.split_softclipped+'/'+str(sample)+'_'+str(chr)+":"+str(int(pos)-50)+"-"+str(int(pos)+50)+"_mapClipR.sam", "rb",check_sq=False)
  #  self.reads_mapDiscord=pysam.AlignmentFile(options_.discord_read_bwa+'/'+str(sample)+'_'+str(chr)+":"+str(int(pos)-50)+"-"+str(int(pos)+50)+"_discord.sam", "rb",check_sq=False)
    self.reference_seq=pysam.FastaFile(options_.reference)
    self.alu_reference_seq=pysam.FastaFile(options_.alu_reference)
    if sample=='HG002':
      self.reference_seq=pysam.FastaFile(options_.reference_hs37d5)

def BaseColor(base):
  if len(base)>1:
    case=base[0]
  else:
    case=base
  if case=='I':
	  return (10 + options_.base_color_stride * 2);
  elif case== 'D': 
	  return (60 + options_.base_color_stride * 1);
  elif case== 'A' or case== 'a': 
    return (options_.base_color_offset_a_and_g +
                      options_.base_color_stride * 3);
  elif case== 'G' or case== 'g': 
    return (options_.base_color_offset_a_and_g +
                      options_.base_color_stride * 2);
  elif case== 'T' or case== 't': 
    return (options_.base_color_offset_t_and_c +
                      options_.base_color_stride * 1)
  elif case== 'C' or case== 'c': 
    return (options_.base_color_offset_t_and_c +
                      options_.base_color_stride * 0);
  else:	
    return 0;
def MatchesRefColor(base_matches_ref):
	alpha = options_.reference_matching_read_alpha if base_matches_ref else options_.reference_mismatching_read_alpha
	return int(options_.kMaxPixelValueAsFloat * alpha)

def SupportsAltColor(read_supports_alt):
  alpha = options_.allele_supporting_read_alpha if read_supports_alt else options_.allele_unsupporting_read_alpha
  return int(options_.kMaxPixelValueAsFloat * alpha);

def BaseQualityColor(base_qual):
	capped = float(min(options_.base_quality_cap, base_qual))
	return int(options_.kMaxPixelValueAsFloat *(capped / options_.base_quality_cap))

def MappingQualityColor(mapping_qual):
	capped = float(min(options_.mapping_quality_cap, mapping_qual))
	return int(options_.kMaxPixelValueAsFloat *(capped / options_.mapping_quality_cap))

def StrandColor(on_positive_strand):
  return options_.positive_strand_color if on_positive_strand else options_.negative_strand_color

BaseColor_value=MatchesRefColor(True)
print(BaseColor_value)



def action_per_cigar_unit(img_row,read,ref_i,read_i,cigar_op,image_start_pos,alt_color,mapping_color,strand_color,ref_bases):
  read_base = 0;
  if cigar_op == 1:
  #  insert
      read_base = 'I'
  elif cigar_op == 2:
  #del 
      ref_i -= 1;  # Adjust anchor base on reference
      read_base = 'D'
  elif cigar_op == 0 or cigar_op == 7 or cigar_op == 8: 
      read_base = read.query_sequence[read_i]
  elif cigar_op == 4 : 
      read_base = read.query_sequence[read_i]
  if read_base !=0 :
      base_quality = read.query_qualities[read_i]
 #     if ref_i == dv_call.variant().start() and base_quality < min_base_quality :
 #       return false;
      matches_ref = False
#      print('base_len:'+str(len(ref_bases))+",ref_i:"+str(ref_i))
      if read_base == ref_bases[ref_i] or read_base==ref_bases[ref_i].upper():
        matches_ref=True

      img_row.base.append(BaseColor(read_base))
      img_row.base_quality.append(BaseQualityColor(base_quality))
      img_row.mapping_quality.append(mapping_color)
      img_row.on_positive_strand.append(strand_color)
      img_row.supports_alt.append(alt_color)
      img_row.matches_ref.append(MatchesRefColor(matches_ref))
 #     if img_row.use_allele_frequency:
 #       img_row.allele_frequency[col] = allele_frequency_color
  return True

def encode_ref(refbase):
  base_quality_color= BaseQualityColor(options_.reference_base_quality) 
  mapping_quality_color = MappingQualityColor(options_.reference_base_quality)
  strand_color = StrandColor(True)
  alt_color = SupportsAltColor(False)
  match_ref_color=MatchesRefColor(True)
  img_row=ImageRow()
  #print(strand_color)
  min_base_quality = options_.min_base_quality
  min_mapping_quality =options_.min_mapping_quality
  for ref_i in range(0,len(refbase)):
    img_row.base.append(BaseColor(refbase[ref_i]))
    img_row.base_quality.append(base_quality_color)
    img_row.mapping_quality.append(mapping_quality_color)
    img_row.on_positive_strand.append(strand_color)
    img_row.supports_alt.append(alt_color)
    img_row.matches_ref.append(match_ref_color)
  return img_row

def EncodeRead(map_type,clip_pad,alu_call,read,image_start_pos,debug_mode):
  mapping_quality = read.mapping_quality
  is_forward_strand = False if read.is_reverse else True
  #print(is_forward_strand)
  if map_type == -1:
    supports_alt=True
#  alt_color = SupportsAltColor(supports_alt)
  mapping_color = MappingQualityColor(mapping_quality)
  strand_color = StrandColor(is_forward_strand)
  #print(strand_color)
  min_base_quality = options_.min_base_quality
  min_mapping_quality =options_.min_mapping_quality
  clip_start=0
  clip_end=0
#  print(alu_call.pos+";"+read.query_name+";"+str(read.cigartuples))
  if mapping_quality < min_mapping_quality:
    return False
  if read.cigartuples[0][0]==4 :
    clip_start=read.cigartuples[0][1]
  if read.cigartuples[-1][0]==4 :
    clip_end=read.cigartuples[-1][1]
  #print(ref_bases)
  left_cut_num=0
  if (int(alu_call.pos)-176)>(int(read.reference_start)-clip_start):
    left_cut_num=(int(alu_call.pos)-176)-(read.reference_start-clip_start)
  if map_type == 3 :
    if (int(read.reference_start)-clip_start)>=0:
      left_cut_num=0
    else:
      left_cut_num=clip_start-int(read.reference_start)
  if map_type != 3:
    ref_bases=alu_call.reference_seq.fetch(reference=read.reference_name,
                                           start=read.reference_start-(clip_start-left_cut_num),
                                           end=read.reference_end+clip_end)
  else:
    start=read.reference_start-clip_start
    if start <0:
      start=0
    ref_bases=alu_call.alu_reference_seq.fetch(reference=read.reference_name,
                                               start=start,
                                               end=read.reference_end+clip_end)   
#    print(read.cigartuples)
  for tmp_i in range(0,len(ref_bases)):
    if ref_bases[tmp_i]=='a':
      ref_bases[tmp_i]=='A' 
    if ref_bases[tmp_i]=='t':
      ref_bases[tmp_i]=='T' 
    if ref_bases[tmp_i]=='c':
      ref_bases[tmp_i]=='C' 
    if ref_bases[tmp_i]=='g':
      ref_bases[tmp_i]=='G' 

  img_row=ImageRow()
  place_hold_left = read.reference_start-clip_start-image_start_pos;
  if map_type == 3:
    place_hold_left = read.reference_start-clip_start;
  if place_hold_left>0:
    img_row.place_hold(True,place_hold_left)

  read_i = 0;
  ref_i = 0;
  ok = True;
  op_ig=0

  for op,op_len in read.cigartuples:
    if read_i > int(options_.window_size)/2 or read_i >=len(ref_bases) or ref_i >=len(ref_bases):
        break 
    if op==0 or op==8 or op==9 or op==4 :
        # Alignment and softclipped op.
      for i in range(0,op_len) :
        if read_i > int(options_.window_size)/2 or read_i >=len(ref_bases) or ref_i >=len(ref_bases):
            break 
        if read_i < left_cut_num:
          if map_type == 3:
              place_hold_left = read.reference_start-clip_start;
          read_i=read_i+1
          continue 
        if map_type == 1 and read_i <clip_pad :
          supports_alt=True
        elif map_type == 2 and read_i >=len(read.query_sequence)-clip_pad :
          supports_alt=True
        elif map_type == 3:
          supports_alt=True
        else:
          supports_alt=False
        alt_color=SupportsAltColor(supports_alt)
        ok = ok and action_per_cigar_unit(img_row,read,ref_i,read_i,op,image_start_pos,alt_color,mapping_color,strand_color,ref_bases)
        ref_i=ref_i+1
        read_i=read_i+1
    elif op==1:
        # Insert op.
      if map_type == 1 and read_i <clip_pad :
        supports_alt=True
      elif map_type == 2 and read_i >=clip_pad :
        supports_alt=True
      elif map_type==3:
        supports_alt=True
      else:
        supports_alt=False
      alt_color=SupportsAltColor(supports_alt)
      ok = action_per_cigar_unit(img_row,read,ref_i-1,read_i,op,image_start_pos,alt_color,mapping_color,strand_color,ref_bases)
      read_i += op_len;
    elif op==2 or op==3 :
        # Delete op.
      if map_type == 1 and read_i <clip_pad :
        supports_alt=True
      elif map_type == 2 and read_i >=clip_pad :
        supports_alt=True
      elif map_type==3:
        supports_alt=True
      else:
        supports_alt=False
      alt_color=SupportsAltColor(supports_alt)
      ok = action_per_cigar_unit(img_row,read,ref_i,read_i - 1,op,image_start_pos,alt_color,mapping_color,strand_color,ref_bases)
      ref_i += op_len;
    elif op==5 or op==6 :
      op_ig=op_ig+1
        # Hardclipped and pad ops.  Do nothing.
      #  print("Ignored ops")       
    else :
      print(str(op)+":Unrecognized CIGAR op")

    # Bail out if we found this read had a low-quality base at the
    # call site.
    if not ok:
      return False
  #print("base_len:"+str(len(img_row.base)))
  #print(img_row.base)
  if len(img_row.base) == 0:
    return False
  place_hold_right=351-len(img_row.base)
  if place_hold_right>0:
#    if map_type == 3:
#       print('place_hold_right:'+str(place_hold_right))
    img_row.place_hold(False,place_hold_right)
  if place_hold_right<0:
    img_row.place_hold(False,place_hold_right)
 #img_row.place_hold(False,col)
 # print("base:"+str(len(img_row.base) ))
  return img_row


def make_alu_examples(hparams,genotype_file,debug_mode=0,shuffle_depth=95):
  record=[]
  print('make Alu trfrecord ....')
  record_num=0
  with open(genotype_file, 'r', encoding='utf-8') as f:
    for record_each in f:
      record_num=record_num+1
#      if record_num >100:
#        break
      chr,pos,gt,data_type=record_each.strip().split('\t')
      print(record_each)
      if not os.path.isfile(hparams.split_softclipped+'/'+str(data_type)+'_'+str(chr)+":"+str(int(pos)-50)+"-"+str(int(pos)+50)+"_mapRef.sam"):
        continue
#      if data_type=='NA12878' and gt==0:
#        continue
      #record_num=record_num+1
      if record_num%100==0:
        print("Generate tfrecord :{0}%,{1} /26110".format(round((record_num + 1) * 100 / 26110),record_num), end="\n")
#      if record_num >500:
#        break
      #print(data_type)
      img_total=ImageRow()
      alu_call=DV_call(chr,pos,data_type)
      img_row_num=0
      ref_bases=alu_call.reference_seq.fetch(reference=chr,start=int(pos)-176,end=int(pos)+175)
     # for tmp_i in range(0,len(ref_bases)):
        #print(tmp_i)
     #   ref_bases[tmp_i]=ref_bases[tmp_i].upper()
      #print(ref_bases)
      ref_rows = ([encode_ref(ref_bases)] *options_.reference_band_height)
      for img_row_each in ref_rows:
        img_row_num=img_row_num+1
        img_total.base.extend(img_row_each.base)
        img_total.base_quality.extend(img_row_each.base_quality)
        img_total.mapping_quality.extend(img_row_each.mapping_quality)
        img_total.on_positive_strand.extend(img_row_each.on_positive_strand)
        img_total.supports_alt.extend(img_row_each.supports_alt)
        img_total.matches_ref.extend(img_row_each.matches_ref)
        img_total.height=img_total.height+1

       
      #support_alu_reads={}
      #with open(hparams.support_alt_reads+'/'+str(data_type)+"_"+str(chr)+":"+str(int(pos)-50)+"-"+str(int(pos)+50)+".txt", 'r', encoding='utf-8') as f2:
      #  for read_name in f2:
      #    support_alu_reads[read_name.strip()]=True
      example = tf.train.Example()
      features = example.features
      for read in alu_call.reads_mapRef:
        #print(support_alt)
        image_start_pos=alu_call.image_start_pos
        img_row_each=EncodeRead(-1,0,alu_call,read,image_start_pos,debug_mode)
        #print(img_row_each.base)
        #sys.exit()
        if img_row_each:
          img_row_num=img_row_num+1
          img_total.base.extend(img_row_each.base)
          img_total.base_quality.extend(img_row_each.base_quality)
          img_total.mapping_quality.extend(img_row_each.mapping_quality)
          img_total.on_positive_strand.extend(img_row_each.on_positive_strand)
          img_total.supports_alt.extend(img_row_each.supports_alt)
          img_total.matches_ref.extend(img_row_each.matches_ref)
     #     print(img_row_each.supports_alt)
          img_total.height=img_total.height+1
 
      for read in alu_call.reads_mapClipR:
        clip_pad=read.next_reference_start
        #print(support_alt)
        image_start_pos=alu_call.image_start_pos
        img_row_each=EncodeRead(2,clip_pad,alu_call,read,image_start_pos,debug_mode)
       #print(img_row_each.base)
        #sys.exit()
        if img_row_each:
          img_row_num=img_row_num+1
          img_total.base.extend(img_row_each.base)
          img_total.base_quality.extend(img_row_each.base_quality)
          img_total.mapping_quality.extend(img_row_each.mapping_quality)
          img_total.on_positive_strand.extend(img_row_each.on_positive_strand)
          img_total.supports_alt.extend(img_row_each.supports_alt)
          img_total.matches_ref.extend(img_row_each.matches_ref)
          img_total.height=img_total.height+1
      #    print(img_row_each.supports_alt)

      for read in alu_call.reads_mapClipL:
        clip_pad=read.next_reference_start
        #print(support_alt)
        image_start_pos=alu_call.image_start_pos
        img_row_each=EncodeRead(1,clip_pad,alu_call,read,image_start_pos,debug_mode)
        if img_row_each:
          img_row_num=img_row_num+1
          img_total.base.extend(img_row_each.base)
          img_total.base_quality.extend(img_row_each.base_quality)
          img_total.mapping_quality.extend(img_row_each.mapping_quality)
          img_total.on_positive_strand.extend(img_row_each.on_positive_strand)
          img_total.supports_alt.extend(img_row_each.supports_alt)
          img_total.matches_ref.extend(img_row_each.matches_ref)
          img_total.height=img_total.height+1
      #    print(img_row_each.supports_alt)


      for read in alu_call.reads_mapDiscord:
        clip_pad=0
        #print(support_alt)
        image_start_pos=alu_call.image_start_pos
#        print('img_row_num:'+str(img_row_num))
        img_row_each=EncodeRead(3,clip_pad,alu_call,read,image_start_pos,debug_mode)
        #print(img_row_each.base)
        #sys.exit()
        if img_row_each:
          img_row_num=img_row_num+1
          img_total.base.extend(img_row_each.base)
          img_total.base_quality.extend(img_row_each.base_quality)
          img_total.mapping_quality.extend(img_row_each.mapping_quality)
          img_total.on_positive_strand.extend(img_row_each.on_positive_strand)
          img_total.supports_alt.extend(img_row_each.supports_alt)
          img_total.matches_ref.extend(img_row_each.matches_ref)
          img_total.height=img_total.height+1

      feature_total=[]
      img_total.base=np.array(img_total.base).reshape((img_total.height,-1))
      img_total.base_quality=np.array(img_total.base_quality).reshape((img_total.height,-1))
      img_total.mapping_quality=np.array(img_total.mapping_quality).reshape((img_total.height,-1))
      img_total.on_positive_strand=np.array(img_total.on_positive_strand).reshape((img_total.height,-1))
      img_total.supports_alt=np.array(img_total.supports_alt).reshape((img_total.height,-1))
      img_total.matches_ref=np.array(img_total.matches_ref).reshape((img_total.height,-1))

      if img_total.height-5 >shuffle_depth:
        rs = np.array(random.sample(range(5, img_total.height), shuffle_depth))
        rs=np.append(rs,[0,1,2,3,4])
        rs.sort()
        img_total.base=img_total.base[rs,]
        img_total.base_quality=img_total.base_quality[rs,]
        img_total.mapping_quality=img_total.mapping_quality[rs,]
        img_total.on_positive_strand=img_total.on_positive_strand[rs,]
        img_total.supports_alt=img_total.supports_alt[rs,]
        img_total.matches_ref=img_total.matches_ref[rs,]
        img_total.height=shuffle_depth
      img_raw_len=len(img_total.base)
      for i in range(img_raw_len,hparams.height):
        img_total.height=img_total.height+1
        img_row_num=img_row_num+1
        img_total.base=np.concatenate((img_total.base,np.array([[0]*351])),axis=0)
        img_total.base_quality=np.concatenate((img_total.base_quality,np.array([[0]*351])),axis=0)
        img_total.mapping_quality=np.concatenate((img_total.mapping_quality,np.array([[0]*351])),axis=0)
        img_total.on_positive_strand=np.concatenate((img_total.on_positive_strand,np.array([[0]*351])),axis=0)
        img_total.supports_alt=np.concatenate((img_total.supports_alt,np.array([[0]*351])),axis=0)
        img_total.matches_ref=np.concatenate((img_total.matches_ref,np.array([[0]*351])),axis=0)
      if len(img_total.base) >100:
        print(np.array(img_total.base).shape)
        break
      feature_total.append([img_total.base])
      feature_total.append([img_total.base_quality])
      feature_total.append([img_total.mapping_quality])
      feature_total.append([img_total.on_positive_strand])
      feature_total.append([img_total.supports_alt])
      feature_total.append([img_total.matches_ref])
      feature_total=np.stack(feature_total,axis=-1).flatten()

      example = tf.train.Example (
        features=tf.train.Features(
            feature={
                'img_data' : tf.train.Feature(float_list=tf.train.FloatList(value=feature_total)),
                'label' : tf.train.Feature(int64_list=tf.train.Int64List(value=[int(gt)])),
                'height' : tf.train.Feature(int64_list=tf.train.Int64List(value=[img_total.height]))
            }))


      yield data_type,example

def generate_tfrecord_datasets(hparams):
  """Writes out TFRecords files for training, evaluation, and test datasets."""
  if not os.path.exists(hparams.out_dir):
    os.makedirs(hparams.out_dir)

  # Fraction of examples in each dataset.
  train_eval_test_split = [0.7, 0.2, 0.1]
  num_train_examples = 0
  num_eval_examples = 0
  num_test_examples = 0
  # Generate training, test, and evaluation examples.
  with TFRecordWriter(os.path.join(hparams.out_dir, _TRAIN)) as train_out, \
       TFRecordWriter(os.path.join(hparams.out_dir, _EVAL)) as eval_out, \
       TFRecordWriter(os.path.join(hparams.out_dir, _TEST)) as test_out:
    all_examples = make_alu_examples(hparams,'input_gt.txt')
  
    #print(all_examples.on_positive_strand[0])
    for data_type,example in all_examples:
      #print(example.on_positive_strand[0])
      #break
      ran_i=random.random()
      if data_type == 'HG002':
        test_out.write(example)
        num_test_examples += 1
      if ran_i <0.2:
        eval_out.write(example)
        num_eval_examples += 1
      else:
        train_out.write(example)
        num_train_examples += 1

  print('# of training examples: %d' % num_train_examples)
  print('# of evaluation examples: %d' % num_eval_examples)
  print('# of test examples: %d' % num_test_examples)
def make_test_dataset(hparams,shuffle_depth):
  num_test_examples = 0
  if os.path.isfile('discord_read_bwa.tar.gz'):
    print('resource existed !')
  else:
    print('copy resource existed ....')
    os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_data/* .')
    os.system('cp -r /content/drive/Shareddrives/ibicqupt/deepalu_data/reference .')
    print('Unpacking resource data ...')
    os.system('tar -xzf discord_read_bwa.tar.gz')
    os.system('tar -xzf split_softclipped_sort.tar.gz')
  with TFRecordWriter(os.path.join(hparams.out_dir, 'test.tfrecord')) as test_out:
    all_examples = make_alu_examples(hparams,'input_gt_HG002.txt',0,shuffle_depth)
    for data_type,example in all_examples:
        test_out.write(example)
        num_test_examples += 1
  print('# of training examples: %d' % num_test_examples)

def make_other_dataset(hparams,input_gt_file,output_file,split_softclipped_file,debug_mode=0,):
  num_test_examples = 0
  if os.path.isfile(split_softclipped_file):
    print('resource existed !')
  else:
    print('copy resource existed ....')
    os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_data/* .')
    os.system('cp -r /content/drive/Shareddrives/ibicqupt/deepalu_data/reference .')
    print('Unpacking resource data ...')
 #   os.system('tar -xzf discord_read_bwa.tar.gz')
    os.system('tar -xzf '+split_softclipped_file)
  hparams.split_softclipped=split_softclipped_file.strip('.tar.gz')
  with TFRecordWriter(os.path.join(hparams.out_dir, output_file)) as test_out:
    all_examples = make_alu_examples(hparams,input_gt_file,debug_mode)
    for data_type,example in all_examples:
        test_out.write(example)
        num_test_examples += 1
  print('# of training examples: %d' % num_test_examples)

def get_dataset(hparams, filename, num_epochs):
  """Reads in and processes the TFRecords dataset.

  Builds a pipeline that returns pairs of features, label.
  """

  # Define field names, types, and sizes for TFRecords.
  proto_features = {
      'img_data':
          tf.io.FixedLenSequenceFeature(shape=[], dtype=tf.float32,allow_missing=True),
      'label':
          tf.io.FixedLenFeature(shape=[1], dtype=tf.int64),
      'height':
          tf.io.FixedLenFeature(shape=[1], dtype=tf.int64),
  }

  def _process_input(proto_string):
    """Helper function for input function that parses a serialized example."""

    parsed_features = tf.io.parse_single_example(
        serialized=proto_string, features=proto_features)

    feature_columns = []
    features=[]
    feature_key=[
                 'base',
                 'base_quality',
                 'mapping_quality',
                 'on_positive_strand',
                 'supports_alt',
                 'matches_ref'
                 ]
    label = parsed_features['label']
    features = tf.reshape(parsed_features['img_data'],[hparams.height,351,6]) 
    return features, label

  ds = tf.data.TFRecordDataset(filenames=filename)
  ds = ds.map(map_func=_process_input)
  return ds

import matplotlib.pyplot as plt
def run_test(hparams, use_existing_data=True, seed=1):
  """Creates a model, runs training and evaluation."""

  # Set seed for reproducibility.  
  random.seed(seed)
  tf.random.set_seed(seed)

 # os.system('mv HG002_combine.tfrecord test.tfrecord')
  if os.path.isfile('test.tfrecord'):
    print("Train dataset exist!")      
  else:
    print("Transfer dataset from google drive ......")
#    os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test.tfrecord .')
 #   os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/HG002_combine.tfrecord test.tfrecord')
    print("Transfer finished ......")

#  train_dataset = get_dataset(
#      hparams, filename=_TRAIN, num_epochs=10)
#  eval_dataset = get_dataset(
#      hparams, filename=_EVAL, num_epochs=10)
  test_dataset = get_dataset(
      hparams, filename=_TEST, num_epochs=10)
#  train_dataset = train_dataset.shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=256)
#  eval_dataset = eval_dataset.shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=108)
  test_dataset_0 = test_dataset
  test_dataset = test_dataset.batch(batch_size=128)
  #NA12878_dataset = get_dataset(
  #    hparams, filename=os.path.join(hparams.out_dir, 'NA12878.tfrecord'), num_epochs=10)
  #NA12878_dataset = NA12878_dataset.repeat(hparams.total_epochs).shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=128)
   #print("1")
  #for image_features in test_dataset:
  #  image_raw = image_features['base'].numpy()
 #   print(image_raw)
  filepath="/content/drive/Shareddrives/ibicqupt/deepalu_data/weights/val_best_model"
  if os.path.isfile(filepath+'/variables/variables.data-00000-of-00001'):
    print("Load existed best model ......")   
    model = keras.models.load_model(filepath)
  else:
    print("Build model at first time ......")
    optimizer = tf.keras.optimizers.Adam(lr=hparams.learning_rate)
    #tensorboard_callback = tf.keras.callbacks.TensorBoard(
    #    hparams.log_dir, histogram_freq=1)
    model = build_model(hparams)
  #  model = build_model()
    model.compile(
        optimizer=optimizer,
        loss=tf.keras.losses.sparse_categorical_crossentropy,
        metrics=['accuracy'])

    model.load_weights("/content/drive/Shareddrives/ibicqupt/deepalu_data/weights/final_model/cp-00.ckpt")
  predict=model.predict(test_dataset)
  i=0
  total_label=list()
  for each_dt in test_dataset_0:
    dt,label=each_dt
    label = tf.make_tensor_proto(label)
    label=tf.make_ndarray(label)[0] 
    total_label.append(label)
  num_00=0
  num_01=0
  num_02=0
  num_10=0
  num_11=0
  num_12=0
  num_20=0
  num_21=0
  num_22=0
  print(len(total_label))
  for i in (range(0,len(total_label))): 
    j=np.argmax(predict[i,])
    label=total_label[i]
    if j==label and j==0:
      num_00=num_00+1
    elif j==label and j==1:
      num_11=num_11+1
    elif j==label and j==2:
      num_22=num_22+1
    elif label==0 and j==1 :
      num_01=num_01+1
    elif label==0 and j==2 :
      num_02=num_02+1
    elif label==1 and j==0 :
      num_10=num_10+1
    elif label==1 and j==2 :
      num_12=num_12+1
    elif label==2 and j==0 :
      num_20=num_20+1
    elif label==2 and j==1 :
      num_21=num_21+1
    else:
      print(label,j)
  print('00',num_00)
  print('01',num_01)
  print('02',num_02)
  print('10',num_10)
  print('11',num_11)
  print('12',num_12)
  print('20',num_20)
  print('21',num_21)
  print('22',num_22)
##  print(np.array(predict).shape)
  print('Load last model complete. Obtaining final metrics...')
  test_metrics = model.evaluate(test_dataset, verbose=2)
  print('Previous final test metrics - loss: %f - accuracy: %f' %(test_metrics[0], test_metrics[1]))
  i=0
  k=6
  genotype_file='input_gt_HG002.txt'
  detail_info_test=[]
  with open(genotype_file, 'r', encoding='utf-8') as f:
    for record_each in f:
      chr,pos,gt,data_type=record_each.strip().split('\t')
      if data_type == 'HG002':
        detail_info_test.append(record_each.strip())
  with open('predict_res.txt', 'w', encoding='utf-8') as res_f:
    for data_each in test_dataset_0:
  #    break
      j=np.argmax(predict[i,])
      max_t=max(predict[i,])
      info_t=detail_info_test[i]
      res_f.write('record:'+info_t+'\t'+str(j)+'\t'+str(max_t)+'\n')
      i=i+1
'''    
      if j!=total_label[i]:
      feature,label=data_each
      plt.figure(figsize=(10,10))
      plt.subplot(k,1,1)
      plt.imshow(feature[0:100,0:351,0], cmap='gray')
      plt.subplot(k,1,2)
      plt.imshow(feature[0:100,0:351,1], cmap='gray')
      plt.subplot(k,1,3)
      plt.imshow(feature[0:100,0:351,2], cmap='gray')
      plt.subplot(k,1,4)
      plt.imshow(feature[0:100,0:351,3], cmap='gray')
      plt.subplot(k,1,5)
      plt.imshow(feature[0:100,0:351,4], cmap='gray')
      plt.subplot(k,1,6)
      plt.imshow(feature[0:100,0:351,5], cmap='gray')
      plt.xlabel(str(total_label[i])+'-'+str(j))
      plt.savefig('not_match_img/'+str(i)+'_'+str(total_label[i])+'-'+str(j)+'.png')
    i=i+1
'''
#os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/eval.tfrecord test.tfrecord')
#os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test.tfrecord test.tfrecord')
run_test(options_,use_existing_data=True)
#make_test_dataset(options_,10)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_10.tfrecord ')
#make_test_dataset(options_,15)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_15.tfrecord ')
#make_test_dataset(options_,20)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_20.tfrecord ')
#make_test_dataset(options_,25)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_25.tfrecord ')
#make_test_dataset(options_,30)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_30.tfrecord ')
#make_test_dataset(options_,35)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_35.tfrecord ')
#make_test_dataset(options_,40)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_40.tfrecord ')
#make_test_dataset(options_,45)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_45.tfrecord ')
#make_test_dataset(options_,50)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_50.tfrecord ')
#make_test_dataset(options_,55)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_55.tfrecord ')
#make_test_dataset(options_,60)
#run_test(options_,use_existing_data=True)
#os.system('cp test.tfrecord /content/drive/Shareddrives/ibicqupt/deepalu_data/input_tfrecord/test_60.tfrecord ')
#    plt.subplot(5,5,i+1)
#    plt.xticks([])
#    plt.yticks([])
#    plt.grid(False)
#    plt.imshow(train_images[i], cmap=plt.cm.binary)
#    plt.xlabel(class_names[train_labels[i]])
#plt.show()
#for data_each in train_dataset.take(10):
#  feature,label=data_each
#  print(label.numpy())
#  if label.numpy()[0]==1:
#  print(label)
 # print(feature[1,0:100,0:351,1])
#  plt.imshow(feature[7,0:100,0:351,0], cmap='gray')

#    plt.subplot(5,5,i+1)
#    plt.xticks([])
#    plt.yticks([])
#    plt.grid(False)
#    plt.imshow(train_images[i], cmap=plt.cm.binary)
#    plt.xlabel(class_names[train_labels[i]])
#plt.show()
#for data_each in train_dataset.take(10):
#  feature,label=data_each
#  print(label.numpy())
#  if label.numpy()[0]==1:
#  print(label)
 # print(feature[1,0:100,0:351,1])
#  plt.imshow(feature[7,0:100,0:351,0], cmap='gray')

#    plt.subplot(5,5,i+1)
#    plt.xticks([])
#    plt.yticks([])
#    plt.grid(False)
#    plt.imshow(train_images[i], cmap=plt.cm.binary)
#    plt.xlabel(class_names[train_labels[i]])
#plt.show()
#for data_each in train_dataset.take(10):
#  feature,label=data_each
#  print(label.numpy())
#  if label.numpy()[0]==1:
#  print(label)
 # print(feature[1,0:100,0:351,1])
#  plt.imshow(feature[7,0:100,0:351,0], cmap='gray')

#    plt.subplot(5,5,i+1)
#    plt.xticks([])
#    plt.yticks([])
#    plt.grid(False)
#    plt.imshow(train_images[i], cmap=plt.cm.binary)
#    plt.xlabel(class_names[train_labels[i]])
#plt.show()
#for data_each in train_dataset.take(10):
#  feature,label=data_each
#  print(label.numpy())
#  if label.numpy()[0]==1:
#  print(label)
 # print(feature[1,0:100,0:351,1])
#  plt.imshow(feature[7,0:100,0:351,0], cmap='gray')

import matplotlib.pyplot as plt
 input_gt_file='input_gt_HG002.txt'
 output_file='HG002.tfrecord'
 split_softclipped_file='split_softclipped_sort_HG002_combine.tar.gz'
! cp drive/Shareddrives/ibicqupt/deepalu_data/input_data/input_gt_HG002_combine.txt .
! cp drive/Shareddrives/ibicqupt/deepalu_data/input_data/split_softclipped_sort_HG002_combine.tar.gz .
!tar -xzf split_softclipped_sort_HG002_combine.tar.gz
#!sed -n '67p' input_gt_HG002.txt input_gt_other.txt 
 make_other_dataset(options_,input_gt_file,output_file,split_softclipped_file,0)
 other_dataset = get_dataset(
         options_, filename=output_file, num_epochs=10)
# for data_each in other_dataset:
#      feature,label=data_each
#      k=10
#      plt.figure(figsize=(10,10))
#      plt.subplot(k,1,1)
#      plt.imshow(feature[0:100,0:351,0], cmap='gray')
#      plt.subplot(k,1,2)
#      plt.imshow(feature[0:100,0:351,1], cmap='gray')
#      plt.subplot(k,1,3)
#      plt.imshow(feature[0:100,0:351,2], cmap='gray')
#      plt.subplot(k,1,4)
#      plt.imshow(feature[0:100,0:351,3], cmap='gray')
#      plt.subplot(k,1,5)
#      plt.imshow(feature[0:100,0:351,4], cmap='gray')
#      plt.subplot(k,1,6)
#      plt.imshow(feature[0:100,0:351,5], cmap='gray')
    #  plt.subplot(k,1,7)
    #  tmp_head=feature[0:90,0:351,4].numpy()
   #   print(tmp_head)
    #  tmp_head=np.append(tmp_head,[[254]*351]*10)
    #  tmp_head=tmp_head.reshape(100,351)
    #  print(tmp_head)
    #  plt.imshow(tmp_head, cmap='gray')
#print(tf.zeros([10]))

generate_tfrecord_datasets(options_)
import matplotlib.pyplot as plt
hparams=options_
train_dataset = get_dataset(
      hparams, filename=_TRAIN, num_epochs=10)
eval_dataset = get_dataset(
      hparams, filename=_EVAL, num_epochs=10)
test_dataset = get_dataset(
      hparams, filename=_TEST, num_epochs=10)
train_dataset = train_dataset.batch(batch_size=256)
eval_dataset = eval_dataset.batch(batch_size=128)
test_dataset = test_dataset.batch(batch_size=128)
  #NA12878_dataset = get_dataset(
  #    hparams, filename=os.path.join(hparams.out_dir, 'NA12878.tfrecord'), num_epochs=10)
  #NA12878_dataset = NA12878_dataset.repeat(hparams.total_epochs).shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=128)
   #print("1")
for data_each in train_dataset.take(10):
  feature,label=data_each
#  print(label.numpy())
#  if label.numpy()[0]==1:
  print(label)
 # print(feature[1,0:100,0:351,1])
  plt.imshow(feature[7,0:100,0:351,0], cmap='gray')
# img_row_each.base)
# img_row_each.base_quality)
# img_row_each.mapping_quality)
# img_row_each.on_positive_strand)
# img_row_each.supports_alt)
# img_row_each.matches_ref)

#!apt-get install samtools bcftools
#!cp 1000g_10_gt_total.bed /content/drive/Shareddrives/ibicqupt/deepalu_data/
#!cp ccHG00096.final.cram .
#!mkdir regions
#!wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240114/HG00096.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240114/HG00096.final.cram.crai ;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240115/HG00097.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240115/HG00097.final.cram.crai ;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240116/HG00099.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240116/HG00099.final.cram.crai;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240117/HG00100.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240117/HG00100.final.cram.crai ;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240118/HG00101.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240118/HG00101.final.cram.crai ;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240119/HG00102.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240119/HG00102.final.cram.crai ;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240120/HG00103.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240120/HG00103.final.cram.crai ;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240121/HG00105.final.cram.crai ;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR324/ERR3240121/HG00105.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR323/ERR3239480/NA12718.final.cram.crai ;wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR323/ERR3239480/NA12718.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR323/ERR3239334/NA12878.final.cram & wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR323/ERR3239334/NA12878.final.cram.crai ;
#!wait
#!mv *.cram cz
#!mv *.crai /content/drive/Shareddrives/ibicqupt/deepalu_data/1000g_bam/download_bam
#!cp HG00096.final.cram /content/drive/Shareddrives/ibicqupt/deepalu_data/1000g_bam/
#!bash order.sh
#!cat hglft_genome_5bbd4_c10660.bed |perl -npe "s/\t/:/;s/\t/\-/"|while read record ;do samtools view -T /content/drive/Shareddrives/ibicqupt/deepalu_data/1000g_bam/Homo_sapiens_assembly38.fasta HG00096.final.cram $record -O BAM -o regions/HG00096_${record}.bam;echo $record;done
#!ls regions|while read file;do mv regions/$file regions/NA12878_$file;done
#!rm HG00096.final.cram
#!cp HG00096.final.cram.crai /content/drive/Shareddrives/ibicqupt/deepalu_data/1000g_bam/
#! ls -lh 
#!cp  /content/drive/Shareddrives/ibicqupt/deepalu_data/region.tar.gz .
#!cp  /content/drive/Shareddrives/ibicqupt/deepalu_data/suppport_alu.tar.gz .
#!cp  /content/drive/Shareddrives/ibicqupt/deepalu_data/suppport_alu.tar.gz .
#!cp  /content/drive/Shareddrives/ibicqupt/deepalu_data/support_alt_reads_NA12878.tar.gz .
#!cp -r /content/drive/Shareddrives/ibicqupt/deepalu_data/NA12878_valiate/ .
#!tar -xzf support_alt_reads_NA12878.tar.gz 
#!tar -xzf region.tar.gz 
#!tar -xzf suppport_alu.tar.gz
#!pip3 uninstall protobuf -y
#!pip3 install protobuf
#!kill `ps -ef |grep "note"|perl -npe "s/ +/\t/g"|cut -f2|head --lines=1`
#!kill 63
#!wget ftp://ftp.sra.ebi.ac.uk/vol1/run/ERR323/ERR3239334/NA12878.final.cram 
#!mv NA12718.final.cram  /content/drive/Shareddrives/ibicqupt/deepalu_data/1000g_bam/
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta .
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.alt .
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.dict .
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.amb .
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.ann .
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.bwt .
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.pac .
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.sa .
#!gsutil cp gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.fai .
#!mv Homo* /content/drive/Shareddrives/ibicqupt/deepalu_data/1000g_bam/
#!wget https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-x86_64.sh
#!wget https://raw.githubusercontent.com/broadinstitute/gatk/master/scripts/funcotator/data_sources/gnomAD/b37ToHg38.over.chain
#!bash convertVCF.sh
#!cp drive/Shareddrives/ibicqupt/deepalu_data/1000g_bam/Homo_sapiens_assembly38.fasta* .
#!gsutil cp \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.dict" \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta" \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.alt" \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.amb" \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.ann" \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.bwt" \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.pac" \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.64.sa" \
#  "gs://genomics-public-data/resources/broad/hg38/v0/Homo_sapiens_assembly38.fasta.fai" \
#  /content/drive/Shareddrives/ibicqupt/deepalu_data/
!cp /content/drive/Shareddrives/ibicqupt/deepalu_data/input_data/* .
!cp -r /content/drive/Shareddrives/ibicqupt/deepalu_data/reference .
#!cp drive/MyDrive/Colab\ Notebooks/1000g_10_gt_total_genotype.txt .
!tar -xzf discord_read_bwa.tar.gz
!tar -xzf split_softclipped.tar.gz

from google.colab import drive
drive.mount('/content/drive')

from __future__ import absolute_import, division, print_function
import math

def get_model(options_):
    model = InceptionV3(num_class=3)
    model.build(input_shape=(None, 100, 351,6))
    model.summary()

    return model


if __name__ == '__main__':
    # GPU settings
    gpus = tf.config.experimental.list_physical_devices('GPU')
    if gpus:
        for gpu in gpus:
            tf.config.experimental.set_memory_growth(gpu, True)


    # get the original_dataset
    use_existing_data=True
    if not use_existing_data:
      print('Generating data...')
      generate_tfrecord_datasets(hparams)
    else:
      if os.path.isfile('train.tfrecord'):
        print("Train dataset exist!")      
      else:
        print("Transfer dataset from google drive ......")
        os.system('cp /content/drive/Shareddrives/ibicqupt/deepalu_data/*.tfrecord .')
        print("Transfer finished ......")

    train_dataset = get_dataset(
        options_, filename=_TRAIN, num_epochs=10)
    valid_dataset = get_dataset(
        options_, filename=_EVAL, num_epochs=10)
    test_dataset = get_dataset(
        options_, filename=_TEST, num_epochs=10)
    train_dataset = train_dataset.shuffle(buffer_size=10000, reshuffle_each_iteration=True).batch(batch_size=512)
    valid_dataset = valid_dataset.batch(batch_size=256)
    test_dataset = test_dataset.batch(batch_size=128)
    for data_each in train_dataset.take(10):
      feature,label=data_each
  #    print(label)
  #  print(train_dataset)
    train_count, valid_count, test_count = 2400,7200,14800


    # create model
    model = get_model(options_)

    # define loss and optimizer
    loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
    optimizer = tf.keras.optimizers.Adadelta()

    train_loss = tf.keras.metrics.Mean(name='train_loss')
    train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')

    valid_loss = tf.keras.metrics.Mean(name='valid_loss')
    valid_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='valid_accuracy')

    @tf.function
    def train_step(images, labels):
        with tf.GradientTape() as tape:
            predictions = model(images, include_aux_logits=False, training=True)
            loss_aux = loss_object(y_true=labels, y_pred=predictions.aux_logits)
            loss = 0.5 * loss_aux + 0.5 * loss_object(y_true=labels, y_pred=predictions.logits)
        gradients = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(grads_and_vars=zip(gradients, model.trainable_variables))

        train_loss(loss)
        train_accuracy(labels, predictions.logits)

    @tf.function
    def valid_step(images, labels):
        predictions = model(images, include_aux_logits=False, training=False)
        v_loss = loss_object(labels, predictions)

        valid_loss(v_loss)
        valid_accuracy(labels, predictions)

    # start training
    for epoch in range(options_.total_epochs):
        train_loss.reset_states()
        train_accuracy.reset_states()
        valid_loss.reset_states()
        valid_accuracy.reset_states()
        step = 0
        for images, labels in train_dataset:
            step += 1
            train_step(images, labels)
            print("Epoch: {}/{}, step: {}/{}, loss: {:.5f}, accuracy: {:.5f}".format(epoch + 1,
                                                                                     config.EPOCHS,
                                                                                     step,
                                                                                     math.ceil(train_count / config.BATCH_SIZE),
                                                                                     train_loss.result(),
                                                                                     train_accuracy.result()))

        for valid_images, valid_labels in valid_dataset:
            valid_step(valid_images, valid_labels)

        print("Epoch: {}/{}, train loss: {:.5f}, train accuracy: {:.5f}, "
              "valid loss: {:.5f}, valid accuracy: {:.5f}".format(epoch + 1,
                                                                  options_.total_epochs,
                                                                  train_loss.result(),
                                                                  train_accuracy.result(),
                                                                  valid_loss.result(),
                                                                  valid_accuracy.result()))

    model.save_weights(filepath=options_.out_dir, save_format='tf')

import tensorflow as tf
#from models.inception_modules import InceptionModule_1, InceptionModule_2, \
#    InceptionModule_3, InceptionModule_4, InceptionModule_5, InceptionAux, Preprocess
from collections import namedtuple

_InceptionOutputs = namedtuple("InceptionOutputs", ["logits", "aux_logits"])


class InceptionV3(tf.keras.Model):
    def __init__(self, num_class, aux_logits=True):
        super(InceptionV3, self).__init__()
        self.aux_logits = aux_logits
        self.preprocess = Preprocess()

        self.block_1 = tf.keras.Sequential([
            InceptionModule_1(filter_num=32),
            InceptionModule_1(filter_num=64),
            InceptionModule_1(filter_num=64)
        ])

        self.block_2 = tf.keras.Sequential([
            InceptionModule_2(),
            InceptionModule_3(filter_num=128),
            InceptionModule_3(filter_num=160),
            InceptionModule_3(filter_num=160),
            InceptionModule_3(filter_num=192),
        ])

        if self.aux_logits:
            self.AuxLogits = InceptionAux(num_classes=num_class)

        self.block_3 = tf.keras.Sequential([
            InceptionModule_4(),
            InceptionModule_5(),
            InceptionModule_5()
        ])
        self.avg_pool = tf.keras.layers.AvgPool2D(pool_size=(3, 3),
                                                  strides=1,
                                                  padding="valid")
        self.dropout = tf.keras.layers.Dropout(rate=0.2)
        self.flatten = tf.keras.layers.Flatten()
        self.fc = tf.keras.layers.Dense(units=num_class, activation=tf.keras.activations.linear)

    def call(self, inputs, training=None, mask=None, include_aux_logits=True):
        x = self.preprocess(inputs, training=training)
        x = self.block_1(x, training=training)
        x = self.block_2(x, training=training)
        if include_aux_logits and self.aux_logits:
            aux = self.AuxLogits(x)
        x = self.block_3(x, training=training)
        x = self.avg_pool(x)
        x = self.dropout(x, training=training)
        x = self.flatten(x)
        x = self.fc(x)
        if include_aux_logits and self.aux_logits:
            return _InceptionOutputs(x, aux)
        return x

class BasicConv2D(tf.keras.layers.Layer):
    def __init__(self, filters, kernel_size, strides, padding):
        super(BasicConv2D, self).__init__()
        self.conv = tf.keras.layers.Conv2D(filters=filters,
                                           kernel_size=kernel_size,
                                           strides=strides,
                                           padding=padding)
        self.bn = tf.keras.layers.BatchNormalization()
        self.relu = tf.keras.layers.ReLU()

    def call(self, inputs, training=None, **kwargs):
        output = self.conv(inputs)
        output = self.bn(output, training=training)
        output = self.relu(output)

        return output

class Preprocess(tf.keras.layers.Layer):
    def __init__(self):
        super(Preprocess, self).__init__()
        self.conv1 = BasicConv2D(filters=32,
                                 kernel_size=(3, 3),
                                 strides=2,
                                 padding="same")
        self.conv2 = BasicConv2D(filters=32,
                                 kernel_size=(3, 3),
                                 strides=1,
                                 padding="same")
        self.conv3 = BasicConv2D(filters=64,
                                 kernel_size=(3, 3),
                                 strides=1,
                                 padding="same")

        self.maxpool1 = tf.keras.layers.MaxPool2D(pool_size=(3, 3),
                                                  strides=2,
                                                  padding="same")
        self.conv4 = BasicConv2D(filters=80,
                                 kernel_size=(3, 3),
                                 strides=1,
                                 padding="same")
        self.conv5 = BasicConv2D(filters=192,
                                 kernel_size=(3, 3),
                                 strides=1,
                                 padding="same")
        self.maxpool2 = tf.keras.layers.MaxPool2D(pool_size=(3, 3),
                                                  strides=2,
                                                  padding="same")

    def call(self, inputs, training=None, **kwargs):
        x = self.conv1(inputs, training=training)
        x = self.conv2(x, training=training)
        x = self.conv3(x, training=training)
        x = self.maxpool1(x)
        x = self.conv4(x, training=training)
        x = self.conv5(x, training=training)
        x = self.maxpool2(x)

        return x


class InceptionAux(tf.keras.layers.Layer):
    def __init__(self, num_classes):
        super(InceptionAux, self).__init__()
        self.avg_pool = tf.keras.layers.AvgPool2D(pool_size=(5, 5),
                                                  strides=3,
                                                  padding="same")
        self.conv1 = BasicConv2D(filters=128,
                                 kernel_size=(1, 1),
                                 strides=1,
                                 padding="same")
        self.conv2 = BasicConv2D(filters=768,
                                 kernel_size=(5, 5),
                                 strides=1,
                                 padding="same")
        self.global_avg_pool = tf.keras.layers.GlobalAveragePooling2D()
        self.flat = tf.keras.layers.Flatten()
        self.fc = tf.keras.layers.Dense(units=num_classes, activation=tf.keras.activations.linear)

    def call(self, inputs, training=None, **kwargs):
        output = self.avg_pool(inputs)
        output = self.conv1(output, training=training)
        output = self.conv2(output, training=training)
        output = self.global_avg_pool(output)
        output = self.flat(output)
        output = self.fc(output)

        return output



class InceptionModule_1(tf.keras.layers.Layer):
    def __init__(self, filter_num):
        super(InceptionModule_1, self).__init__()
        # branch 0
        self.conv_b0_1 = BasicConv2D(filters=64,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")

        # branch 1
        self.conv_b1_1 = BasicConv2D(filters=48,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")

        self.conv_b1_2 = BasicConv2D(filters=64,
                                     kernel_size=(5, 5),
                                     strides=1,
                                     padding="same")

        # branch 2
        self.conv_b2_1 = BasicConv2D(filters=64,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")

        self.conv_b2_2 = BasicConv2D(filters=96,
                                     kernel_size=(3, 3),
                                     strides=1,
                                     padding="same")
        self.conv_b2_3 = BasicConv2D(filters=96,
                                     kernel_size=(3, 3),
                                     strides=1,
                                     padding="same")

        # branch 3
        self.avgpool_b3_1 = tf.keras.layers.AvgPool2D(pool_size=(3, 3),
                                                      strides=1,
                                                      padding="same")
        self.conv_b3_2 = BasicConv2D(filters=filter_num,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")

    def call(self, inputs, training=None, **kwargs):

        b0 = self.conv_b0_1(inputs, training=training)

        b1 = self.conv_b1_1(inputs, training=training)
        b1 = self.conv_b1_2(b1, training=training)

        b2 = self.conv_b2_1(inputs, training=training)
        b2 = self.conv_b2_2(b2, training=training)
        b2 = self.conv_b2_3(b2, training=training)

        b3 = self.avgpool_b3_1(inputs)
        b3 = self.conv_b3_2(b3, training=training)

        output = tf.keras.layers.concatenate([b0, b1, b2, b3], axis=-1)
        return output


class InceptionModule_2(tf.keras.layers.Layer):
    def __init__(self):
        super(InceptionModule_2, self).__init__()
        # branch 0
        self.conv_b0_1 = BasicConv2D(filters=384,
                                     kernel_size=(3, 3),
                                     strides=2,
                                     padding="valid")

        # branch 1
        self.conv_b1_1 = BasicConv2D(filters=64,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")
        self.conv_b1_2 = BasicConv2D(filters=96,
                                     kernel_size=(3, 3),
                                     strides=1,
                                     padding="same")
        self.conv_b1_3 = BasicConv2D(filters=96,
                                     kernel_size=(3, 3),
                                     strides=2,
                                     padding="valid")

        # branch 2
        self.maxpool_b2_1 = tf.keras.layers.MaxPool2D(pool_size=(3, 3),
                                                      strides=2,
                                                      padding="valid")

    def call(self, inputs, training=None, **kwargs):
        b0 = self.conv_b0_1(inputs, training=training)

        b1 = self.conv_b1_1(inputs, training=training)
        b1 = self.conv_b1_2(b1, training=training)
        b1 = self.conv_b1_3(b1, training=training)

        b2 = self.maxpool_b2_1(inputs)

        output = tf.keras.layers.concatenate([b0, b1, b2], axis=-1)
        return output


class InceptionModule_3(tf.keras.layers.Layer):
    def __init__(self, filter_num):
        super(InceptionModule_3, self).__init__()
        # branch 0
        self.conv_b0_1 = BasicConv2D(filters=192,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")

        # branch 1
        self.conv_b1_1 = BasicConv2D(filters=filter_num,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")
        self.conv_b1_2 = BasicConv2D(filters=filter_num,
                                     kernel_size=(1, 7),
                                     strides=1,
                                     padding="same")
        self.conv_b1_3 = BasicConv2D(filters=192,
                                     kernel_size=(7, 1),
                                     strides=1,
                                     padding="same")

        # branch 2
        self.conv_b2_1 = BasicConv2D(filters=filter_num,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")
        self.conv_b2_2 = BasicConv2D(filters=filter_num,
                                     kernel_size=(7, 1),
                                     strides=1,
                                     padding="same")
        self.conv_b2_3 = BasicConv2D(filters=filter_num,
                                     kernel_size=(1, 7),
                                     strides=1,
                                     padding="same")
        self.conv_b2_4 = BasicConv2D(filters=filter_num,
                                     kernel_size=(7, 1),
                                     strides=1,
                                     padding="same")
        self.conv_b2_5 = BasicConv2D(filters=192,
                                     kernel_size=(1, 7),
                                     strides=1,
                                     padding="same")

        # branch 3
        self.avgpool_b3_1 = tf.keras.layers.MaxPool2D(pool_size=(3, 3),
                                                      strides=1,
                                                      padding="same")
        self.conv_b3_2 = BasicConv2D(filters=192,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")

    def call(self, inputs, training=None, **kwargs):
        b0 = self.conv_b0_1(inputs, training=training)

        b1 = self.conv_b1_1(inputs, training=training)
        b1 = self.conv_b1_2(b1, training=training)
        b1 = self.conv_b1_3(b1, training=training)

        b2 = self.conv_b2_1(inputs, training=training)
        b2 = self.conv_b2_2(b2, training=training)
        b2 = self.conv_b2_3(b2, training=training)
        b2 = self.conv_b2_4(b2, training=training)
        b2 = self.conv_b2_5(b2, training=training)

        b3 = self.avgpool_b3_1(inputs)
        b3 = self.conv_b3_2(b3, training=training)

        output = tf.keras.layers.concatenate([b0, b1, b2, b3], axis=-1)
        return output


class InceptionModule_4(tf.keras.layers.Layer):
    def __init__(self):
        super(InceptionModule_4, self).__init__()
        # branch 0
        self.conv_b0_1 = BasicConv2D(filters=192,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")
        self.conv_b0_2 = BasicConv2D(filters=320,
                                     kernel_size=(3, 3),
                                     strides=2,
                                     padding="valid")

        # branch 1
        self.conv_b1_1 = BasicConv2D(filters=192,
                                     kernel_size=(1, 1),
                                     strides=1,
                                     padding="same")

        self.conv_b1_2 = BasicConv2D(filters=192,
                                     kernel_size=(1, 7),
                                     strides=1,
                                     padding="same")

        self.conv_b1_3 = BasicConv2D(filters=192,
                                     kernel_size=(7, 1),
                                     strides=1,
                                     padding="same")

        self.conv_b1_4 = BasicConv2D(filters=192,
                                     kernel_size=(3, 3),
                                     strides=2,
                                     padding="valid")


        # branch 2
        self.maxpool_b2_1 = tf.keras.layers.MaxPool2D(pool_size=(3, 3),
                                                      strides=2,
                                                      padding="valid")

    def call(self, inputs, training=None, **kwargs):
        b0 = self.conv_b0_1(inputs, training=training)
        b0 = self.conv_b0_2(b0, training=training)

        b1 = self.conv_b1_1(inputs, training=training)
        b1 = self.conv_b1_2(b1, training=training)
        b1 = self.conv_b1_3(b1, training=training)
        b1 = self.conv_b1_4(b1, training=training)

        b2 = self.maxpool_b2_1(inputs)

        output = tf.keras.layers.concatenate([b0, b1, b2], axis=-1)
        return output


class InceptionModule_5(tf.keras.layers.Layer):
    def __init__(self):
        super(InceptionModule_5, self).__init__()
        self.conv1 = BasicConv2D(filters=320,
                                 kernel_size=(1, 1),
                                 strides=1,
                                 padding="same")
        self.conv2 = BasicConv2D(filters=384,
                                 kernel_size=(1, 1),
                                 strides=1,
                                 padding="same")
        self.conv3 = BasicConv2D(filters=448,
                                 kernel_size=(1, 1),
                                 strides=1,
                                 padding="same")
        self.conv4 = BasicConv2D(filters=384,
                                 kernel_size=(1, 3),
                                 strides=1,
                                 padding="same")
        self.conv5 = BasicConv2D(filters=384,
                                 kernel_size=(3, 1),
                                 strides=1,
                                 padding="same")
        self.conv6 = BasicConv2D(filters=384,
                                 kernel_size=(3, 3),
                                 strides=1,
                                 padding="same")
        self.conv7 = BasicConv2D(filters=192,
                                 kernel_size=(1, 1),
                                 strides=1,
                                 padding="same")
        self.avgpool = tf.keras.layers.AvgPool2D(pool_size=(3, 3),
                                                 strides=1,
                                                 padding="same")

    def call(self, inputs, training=None, **kwargs):
        b0 = self.conv1(inputs, training=training)

        b1 = self.conv2(inputs, training=training)
        b1_part_a = self.conv4(b1, training=training)
        b1_part_b = self.conv5(b1, training=training)
        b1 = tf.keras.layers.concatenate([b1_part_a, b1_part_b], axis=-1)

        b2 = self.conv3(inputs, training=training)
        b2 = self.conv6(b2, training=training)
        b2_part_a = self.conv4(b2, training=training)
        b2_part_b = self.conv5(b2, training=training)
        b2 = tf.keras.layers.concatenate([b2_part_a, b2_part_b], axis=-1)
        b3 = self.avgpool(inputs)
        b3 = self.conv7(b3, training=training)

        output = tf.keras.layers.concatenate([b0, b1, b2, b3], axis=-1)
        return output

