packages feed

BioHMM 1.0.5 → 1.0.6

raw patch · 3 files changed

+56/−40 lines, 3 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Bio.HMMDraw: drawHMMER3 :: String -> Int -> Double -> Double -> String -> Vector (String, Colour Double) -> (HMMER3, Maybe StockholmAlignment, Vector (Int, Vector (Colour Double)), Colour Double) -> (QDiagram Cairo V2 Double Any, QDiagram Cairo V2 Double Any)
+ Bio.HMMDraw: drawHMMER3 :: String -> Int -> Double -> Double -> Double -> String -> Vector (String, Colour Double) -> (HMMER3, Maybe StockholmAlignment, Vector (Int, Vector (Colour Double)), Colour Double) -> (QDiagram Cairo V2 Double Any, QDiagram Cairo V2 Double Any)
- Bio.HMMDraw: drawSingleHMMComparison :: String -> Int -> String -> Double -> Double -> [HMMER3] -> [Maybe StockholmAlignment] -> [HMMCompareResult] -> [(QDiagram Cairo V2 Double Any, QDiagram Cairo V2 Double Any)]
+ Bio.HMMDraw: drawSingleHMMComparison :: String -> Int -> Double -> String -> Double -> Double -> [HMMER3] -> [Maybe StockholmAlignment] -> [HMMCompareResult] -> [(QDiagram Cairo V2 Double Any, QDiagram Cairo V2 Double Any)]
- Bio.HMMDraw: drawSingleHMMER3s :: String -> Int -> Double -> Double -> String -> [HMMER3] -> [Maybe StockholmAlignment] -> [(QDiagram Cairo V2 Double Any, QDiagram Cairo V2 Double Any)]
+ Bio.HMMDraw: drawSingleHMMER3s :: String -> Int -> Double -> Double -> Double -> String -> [HMMER3] -> [Maybe StockholmAlignment] -> [(QDiagram Cairo V2 Double Any, QDiagram Cairo V2 Double Any)]

Files

