Some background: I work mostly in Python (specifically numpy), doing Bioinformatics type work. I am interested in moving towards Haskell. Initially, I hope it will be possible to replace some of the simple exploratory scripting I've been doing with Haskell. The following is not something that would actually be particularly useful, but I thought it might be a good starting point for my first program in Haskell!
The following code takes two files:
- Describes regions of a chromosome that have been categorized as similar. Line 1 shows the start basepair of the region, line 2 the end basepair, and so on. A shortened example: http://pastebin.com/RMd13Kv3
- Shows an interaction matrix between "bins" of the chromosome. A row has chrmName startBp endBp, followed by the row of the interaction matrix. This is not necessarily in order. Example: http://pastebin.com/Q5CaVHAu
The code is attempting to work out the fraction of the whole chromosome spanned by the regions.
import System.IO import System.Environment(getArgs) import Data.Either import Data.List joinLinePairs :: [a] -> ([a], [a]) joinLinePairs x = partitionEithers $ zipWith ($) (cycle [Left, Right]) x zipLinesPairs :: ([a], [a]) -> [(a, a)] zipLinesPairs (a, b) = zip a b pairDifference :: (String, String) -> Int pairDifference (a, b) = (read b) - (read a) domainArea :: [String] -> Int domainArea inpLines = sum (map pairDifference $ zipLinesPairs $ joinLinePairs inpLines) processRawMat :: [String] -> [[Int]] processRawMat x = map (processMatRow . words) x processMatRow :: [String] -> [Int] processMatRow (x:y:z:_) = [read y, read z] maxMinBin :: [[Int]] -> (Int, Int) maxMinBin lst = (minimum vals, maximum vals) where vals = concat lst coverageFrac :: (Integral a, Fractional b) => (a, a) -> a -> b coverageFrac (mn, mx) domArea = (fromIntegral domArea) / ((fromIntegral mx) - (fromIntegral mn)) main :: IO () main = do args <- getArgs rawDomains <- readFile (args !! 0) let coveredArea = domainArea $ lines rawDomains print $ coveredArea rawMatrix <- readFile (args !! 1) let rawMatLines = lines rawMatrix let listolists = processRawMat rawMatLines print $ coverageFrac (maxMinBin listolists) coveredArea
One thing I noticed is that this code is very slow when running on real data (in reality the second file can run to tens of thousands of lines, and hundreds of mb). As most of the things I would be doing involve dealing with very large text files (these would be considered small, by comparison), this worries me a bit!
I would appreciate any feedback anyone could offer me. Thanks!