From 49dfdc0c986901683f3e00e65f922e2318e0f330 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Fri, 15 Feb 2019 08:41:28 +0300
Subject: Migrate code from Piddle to Pillow

* wqflask/wqflask/marker_regression/display_mapping_results.py: Add font files
(DisplayMappingResults): Update the code from the Piddle way of things to the
Pillow way of things, for example, replace:
- pid.drawRect(...) with im_drawer.rectangle(...)
- pid.drawString(...) with im_drawer.text(...)
- pid.drawPolygon(...) with im_drawer.polygon(...) etc.
* wqflask/utility/Plot.py: Migrate code from the older, unsupported Piddle to
the newer Pillow library.
---
 wqflask/utility/Plot.py | 87 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 64 insertions(+), 23 deletions(-)

(limited to 'wqflask/utility')

diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py
index 9bc84d22..c557bcc6 100644
--- a/wqflask/utility/Plot.py
+++ b/wqflask/utility/Plot.py
@@ -26,7 +26,7 @@
 
 from __future__ import print_function
 
-import piddle as pid
+from PIL import (Image, ImageColor, ImageDraw, ImageFont)
 from pprint import pformat as pf
 
 from math import *
@@ -42,6 +42,17 @@ from base import webqtlConfig
 import utility.logger
 logger = utility.logger.getLogger(__name__ )
 
+# ---- Define common colours ---- #
+BLUE = ImageColor.getrgb("blue")
+BLACK = ImageColor.getrgb("black")
+# ---- END: Define common colours ---- #
+
+# ---- FONT FILES ---- #
+VERDANA_FILE = "fonts/ttf/verdana.ttf"
+COUR_FILE = "fonts/ttf/courbd.ttf"
+TAHOMA_FILE = "fonts/ttf/tahoma.ttf"
+# ---- END: FONT FILES ---- #
+
 def cformat(d, rank=0):
     'custom string format'
     strD = "%2.6f" % d
@@ -114,7 +125,8 @@ def find_outliers(vals):
 
 # parameter: data is either object returned by reaper permutation function (called by MarkerRegressionPage.py)
 # or the first object returned by direct (pair-scan) permu function (called by DirectPlotPage.py)
-def plotBar(canvas, data, barColor=pid.blue, axesColor=pid.black, labelColor=pid.black, XLabel=None, YLabel=None, title=None, offset= (60, 20, 40, 40), zoom = 1):
+def plotBar(canvas, data, barColor=BLUE, axesColor=BLACK, labelColor=BLACK, XLabel=None, YLabel=None, title=None, offset= (60, 20, 40, 40), zoom = 1):
+    im_drawer = ImageDraw.Draw(canvas)
     xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
 
     plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
