#!/usr/bin/ruby -w
#
# tsl - Shell script for running Two Sample Logo from the command
# line.
#
# Vladimir Vacic, University of California, Riverside
# Lilia Iakoucheva, The Rockefeller University, New York
# Predrag Radivojac, Indiana University, Bloomington
#
# Oct-15-2005

require "Template.rb"
require "TSL.rb"
require "Util.rb"


def usage
    temp =<<END

Usage: tsl -P <pos file> -N <neg file> -K[A|N] -O <out file> [options]
Creates a two sample logo for the given input filename.

Mandatory arguments:
  -P <positive sample file>
  -N <negative sample file>
  -K <kind of data>          A for amino acid, N for nucleic acid.
  -O <output file>           Output file name.

Run tsl -h to get a list of all options.
END
    puts temp
end



def help
    temp =<<END
Usage: tsl -P <pos file> -N <neg file> -K[A|N] -O <out file> [options]
Creates a two sample logo for the given input filename.

Mandatory arguments:
  -P <positive sample file>
  -N <negative sample file>
  -K <kind of data>          A for amino acid, N for nucleic acid.
  -O <output file>           Output file name.

Optional arguments:
  -A <box shrink factor>     Shrink factor of characters if option s 
                             (show box) is toggled. Defaults ot 0.5.
  -C <color scheme>          One of the following:        
                             amino_bw (Black and white)
                             amino_weblogo (WebLogo default colors)
                             amino_colors (Amino colors)
                             amino_shapley (Shapley colors)
                             amino_charge (Charge)
                             amino_hydro (Hydrophobicity)
                             amino_surface (Surface exposure)
                             amino_flex (Vihinen's flexibility)
                             amino_disorder (Disorder propencity)
                             nucleo_bw (Black and white)
                             nucleo_weblogo (WebLogo default colors)
                             nucleo_shapley (Shapley colors)
                             Defaults to amino_weblogo.
  -E <sequence end>          
  -F <format>                Format of output (EPS, GIF, PDF, PNG). 
                             Defaults to PNG.
  -H <logo height>           Height of output logo. Defaults to 5.
  -I <title>                 Text of title, enclosed in "" if more than one 
                             word.
  -M <first index>           Defaults to 1.
  -R <resolution>            Bitmap resolution. Defaults to 96.
  -S <sequence start>        Sequence start number. Defaults to 1.
  -T <statistical test>      T for t-test, B for binomial test.
                             Defaults to B.
  -U <units>                 Logo dimensions units (cm, inch, pixel, point).
                             Defaults to cm. 
  -V <p value>
  -W <logo width>            Width of output logo. Defaults to 8.
  -X <res units>             Resolution units when bitmap resolution is 
                             specified (ppi, ppc, ppp). Defaults to ppi.

Optional toggles (no values associated):
  -a                         Toggle antialiasing
  -b                         Toggle Bonferroni correction
  -f                         Toggle fixed height output characters 
  -o                         Toggle outlining of characters
  -s                         Toggle show box
  -x                         Toggle numbering along the x-axis
  -y                         Toggle labels on y-axis

END
    puts temp     
end



def init
    opts = Util.getopts('P:N:K:O:A:C:E:F:H:I:M:R:S:T:U:V:W:X:abfosxyh')

    if (opts['h'])
        help
        exit
    end

    # Check postive sample file
    if opts['P'] != nil
        if !FileTest.exists?(opts['P'])
            puts "Could not open positive sample file #{opts['P']}."
            usage
            exit
        end
    else
        puts "Positive sample file not specified, terminating."
        usage
        exit
    end

    # Check negative sample file
    if opts['N'] != nil
        if !FileTest.exists?(opts['N'])
            puts "Could not open negative input file #{opts['N']}."
            usage
            exit
        end
    else
        puts "Negative sample file not specified, terminating."
        usage
        exit
    end

    # Check input kind
    if opts['K']!=nil
        if opts['K']!="A" && opts['K']!="N"
            puts "Input kind must be A or N, but is #{opts['K']}."
            usage
            exit
        end
    else
        puts "Input kind not specified, terminating."
        usage
        exit
    end

    # Check output format
    if opts['F']!=nil
        if opts['F'].upcase!="GIF" && opts['F'].upcase!="PNG" && opts['F'].upcase!="EPS" && opts['F'].upcase!="PDF"
            puts "Supported output formats are PNG, GIF, EPS and PDF, found #{opts['F']}."
            usage
            exit
        end
    else
        opts['F'] = "PNG"
    end

    # Check output file name
    if opts['O']==nil
        puts "Output file name not specified, terminating."
        usage   
        exit
    end 

    # scaling factor
    if opts['A'] != nil && (opts['A'].to_f <= 0 || opts['A'].to_f > 1)
        puts "Option A must be a real between 0 and 1, but is #{opts['A']}."
        usage
        exit
    end

    if opts['E'] != nil && (opts['E'].to_f <= 0 || opts['E'].to_f > 1)
        puts "Option E must be a real between 0 and 1, but is #{opts['E']}."
        usage
        exit
    end

    # logo height
    if opts['H'] != nil && opts['H'].to_f <= 0
        put "Option H must be a positive real, but is #{opts['H']}"
        usage
        exit
    end

    # logo width
    if opts['W'] != nil && opts['W'].to_f <= 0
        puts "Option W must be a positive real, but is #{opts['W']}"
        usage
        exit
    end

    # logo start
    if opts['S'] != nil && opts['S'].to_i <= 0
        puts "\nOption S must be a positive integer, but is #{opts['S']}\n"
        usage
        exit
    end

    # logo end
    if opts['E'] != nil && opts['E'].to_i <= 0
        puts "\nOption E must be a positive integer, but is #{opts['E']}\n"
        usage
        exit
    end

    # p value
    if (opts['V']== nil || opts['V'].to_f <= 0)
        opts['V']=0.05
    else
        opts['V'] = opts['V'].to_f
    end

    opts['b']=false if opts['b']==nil 
    opts['f']=false if opts['f']==nil 
    opts['a']=false if opts['a']==nil

    return opts
end



#
# MAIN FUNCTION
#

opts = init

pos_file = IO.readlines(opts['P'])
neg_file = IO.readlines(opts['N'])

params = {
    'INPUT_KIND'   => opts['K'],
    'TEST'         => opts['T'],
    'P_VALUE'      => opts['V'],
    'BONFERRONI'   => opts['b'],
    'FIXED_HEIGHT' => opts['f']
}

result   = TSL.get_heights(pos_file, neg_file, params)

error_code  = result[0]
error_line  = result[1]
length      = result[2]
conserved   = result[3]
enriched    = result[4]
depleted    = result[5]
max_height  = result[6]

case error_code
when 0   
    max_height=0.05 if max_height==0    

    options = {
        'INPUT_KIND'    => opts['K'],
        'LOGO_HEIGHT'   => opts['H'],
        'LOGO_WIDTH'    => opts['W'],
        'LOGO_UNITS'    => opts['U'],
        'COLOR_SCHEME'  => opts['C'],
        'LOGO_START'    => opts['S'],
        'LOGO_END'      => opts['E'],
        'START_NUM'     => opts['M'],
        'TITLE'         => opts['I'],
        'XAXIS'         => opts['x'],
        'YAXIS'         => opts['y'],
        'SHRINK_FACTOR' => opts['A'],
        'FIXED_HEIGHT'  => opts['f'],
        'MAX_HEIGHT'    => max_height,
        'RES'           => opts['R'],
        'RES_UNITS'     => opts['X'],
        'FORMAT'        => opts['F'].upcase,
        'ANTIALIAS'     => opts['a'],
        'OUTLINE'       => opts['o'],
        'SHOW_BOX'      => opts['s']
    }

    Template.create_template(conserved, enriched, depleted, options, opts['O'], "")

when 101
    puts "Error: Positive example #{error_line} is malformatted."

when 102
    puts "Error: Positive example #{error_line} differs in length."

when 103
    puts "Error: Negative example #{error_line} is malformatted."

when 104
    puts "Error: Negative example #{error_line} differs in length."

when 105
    puts "Error: Positive and negative samples differ in sequence length."

end