BioHMM.cabal view
@@ -1,5 +1,5 @@ name:                BioHMM-version:             1.0.5+version:             1.0.6 synopsis:            Libary for Hidden Markov Models in HMMER3 format.  description:         Libary containing parsing and visualisation functions and datastructures for Hidden Markov Models in HMMER3 format.   license:             GPL-3@@ -20,8 +20,8 @@  source-repository this   type:     git-  location: https://github.com/eggzilla/BioHMM/tree/1.0.5-  tag:      1.0.5+  location: https://github.com/eggzilla/BioHMM/tree/1.0.6+  tag:      1.0.6  library   -- Modules exported by the library.
changelog view
@@ -1,4 +1,7 @@ -*-change-log-*-+1.0.6 Florian Eggenhofer <egg@informatik.uni-freiburg.de> 15. March 2017+	* Added cutoff for displayed transition probabilities+	* Improvements for detailed node layout 1.0.5 Florian Eggenhofer <egg@informatik.uni-freiburg.de> 26. February 2017 	* Added labels and text to simple and minimal node vis 	* Flat detail is now minimal detail corresponding to cmvis
src/Bio/HMMDraw.hs view
@@ -32,12 +32,12 @@ import Graphics.SVGFonts import Bio.StockholmFont -drawSingleHMMComparison :: String -> Int -> String -> Double -> Double -> [HM.HMMER3] -> [Maybe S.StockholmAlignment] -> [HMMCompareResult] -> [(QDiagram Cairo V2 Double Any,QDiagram Cairo V2 Double Any)]-drawSingleHMMComparison modelDetail entryNumberCutoff emissiontype maxWidth scalef hmms alns comparisons-   | modelDetail == "minimal" = map (drawHMMER3 modelDetail entryNumberCutoff maxWidth scalef emissiontype nameColorVector) zippedInput-   | modelDetail == "simple" = map (drawHMMER3 modelDetail entryNumberCutoff maxWidth scalef emissiontype nameColorVector) zippedInput-   | modelDetail == "detailed" = map (drawHMMER3 modelDetail entryNumberCutoff maxWidth scalef emissiontype nameColorVector) zippedInput-   | otherwise = map (drawHMMER3 modelDetail entryNumberCutoff maxWidth scalef emissiontype nameColorVector) zippedInput+drawSingleHMMComparison :: String -> Int -> Double -> String -> Double -> Double -> [HM.HMMER3] -> [Maybe S.StockholmAlignment] -> [HMMCompareResult] -> [(QDiagram Cairo V2 Double Any,QDiagram Cairo V2 Double Any)]+drawSingleHMMComparison modelDetail entryNumberCutoff transitionCutoff emissiontype maxWidth scalef hmms alns comparisons+   | modelDetail == "minimal" = map (drawHMMER3 modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype nameColorVector) zippedInput+   | modelDetail == "simple" = map (drawHMMER3 modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype nameColorVector) zippedInput+   | modelDetail == "detailed" = map (drawHMMER3 modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype nameColorVector) zippedInput+   | otherwise = map (drawHMMER3 modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype nameColorVector) zippedInput      where zippedInput = zip4 hmms alns comparisonNodeLabels (V.toList colorVector)            colorVector = makeColorVector modelNumber            modelNumber = length hmms@@ -45,20 +45,20 @@            nameColorVector = V.zipWith (\a b -> (a,b)) modelNames colorVector            comparisonNodeLabels = map (getComparisonNodeLabels comparisons nameColorVector) hmms -drawSingleHMMER3s :: String -> Int -> Double -> Double -> String -> [HM.HMMER3] -> [Maybe S.StockholmAlignment] -> [(QDiagram Cairo V2 Double Any,QDiagram Cairo V2 Double Any)]-drawSingleHMMER3s modelDetail entryNumberCutoff maxWidth scalef emissiontype hmms alns-  | modelDetail == "minimal" = map (drawHMMER3 modelDetail entryNumberCutoff maxWidth scalef emissiontype emptyColorNameVector) zippedInput-  | modelDetail == "simple" = map (drawHMMER3 modelDetail entryNumberCutoff maxWidth scalef emissiontype emptyColorNameVector) zippedInput-  | modelDetail == "detailed" = map (drawHMMER3 modelDetail entryNumberCutoff maxWidth scalef emissiontype emptyColorNameVector) zippedInput-  | otherwise = map (drawHMMER3 modelDetail entryNumberCutoff maxWidth scalef emissiontype emptyColorNameVector) zippedInput+drawSingleHMMER3s :: String -> Int -> Double -> Double -> Double -> String -> [HM.HMMER3] -> [Maybe S.StockholmAlignment] -> [(QDiagram Cairo V2 Double Any,QDiagram Cairo V2 Double Any)]+drawSingleHMMER3s modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype hmms alns+  | modelDetail == "minimal" = map (drawHMMER3 modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype emptyColorNameVector) zippedInput+  | modelDetail == "simple" = map (drawHMMER3 modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype emptyColorNameVector) zippedInput+  | modelDetail == "detailed" = map (drawHMMER3 modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype emptyColorNameVector) zippedInput+  | otherwise = map (drawHMMER3 modelDetail entryNumberCutoff transitionCutoff maxWidth scalef emissiontype emptyColorNameVector) zippedInput     where zippedInput = zip4 hmms alns blankComparisonNodeLabels colorList           blankComparisonNodeLabels = map getBlankComparisonNodeLabels hmms           colorList = replicate (length hmms) white           emptyColorNameVector = V.empty  -- |-drawHMMER3 :: String -> Int -> Double -> Double -> String -> V.Vector (String,Colour Double) -> (HM.HMMER3,Maybe S.StockholmAlignment, V.Vector (Int,V.Vector (Colour Double)), Colour Double) -> (QDiagram Cairo V2 Double Any,QDiagram Cairo V2 Double Any)-drawHMMER3 modelDetail entriesNumberCutoff maxWidth scalef emissiontype nameColorVector (model,aln,comparisonNodeLabels,modelColor)+drawHMMER3 :: String -> Int -> Double -> Double -> Double -> String -> V.Vector (String,Colour Double) -> (HM.HMMER3,Maybe S.StockholmAlignment, V.Vector (Int,V.Vector (Colour Double)), Colour Double) -> (QDiagram Cairo V2 Double Any,QDiagram Cairo V2 Double Any)+drawHMMER3 modelDetail entriesNumberCutoff transitionCutoff maxWidth scalef emissiontype nameColorVector (model,aln,comparisonNodeLabels,modelColor)    | modelDetail == "minimal" = ((applyAll ([bg white]) minimalNodesHeader) # scale scalef,alignmentDiagram)    | modelDetail == "simple" = ((applyAll ([bg white]) simpleNodesHeader) # scale scalef,alignmentDiagram)    | modelDetail == "detailed" = ((applyAll ([bg white]) verboseNodesHeader) # scale scalef,alignmentDiagram)@@ -69,13 +69,13 @@            nodeAlignmentColIndices =  V.map (fromJust . HM.nma) currentNodes            alphabet = HM.alpha model            alphabetSymbols = HM.alphabetToSymbols alphabet-           boxlength = (fromIntegral (length alphabetSymbols)) * 1.15  + 1+           boxlength = (fromIntegral (length alphabetSymbols)) * 1.25  + 0.3            nodeWidth = 6.0 :: Double            nodeNumberPerRow = floor (maxWidth / nodeWidth - 2)            nodesIntervals = makeNodeIntervals nodeNumberPerRow nodeNumber            minimalNodes = hcat (V.toList (V.map (drawHMMNodeMinimal comparisonNodeLabels)currentNodes)) # scale scalef            simpleNodes = hcat (V.toList (V.map (drawHMMNodeSimple alphabetSymbols emissiontype boxlength comparisonNodeLabels) currentNodes)) # scale scalef-           verboseNodes = vcat' with { _sep = 3 } (V.toList (V.map (drawDetailedNodeRow alphabetSymbols emissiontype boxlength nodeNumber currentNodes comparisonNodeLabels) nodesIntervals))+           verboseNodes = vcat' with { _sep = 3 } (V.toList (V.map (drawDetailedNodeRow alphabetSymbols emissiontype boxlength transitionCutoff nodeNumber currentNodes comparisonNodeLabels) nodesIntervals))            minimalNodesHeader = alignTL (vcat' with { _sep = 5 }  [modelHeader,minimalNodes])            simpleNodesHeader = alignTL (vcat' with { _sep = 5 }  [modelHeader,simpleNodes])            verboseNodesHeader = alignTL (vcat' with { _sep = 5 }  [modelHeader,verboseNodes])@@ -83,7 +83,7 @@            alignmentDiagram = maybe mempty (drawStockholmLines entriesNumberCutoff maxWidth nodeAlignmentColIndices comparisonNodeLabels) aln  makeModelHeader :: String -> Colour Double -> V.Vector (String,Colour Double) -> QDiagram Cairo V2 Double Any-makeModelHeader mName modelColor nameColorVector = strutX 2 ||| setModelName mName ||| strutX 1 ||| rect 12 12 # lw 0.1 # fc modelColor # translate (r2 (negate 0, 5)) ||| strutX 30 ||| modelLegend+makeModelHeader mName modelColor nameColorVector = strutX 2 ||| setModelName mName ||| strutX 1 ||| rect 6 6 # lw 0.1 # fc modelColor # translate (r2 (negate 0, 3)) ||| strutX 30 ||| modelLegend   where modelLegend = makeModelLegend otherModelsNameColorVector         otherModelsNameColorVector = V.filter ((/=mName) . fst) nameColorVector @@ -120,16 +120,18 @@         rowLength = nodeNumberPerRow         safeLength = if rowStart + rowLength >= nodeNumber then nodeNumber - rowStart else rowLength -drawDetailedNodeRow :: String -> String -> Double -> Int -> V.Vector HM.HMMER3Node -> V.Vector (Int,V.Vector (Colour Double)) -> (Int, Int) -> QDiagram Cairo V2 Double Any-drawDetailedNodeRow alphabetSymbols emissiontype boxLength lastIndex allNodes comparisonNodeLabels (currentIndex,nodeSliceLength) = detailedRow+drawDetailedNodeRow :: String -> String -> Double -> Double -> Int -> V.Vector HM.HMMER3Node -> V.Vector (Int,V.Vector (Colour Double)) -> (Int, Int) -> QDiagram Cairo V2 Double Any+drawDetailedNodeRow alphabetSymbols emissiontype transitionCutoff boxLength lastIndex allNodes comparisonNodeLabels (currentIndex,nodeSliceLength) = detailedRow   where currentNodes = V.slice currentIndex nodeSliceLength allNodes         --withLastRowNodes = V.slice (currentIndex -1) (nodeSliceLength +1) allNodes         detailedRow = applyAll (lastRowList ++ arrowList ++ labelList) detailedNodes         nextIndex = currentIndex + nodeSliceLength         detailedNodes = hcat (V.toList (V.map (drawHMMNodeVerbose alphabetSymbols emissiontype boxLength currentIndex nextIndex lastIndex comparisonNodeLabels) currentNodes))         arrowNodes = currentNodes-        connectedNodes = makeConnections boxLength arrowNodes-        selfConnectedNodes = makeSelfConnections boxLength arrowNodes+        allConnectedNodes = makeConnections boxLength arrowNodes+        connectedNodes = V.filter (\(_,_,weight,_) -> weight >= transitionCutoff) allConnectedNodes                +        allSelfConnectedNodes = makeSelfConnections boxLength arrowNodes+        selfConnectedNodes = V.filter (\(_,_,weight,_) -> weight >= transitionCutoff) allSelfConnectedNodes         arrowList = V.toList (V.map makeArrow connectedNodes V.++ V.map makeSelfArrow selfConnectedNodes)         labelList = V.toList (V.map makeLabel connectedNodes V.++ V.map makeSelfLabel selfConnectedNodes)         --add arrows and labels for transitions from previous row@@ -138,13 +140,13 @@         lastRowList = V.toList (V.map makeArrow lastRowConnections V.++ V.map makeLabel lastRowConnections)  setLabelLetter :: String -> QDiagram Cairo V2 Double Any-setLabelLetter t = textWithSize' t 2.0+setLabelLetter t = textWithSize' t 1.8  makeLastRowConnections :: Double -> V.Vector HM.HMMER3Node -> V.Vector (String, String, Double, (Double, Double)) makeLastRowConnections boxlength currentnodes =  mm1A V.++ md1A V.++ im1A V.++ dm1A V.++ dd1A   where mm1A = V.map makemm1A currentnodes         md1A = V.map (makemd1A boxlength) currentnodes-        im1A = V.map makeim1A currentnodes+        im1A = V.map (makeim1A boxlength) currentnodes         dm1A = V.map (makedm1A boxlength) currentnodes         dd1A = V.map makedd1A currentnodes @@ -153,7 +155,7 @@   where mm1A = V.map makemm1A currentnodes         miA = V.map (makemiA boxlength) currentnodes         md1A = V.map (makemd1A boxlength) currentnodes-        im1A = V.map makeim1A currentnodes+        im1A = V.map (makeim1A boxlength) currentnodes         dm1A = V.map (makedm1A boxlength) currentnodes         dd1A = V.map makedd1A currentnodes @@ -161,25 +163,31 @@ makeSelfConnections boxlength currentnodes = V.map (makeiiA boxlength) currentnodes  makemm1A :: HM.HMMER3Node -> (String, String, Double, (Double, Double))-makemm1A currentNode = (show (HM.nodeId currentNode) ++ "m", show (HM.nodeId currentNode + 1) ++ "m", maybe 0 (roundPos 2 . exp . negate) (HM.m2m currentNode),(0,0.5))+makemm1A currentNode = (show (HM.nodeId currentNode) ++ "m", show (HM.nodeId currentNode + 1) ++ "m", maybe 0 (roundPos 2 . exp . negate) (HM.m2m currentNode),(0.1,negate 0.3)) makemiA :: Double -> HM.HMMER3Node -> (String, String, Double, (Double, Double)) makemiA boxlength currentNode = (show (HM.nodeId currentNode) ++ "m", show (HM.nodeId currentNode) ++ "i",  maybe 0 (roundPos 2 . exp . negate) (HM.m2i currentNode),(0,setiayOffset boxlength)) makemd1A :: Double -> HM.HMMER3Node -> (String, String, Double, (Double, Double))-makemd1A _ currentNode = (show (HM.nodeId currentNode) ++ "m", show (HM.nodeId currentNode + 1) ++ "d", maybe 0 (roundPos 2 . exp . negate) (HM.m2d currentNode),(1.5,2.0))-makeim1A :: HM.HMMER3Node -> (String, String, Double, (Double, Double))-makeim1A currentNode = (show (HM.nodeId currentNode) ++ "i", show (HM.nodeId currentNode + 1) ++ "m", maybe 0 (roundPos 2 . exp . negate) (HM.i2m currentNode),(0,negate 0.1))+makemd1A _ currentNode = (show (HM.nodeId currentNode) ++ "m", show (HM.nodeId currentNode + 1) ++ "d", maybe 0 (roundPos 2 . exp . negate) (HM.m2d currentNode),(0.3,1.7))+makeim1A :: Double -> HM.HMMER3Node -> (String, String, Double, (Double, Double))+makeim1A boxlength currentNode = (show (HM.nodeId currentNode) ++ "i", show (HM.nodeId currentNode + 1) ++ "m", maybe 0 (roundPos 2 . exp . negate) (HM.i2m currentNode),(negate 0.1,setim1AOffset boxlength))+  where  makeiiA :: Double -> HM.HMMER3Node -> (String, String, Double, (Double, Double)) makeiiA _ currentNode = (show (HM.nodeId currentNode) ++ "i", show (HM.nodeId currentNode) ++ "i", maybe 0 (roundPos 2 . exp . negate) (HM.i2i currentNode),(0,4.7)) makedm1A :: Double -> HM.HMMER3Node -> (String, String, Double, (Double, Double)) makedm1A _ currentNode = (show (HM.nodeId currentNode) ++ "d", show (HM.nodeId currentNode + 1) ++ "m", maybe 0 (roundPos 2 . exp . negate) (HM.d2m currentNode),(negate 1.5,3.0)) makedd1A :: HM.HMMER3Node -> (String, String, Double, (Double, Double))-makedd1A currentNode = (show (HM.nodeId currentNode) ++ "d", show (HM.nodeId currentNode + 1) ++ "d", maybe 0 (roundPos 2 . exp . negate) (HM.d2d currentNode),(0,1))+makedd1A currentNode = (show (HM.nodeId currentNode) ++ "d", show (HM.nodeId currentNode + 1) ++ "d", maybe 0 (roundPos 2 . exp . negate) (HM.d2d currentNode),(negate 0.6,1))  setiayOffset :: Double -> Double setiayOffset boxlength   | boxlength <= 10 = 0.6-  | otherwise = 5+  | otherwise = 5.9 +setim1AOffset :: Double -> Double+setim1AOffset boxlength+  | boxlength <= 10 = negate 0.3+  | otherwise = negate 2.3+                 makeArrow :: (String,String,Double,(Double,Double)) -> QDiagram Cairo V2 Double Any -> QDiagram Cairo V2 Double Any makeArrow (lab1,lab2,weight,_) = connectOutside' arrowStyle1 lab1 lab2   where arrowStyle1 = with & arrowHead .~ spike & shaftStyle %~ lw (local 0.1) & headLength .~ local 0.001 & shaftStyle %~ dashingG [weight, 0.1] 0 & headStyle %~ fc black . opacity (weight * 2)@@ -251,7 +259,7 @@ emptyIdBox = rect 1.5 1.5 # lw 0  rowStartBox :: Int -> Double -> QDiagram Cairo V2 Double Any-rowStartBox idNumber boxlength = rect 0 1.5 #lw 0.0 === rect 0 6 # lw 0.1 # named (nid ++ "d") === rect 0 6 # lw 0.1 #named (nid ++ "i") === rect 0 (boxlength + 2) # lw 0.1 # named (nid ++ "m") ||| strutX 7+rowStartBox idNumber boxlength = rect 0 1.5 #lw 0.0 === rect 0 6 # lw 0.1 # named (nid ++ "d") === rect 0 8 # lw 0.1 #named (nid ++ "i") === rect 0 (boxlength + 2) # lw 0.1 # named (nid ++ "m") ||| strutX 7   where nid = show (idNumber - 1)  rowEndBox :: Int -> Double -> QDiagram Cairo V2 Double Any@@ -271,13 +279,18 @@ emptyInsertions = rect 4.2426 4.2426 # lw 0 # rotateBy (1/8) # fc white  matches :: String -> String -> Double -> HM.HMMER3Node -> QDiagram Cairo V2 Double Any-matches alphabetSymbols emissiontype boxlength node = entries # translate (r2 (negate 2.5,boxlength/2 -1)) <> outerbox # named (nid ++ "m")-  where outerbox = rect 6 boxlength # lw 0.1 # fc white+matches alphabetSymbols emissiontype boxlength node = entries # translate (r2 (negate 2.5,(boxlength/2)- matchesOffset boxlength)) <> outerbox # named (nid ++ "m")+  where outerbox = rect 6 (boxlength * 1.1) # lw 0.1 # fc white         entries = vcat (map (emissionEntry emissiontype) symbolsAndEmissions)         symbolsAndEmissions = zip (map wrap alphabetSymbols) (V.toList emissionEntries)         emissionEntries = setEmissions emissiontype (HM.matchEmissions node)         nid = show $ HM.nodeId node +matchesOffset :: Double -> Double+matchesOffset boxlength+  | boxlength <= 10 = 0.5+  | otherwise = 0+ wheel :: [Colour Double] -> QDiagram Cairo V2 Double Any wheel colors = wheel' # rotate r    where@@ -290,12 +303,12 @@ -- B → M 1 , B → I 0 , B → D 1 ; I 0 → M 1 , I 0 → I 0 beginState :: Double -> String -> QDiagram Cairo V2 Double Any --beginState boxlength nid = alignedText 0.5 0.5 "BEGIN" <> outerbox # named (nid ++ "m") <> rect 6 boxlength # named (nid ++ "d")  # lw 0.1-beginState boxlength nid = textWithSize' "BEGIN" 1.5 # translate (r2 (negate 1.5,0)) <> outerbox # named (nid ++ "m") <> rect 6 boxlength # named (nid ++ "d")  # lw 0.1-  where outerbox = rect 6 boxlength # lw 0.1 # fc white+beginState boxlength nid = textWithSize' "BEGIN" 1.5 # translate (r2 (negate 1.5,0)) <> outerbox # named (nid ++ "m") <> rect 5 (boxlength + 2) # named (nid ++ "d")  # lw 0.1+  where outerbox = rect 5 (boxlength + 2) # lw 0.1 # fc white  endState :: Double -> Int -> QDiagram Cairo V2 Double Any --endState boxlength idNumber = alignedText 0.5 0.5 "END" <> outerbox # named (nid ++ "m") <> rect 6 boxlength # named (nid ++ "d")  # lw 0.1 <> rect 6 boxlength # named (nid ++ "i")  # lw 0.1-endState boxlength idNumber = textWithSize' "END" 2 <> outerbox # named (nid ++ "m") <> rect 6 boxlength # named (nid ++ "d")  # lw 0.1 <> rect 6 boxlength # named (nid ++ "i")  # lw 0.1+endState boxlength idNumber = strutX 0.5 ||| (textWithSize' "END" 2 <> outerbox # named (nid ++ "m") <> rect 6 boxlength # named (nid ++ "d")  # lw 0.1 <> rect 6 boxlength # named (nid ++ "i")  # lw 0.1)   where outerbox = rect 6 boxlength # lw 0.1 # fc white         nid = show (idNumber + 1) @@ -325,7 +338,7 @@           textentry = textWithSize' (symbol ++ " " ++ printf "%.3f" emission) 1           --barentry =  stroke (textSVG symbol 2) ||| bar emission           --barentry = (alignedText 0 0.01 symbol  # translate (r2 (negate 0.25,negate 0.3)) <> (rect 2 1 # lw 0 )) ||| bar emission-          barentry = (textWithSize' symbol 0.9 <> (rect 1 1 # lw 0 )) ||| strutX 1 ||| bar emission+          barentry = (textWithSize' symbol 1.1 #  translate (r2 (0.4,0.0)) <> (rect 1.3 1.1 # lw 0 )) ||| strutX 0.5 ||| bar emission  bar :: Double -> QDiagram Cairo V2 Double Any bar emission = rect (4 * emission) 1 # lw 0 # fc black # translate (r2 (negate (2 - (4 * emission/2)),0)) <> rect 4 1 # lw 0.03