@@ -161,43 +173,67 @@ def plotBar(canvas, data, barColor=pid.blue, axesColor=pid.black, labelColor=pid
        if count:
            xc = (dataXY[i]-xLow)*xScale+xLeftOffset
            yc =-(count-yLow)*yScale+yTopOffset+plotHeight
-           canvas.drawRect(xc+2,yc,xc+barWidth-2,yTopOffset+plotHeight,edgeColor=barColor,fillColor=barColor)
+           im_drawer.rectangle(
+               xy=((xc+2,yc),(xc+barWidth-2,yTopOffset+plotHeight)),
+               outline=barColor, fill=barColor)
 
     #draw drawing region
-    canvas.drawRect(xLeftOffset, yTopOffset, xLeftOffset+plotWidth, yTopOffset+plotHeight)
+    im_drawer.rectangle(
+        xy=((xLeftOffset, yTopOffset), (xLeftOffset+plotWidth, yTopOffset+plotHeight))
+    )
 
     #draw scale
-    scaleFont=pid.Font(ttf="cour",size=11,bold=1)
+    scaleFont=ImageFont.truetype(font=COUR_FILE,size=11)
     x=xLow
     for i in range(int(stepX)+1):
        xc=xLeftOffset+(x-xLow)*xScale
-       canvas.drawLine(xc,yTopOffset+plotHeight,xc,yTopOffset+plotHeight+5, color=axesColor)
+       im_drawer.line(
+           xy=((xc,yTopOffset+plotHeight),(xc,yTopOffset+plotHeight+5)),
+           fill=axesColor)
        strX = cformat(d=x, rank=0)
-       canvas.drawString(strX,xc-canvas.stringWidth(strX,font=scaleFont)/2,yTopOffset+plotHeight+14,font=scaleFont)
+       im_drawer.text(
+           text=strX,
+           xy=(xc-im_drawer.textsize(strX,font=scaleFont)[0]/2,
+               yTopOffset+plotHeight+14),font=scaleFont)
        x+= (xTop - xLow)/stepX
 
     y=yLow
     for i in range(int(stepY)+1):
        yc=yTopOffset+plotHeight-(y-yLow)*yScale
-       canvas.drawLine(xLeftOffset,yc,xLeftOffset-5,yc, color=axesColor)
+       im_drawer.line(xy=((xLeftOffset,yc),(xLeftOffset-5,yc)), fill=axesColor)
        strY = "%d" %y
-       canvas.drawString(strY,xLeftOffset-canvas.stringWidth(strY,font=scaleFont)-6,yc+5,font=scaleFont)
+       im_drawer.text(
+           text=strY,
+           xy=(xLeftOffset-im_drawer.textsize(strY,font=scaleFont)[0]-6,yc+5),
+           font=scaleFont)
        y+= (yTop - yLow)/stepY
 
     #draw label
-    labelFont=pid.Font(ttf="tahoma",size=17,bold=0)
+    labelFont=ImageFont.truetype(font=TAHOMA_FILE,size=17)
     if XLabel:
-       canvas.drawString(XLabel,xLeftOffset+(plotWidth-canvas.stringWidth(XLabel,font=labelFont))/2.0,
-               yTopOffset+plotHeight+yBottomOffset-10,font=labelFont,color=labelColor)
+       im_drawer.text(
+           text=XLabel,
+           xy=(xLeftOffset+(
+               plotWidth-im_drawer.textsize(XLabel,font=labelFont)[0])/2.0,
+               yTopOffset+plotHeight+yBottomOffset-10),
+           font=labelFont,fill=labelColor)
 
     if YLabel:
-       canvas.drawString(YLabel, 19, yTopOffset+plotHeight-(plotHeight-canvas.stringWidth(YLabel,font=labelFont))/2.0,
-               font=labelFont,color=labelColor,angle=90)
-
-    labelFont=pid.Font(ttf="verdana",size=16,bold=0)
+       im_drawer.text(
+           text=YLabel,
+           xy=(19,
+               yTopOffset+plotHeight-(plotHeight-im_drawer.textsize(
+                   YLabel,font=labelFont)[0])/2.0),
+           font=labelFont,fill=labelColor,angle=90)
+
+    labelFont=ImageFont.truetype(font=VERDANA_FILE,size=16)
     if title:
-       canvas.drawString(title,xLeftOffset+(plotWidth-canvas.stringWidth(title,font=labelFont))/2.0,
-               20,font=labelFont,color=labelColor)
+       im_drawer.text(
+           text=title,
+           xy=(xLeftOffset+(plotWidth-im_drawer.textsize(
+               title,font=labelFont)[0])/2.0,
+               20),
+           font=labelFont,fill=labelColor)
 
 # This function determines the scale of the plot
 def detScaleOld(min,max):
@@ -265,16 +301,21 @@ def greenfunc(x):
 def colorSpectrum(n=100):
     multiple = 10
     if n == 1:
-        return [pid.Color(1,0,0)]
+        return [ImageColor.getrgb("rgb(100%,0%,0%)")]
     elif n == 2:
-        return [pid.Color(1,0,0),pid.Color(0,0,1)]
+        return [ImageColor.getrgb("100%,0%,0%)"),
+                ImageColor.getrgb("rgb(0%,0%,100%)")]
     elif n == 3:
-        return [pid.Color(1,0,0),pid.Color(0,1,0),pid.Color(0,0,1)]
+        return [ImageColor.getrgb("rgb(100%,0%,0%)"),
+                ImageColor.getrgb("rgb(0%,100%,0%)"),
+                ImageColor.getrgb("rgb(0%,0%,100%)")]
     N = n*multiple
     out = [None]*N;
     for i in range(N):
         x = float(i)/N
-        out[i] = pid.Color(redfunc(x), greenfunc(x), bluefunc(x));
+        out[i] = ImageColor.getrgb("rgb({}%,{}%,{}%".format(
+            *[int(i*100) for i in (
+                redfunc(x), greenfunc(x), bluefunc(x))]))
     out2 = [out[0]]
     step = N/float(n-1)
     j = 0
@@ -290,4 +331,4 @@ def _test():
 
 
 if __name__=="__main__":
-    _test()
\ No newline at end of file
+    _test()
-- 
cgit v1.2.3


From 95dbb4a18a205b475ca8eb72210d7d2193062295 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Sat, 23 Feb 2019 07:32:29 +0300
Subject: Fix font paths

* wqflask/utility/Plot.py: Update font paths.
* wqflask/fonts/ttf: Update font files.
---
 wqflask/fonts/ttf/arial.ttf             | Bin 151232 -> 0 bytes
 wqflask/fonts/ttf/courbd.ttf            | Bin 181388 -> 0 bytes
 wqflask/fonts/ttf/fnt_bs.ttf            | Bin 20988 -> 0 bytes
 wqflask/fonts/ttf/tahoma.ttf            | Bin 249012 -> 0 bytes
 wqflask/fonts/ttf/trebucbd.ttf          | Bin 123828 -> 0 bytes
 wqflask/fonts/ttf/verdana.ttf           | Bin 139640 -> 0 bytes
 wqflask/utility/Plot.py                 |   6 +++---
 wqflask/wqflask/static/fonts/courbd.ttf | Bin 0 -> 181388 bytes
 wqflask/wqflask/static/fonts/tahoma.ttf | Bin 0 -> 249012 bytes
 9 files changed, 3 insertions(+), 3 deletions(-)
 delete mode 100644 wqflask/fonts/ttf/arial.ttf
 delete mode 100644 wqflask/fonts/ttf/courbd.ttf
 delete mode 100644 wqflask/fonts/ttf/fnt_bs.ttf
 delete mode 100644 wqflask/fonts/ttf/tahoma.ttf
 delete mode 100644 wqflask/fonts/ttf/trebucbd.ttf
 delete mode 100644 wqflask/fonts/ttf/verdana.ttf
 create mode 100644 wqflask/wqflask/static/fonts/courbd.ttf
 create mode 100644 wqflask/wqflask/static/fonts/tahoma.ttf

(limited to 'wqflask/utility')

diff --git a/wqflask/fonts/ttf/arial.ttf b/wqflask/fonts/ttf/arial.ttf
deleted file mode 100644
index bf0d4a95..00000000
Binary files a/wqflask/fonts/ttf/arial.ttf and /dev/null differ
diff --git a/wqflask/fonts/ttf/courbd.ttf b/wqflask/fonts/ttf/courbd.ttf
deleted file mode 100644
index c8081467..00000000
Binary files a/wqflask/fonts/ttf/courbd.ttf and /dev/null differ
diff --git a/wqflask/fonts/ttf/fnt_bs.ttf b/wqflask/fonts/ttf/fnt_bs.ttf
deleted file mode 100644
index 712c38cf..00000000
Binary files a/wqflask/fonts/ttf/fnt_bs.ttf and /dev/null differ
diff --git a/wqflask/fonts/ttf/tahoma.ttf b/wqflask/fonts/ttf/tahoma.ttf
deleted file mode 100644
index bb314be3..00000000
Binary files a/wqflask/fonts/ttf/tahoma.ttf and /dev/null differ
diff --git a/wqflask/fonts/ttf/trebucbd.ttf b/wqflask/fonts/ttf/trebucbd.ttf
deleted file mode 100644
index 1ab1ae0a..00000000
Binary files a/wqflask/fonts/ttf/trebucbd.ttf and /dev/null differ
diff --git a/wqflask/fonts/ttf/verdana.ttf b/wqflask/fonts/ttf/verdana.ttf
deleted file mode 100644
index 754a9b7b..00000000
Binary files a/wqflask/fonts/ttf/verdana.ttf and /dev/null differ
diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py
index c557bcc6..e7115036 100644
--- a/wqflask/utility/Plot.py
+++ b/wqflask/utility/Plot.py
@@ -48,9 +48,9 @@ BLACK = ImageColor.getrgb("black")
 # ---- END: Define common colours ---- #
 
 # ---- FONT FILES ---- #
-VERDANA_FILE = "fonts/ttf/verdana.ttf"
-COUR_FILE = "fonts/ttf/courbd.ttf"
-TAHOMA_FILE = "fonts/ttf/tahoma.ttf"
+VERDANA_FILE = "./wqflask/static/fonts/verdana.ttf"
+COUR_FILE = "./wqflask/static/fonts/courbd.ttf"
+TAHOMA_FILE = "./wqflask/static/fonts/tahoma.ttf"
 # ---- END: FONT FILES ---- #
 
 def cformat(d, rank=0):
diff --git a/wqflask/wqflask/static/fonts/courbd.ttf b/wqflask/wqflask/static/fonts/courbd.ttf
new file mode 100644
index 00000000..c8081467
Binary files /dev/null and b/wqflask/wqflask/static/fonts/courbd.ttf differ
diff --git a/wqflask/wqflask/static/fonts/tahoma.ttf b/wqflask/wqflask/static/fonts/tahoma.ttf
new file mode 100644
index 00000000..bb314be3
Binary files /dev/null and b/wqflask/wqflask/static/fonts/tahoma.ttf differ
-- 
cgit v1.2.3


From dcd053e0249b14c938d94eb749a8b4095c80be29 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Fri, 8 Mar 2019 10:39:53 +0300
Subject: Create new utility module for drawing

* wqflask/utility/pillow_utils.py: Create a module to hold some utility
functions for drawing with Pillow. Initialise the module with a function to draw
rotated text.
---
 wqflask/utility/pillow_utils.py | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 wqflask/utility/pillow_utils.py

(limited to 'wqflask/utility')

diff --git a/wqflask/utility/pillow_utils.py b/wqflask/utility/pillow_utils.py
new file mode 100644
index 00000000..4a666e4b
--- /dev/null
+++ b/wqflask/utility/pillow_utils.py
@@ -0,0 +1,16 @@
+from PIL import Image, ImageColor, ImageDraw, ImageFont
+
+import utility.logger
+logger = utility.logger.getLogger(__name__ )
+
+BLACK = ImageColor.getrgb("black")
+# def draw_rotated_text(canvas: Image, text: str, font: ImageFont, xy: tuple, fill: ImageColor=BLACK, angle: int=-90):
+def draw_rotated_text(canvas, text, font, xy, fill=BLACK, angle=-90):
+    # type: (Image, str, ImageFont, tuple, ImageColor, int)
+    """Utility function draw rotated text"""
+    tmp_img = Image.new("RGBA", font.getsize(text), color=(0,0,0,0))
+    draw_text = ImageDraw.Draw(tmp_img)
+    draw_text.text(text=text, xy=(0,0), font=font, fill=fill)
+    tmp_img2 = tmp_img.rotate(angle, expand=1)
+    tmp_img2.save("/tmp/{}.png".format(text), format="png")
+    canvas.paste(im=tmp_img2, box=tuple([int(i) for i in xy]))
-- 
cgit v1.2.3


From 6e1102e36737a3f48a74cf431819c269c54f2601 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Fri, 8 Mar 2019 10:41:40 +0300
Subject: Use draw_rotated_text()

Use the new draw_rotated_text() function to draw the text rotated as was
formerly done.

* wqflask/utility/Plot.py (plotBar): Use draw_rotated_text().
* wqflask/wqflask/marker_regression/display_mapping_results.py:
(DisplayMappingResults) Use draw_rotated_text().
---
 wqflask/utility/Plot.py                            | 14 ++++++-------
 .../marker_regression/display_mapping_results.py   | 24 +++++++++++++---------
 2 files changed, 21 insertions(+), 17 deletions(-)

(limited to 'wqflask/utility')

diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py
index e7115036..d4373412 100644
--- a/wqflask/utility/Plot.py
+++ b/wqflask/utility/Plot.py
@@ -38,7 +38,7 @@ from numarray import ones, array, dot, swapaxes
 import webqtlUtil
 import corestats
 from base import webqtlConfig
-
+from utility.pillow_utils import draw_rotated_text
 import utility.logger
 logger = utility.logger.getLogger(__name__ )
 
@@ -219,12 +219,12 @@ def plotBar(canvas, data, barColor=BLUE, axesColor=BLACK, labelColor=BLACK, XLab
            font=labelFont,fill=labelColor)
 
     if YLabel:
-       im_drawer.text(
-           text=YLabel,
-           xy=(19,
-               yTopOffset+plotHeight-(plotHeight-im_drawer.textsize(
-                   YLabel,font=labelFont)[0])/2.0),
-           font=labelFont,fill=labelColor,angle=90)
+        draw_rotated_text(canvas, text=YLabel,
+                          xy=(19,
+                              yTopOffset+plotHeight-(
+                                  plotHeight-im_drawer.textsize(
+                                      YLabel,font=labelFont)[0])/2.0),
+                          font=labelFont, fill=labelColor, angle=90)
 
     labelFont=ImageFont.truetype(font=VERDANA_FILE,size=16)
     if title:
diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py
index 39067fc5..b03902a5 100644
--- a/wqflask/wqflask/marker_regression/display_mapping_results.py
+++ b/wqflask/wqflask/marker_regression/display_mapping_results.py
@@ -45,6 +45,7 @@ from utility import Plot
 from utility.benchmark import Bench
 from wqflask.interval_analyst import GeneUtil
 from base.webqtlConfig import TMPDIR, GENERATED_TEXT_DIR, GENERATED_IMAGE_DIR
+from utility.pillow_utils import draw_rotated_text
 
 import utility.logger
 logger = utility.logger.getLogger(__name__ )
@@ -1519,11 +1520,12 @@ class DisplayMappingResults(object):
 
 
                             if lastGene == 0:
-                                im_drawer.text(
-                                    text="%s" % (_chr[j].name),
+                                draw_rotated_text(
+                                    canvas, text="%s" % (_chr[j].name),
+                                    font=ImageFont.truetype(font=VERDANA_FILE,
+                                                            size=12),
                                     xy=(geneStartPix,
                                         geneYLocation+17+2*maxind*self.EACH_GENE_HEIGHT*zoom),
-                                    font=ImageFont.truetype(font=VERDANA_FILE, size=12),
                                     fill=BLACK, angle=-90)
 
                             oldgeneEndPix = geneEndPix;
@@ -1804,9 +1806,10 @@ class DisplayMappingResults(object):
                                 (startPosX+tickdists*plotXScale, yZero + 7)),
                             fill=BLACK, width=1*zoom)
                         if j % 2 == 0:
