-- |  Calculate library diversity from a clustering and a library table
-- TODO: remove zeros!

module Main where

import System.Environment (getArgs)
import Data.Set as S hiding (map)
import Data.Map as M hiding (map)
import Data.List (sort, intersperse)

import Formats

main = do
  [lib,cs] <- getArgs -- catch etc
  lt <- readPatternTable lib
  tot <- totalsByLib lt cs
  cls <- countClusters lt `fmap` readClusters cs
  writeColumns lt $ mkColumns lt cls
  
-- | Use cluster counts to generate a set of columns, indexed by library
mkColumns :: LibTable -> [(String,[Int])] -> M.Map String [Int]
mkColumns lt = M.fromListWith append . concatMap mkentry
    where append old new = new++old
          mkentry row = zip (map snd lt) (map return $ snd row)

-- | ouput columns, in a format suitable for gnuplotting:
writeColumns lt cm = do
  let cols = map (interpolate 1 . cumpercent . reverse . sort . Prelude.filter (/=0) . mylookup cm . snd) lt
      rows = transpose ([0..100]:cols)
  writeRow $ map snd lt
  mapM_ writeRow $ map (map show) $ rows

mylookup m v = case M.lookup v m of Just x -> x
                                    Nothing -> error ("Couldn't find library "++show v
                                                     ++"\namong: "++show (M.keys m))

interpolate :: Double -> [(Double,Double)] -> [Double]
interpolate delta cs = go 0 cs
    where go x xs@(a:b:rest) = if fst a<=x then if fst b>x then snd a + (x-fst a)*(snd b-snd a)/(fst b-fst a) : go (x+delta) xs
                                               else go x (b:rest)
                               else error "interpolation failed"
          go _ [(_,y)] = [y] -- last should always be 100%
  
-- calculate cumulative percentages of total 
cumpercent :: [Int] -> [(Double,Double)]
cumpercent xs = let total = fromIntegral $ sum xs
                    cum  = scanl (+) 0 $ map ((/total) . (*100) . fromIntegral) xs
                    step = 100 / fromIntegral (length xs)
                in zip (iterate (+step) 0) cum 

-- transpose a set of infinite/equally-sized lists
transpose xs = map head xs : transpose (map tail xs)
writeRow = putStrLn . concat . intersperse "\t" 