#!python
# Copyright (c) 2012, Sven Thiele <sthiele78@gmail.com>
#
# This file is part of iggy.
#
# iggy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# iggy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with iggy.  If not, see <http://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from pyasp.asp import *
import argparse
from __iggy__ import query, utils, bioquali

if __name__ == '__main__':
       
    parser = argparse.ArgumentParser()
    parser.add_argument("networkfile",
                        help="influence graph in SIF format")
    parser.add_argument("observationfiles",
                        help="directory of observations in bioquali format")

    parser.add_argument('--no_zero_constraints',
			help="turn constraints on zero variations OFF, default is ON",
			action="store_true")

    parser.add_argument('--propagate_unambigious_influences',
			help="turn constraints ON that if all predecessor of a node have the same influence this must have an effect, default is ON",
			action="store_true")

    parser.add_argument('--no_founded_constraint',
			help="turn constraints OFF that every variation must be explained by an input, default is ON",
			action="store_true")

    parser.add_argument('--autoinputs',
			help="compute possible inputs of the network (nodes with indegree 0)",
			action="store_true")
			
    parser.add_argument('--show_repairs',type=int, default=-1,
			help="number of repairs to show, default is OFF, 0=all")
			
    parser.add_argument('--opt_graph',
			help="compute opt-graph repairs (allows also adding edges), default is only removing edges",
			action="store_true")
			

    args = parser.parse_args()
    
    net_string = args.networkfile
    obs_dir = args.observationfiles

    LC =args.propagate_unambigious_influences
    CZ= not (args.no_zero_constraints)
    FC= not (args.no_founded_constraint)

    print ' all observed changes must be explained by an predecessor'
    if LC : print ' unambigious influences propagate'
    if CZ : print ' no-change observations must be explained'
    if FC : print ' all observed changes must be explained by an input'
    
    print '\nReading network',net_string, '...',
    net = bioquali.readSIFGraph(net_string)
    print 'done.'
    edge_counter=0
    activation_counter=0
    inhibition_counter=0
    node_counter=0
    for a in net:
      if a.pred() == 'edge' : edge_counter+=1
      if a.pred() == 'obs_elabel' :
	if a.arg(2) == '1' : activation_counter+=1
        if a.arg(2) == '-1' : inhibition_counter+=1
      if a.pred() == 'vertex' : node_counter+=1
    print "   Nodes:",node_counter," Edges:",edge_counter," Activations:",activation_counter," Inhibitions:",inhibition_counter," Unspecified:",(edge_counter-(activation_counter+inhibition_counter))
    
    flist =  os.listdir(obs_dir)
    print '\nReading',len(flist),'observations from ',obs_dir, '...',
    MU = TermSet()
    for f in flist :
      exp= os.path.join(obs_dir,f)
      mu = bioquali.readProfile(exp)
      MU = MU.union(mu)
    print 'done.'

    if args.autoinputs :
      print '\nComputing input nodes ...',
      inputs = query.guess_inputs(net)
      net = net.union(inputs)
      print 'done.'
      print "   number of inputs:", len(inputs)
      
    net_with_data = net.union(MU)

    if not args.opt_graph :
      print '\nComputing minimal number of removed edges ...',
      (scenfit,repairs) = query.get_opt_remove_edges(net_with_data, LucaConstraint=LC, ConstrainedZero=CZ, FoundedConstraint=FC)
      print 'done.'
      print "   The network and data can reach a scenfit of",scenfit,'with',repairs,'removed edges.'

      if args.show_repairs >= 0 and repairs > 0:
	print '\nCompute optimal repairs...',
	repairs = query.get_opt_repairs_remove_edges(net_with_data,args.show_repairs, LucaConstraint=LC, ConstrainedZero=CZ, FoundedConstraint=FC)
	print 'done.'
	count=0
	for r in repairs :
	  count+=1
	  print 'Repair',str(count)+':'
	  utils.print_repairs(r)
    

    if args.opt_graph :
      print '\nComputing minimal number of changes add/remove edges ...',
      (scenfit,repairs) = query.get_opt_add_remove_edges(net_with_data, LucaConstraint=LC, ConstrainedZero=CZ, FoundedConstraint=FC)
      print 'done.'
      print "   The network and data can reach a scenfit of",scenfit,'with',repairs,'repairs.'

      
      if args.show_repairs >= 0 and repairs > 0:
	print '\nCompute optimal repairs...',
	repairs = query.get_opt_repairs_add_remove_edges(net_with_data,args.show_repairs, LucaConstraint=LC, ConstrainedZero=CZ, FoundedConstraint=FC)
	print 'done.'
	count=0
	for r in repairs :
	  count+=1
	  print 'Repair',str(count)+':'
	  utils.print_repairs(r)


    utils.clean_up()