-                            im_drawer.text(
-                                xy=(startPosX+tickdists*plotXScale, yZero+10*zoom),
-                                text=str(tickdists), fill=BLACK, font=MBLabelFont, angle=270)
+                            draw_rotated_text(
+                                canvas, text=str(tickdists), font=MBLabelFont,
+                                xy=(startPosX+tickdists*plotXScale,
+                                    yZero+10*zoom), fill=BLACK, angle=270)
                     startPosX +=  (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale
 
             megabaseLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5))
@@ -2037,11 +2040,12 @@ class DisplayMappingResults(object):
         LRSLODFont=ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5))
         yZero = yTopOffset + plotHeight
 
-        im_drawer.text(
-            text=self.LRS_LOD,
-            xy=(xLeftOffset - im_drawer.textsize("999.99", font=LRSScaleFont)[0] - 15*(zoom-1),
+        draw_rotated_text(
+            canvas, text=self.LRS_LOD, font=LRSLODFont,
+            xy=(xLeftOffset - im_drawer.textsize(
+                "999.99", font=LRSScaleFont)[0] - 15*(zoom-1),
                 yZero - 150 - 300*(zoom - 1)),
-            font=LRSLODFont, fill=BLACK, angle=90)
+            fill=BLACK, angle=90)
 
         for item in LRSAxisList:
             if LRS_LOD_Max == 0.0:
-- 
cgit v1.2.3


From e3c0745fdc3bf33cb10256643f3b1469ee6614c4 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Sat, 9 Mar 2019 08:33:19 +0300
Subject: Add draw_open_polygon() utility

* wqflask/utility/pillow_utils.py: New method.
---
 wqflask/utility/pillow_utils.py | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'wqflask/utility')

diff --git a/wqflask/utility/pillow_utils.py b/wqflask/utility/pillow_utils.py
index 4a666e4b..dfbf3e19 100644
--- a/wqflask/utility/pillow_utils.py
+++ b/wqflask/utility/pillow_utils.py
@@ -4,6 +4,8 @@ import utility.logger
 logger = utility.logger.getLogger(__name__ )
 
 BLACK = ImageColor.getrgb("black")
+WHITE = ImageColor.getrgb("white")
+
 # def draw_rotated_text(canvas: Image, text: str, font: ImageFont, xy: tuple, fill: ImageColor=BLACK, angle: int=-90):
 def draw_rotated_text(canvas, text, font, xy, fill=BLACK, angle=-90):
     # type: (Image, str, ImageFont, tuple, ImageColor, int)
@@ -14,3 +16,10 @@ def draw_rotated_text(canvas, text, font, xy, fill=BLACK, angle=-90):
     tmp_img2 = tmp_img.rotate(angle, expand=1)
     tmp_img2.save("/tmp/{}.png".format(text), format="png")
     canvas.paste(im=tmp_img2, box=tuple([int(i) for i in xy]))
+
+# def draw_open_polygon(canvas: Image, xy: tuple, fill: ImageColor=WHITE, outline: ImageColor=BLACK):
+def draw_open_polygon(canvas, xy, fill=None, outline=BLACK, width=0):
+    # type: (Image, tuple, ImageColor, ImageColor)
+    draw_ctx = ImageDraw.Draw(canvas)
+    draw_ctx.polygon(xy, fill=fill)
+    draw_ctx.line(xy, fill=outline, width=width)
-- 
cgit v1.2.3