about summary refs log tree commit diff
diff options
context:
space:
mode:
authorzsloan2020-08-17 17:14:29 -0500
committerGitHub2020-08-17 17:14:29 -0500
commit75ebbf446606d7498bb16a01a4912c66eba17cb5 (patch)
tree0bca7be443ff8b897e3b84075d5c756a4d4fd66b
parent1e421a063d750df485a768aa6da14b3db592d409 (diff)
parentd157019159ae3eb2e3efb02d874a1b4edfc559cb (diff)
downloadgenenetwork2-75ebbf446606d7498bb16a01a4912c66eba17cb5.tar.gz
Merge pull request #417 from BonfaceKilz/feature/pil-pillow-conversion
Resolve merge conflicts from Pil Pillow conversion branch
-rw-r--r--wqflask/tests/wqflask/__init__.py (renamed from wqflask/tests/api/__init__.py)0
-rw-r--r--wqflask/tests/wqflask/api/__init__.py0
-rw-r--r--wqflask/tests/wqflask/api/test_gen_menu.py (renamed from wqflask/tests/api/test_gen_menu.py)0
-rw-r--r--wqflask/tests/wqflask/marker_regression/__init__.py0
-rw-r--r--wqflask/tests/wqflask/marker_regression/test_display_marking_results.py9
-rw-r--r--wqflask/utility/Plot.py89
-rw-r--r--wqflask/utility/pillow_utils.py25
-rw-r--r--wqflask/wqflask/marker_regression/display_mapping_results.py928
-rw-r--r--wqflask/wqflask/snp_browser/snp_browser.py4
-rw-r--r--wqflask/wqflask/static/fonts/README1
-rw-r--r--wqflask/wqflask/static/fonts/arial.ttfbin0 -> 151232 bytes
-rw-r--r--wqflask/wqflask/static/fonts/courbd.ttfbin0 -> 181388 bytes
-rw-r--r--wqflask/wqflask/static/fonts/fnt_bs.ttfbin0 -> 20988 bytes
-rw-r--r--wqflask/wqflask/static/fonts/tahoma.ttfbin0 -> 249012 bytes
-rw-r--r--wqflask/wqflask/static/fonts/trebucbd.ttfbin0 -> 123828 bytes
-rw-r--r--wqflask/wqflask/static/fonts/verdana.ttfbin0 -> 139640 bytes
-rw-r--r--wqflask/wqflask/static/fonts/verdanab.ttfbin0 -> 156340 bytes
17 files changed, 788 insertions, 268 deletions
diff --git a/wqflask/tests/api/__init__.py b/wqflask/tests/wqflask/__init__.py
index e69de29b..e69de29b 100644
--- a/wqflask/tests/api/__init__.py
+++ b/wqflask/tests/wqflask/__init__.py
diff --git a/wqflask/tests/wqflask/api/__init__.py b/wqflask/tests/wqflask/api/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/wqflask/api/__init__.py
diff --git a/wqflask/tests/api/test_gen_menu.py b/wqflask/tests/wqflask/api/test_gen_menu.py
index 79c77fec..79c77fec 100644
--- a/wqflask/tests/api/test_gen_menu.py
+++ b/wqflask/tests/wqflask/api/test_gen_menu.py
diff --git a/wqflask/tests/wqflask/marker_regression/__init__.py b/wqflask/tests/wqflask/marker_regression/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/wqflask/marker_regression/__init__.py
diff --git a/wqflask/tests/wqflask/marker_regression/test_display_marking_results.py b/wqflask/tests/wqflask/marker_regression/test_display_marking_results.py
new file mode 100644
index 00000000..67da508b
--- /dev/null
+++ b/wqflask/tests/wqflask/marker_regression/test_display_marking_results.py
@@ -0,0 +1,9 @@
+import unittest
+
+from wqflask.marker_regression.display_mapping_results import DisplayMappingResults
+
+class TestDisplayMappingResults(unittest.TestCase):
+    def test_pil_colors(self):
+        """Test that colors use PILLOW color format"""
+        self.assertEqual(DisplayMappingResults.CLICKABLE_WEBQTL_REGION_COLOR,
+                         (245, 211, 211))
diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py
index 9bc84d22..d4373412 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 *
@@ -38,10 +38,21 @@ 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__ )
 
+# ---- Define common colours ---- #
+BLUE = ImageColor.getrgb("blue")
+BLACK = ImageColor.getrgb("black")
+# ---- END: Define common colours ---- #
+
+# ---- FONT FILES ---- #
+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):
     '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)
+        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:
-       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()
diff --git a/wqflask/utility/pillow_utils.py b/wqflask/utility/pillow_utils.py
new file mode 100644
index 00000000..dfbf3e19
--- /dev/null
+++ b/wqflask/utility/pillow_utils.py
@@ -0,0 +1,25 @@
+from PIL import Image, ImageColor, ImageDraw, ImageFont
+
+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)
+    """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]))
+
+# 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)
diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py
index 9ac4946b..bda899fb 100644
--- a/wqflask/wqflask/marker_regression/display_mapping_results.py
+++ b/wqflask/wqflask/marker_regression/display_mapping_results.py
@@ -27,7 +27,7 @@
 import datetime
 import string
 from math import *
-import piddle as pid
+from PIL import (Image,ImageDraw,ImageFont,ImageColor)
 import sys,os
 import cPickle
 import httplib
@@ -45,10 +45,43 @@ 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, draw_open_polygon
 
 import utility.logger
 logger = utility.logger.getLogger(__name__ )
 
+RED = ImageColor.getrgb("red")
+BLUE = ImageColor.getrgb("blue")
+GRAY = ImageColor.getrgb("gray")
+GOLD = ImageColor.getrgb("gold")
+BLACK = ImageColor.getrgb("black")
+GREEN = ImageColor.getrgb("green")
+PURPLE = ImageColor.getrgb("purple")
+ORANGE = ImageColor.getrgb("orange")
+YELLOW = ImageColor.getrgb("yellow")
+DARKRED = ImageColor.getrgb("darkred")
+DARKBLUE = ImageColor.getrgb("darkblue")
+DARKGRAY = ImageColor.getrgb("darkgray")
+DEEPPINK = ImageColor.getrgb("deeppink")
+DARKGREEN = ImageColor.getrgb("darkgreen")
+GAINSBORO = ImageColor.getrgb("gainsboro")
+LIGHTBLUE = ImageColor.getrgb("lightblue")
+DARKORANGE = ImageColor.getrgb("darkorange")
+DARKVIOLET = ImageColor.getrgb("darkviolet")
+MEDIUMPURPLE = ImageColor.getrgb("mediumpurple")
+# ---- END: Define common colours ---- #
+
+# ---- FONT FILES ---- #
+VERDANA_FILE = "./wqflask/static/fonts/verdana.ttf"
+VERDANA_BOLD_FILE = "./wqflask/static/fonts/verdanab.ttf"
+TREBUC_FILE = "./wqflask/static/fonts/trebucbd.ttf"
+FNT_BS_FILE = "./wqflask/static/fonts/fnt_bs.ttf"
+ARIAL_FILE = "./wqflask/static/fonts/arial.ttf"
+
+assert(os.path.isfile(VERDANA_FILE))
+
+# ---- END: FONT FILES ---- #
+
 #########################################
 #      Inteval Mapping Plot Page
 #########################################
@@ -96,47 +129,47 @@ class DisplayMappingResults(object):
 
     LODFACTOR = 4.61
 
-    SNP_COLOR           = pid.orange # Color for the SNP "seismograph"
-    TRANSCRIPT_LOCATION_COLOR = pid.mediumpurple
+    SNP_COLOR           = ORANGE # Color for the SNP "seismograph"
+    TRANSCRIPT_LOCATION_COLOR = MEDIUMPURPLE
 
-    BOOTSTRAP_BOX_COLOR = pid.yellow
-    LRS_COLOR           = pid.HexColor(0x0000FF)
-    SIGNIFICANT_COLOR   = pid.HexColor(0xEBC7C7)
-    SUGGESTIVE_COLOR    = pid.gainsboro
+    BOOTSTRAP_BOX_COLOR = YELLOW
+    LRS_COLOR           = ImageColor.getrgb("#0000FF")
+    SIGNIFICANT_COLOR   = ImageColor.getrgb("#EBC7C7")
+    SUGGESTIVE_COLOR    = GAINSBORO
     SIGNIFICANT_WIDTH = 5
     SUGGESTIVE_WIDTH = 5
-    ADDITIVE_COLOR_POSITIVE = pid.green
-    ADDITIVE_COLOR_NEGATIVE = pid.orange
-    DOMINANCE_COLOR_POSITIVE = pid.darkviolet
-    DOMINANCE_COLOR_NEGATIVE = pid.red
+    ADDITIVE_COLOR_POSITIVE = GREEN
+    ADDITIVE_COLOR_NEGATIVE = ORANGE
+    DOMINANCE_COLOR_POSITIVE = DARKVIOLET
+    DOMINANCE_COLOR_NEGATIVE = RED
 
     ## BEGIN HaplotypeAnalyst
-    HAPLOTYPE_POSITIVE = pid.green
-    HAPLOTYPE_NEGATIVE = pid.red
-    HAPLOTYPE_HETEROZYGOUS = pid.blue
-    HAPLOTYPE_RECOMBINATION = pid.darkgray
+    HAPLOTYPE_POSITIVE = GREEN
+    HAPLOTYPE_NEGATIVE = RED
+    HAPLOTYPE_HETEROZYGOUS = BLUE
+    HAPLOTYPE_RECOMBINATION = DARKGRAY
     ## END HaplotypeAnalyst
 
-    TOP_RIGHT_INFO_COLOR = pid.black
+    TOP_RIGHT_INFO_COLOR = BLACK
 
-    CLICKABLE_WEBQTL_REGION_COLOR     = pid.HexColor(0xF5D3D3)
-    CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR = pid.HexColor(0xFCE9E9)
-    CLICKABLE_WEBQTL_TEXT_COLOR       = pid.HexColor(0x912828)
+    CLICKABLE_WEBQTL_REGION_COLOR     = ImageColor.getrgb("#F5D3D3")
+    CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR = ImageColor.getrgb("#FCE9E9")
+    CLICKABLE_WEBQTL_TEXT_COLOR       = ImageColor.getrgb("#912828")
 
-    CLICKABLE_PHENOGEN_REGION_COLOR   = pid.HexColor(0xA2FB94)
-    CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR = pid.HexColor(0xCEFEC7)
-    CLICKABLE_PHENOGEN_TEXT_COLOR     = pid.HexColor(0x1FD504)
+    CLICKABLE_PHENOGEN_REGION_COLOR   = ImageColor.getrgb("#A2FB94")
+    CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR = ImageColor.getrgb("#CEFEC7")
+    CLICKABLE_PHENOGEN_TEXT_COLOR     = ImageColor.getrgb("#1FD504")
 
-    CLICKABLE_UCSC_REGION_COLOR     = pid.HexColor(0xDDDDEE)
-    CLICKABLE_UCSC_REGION_OUTLINE_COLOR = pid.HexColor(0xEDEDFF)
-    CLICKABLE_UCSC_TEXT_COLOR       = pid.HexColor(0x333366)
+    CLICKABLE_UCSC_REGION_COLOR     = ImageColor.getrgb("#DDDDEE")
+    CLICKABLE_UCSC_REGION_OUTLINE_COLOR = ImageColor.getrgb("#EDEDFF")
+    CLICKABLE_UCSC_TEXT_COLOR       = ImageColor.getrgb("#333366")
 
-    CLICKABLE_ENSEMBL_REGION_COLOR  = pid.HexColor(0xEEEEDD)
-    CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR = pid.HexColor(0xFEFEEE)
-    CLICKABLE_ENSEMBL_TEXT_COLOR    = pid.HexColor(0x555500)
+    CLICKABLE_ENSEMBL_REGION_COLOR  = ImageColor.getrgb("#EEEEDD")
+    CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR = ImageColor.getrgb("#FEFEEE")
+    CLICKABLE_ENSEMBL_TEXT_COLOR    = ImageColor.getrgb("#555500")
 
-    GRAPH_BACK_LIGHT_COLOR = pid.HexColor(0xFBFBFF)
-    GRAPH_BACK_DARK_COLOR  = pid.HexColor(0xF1F1F9)
+    GRAPH_BACK_LIGHT_COLOR = ImageColor.getrgb("#FBFBFF")
+    GRAPH_BACK_DARK_COLOR  = ImageColor.getrgb("#F1F1F9")
 
     HELP_PAGE_REF = '/glossary.html'
 
@@ -466,21 +499,28 @@ class DisplayMappingResults(object):
         # Plots goes here
         ################################################################
         showLocusForm = ""
-        intCanvas = pid.PILCanvas(size=(self.graphWidth, self.graphHeight))
+        intCanvas = Image.new("RGBA", size=(self.graphWidth, self.graphHeight))
         with Bench("Drawing Plot"):
             gifmap = self.plotIntMapping(intCanvas, startMb = self.startMb, endMb = self.endMb, showLocusForm= showLocusForm)
 
         self.gifmap = gifmap.__str__()
 
         self.filename= webqtlUtil.genRandStr("Itvl_")
-        intCanvas.save(os.path.join(webqtlConfig.GENERATED_IMAGE_DIR, self.filename), format='png')
+        intCanvas.save(
+            "{}.png".format(
+                os.path.join(webqtlConfig.GENERATED_IMAGE_DIR, self.filename)),
+            format='png')
         intImg=HT.Image('/image/'+self.filename+'.png', border=0, usemap='#WebQTLImageMap')
 
         #Scales plot differently for high resolution
         if self.draw2X:
-            intCanvasX2 = pid.PILCanvas(size=(self.graphWidth*2,self.graphHeight*2))
+            intCanvasX2 = Image.new("RGBA", size=(self.graphWidth*2,self.graphHeight*2))
             gifmapX2 = self.plotIntMapping(intCanvasX2, startMb = self.startMb, endMb = self.endMb, showLocusForm= showLocusForm, zoom=2)
-            intCanvasX2.save(os.path.join(webqtlConfig.GENERATED_IMAGE_DIR, self.filename+"X2"), format='png')
+            intCanvasX2.save(
+                "{}.png".format(
+                    os.path.join(webqtlConfig.GENERATED_IMAGE_DIR,
+                                 self.filename+"X2")),
+                format='png')
 
         ################################################################
         # Outputs goes here
@@ -508,6 +548,7 @@ class DisplayMappingResults(object):
             btminfo.append(HT.BR(), 'Mapping using genotype data as a trait will result in infinity LRS at one locus. In order to display the result properly, all LRSs higher than 100 are capped at 100.')
 
     def plotIntMapping(self, canvas, offset= (80, 120, 20, 100), zoom = 1, startMb = None, endMb = None, showLocusForm = ""):
+        im_drawer = ImageDraw.Draw(canvas)
         #calculating margins
         xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
         if self.multipleInterval:
@@ -601,6 +642,7 @@ class DisplayMappingResults(object):
         return gifmap
 
     def drawBootStrapResult(self, canvas, nboot, drawAreaHeight, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+        im_drawer = ImageDraw.Draw(canvas)
         xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
         plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
         plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
@@ -687,8 +729,10 @@ class DisplayMappingResults(object):
                 if item[1] > xLeftOffset+plotWidth:
                     item[1] = xLeftOffset+plotWidth
                 if item[0] != item[1]:
-                    canvas.drawRect(item[0], yZero, item[1], yZero - item[2]*bootHeightThresh/maxBootCount,
-                    fillColor=self.BOOTSTRAP_BOX_COLOR)
+                    im_drawer.rectangle(
+                        xy=((item[0], yZero),
+                            (item[1], yZero - item[2]*bootHeightThresh/maxBootCount)),
+                        fill=self.BOOTSTRAP_BOX_COLOR, outline=BLACK)
 
         ###draw boot scale
         highestPercent = (maxBootCount*100.0)/nboot
@@ -697,26 +741,44 @@ class DisplayMappingResults(object):
         bootScale = bootScale[:-1] + [highestPercent]
 
         bootOffset = 50*fontZoom
-        bootScaleFont=pid.Font(ttf="verdana",size=13*fontZoom,bold=0)
-        canvas.drawRect(canvas.size[0]-bootOffset,yZero-bootHeightThresh,canvas.size[0]-bootOffset-15*zoom,yZero,fillColor = pid.yellow)
-        canvas.drawLine(canvas.size[0]-bootOffset+4, yZero, canvas.size[0]-bootOffset, yZero, color=pid.black)
-        canvas.drawString('0%' ,canvas.size[0]-bootOffset+10,yZero+5,font=bootScaleFont,color=pid.black)
+        bootScaleFont=ImageFont.truetype(font=VERDANA_FILE,size=13*fontZoom)
+        im_drawer.rectangle(
+            xy=((canvas.size[0]-bootOffset, yZero-bootHeightThresh),
+                (canvas.size[0]-bootOffset-15*zoom,yZero)),
+            fill = YELLOW, outline=BLACK)
+        im_drawer.line(
+            xy=((canvas.size[0]-bootOffset+4, yZero),
+                (canvas.size[0]-bootOffset, yZero)),
+            fill=BLACK)
+        TEXT_Y_DISPLACEMENT = -8
+        im_drawer.text(xy=(canvas.size[0]-bootOffset+10,yZero+TEXT_Y_DISPLACEMENT), text='0%',
+                       font=bootScaleFont, fill=BLACK)
+
         for item in bootScale:
             if item == 0:
                 continue
             bootY = yZero-bootHeightThresh*item/highestPercent
-            canvas.drawLine(canvas.size[0]-bootOffset+4,bootY,canvas.size[0]-bootOffset,bootY,color=pid.black)
-            canvas.drawString('%2.1f'%item ,canvas.size[0]-bootOffset+10,bootY+5,font=bootScaleFont,color=pid.black)
+            im_drawer.line(
+                xy=((canvas.size[0]-bootOffset+4,bootY),
+                 (canvas.size[0]-bootOffset,bootY)),
+                fill=BLACK)
+            im_drawer.text(xy=(canvas.size[0]-bootOffset+10,bootY+TEXT_Y_DISPLACEMENT),
+                           text='%2.1f'%item, font=bootScaleFont, fill=BLACK)
 
         if self.legendChecked:
             startPosY = 30
             nCol = 2
-            smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1)
+            smallLabelFont = ImageFont.truetype(font=TREBUC_FILE, size=12*fontZoom)
             leftOffset = xLeftOffset+(nCol-1)*200
-            canvas.drawRect(leftOffset,startPosY-6, leftOffset+12,startPosY+6, fillColor=pid.yellow)
-            canvas.drawString('Frequency of the Peak LRS',leftOffset+ 20, startPosY+5,font=smallLabelFont,color=pid.black)
+            im_drawer.rectangle(
+                xy=((leftOffset,startPosY-6), (leftOffset+12,startPosY+6)),
+                fill=YELLOW, outline=BLACK)
+            im_drawer.text(xy=(leftOffset+ 20, startPosY+TEXT_Y_DISPLACEMENT),
+                           text='Frequency of the Peak LRS',
+                           font=smallLabelFont, fill=BLACK)
 
     def drawProbeSetPosition(self, canvas, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+        im_drawer = ImageDraw.Draw(canvas)
         if len(self.traitList) != 1:
             return
 
@@ -784,20 +846,33 @@ class DisplayMappingResults(object):
                             break
         if locPixel >= 0 and self.plotScale == 'physic':
             traitPixel = ((locPixel, yZero), (locPixel-7, yZero+14), (locPixel+7, yZero+14))
-            canvas.drawPolygon(traitPixel, edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1)
+            draw_open_polygon(canvas, xy=traitPixel, outline=BLACK,
+                              fill=self.TRANSCRIPT_LOCATION_COLOR)
 
         if self.legendChecked:
             startPosY = 15
             nCol = 2
-            smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1)
+            smallLabelFont = ImageFont.truetype(font=TREBUC_FILE, size=12*fontZoom)
             if self.manhattan_plot:
                 leftOffset = xLeftOffset
             else:
                 leftOffset = xLeftOffset+(nCol-1)*200*fontZoom
-            canvas.drawPolygon(((leftOffset+7, startPosY-7), (leftOffset, startPosY+7), (leftOffset+14, startPosY+7)), edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1)
-            canvas.drawString("Sequence Site", (leftOffset+15), (startPosY+5), smallLabelFont, self.TOP_RIGHT_INFO_COLOR)
+            draw_open_polygon(
+                canvas,
+                xy=(
+                    (leftOffset+7, startPosY-7),
+                    (leftOffset, startPosY+7),
+                    (leftOffset+14, startPosY+7)),
+                outline=BLACK, fill=self.TRANSCRIPT_LOCATION_COLOR
+            )
+            TEXT_Y_DISPLACEMENT = -8
+            im_drawer.text(
+                text="Sequence Site",
+                xy=(leftOffset+15,startPosY+TEXT_Y_DISPLACEMENT), font=smallLabelFont,
+                fill=self.TOP_RIGHT_INFO_COLOR)
 
     def drawSNPTrackNew(self, canvas, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+        im_drawer = ImageDraw.Draw(canvas)
         if self.plotScale != 'physic' or self.selectedChr == -1 or not self.diffCol:
             return
 
@@ -835,12 +910,15 @@ class DisplayMappingResults(object):
             if maxCount>0:
                 for i in range(xLeftOffset, xLeftOffset + plotWidth):
                     snpDensity = float(SNPCounts[i-xLeftOffset]*SNP_HEIGHT_MODIFIER/maxCount)
-                    canvas.drawLine(i, drawSNPLocationY+(snpDensity)*zoom, i, drawSNPLocationY-(snpDensity)*zoom, color=self.SNP_COLOR, width=1)
+                    im_drawer.line(
+                        xy=((i, drawSNPLocationY+(snpDensity)*zoom),
+                           (i, drawSNPLocationY-(snpDensity)*zoom)),
+                        fill=self.SNP_COLOR, width=1)
 
     def drawMultiTraitName(self, fd, canvas, gifmap, showLocusForm, offset= (40, 120, 80, 10), zoom = 1):
         nameWidths = []
         yPaddingTop = 10
-        colorFont=pid.Font(ttf="trebuc",size=12,bold=1)
+        colorFont=ImageFont.truetype(font=TREBUC_FILE,size=12)
         if len(self.qtlresults) >20 and self.selectedChr > -1:
             rightShift = 20
             rightShiftStep = 60
@@ -859,11 +937,16 @@ class DisplayMappingResults(object):
                 rightShift += rightShiftStep
 
             name = thisTrait.displayName()
-            nameWidth = canvas.stringWidth(name,font=colorFont)
+            nameWidth, nameHeight = im_drawer.textsize(name,font=colorFont)
             nameWidths.append(nameWidth)
 
-            canvas.drawRect(rightShift,yPaddingTop+kstep*15, rectWidth+rightShift,yPaddingTop+10+kstep*15, fillColor=thisLRSColor)
-            canvas.drawString(name,rectWidth+2+rightShift,yPaddingTop+10+kstep*15,font=colorFont,color=pid.black)
+            im_drawer.rectangle(
+                xy=((rightShift,yPaddingTop+kstep*15),
+                    (rectWidth+rightShift,yPaddingTop+10+kstep*15)),
+                fill=thisLRSColor, outline=BLACK)
+            im_drawer.text(
+                text=name,xy=(rectWidth+2+rightShift,yPaddingTop+10+kstep*15),
+                font=colorFont,fill=BLACK)
             if thisTrait.db:
                 COORDS = "%d,%d,%d,%d" %(rectWidth+2+rightShift,yPaddingTop+kstep*15,rectWidth+2+rightShift+nameWidth,yPaddingTop+10+kstep*15,)
                 HREF= "javascript:showDatabase3('%s','%s','%s','');" % (showLocusForm, thisTrait.db.name, thisTrait.name)
@@ -871,54 +954,91 @@ class DisplayMappingResults(object):
                 gifmap.areas.append(Areas)
 
     def drawLegendPanel(self, canvas, offset= (40, 120, 80, 10), zoom = 1):
+        im_drawer = ImageDraw.Draw(canvas)
         xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
         plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
         plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
         yZero = canvas.size[1] - yBottomOffset
+        TEXT_Y_DISPLACEMENT = -8
         fontZoom = zoom
         if zoom == 2:
             fontZoom = 1.5
 
-        labelFont=pid.Font(ttf="trebuc",size=12*fontZoom, bold=1)
+        labelFont=ImageFont.truetype(font=TREBUC_FILE,size=12*fontZoom)
         startPosY = 15
         stepPosY = 12*fontZoom
         if self.manhattan_plot != True:
-            canvas.drawLine(xLeftOffset,startPosY,xLeftOffset+32,startPosY,color=self.LRS_COLOR, width=2)
-            canvas.drawString(self.LRS_LOD, xLeftOffset+40,startPosY+5,font=labelFont,color=pid.black)
+            im_drawer.line(
+                xy=((xLeftOffset,startPosY),(xLeftOffset+32,startPosY)),
+                fill=self.LRS_COLOR, width=2)
+            im_drawer.text(
+                text=self.LRS_LOD, xy=(xLeftOffset+40,startPosY+TEXT_Y_DISPLACEMENT),
+                font=labelFont,fill=BLACK)
             startPosY += stepPosY
 
         if self.additiveChecked:
             startPosX = xLeftOffset
-            canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.ADDITIVE_COLOR_POSITIVE, width=2)
-            canvas.drawLine(startPosX+18,startPosY,startPosX+32,startPosY,color=self.ADDITIVE_COLOR_NEGATIVE, width=2)
-            canvas.drawString('Additive Effect',startPosX+40,startPosY+5,font=labelFont,color=pid.black)
+            im_drawer.line(
+                xy=((startPosX,startPosY),(startPosX+17,startPosY)),
+                fill=self.ADDITIVE_COLOR_POSITIVE, width=2)
+            im_drawer.line(
+                xy=((startPosX+18,startPosY),(startPosX+32,startPosY)),
+                fill=self.ADDITIVE_COLOR_NEGATIVE, width=2)
+            im_drawer.text(
+                text='Additive Effect',xy=(startPosX+40,startPosY+TEXT_Y_DISPLACEMENT),
+                font=labelFont,fill=BLACK)
 
         if self.genotype.type == 'intercross' and self.dominanceChecked:
             startPosX = xLeftOffset
             startPosY += stepPosY
-            canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.DOMINANCE_COLOR_POSITIVE, width=4)
-            canvas.drawLine(startPosX+18,startPosY,startPosX+35,startPosY,color=self.DOMINANCE_COLOR_NEGATIVE, width=4)
-            canvas.drawString('Dominance Effect',startPosX+42,startPosY+5,font=labelFont,color=pid.black)
+            im_drawer.line(
+                xy=((startPosX,startPosY),(startPosX+17,startPosY)),
+                fill=self.DOMINANCE_COLOR_POSITIVE, width=4)
+            im_drawer.line(
+                xy=((startPosX+18,startPosY),(startPosX+35,startPosY)),
+                fill=self.DOMINANCE_COLOR_NEGATIVE, width=4)
+            im_drawer.text(
+                text='Dominance Effect', xy=(startPosX+42,startPosY+5),
+                font=labelFont,fill=BLACK)
 
         if self.haplotypeAnalystChecked:
             startPosY += stepPosY
             startPosX = xLeftOffset
-            canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.HAPLOTYPE_POSITIVE, width=4)
-            canvas.drawLine(startPosX+18,startPosY,startPosX+35,startPosY,color=self.HAPLOTYPE_NEGATIVE, width=4)
-            canvas.drawLine(startPosX+36,startPosY,startPosX+53,startPosY,color=self.HAPLOTYPE_HETEROZYGOUS, width=4)
-            canvas.drawLine(startPosX+54,startPosY,startPosX+67,startPosY,color=self.HAPLOTYPE_RECOMBINATION, width=4)
-            canvas.drawString('Haplotypes (Pat, Mat, Het, Unk)',startPosX+76,startPosY+5,font=labelFont,color=pid.black)
+            im_drawer.line(
+                xy=((startPosX,startPosY),(startPosX+17,startPosY)),
+                fill=self.HAPLOTYPE_POSITIVE, width=4)
+            im_drawer.line(
+                xy=((startPosX+18,startPosY),(startPosX+35,startPosY)),
+                fill=self.HAPLOTYPE_NEGATIVE, width=4)
+            im_drawer.line(
+                xy=((startPosX+36,startPosY),(startPosX+53,startPosY)),
+                fill=self.HAPLOTYPE_HETEROZYGOUS, width=4)
+            im_drawer.line(
+                xy=((startPosX+54,startPosY),(startPosX+67,startPosY)),
+                fill=self.HAPLOTYPE_RECOMBINATION, width=4)
+            im_drawer.text(
+                text='Haplotypes (Pat, Mat, Het, Unk)',
+                xy=(startPosX+76,startPosY+5),font=labelFont,fill=BLACK)
 
         if self.permChecked and self.nperm > 0:
             startPosY += stepPosY
             startPosX = xLeftOffset
-            canvas.drawLine(startPosX, startPosY, startPosX + 32, startPosY, color=self.SIGNIFICANT_COLOR, width=self.SIGNIFICANT_WIDTH)
-            canvas.drawLine(startPosX, startPosY + stepPosY, startPosX + 32, startPosY + stepPosY, color=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH)
-            canvas.drawString('Significant %s = %2.2f' % (self.LRS_LOD, self.significant),xLeftOffset+42,startPosY +5,font=labelFont,color=pid.black)
-            canvas.drawString('Suggestive %s = %2.2f' % (self.LRS_LOD, self.suggestive),xLeftOffset+42,startPosY + 5 +stepPosY,font=labelFont,color=pid.black)
-
-        labelFont = pid.Font(ttf="verdana",size=12*fontZoom)
-        labelColor = pid.black
+            im_drawer.line(
+                xy=((startPosX, startPosY),( startPosX + 32, startPosY)),
+                fill=self.SIGNIFICANT_COLOR, width=self.SIGNIFICANT_WIDTH)
+            im_drawer.line(
+                xy=((startPosX, startPosY + stepPosY),( startPosX + 32, startPosY + stepPosY)),
+                fill=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH)
+            im_drawer.text(
+                text='Significant %s = %2.2f' % (self.LRS_LOD,self.significant),
+                xy=(xLeftOffset+42,startPosY+TEXT_Y_DISPLACEMENT),font=labelFont,fill=BLACK)
+            im_drawer.text(
+                text='Suggestive %s = %2.2f' % (self.LRS_LOD, self.suggestive),
+                xy=(xLeftOffset+42,startPosY + TEXT_Y_DISPLACEMENT +stepPosY),font=labelFont,
+                fill=BLACK)
+
+        labelFont = ImageFont.truetype(font=VERDANA_FILE,size=12*fontZoom)
+        labelColor = BLACK
         if self.dataset.type == "Publish" or self.dataset.type == "Geno":
             dataset_label = self.dataset.fullname
         else:
@@ -979,20 +1099,32 @@ class DisplayMappingResults(object):
                 identification += "Trait: %s" % (self.this_trait.name)
             identification += " with %s samples" % (self.n_samples)
 
-            d = 4+ max(canvas.stringWidth(identification, font=labelFont), canvas.stringWidth(string1, font=labelFont), canvas.stringWidth(string2, font=labelFont))
-            canvas.drawString(identification,canvas.size[0] - xRightOffset-d,20*fontZoom,font=labelFont,color=labelColor)
-        else:
-            d = 4+ max(canvas.stringWidth(string1, font=labelFont), canvas.stringWidth(string2, font=labelFont))
-        canvas.drawString(string1,canvas.size[0] - xRightOffset-d,35*fontZoom,font=labelFont,color=labelColor)
-        canvas.drawString(string2,canvas.size[0] - xRightOffset-d,50*fontZoom,font=labelFont,color=labelColor)
-        canvas.drawString(string3,canvas.size[0] - xRightOffset-d,65*fontZoom,font=labelFont,color=labelColor)
-        if string4 != '':
-            canvas.drawString(string4,canvas.size[0] - xRightOffset-d,80*fontZoom,font=labelFont,color=labelColor)
-            canvas.drawString("Created at: " + str(datetime.datetime.now()).split('.')[0], canvas.size[0] - xRightOffset-d,95*fontZoom,font=labelFont,color=labelColor)
+            d = 4+ max(
+                im_drawer.textsize(identification, font=labelFont)[0],
+                im_drawer.textsize(string1, font=labelFont)[0],
+                im_drawer.textsize(string2, font=labelFont)[0])
+            im_drawer.text(
+                text=identification,
+                xy=(canvas.size[0] - xRightOffset-d,20*fontZoom),font=labelFont,
+                fill=labelColor)
         else:
-            canvas.drawString("Created at: " + str(datetime.datetime.now()).split('.')[0], canvas.size[0] - xRightOffset-d,80*fontZoom,font=labelFont,color=labelColor)
+            d = 4+ max(
+                im_drawer.textsize(string1, font=labelFont)[0],
+                im_drawer.textsize(string2, font=labelFont)[0])
+        im_drawer.text(
+            text=string1,xy=(canvas.size[0] - xRightOffset-d,35*fontZoom),
+            font=labelFont,fill=labelColor)
+        im_drawer.text(
+            text=string2,xy=(canvas.size[0] - xRightOffset-d,50*fontZoom),
+            font=labelFont,fill=labelColor)
+        if string3 != '':
+            im_drawer.text(
+                text=string3,xy=(canvas.size[0] - xRightOffset-d,65*fontZoom),
+                font=labelFont,fill=labelColor)
+
 
     def drawGeneBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+        im_drawer = ImageDraw.Draw(canvas)
         if self.plotScale != 'physic' or self.selectedChr == -1 or not self.geneCol:
             return
 
@@ -1042,19 +1174,19 @@ class DisplayMappingResults(object):
 
                 densities=[1.0000000000000001e-05, 0.094094033555233408, 0.3306166377816987, 0.88246026851027781, 2.6690084029581951, 4.1, 61.0]
                 if SNPdensity < densities[0]:
-                    myColor = pid.black
+                    myColor = BLACK
                 elif SNPdensity < densities[1]:
-                    myColor = pid.purple
+                    myColor = PURPLE
                 elif SNPdensity < densities[2]:
-                    myColor = pid.darkblue
+                    myColor = DARKBLUE
                 elif SNPdensity < densities[3]:
-                    myColor = pid.darkgreen
+                    myColor = DARKGREEN
                 elif SNPdensity < densities[4]:
-                    myColor = pid.gold
+                    myColor = GOLD
                 elif SNPdensity < densities[5]:
-                    myColor = pid.darkorange
+                    myColor = DARKORANGE
                 else:
-                    myColor = pid.darkred
+                    myColor = DARKRED
 
                 outlineColor = myColor
                 fillColor    = myColor
@@ -1086,14 +1218,14 @@ class DisplayMappingResults(object):
                 elif (geneStartPix < xLeftOffset):
                     geneStartPix = xLeftOffset; # clip the first in-range gene
 
-                outlineColor = pid.darkblue
-                fillColor = pid.darkblue
+                outlineColor = DARKBLUE
+                fillColor = DARKBLUE
                 TITLE = "Gene: %s\nFrom %2.3f to %2.3f Mb (%s)" % (geneSymbol, float(txStart), float(txEnd), strand)
                 # NL: 06-02-2011 Rob required to change this link for gene related
                 HREF=geneNCBILink %geneSymbol
             else:
-                outlineColor = pid.orange
-                fillColor = pid.orange
+                outlineColor = ORANGE
+                fillColor = ORANGE
                 TITLE = "Gene: %s" % geneSymbol
 
             #Draw Genes
@@ -1105,11 +1237,15 @@ class DisplayMappingResults(object):
 
             #draw the detail view
             if self.endMb - self.startMb <= self.DRAW_DETAIL_MB and geneEndPix - geneStartPix > self.EACH_GENE_ARROW_SPACING * 3:
-                utrColor = pid.Color(0.66, 0.66, 0.66)
-                arrowColor = pid.Color(0.7, 0.7, 0.7)
+                utrColor = ImageColor.getrgb("rgb(66%, 66%, 66%)")
+                arrowColor = ImageColor.getrgb("rgb(70%, 70%, 70%)")
 
                 #draw the line that runs the entire length of the gene
-                canvas.drawLine(geneStartPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom, geneEndPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom, color=outlineColor, width=1)
+                im_drawer.line(
+                    xy=(
+                        (geneStartPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom),
+                        ( geneEndPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom)),
+                    fill=outlineColor, width=1)
 
                 #draw the arrows
                 if geneEndPix - geneStartPix < 1:
@@ -1120,11 +1256,30 @@ class DisplayMappingResults(object):
 
                     if (xCoord % self.EACH_GENE_ARROW_SPACING == 0 and xCoord + self.EACH_GENE_ARROW_SPACING < geneEndPix-geneStartPix) or xCoord == 0:
                         if strand == "+":
-                            canvas.drawLine(geneStartPix + xCoord, geneYLocation, geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1)
-                            canvas.drawLine(geneStartPix + xCoord, geneYLocation + self.EACH_GENE_HEIGHT*zoom, geneStartPix + xCoord+self.EACH_GENE_ARROW_WIDTH, geneYLocation + (self.EACH_GENE_HEIGHT / 2) * zoom, color=arrowColor, width=1)
+                            im_drawer.line(
+                                xy=((geneStartPix + xCoord, geneYLocation),
+                                    (geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH,
+                                     geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom)),
+                                fill=arrowColor, width=1)
+                            im_drawer.line(
+                                xy=((geneStartPix + xCoord,
+                                     geneYLocation + self.EACH_GENE_HEIGHT*zoom),
+                                    (geneStartPix + xCoord+self.EACH_GENE_ARROW_WIDTH,
+                                     geneYLocation + (self.EACH_GENE_HEIGHT / 2) * zoom)),
+                                fill=arrowColor, width=1)
                         else:
-                            canvas.drawLine(geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation, geneStartPix + xCoord, geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1)
-                            canvas.drawLine(geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation + self.EACH_GENE_HEIGHT*zoom, geneStartPix + xCoord, geneYLocation + (self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1)
+                            im_drawer.line(
+                                xy=((geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH,
+                                     geneYLocation),
+                                    ( geneStartPix + xCoord,
+                                      geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom)),
+                                fill=arrowColor, width=1)
+                            im_drawer.line(
+                                xy=((geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH,
+                                     geneYLocation + self.EACH_GENE_HEIGHT*zoom),
+                                    ( geneStartPix + xCoord,
+                                      geneYLocation + (self.EACH_GENE_HEIGHT / 2)*zoom)),
+                                fill=arrowColor, width=1)
 
                 #draw the blocks for the exon regions
                 for i in range(0, len(exonStarts)):
@@ -1138,7 +1293,10 @@ class DisplayMappingResults(object):
                         exonEndPix = xLeftOffset + plotWidth
                     if (exonStartPix > xLeftOffset + plotWidth):
                         exonStartPix = xLeftOffset + plotWidth
-                    canvas.drawRect(exonStartPix, geneYLocation, exonEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom), edgeColor = outlineColor, fillColor = fillColor)
+                    im_drawer.rectangle(
+                        xy=((exonStartPix, geneYLocation),
+                            (exonEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom))),
+                        outline = outlineColor, fill = fillColor)
 
                 #draw gray blocks for 3' and 5' UTR blocks
                 if cdsStart and cdsEnd:
@@ -1152,14 +1310,16 @@ class DisplayMappingResults(object):
                         utrEndPix = xLeftOffset + plotWidth
                     if (utrStartPix > xLeftOffset + plotWidth):
                         utrStartPix = xLeftOffset + plotWidth
-                    #canvas.drawRect(utrStartPix, geneYLocation, utrEndPix, (geneYLocation+self.EACH_GENE_HEIGHT*zoom), edgeColor=utrColor, fillColor =utrColor)
 
                     if self.endMb - self.startMb <= self.DRAW_UTR_LABELS_MB:
                         if strand == "-":
                             labelText = "3'"
                         else:
                             labelText = "5'"
-                        canvas.drawString(labelText, utrStartPix-9, geneYLocation+self.EACH_GENE_HEIGHT, pid.Font(face="helvetica", size=2))
+                        im_drawer.text(
+                            text=labelText,
+                            xy=(utrStartPix-9, geneYLocation+self.EACH_GENE_HEIGHT),
+                            font=ImageFont.truetype(font=ARIAL_FILE, size=2))
 
                     #the second UTR region
 
@@ -1173,18 +1333,23 @@ class DisplayMappingResults(object):
                         utrEndPix = xLeftOffset + plotWidth
                     if (utrStartPix > xLeftOffset + plotWidth):
                         utrStartPix = xLeftOffset + plotWidth
-                    #canvas.drawRect(utrStartPix, geneYLocation, utrEndPix, (geneYLocation+self.EACH_GENE_HEIGHT*zoom), edgeColor=utrColor, fillColor =utrColor)
 
                     if self.endMb - self.startMb <= self.DRAW_UTR_LABELS_MB:
                         if strand == "-":
                             labelText = "5'"
                         else:
                             labelText = "3'"
-                        canvas.drawString(labelText, utrEndPix+2, geneYLocation+self.EACH_GENE_HEIGHT, pid.Font(face="helvetica", size=2))
+                            im_drawer.text(
+                                text=labelText,
+                                xy=(utrEndPix+2,geneYLocation+self.EACH_GENE_HEIGHT),
+                                font=ImageFont.truetype(font=ARIAL_FILE, size=2))
 
             #draw the genes as rectangles
             else:
-                canvas.drawRect(geneStartPix, geneYLocation, geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom), edgeColor = outlineColor, fillColor = fillColor)
+                im_drawer.rectangle(
+                    xy=((geneStartPix, geneYLocation),
+                        (geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom))),
+                    outline= outlineColor, fill = fillColor)
 
             COORDS = "%d, %d, %d, %d" %(geneStartPix, geneYLocation, geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT))
             # NL: 06-02-2011 Rob required to display NCBI info in a new window
@@ -1287,7 +1452,7 @@ class DisplayMappingResults(object):
                         drawit = 1
 
                     if drawit == 1:
-                        myColor = pid.darkblue
+                        myColor = DARKBLUE
                         outlineColor = myColor
                         fillColor    = myColor
 
@@ -1333,12 +1498,22 @@ class DisplayMappingResults(object):
                                     else:
                                         mylineColor = self.HAPLOTYPE_RECOMBINATION # XZ: Unknown
 
-                                    canvas.drawLine(drawStart, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, drawEnd, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, color = mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2))
+                                    im_drawer.line(
+                                        xy=((drawStart,
+                                             geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom),
+                                            (drawEnd,
+                                             geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom)),
+                                        fill= mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2))
 
-                                    fillColor=pid.black
-                                    outlineColor=pid.black
+                                    fillColor=BLACK
+                                    outlineColor=BLACK
                                     if lastGene == 0:
-                                        canvas.drawRect(geneStartPix, geneYLocation+2*ind*self.EACH_GENE_HEIGHT*zoom, geneEndPix, geneYLocation+2*ind*self.EACH_GENE_HEIGHT+ 2*self.EACH_GENE_HEIGHT*zoom, edgeColor = outlineColor, fillColor = fillColor)
+                                        im_drawer.rectangle(
+                                            xy=((geneStartPix,
+                                                 geneYLocation+2*ind*self.EACH_GENE_HEIGHT*zoom),
+                                                (geneEndPix,
+                                                 geneYLocation+2*ind*self.EACH_GENE_HEIGHT+ 2*self.EACH_GENE_HEIGHT*zoom)),
+                                            outline=outlineColor, fill=fillColor)
 
 
                                     COORDS = "%d, %d, %d, %d" %(geneStartPix, geneYLocation+ind*self.EACH_GENE_HEIGHT, geneEndPix+1, (geneYLocation + ind*self.EACH_GENE_HEIGHT))
@@ -1351,11 +1526,22 @@ class DisplayMappingResults(object):
                                     if (plotRight < (xLeftOffset + plotWidth - 3)) and (lastGene == 0):
                                         drawEnd = xLeftOffset + plotWidth - 6
                                         mylineColor = self.HAPLOTYPE_RECOMBINATION
-                                        canvas.drawLine(plotRight, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, drawEnd, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, color = mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2))
+                                im_drawer.line(
+                                    xy=((plotRight,
+                                         geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom),
+                                        (drawEnd,
+                                         geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom)),
+                                    fill= mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2))
 
 
                             if lastGene == 0:
-                                canvas.drawString("%s" % (_chr[j].name), geneStartPix , geneYLocation+17+2*maxind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black, angle=-90)
+                                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),
+                                    fill=BLACK, angle=-90)
 
                             oldgeneEndPix = geneEndPix;
                             oldgeno = _chr[j].genotype
@@ -1384,12 +1570,23 @@ class DisplayMappingResults(object):
                                 expr = item.value
 
                         # Place where font is hardcoded
-                        canvas.drawString("%s" % (samplelist[j]), (xLeftOffset + plotWidth + 10) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black)
-                        canvas.drawString("%2.2f" % (expr), (xLeftOffset + plotWidth + 60) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black)
+                        im_drawer.text(
+                            text="%s" % (samplelist[j]),
+                            xy=((xLeftOffset + plotWidth + 10),
+                                geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom),
+                            font=ImageFont.truetype(font=VERDANA_FILE, size=12),
+                            fill=BLACK)
+                        im_drawer.text(
+                            text="%2.2f" % (expr),
+                            xy=((xLeftOffset + plotWidth + 60),
+                                geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom),
+                            font=ImageFont.truetype(font=VERDANA_FILE, size=12),
+                            fill=BLACK)
 
 ## END HaplotypeAnalyst
 
     def drawClickBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+        im_drawer = ImageDraw.Draw(canvas)
         if self.plotScale != 'physic' or self.selectedChr == -1:
             return
 
@@ -1405,7 +1602,7 @@ class DisplayMappingResults(object):
         # but it makes the HTML huge, and takes forever to render the page in the first place)
         # Draw the bands that you can click on to go to UCSC / Ensembl
         MAX_CLICKABLE_REGION_DIVISIONS = 100
-        clickableRegionLabelFont=pid.Font(ttf="verdana", size=9, bold=0)
+        clickableRegionLabelFont=ImageFont.truetype(font=VERDANA_FILE, size=9)
         pixelStep = max(5, int(float(plotWidth)/MAX_CLICKABLE_REGION_DIVISIONS))
         # pixelStep: every N pixels, we make a new clickable area for the user to go to that area of the genome.
 
@@ -1442,8 +1639,14 @@ class DisplayMappingResults(object):
 
                 WEBQTL_TITLE = "Click to view this section of the genome in WebQTL"
                 gifmap.areas.append(HT.Area(shape='rect',coords=WEBQTL_COORDS,href=WEBQTL_HREF, title=WEBQTL_TITLE))
-                canvas.drawRect(xBrowse1, paddingTop, xBrowse2, (paddingTop + self.BAND_HEIGHT), edgeColor=self.CLICKABLE_WEBQTL_REGION_COLOR, fillColor=self.CLICKABLE_WEBQTL_REGION_COLOR)
-                canvas.drawLine(xBrowse1, paddingTop, xBrowse1, (paddingTop + self.BAND_HEIGHT), color=self.CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR)
+                im_drawer.rectangle(
+                    xy=((xBrowse1, paddingTop),
+                        (xBrowse2, (paddingTop + self.BAND_HEIGHT))),
+                    outline=self.CLICKABLE_WEBQTL_REGION_COLOR,
+                    fill=self.CLICKABLE_WEBQTL_REGION_COLOR)
+                im_drawer.line(
+                    xy=((xBrowse1, paddingTop),( xBrowse1, (paddingTop + self.BAND_HEIGHT))),
+                    fill=self.CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR)
 
                 if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat":
                     PHENOGEN_COORDS = "%d, %d, %d, %d" % (xBrowse1, phenogenPaddingTop, xBrowse2, (phenogenPaddingTop+self.BAND_HEIGHT))
@@ -1453,8 +1656,14 @@ class DisplayMappingResults(object):
                         PHENOGEN_HREF = "https://phenogen.org/gene.jsp?speciesCB=Mm&auto=Y&geneTxt=chr%s:%d-%d&genomeVer=mm10" % (self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases)
                     PHENOGEN_TITLE = "Click to view this section of the genome in PhenoGen"
                     gifmap.areas.append(HT.Area(shape='rect',coords=PHENOGEN_COORDS,href=PHENOGEN_HREF, title=PHENOGEN_TITLE))
-                    canvas.drawRect(xBrowse1, phenogenPaddingTop, xBrowse2, (phenogenPaddingTop+self.BAND_HEIGHT), edgeColor=self.CLICKABLE_PHENOGEN_REGION_COLOR, fillColor=self.CLICKABLE_PHENOGEN_REGION_COLOR)
-                    canvas.drawLine(xBrowse1, phenogenPaddingTop, xBrowse1, (phenogenPaddingTop+self.BAND_HEIGHT), color=self.CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR)
+                    im_drawer.rectangle(
+                        xy=((xBrowse1, phenogenPaddingTop),
+                            (xBrowse2, (phenogenPaddingTop+self.BAND_HEIGHT))),
+                        outline=self.CLICKABLE_PHENOGEN_REGION_COLOR,
+                        fill=self.CLICKABLE_PHENOGEN_REGION_COLOR)
+                    im_drawer.line(
+                        xy=((xBrowse1, phenogenPaddingTop),( xBrowse1, (phenogenPaddingTop+self.BAND_HEIGHT))),
+                        fill=self.CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR)
 
                 UCSC_COORDS = "%d, %d, %d, %d" %(xBrowse1, ucscPaddingTop, xBrowse2, (ucscPaddingTop+self.BAND_HEIGHT))
                 if self.dataset.group.species == "mouse":
@@ -1463,8 +1672,15 @@ class DisplayMappingResults(object):
                     UCSC_HREF = "http://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=chr%s:%d-%d" % (self._ucscDb, self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases)
                 UCSC_TITLE = "Click to view this section of the genome in the UCSC Genome Browser"
                 gifmap.areas.append(HT.Area(shape='rect',coords=UCSC_COORDS,href=UCSC_HREF, title=UCSC_TITLE))
-                canvas.drawRect(xBrowse1, ucscPaddingTop, xBrowse2, (ucscPaddingTop+self.BAND_HEIGHT), edgeColor=self.CLICKABLE_UCSC_REGION_COLOR, fillColor=self.CLICKABLE_UCSC_REGION_COLOR)
-                canvas.drawLine(xBrowse1, ucscPaddingTop, xBrowse1, (ucscPaddingTop+self.BAND_HEIGHT), color=self.CLICKABLE_UCSC_REGION_OUTLINE_COLOR)
+                im_drawer.rectangle(
+                    xy=((xBrowse1, ucscPaddingTop),
+                        (xBrowse2, (ucscPaddingTop+self.BAND_HEIGHT))),
+                    outline=self.CLICKABLE_UCSC_REGION_COLOR,
+                    fill=self.CLICKABLE_UCSC_REGION_COLOR)
+                im_drawer.line(
+                    xy=((xBrowse1, ucscPaddingTop),
+                        (xBrowse1, (ucscPaddingTop+self.BAND_HEIGHT))),
+                    fill=self.CLICKABLE_UCSC_REGION_OUTLINE_COLOR)
 
                 ENSEMBL_COORDS = "%d, %d, %d, %d" %(xBrowse1, ensemblPaddingTop, xBrowse2, (ensemblPaddingTop+self.BAND_HEIGHT))
                 if self.dataset.group.species == "mouse":
@@ -1473,32 +1689,57 @@ class DisplayMappingResults(object):
                     ENSEMBL_HREF = "http://www.ensembl.org/Rattus_norvegicus/contigview?chr=%s&start=%d&end=%d" % (self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases)
                 ENSEMBL_TITLE = "Click to view this section of the genome in the Ensembl Genome Browser"
                 gifmap.areas.append(HT.Area(shape='rect',coords=ENSEMBL_COORDS,href=ENSEMBL_HREF, title=ENSEMBL_TITLE))
-                canvas.drawRect(xBrowse1, ensemblPaddingTop, xBrowse2, (ensemblPaddingTop+self.BAND_HEIGHT), edgeColor=self.CLICKABLE_ENSEMBL_REGION_COLOR, fillColor=self.CLICKABLE_ENSEMBL_REGION_COLOR)
-                canvas.drawLine(xBrowse1, ensemblPaddingTop, xBrowse1, (ensemblPaddingTop+self.BAND_HEIGHT), color=self.CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR)
+                im_drawer.rectangle(
+                    xy=((xBrowse1, ensemblPaddingTop),
+                        (xBrowse2, (ensemblPaddingTop+self.BAND_HEIGHT))),
+                    outline=self.CLICKABLE_ENSEMBL_REGION_COLOR,
+                    fill=self.CLICKABLE_ENSEMBL_REGION_COLOR)
+                im_drawer.line(
+                    xy=((xBrowse1, ensemblPaddingTop),
+                        (xBrowse1, (ensemblPaddingTop+self.BAND_HEIGHT))),
+                    fill=self.CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR)
             # end for
 
-            canvas.drawString("Click to view the corresponding section of the genome in an 8x expanded WebQTL map", (xLeftOffset + 10), paddingTop + self.BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_WEBQTL_TEXT_COLOR)
+            im_drawer.text(
+                text="Click to view the corresponding section of the genome in an 8x expanded WebQTL map",
+                xy=((xLeftOffset + 10), paddingTop),# + self.BAND_HEIGHT/2),
+                font=clickableRegionLabelFont,
+                fill=self.CLICKABLE_WEBQTL_TEXT_COLOR)
             if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat":
-                canvas.drawString("Click to view the corresponding section of the genome in PhenoGen", (xLeftOffset + 10), phenogenPaddingTop + self.BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_PHENOGEN_TEXT_COLOR)
-            canvas.drawString("Click to view the corresponding section of the genome in the UCSC Genome Browser", (xLeftOffset + 10), ucscPaddingTop + self.BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_UCSC_TEXT_COLOR)
-            canvas.drawString("Click to view the corresponding section of the genome in the Ensembl Genome Browser", (xLeftOffset+10), ensemblPaddingTop + self.BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_ENSEMBL_TEXT_COLOR)
+                im_drawer.text(
+                    text="Click to view the corresponding section of the genome in PhenoGen",
+                    xy=((xLeftOffset + 10), phenogenPaddingTop),# + self.BAND_HEIGHT/2),
+                    font=clickableRegionLabelFont, fill=self.CLICKABLE_PHENOGEN_TEXT_COLOR)
+            im_drawer.text(
+                text="Click to view the corresponding section of the genome in the UCSC Genome Browser",
+                xy=((xLeftOffset + 10), ucscPaddingTop),# + self.BAND_HEIGHT/2),
+                font=clickableRegionLabelFont, fill=self.CLICKABLE_UCSC_TEXT_COLOR)
+            im_drawer.text(
+                text="Click to view the corresponding section of the genome in the Ensembl Genome Browser",
+                xy=((xLeftOffset+10), ensemblPaddingTop),# + self.BAND_HEIGHT/2),
+                font=clickableRegionLabelFont, fill=self.CLICKABLE_ENSEMBL_TEXT_COLOR)
 
             #draw the gray text
-            chrFont = pid.Font(ttf="verdana", size=26*zoom, bold=1)
-            traitFont = pid.Font(ttf="verdana", size=14, bold=0)
-            chrX = xLeftOffset + plotWidth - 2 - canvas.stringWidth("Chr %s" % self.ChrList[self.selectedChr][0], font=chrFont)
-            canvas.drawString("Chr %s" % self.ChrList[self.selectedChr][0], chrX, ensemblPaddingTop-5, font=chrFont, color=pid.gray)
+            chrFont = ImageFont.truetype(font=VERDANA_BOLD_FILE, size=26*zoom)
+            chrX = xLeftOffset + plotWidth - 2 - im_drawer.textsize(
+                "Chr %s" % self.ChrList[self.selectedChr][0], font=chrFont)[0]
+            im_drawer.text(
+                text="Chr %s" % self.ChrList[self.selectedChr][0],
+                xy=(chrX, phenogenPaddingTop), font=chrFont, fill=GRAY)
             # end of drawBrowserClickableRegions
         else:
             #draw the gray text
-            chrFont = pid.Font(ttf="verdana", size=26*zoom, bold=1)
-            traitFont = pid.Font(ttf="verdana", size=14, bold=0)
-            chrX = xLeftOffset + (plotWidth - canvas.stringWidth("Chr %s" % currentChromosome, font=chrFont))/2
-            canvas.drawString("Chr %s" % currentChromosome, chrX, 32, font=chrFont, color=pid.gray)
+            chrFont = ImageFont.truetype(font=VERDANA_FILE, size=26*zoom)
+            chrX = xLeftOffset + (plotWidth - im_drawer.textsize(
+                "Chr %s" % currentChromosome, font=chrFont)[0])/2
+            im_drawer.text(
+                text="Chr %s" % currentChromosome, xy=(chrX, 32), font=chrFont,
+                fill=GRAY)
             # end of drawBrowserClickableRegions
         pass
 
     def drawXAxis(self, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+        im_drawer = ImageDraw.Draw(canvas)
         xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
         plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
         plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
@@ -1509,21 +1750,21 @@ class DisplayMappingResults(object):
 
         #Parameters
         NUM_MINOR_TICKS = 5 # Number of minor ticks between major ticks
-        X_MAJOR_TICK_THICKNESS = 2
+        X_MAJOR_TICK_THICKNESS = 3
         X_MINOR_TICK_THICKNESS = 1
         X_AXIS_THICKNESS = 1*zoom
 
         # ======= Alex: Draw the X-axis labels (megabase location)
-        MBLabelFont = pid.Font(ttf="verdana", size=15*zoom, bold=0)
+        MBLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=15*zoom)
         xMajorTickHeight = 10 * zoom # How high the tick extends below the axis
         xMinorTickHeight = 5*zoom
-        xAxisTickMarkColor = pid.black
-        xAxisLabelColor = pid.black
+        xAxisTickMarkColor = BLACK
+        xAxisLabelColor = BLACK
         fontHeight = 12*fontZoom # How tall the font that we're using is
-        spacingFromLabelToAxis = 5
+        spacingFromLabelToAxis = 10
 
         if self.plotScale == 'physic':
-            strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont)
+            strYLoc = yZero + MBLabelFont.font.height/2
             ###Physical single chromosome view
             if self.selectedChr > -1:
                 XScale = Plot.detScale(startMb, endMb)
@@ -1544,13 +1785,21 @@ class DisplayMappingResults(object):
                         continue
                     Xc = xLeftOffset + plotXScale*(_Mb - startMb)
                     if counter % NUM_MINOR_TICKS == 0: # Draw a MAJOR mark, not just a minor tick mark
-                        canvas.drawLine(Xc, yZero, Xc, yZero+xMajorTickHeight, color=xAxisTickMarkColor, width=X_MAJOR_TICK_THICKNESS) # Draw the MAJOR tick mark
+                        im_drawer.line(xy=((Xc,yZero),
+                                           (Xc,yZero+xMajorTickHeight)),
+                                       fill=xAxisTickMarkColor,
+                                       width=X_MAJOR_TICK_THICKNESS) # Draw the MAJOR tick mark
                         labelStr = str(formatStr % _Mb) # What Mbase location to put on the label
-                        strWidth = canvas.stringWidth(labelStr, font=MBLabelFont)
+                        strWidth, strHeight = im_drawer.textsize(labelStr, font=MBLabelFont)
                         drawStringXc = (Xc - (strWidth / 2.0))
-                        canvas.drawString(labelStr, drawStringXc, strYLoc, font=MBLabelFont, color=xAxisLabelColor, angle=0)
+                        im_drawer.text(xy=(drawStringXc, strYLoc),
+                                       text=labelStr, font=MBLabelFont,
+                                       fill=xAxisLabelColor)
                     else:
-                        canvas.drawLine(Xc, yZero, Xc, yZero+xMinorTickHeight, color=xAxisTickMarkColor, width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark
+                        im_drawer.line(xy=((Xc,yZero),
+                                          (Xc,yZero+xMinorTickHeight)),
+                                       fill=xAxisTickMarkColor,
+                                       width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark
 
             ###Physical genome wide view
             else:
@@ -1565,17 +1814,28 @@ class DisplayMappingResults(object):
                         else:
                             distScale = 5
                     for j, tickdists in enumerate(range(distScale, int(ceil(distLen)), distScale)):
-                        canvas.drawLine(startPosX + tickdists*plotXScale, yZero, startPosX + tickdists*plotXScale, yZero + 7, color=pid.black, width=1*zoom)
+                        im_drawer.line(
+                            xy=((startPosX+tickdists*plotXScale, yZero),
+                                (startPosX+tickdists*plotXScale, yZero + 7)),
+                            fill=BLACK, width=1*zoom)
                         if j % 2 == 0:
-                            canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=pid.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 = pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0)
-            canvas.drawString("Megabases", xLeftOffset + (plotWidth - canvas.stringWidth("Megabases", font=megabaseLabelFont))/2,
-                    strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=megabaseLabelFont, color=pid.black)
+            megabaseLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5))
+            im_drawer.text(
+                text="Megabases",
+                xy=(
+                    xLeftOffset+(plotWidth-im_drawer.textsize(
+                        "Megabases",font=megabaseLabelFont)[0])/2,
+                    strYLoc+MBLabelFont.font.height+10*(zoom%2)),
+                font=megabaseLabelFont, fill=BLACK)
             pass
         else:
-            strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) + 8
+            strYLoc = yZero + spacingFromLabelToAxis + MBLabelFont.font.height/2
             ChrAInfo = []
             preLpos = -1
             distinctCount = 0.0
@@ -1619,7 +1879,7 @@ class DisplayMappingResults(object):
             LRectWidth = 10
             LRectHeight = 3
             offsetA = -stepA
-            lineColor = pid.lightblue
+            lineColor = LIGHTBLUE
             startPosX = xLeftOffset
 
             for j, ChrInfo in enumerate(ChrAInfo):
@@ -1638,18 +1898,26 @@ class DisplayMappingResults(object):
                     else:
                         Zorder = 0
                     if differ:
-                        canvas.drawLine(startPosX+Lpos,yZero,xLeftOffset+offsetA,\
-                        yZero+25, color=lineColor)
-                        canvas.drawLine(xLeftOffset+offsetA,yZero+25,xLeftOffset+offsetA,\
-                        yZero+40+Zorder*(LRectWidth+3),color=lineColor)
-                        rectColor = pid.orange
+                        im_drawer.line(
+                            xy=((startPosX+Lpos,yZero),(xLeftOffset+offsetA,\
+                        yZero+25)),
+                            fill=lineColor)
+                        im_drawer.line(
+                            xy=((xLeftOffset+offsetA,yZero+25),(xLeftOffset+offsetA,\
+                        yZero+40+Zorder*(LRectWidth+3))),
+                            fill=lineColor)
+                        rectColor = ORANGE
                     else:
-                        canvas.drawLine(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)-3,\
-                        xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),color=lineColor)
-                        rectColor = pid.deeppink
-                    canvas.drawRect(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),\
-                            xLeftOffset+offsetA-LRectHeight,yZero+40+Zorder*(LRectWidth+3)+LRectWidth,\
-                            edgeColor=rectColor,fillColor=rectColor,edgeWidth = 0)
+                        im_drawer.line(
+                            xy=((xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)-3),(\
+                        xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3))),
+                            fill=lineColor)
+                        rectColor = DEEPPINK
+                    im_drawer.rectangle(
+                        xy=((xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)),
+                            (xLeftOffset+offsetA-LRectHeight,
+                             yZero+40+Zorder*(LRectWidth+3)+LRectWidth)),
+                        outline=rectColor,fill=rectColor,width = 0)
                     COORDS="%d,%d,%d,%d"%(xLeftOffset+offsetA-LRectHeight, yZero+40+Zorder*(LRectWidth+3),\
                             xLeftOffset+offsetA,yZero+40+Zorder*(LRectWidth+3)+LRectWidth)
                     HREF="/show_trait?trait_id=%s&dataset=%s" % (Lname, self.dataset.group.name+"Geno")
@@ -1658,17 +1926,25 @@ class DisplayMappingResults(object):
                     gifmap.areas.append(Areas)
                 ##piddle bug
                 if j == 0:
-                    canvas.drawLine(startPosX,yZero,startPosX,yZero+40, color=lineColor)
+                    im_drawer.line(
+                        xy=((startPosX,yZero),(startPosX,yZero+40)),
+                        fill=lineColor)
                 startPosX += (self.ChrLengthDistList[j]+self.GraphInterval)*plotXScale
 
-            centimorganLabelFont = pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0)
-            canvas.drawString("Centimorgans", xLeftOffset + (plotWidth - canvas.stringWidth("Megabases", font=centimorganLabelFont))/2,
-                    strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=centimorganLabelFont, color=pid.black)
+            centimorganLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5))
+            im_drawer.text(
+                text="Centimorgans",
+                xy=(xLeftOffset+(plotWidth-im_drawer.textsize(
+                    "Centimorgans", font=centimorganLabelFont)[0])/2,
+                    strYLoc + MBLabelFont.font.height+ 10*(zoom%2)),
+                font=centimorganLabelFont, fill=BLACK)
 
-        canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.black, width=X_AXIS_THICKNESS) # Draw the X axis itself
+        im_drawer.line(xy=((xLeftOffset,yZero), (xLeftOffset+plotWidth,yZero)),
+                       fill=BLACK, width=X_AXIS_THICKNESS) # Draw the X axis itself
 
 
     def drawQTL(self, canvas, drawAreaHeight, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None):
+        im_drawer = ImageDraw.Draw(canvas)
         xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
         plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
         plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
@@ -1733,8 +2009,8 @@ class DisplayMappingResults(object):
             js_data['max_score'] = LRS_LOD_Max
         self.js_data = json.dumps(js_data)
 
-        LRSScaleFont=pid.Font(ttf="verdana", size=16*zoom, bold=0)
-        LRSLODFont=pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0)
+        LRSScaleFont=ImageFont.truetype(font=VERDANA_FILE, size=16*zoom)
+        LRSLODFont=ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5))
 
         yZero = yTopOffset + plotHeight
         LRSHeightThresh = drawAreaHeight
@@ -1766,29 +2042,52 @@ class DisplayMappingResults(object):
             else:
                 all_int = False
                 break
+        # TODO(PIL): Convert from PIL
+        # if all_int:
+        #     max_lrs_width = canvas.stringWidth("%d" % LRS_LOD_Max, font=LRSScaleFont) + 40
+        # else:
+        #     max_lrs_width = canvas.stringWidth("%2.1f" % LRS_LOD_Max, font=LRSScaleFont) + 30
+
+        #draw the "LRS" or "LOD" string to the left of the axis
+        LRSScaleFont=ImageFont.truetype(font=VERDANA_FILE, size=16*zoom)
+        LRSLODFont=ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5))
+        yZero = yTopOffset + plotHeight
 
+        # TEXT_X_DISPLACEMENT = -20
+        #TEXT_Y_DISPLACEMENT = -215
         if all_int:
-            max_lrs_width = canvas.stringWidth("%d" % LRS_LOD_Max, font=LRSScaleFont) + 40
+            TEXT_X_DISPLACEMENT = -12
         else:
-            max_lrs_width = canvas.stringWidth("%2.1f" % LRS_LOD_Max, font=LRSScaleFont) + 30
-
-        #draw the "LRS" or "LOD" string to the left of the axis
-        canvas.drawString(self.LRS_LOD, xLeftOffset - max_lrs_width - 15*(zoom-1), \
-                                          yZero - 150 - 300*(zoom - 1), font=LRSLODFont, color=pid.black, angle=90)
+            TEXT_X_DISPLACEMENT = -30
+        if self.LRS_LOD == "-log(p)":
+            TEXT_Y_DISPLACEMENT = -242
+        else:
+            TEXT_Y_DISPLACEMENT = -210
+        draw_rotated_text(
+            canvas, text=self.LRS_LOD, font=LRSLODFont,
+            xy=(xLeftOffset - im_drawer.textsize(
+                "999.99", font=LRSScaleFont)[0] - 15*(zoom-1) + TEXT_X_DISPLACEMENT,
+                yZero + TEXT_Y_DISPLACEMENT - 300*(zoom - 1)),
+            fill=BLACK, angle=90)
 
         for item in LRSAxisList:
             if LRS_LOD_Max == 0.0:
                 LRS_LOD_Max = 0.000001
             yTopOffset + 30*(zoom - 1)
             yLRS = yZero - (item/LRS_LOD_Max) * LRSHeightThresh
-            #yLRS = yZero - (item/LRSAxisList[-1]) * LRSHeightThresh
-            canvas.drawLine(xLeftOffset, yLRS, xLeftOffset - 4, yLRS, color=self.LRS_COLOR, width=1*zoom)
+            im_drawer.line(xy=((xLeftOffset,yLRS), (xLeftOffset-4,yLRS)),
+                           fill=self.LRS_COLOR, width=1*zoom)
             if all_int:
                 scaleStr = "%d" % item
             else:
                 scaleStr = "%2.1f" % item
             #Draw the LRS/LOD Y axis label
-            canvas.drawString(scaleStr, xLeftOffset-4-canvas.stringWidth(scaleStr, font=LRSScaleFont)-5, yLRS+3, font=LRSScaleFont, color=self.LRS_COLOR)
+            TEXT_Y_DISPLACEMENT = -10
+            im_drawer.text(
+                text=scaleStr,
+                xy=(xLeftOffset-4-im_drawer.textsize(scaleStr, font=LRSScaleFont)[0]-5,
+                    yLRS+TEXT_Y_DISPLACEMENT),
+                font=LRSScaleFont, fill=self.LRS_COLOR)
 
         if self.permChecked and self.nperm > 0 and not self.multipleInterval:
             significantY = yZero - self.significant*LRSHeightThresh/LRS_LOD_Max
@@ -1803,10 +2102,19 @@ class DisplayMappingResults(object):
             #ZS: I don't know if what I did here with this inner function is clever or overly complicated, but it's the only way I could think of to avoid duplicating the code inside this function
             def add_suggestive_significant_lines_and_legend(start_pos_x, chr_length_dist):
                 rightEdge = int(start_pos_x + chr_length_dist*plotXScale - self.SUGGESTIVE_WIDTH/1.5)
-                canvas.drawLine(start_pos_x+self.SUGGESTIVE_WIDTH/1.5, suggestiveY, rightEdge, suggestiveY, color=self.SUGGESTIVE_COLOR,
-                        width=self.SUGGESTIVE_WIDTH*zoom, clipX=(xLeftOffset, xLeftOffset + plotWidth-2))
-                canvas.drawLine(start_pos_x+self.SUGGESTIVE_WIDTH/1.5, significantY, rightEdge, significantY, color=self.SIGNIFICANT_COLOR,
-                        width=self.SIGNIFICANT_WIDTH*zoom, clipX=(xLeftOffset, xLeftOffset + plotWidth-2))
+                im_drawer.line(
+                    xy=((start_pos_x+self.SUGGESTIVE_WIDTH/1.5, suggestiveY),
+                        (rightEdge, suggestiveY)),
+                    fill=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH*zoom
+                    #,clipX=(xLeftOffset, xLeftOffset + plotWidth-2)
+                )
+                im_drawer.line(
+                    xy=((start_pos_x+self.SUGGESTIVE_WIDTH/1.5, significantY),
+                       (rightEdge, significantY)),
+                    fill=self.SIGNIFICANT_COLOR,
+                    width=self.SIGNIFICANT_WIDTH*zoom
+                    #, clipX=(xLeftOffset, xLeftOffset + plotWidth-2)
+                )
                 sugg_coords = "%d, %d, %d, %d" % (start_pos_x, suggestiveY-2, rightEdge + 2*zoom, suggestiveY+2)
                 sig_coords = "%d, %d, %d, %d" % (start_pos_x, significantY-2, rightEdge + 2*zoom, significantY+2)
                 if self.LRS_LOD == 'LRS':
@@ -1838,7 +2146,7 @@ class DisplayMappingResults(object):
         else:
             if self.additiveChecked:
                 additiveMax = max(map(lambda X : abs(X['additive']), self.qtlresults))
-            lrsEdgeWidth = 2
+            lrsEdgeWidth = 3
 
         if zoom == 2:
             lrsEdgeWidth = 2 * lrsEdgeWidth
@@ -1847,7 +2155,7 @@ class DisplayMappingResults(object):
         AdditiveCoordXY = []
         DominanceCoordXY = []
 
-        symbolFont = pid.Font(ttf="fnt_bs", size=5,bold=0) #ZS: For Manhattan Plot
+        symbolFont = ImageFont.truetype(font=FNT_BS_FILE, size=5) #ZS: For Manhattan Plot
 
         previous_chr = 1
         previous_chr_as_int = 0
@@ -1859,7 +2167,14 @@ class DisplayMappingResults(object):
             thisLRSColor = self.colorCollection[0]
             if qtlresult['chr'] != previous_chr and self.selectedChr == -1:
                 if self.manhattan_plot != True:
-                    canvas.drawPolygon(LRSCoordXY,edgeColor=thisLRSColor,closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                    # im_drawer.polygon(
+                    #     xy=LRSCoordXY,
+                    #     outline=thisLRSColor
+                    #     # , closed=0, edgeWidth=lrsEdgeWidth,
+                    #     # clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                    # )
+                    draw_open_polygon(canvas, xy=LRSCoordXY,
+                                      outline=thisLRSColor, width=lrsEdgeWidth)
 
                 if not self.multipleInterval and self.additiveChecked:
                     plusColor = self.ADDITIVE_COLOR_POSITIVE
@@ -1874,22 +2189,58 @@ class DisplayMappingResults(object):
                                 else:
                                     Xcm = (yZero-Yc0)/((Yc-Yc0)/(Xc-Xc0)) +Xc0
                                 if Yc0 < yZero:
-                                    canvas.drawLine(Xc0, Yc0, Xcm, yZero, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
-                                    canvas.drawLine(Xcm, yZero, Xc, yZero-(Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                                    im_drawer.line(
+                                        xy=((Xc0, Yc0), (Xcm, yZero)),
+                                        fill=plusColor, width=lineWidth
+                                        #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                                    )
+                                    im_drawer.line(
+                                        xy=((Xcm, yZero), (Xc, yZero-(Yc-yZero))),
+                                        fill=minusColor, width=lineWidth
+                                        #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                                    )
                                 else:
-                                    canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xcm, yZero, color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
-                                    canvas.drawLine(Xcm, yZero, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                                    im_drawer.line(
+                                        xy=((Xc0, yZero-(Yc0-yZero)),
+                                            (Xcm, yZero)),
+                                        fill=minusColor, width=lineWidth
+                                        #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                                    )
+                                    im_drawer.line(
+                                        xy=((Xcm, yZero), (Xc, Yc)),
+                                        fill=plusColor, width=lineWidth
+                                        #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                                    )
                             elif (Yc0-yZero)*(Yc-yZero) > 0:
                                 if Yc < yZero:
-                                    canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                                    im_drawer.line(
+                                        xy=((Xc0, Yc0), (Xc, Yc)),
+                                        fill=plusColor,
+                                        width=lineWidth
+                                        #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                                    )
                                 else:
-                                    canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                                    im_drawer.line(
+                                        xy=((Xc0, yZero - (Yc0-yZero)),
+                                            (Xc, yZero - (Yc-yZero))),
+                                        fill=minusColor, width=lineWidth
+                                        #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                                    )
                             else:
                                 minYc = min(Yc-yZero, Yc0-yZero)
                                 if minYc < 0:
-                                    canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                                    im_drawer.line(
+                                        xy=((Xc0, Yc0), (Xc, Yc)),
+                                        fill=plusColor, width=lineWidth
+                                        #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                                    )
                                 else:
-                                    canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                                    im_drawer.line(
+                                        xy=((Xc0, yZero - (Yc0-yZero)),
+                                            (Xc, yZero - (Yc-yZero))),
+                                        fill=minusColor, width=lineWidth
+                                        #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                                    )
 
                 LRSCoordXY = []
                 AdditiveCoordXY = []
@@ -1955,18 +2306,15 @@ class DisplayMappingResults(object):
 
                 if self.manhattan_plot == True:
                     if self.selectedChr == -1 and (previous_chr_as_int % 2 == 1):
-                        point_color = pid.red
-                    else:
-                        point_color = pid.blue
-
-                    final_x_pos = Xc-canvas.stringWidth("5",font=symbolFont)/2+1
-                    if final_x_pos > (xLeftOffset + plotWidth):
-                        continue
-                        #break ZS: This is temporary until issue with sorting for GEMMA is fixed
-                    elif final_x_pos < xLeftOffset:
-                        continue
+                        point_color = RED
                     else:
-                        canvas.drawString("5", final_x_pos,Yc+2,color=point_color, font=symbolFont)
+                        point_color = BLUE
+                    im_drawer.text(
+                        text="5",
+                        xy=(
+                            Xc-im_drawer.textsize("5",font=symbolFont)[0]/2+1,
+                            Yc-4),
+                        fill=point_color, font=symbolFont)
                 else:
                     LRSCoordXY.append((Xc, Yc))
 
@@ -1979,7 +2327,13 @@ class DisplayMappingResults(object):
                 m += 1
 
         if self.manhattan_plot != True:
-            canvas.drawPolygon(LRSCoordXY,edgeColor=thisLRSColor,closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+            # im_drawer.polygon(
+            #     xy=LRSCoordXY,
+            #     outline=thisLRSColor
+            #     #, closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+            # )
+            draw_open_polygon(canvas, xy=LRSCoordXY, outline=thisLRSColor,
+                              width=lrsEdgeWidth)
 
         if not self.multipleInterval and self.additiveChecked:
             plusColor = self.ADDITIVE_COLOR_POSITIVE
@@ -1994,22 +2348,57 @@ class DisplayMappingResults(object):
                         else:
                             Xcm = (yZero-Yc0)/((Yc-Yc0)/(Xc-Xc0)) +Xc0
                         if Yc0 < yZero:
-                            canvas.drawLine(Xc0, Yc0, Xcm, yZero, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
-                            canvas.drawLine(Xcm, yZero, Xc, yZero-(Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, Yc0), (Xcm, yZero)),
+                                fill=plusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
+                            im_drawer.line(
+                                xy=((Xcm, yZero), (Xc, yZero-(Yc-yZero))),
+                                fill=minusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                         else:
-                            canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xcm, yZero, color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
-                            canvas.drawLine(Xcm, yZero, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, yZero - (Yc0-yZero)),
+                                    (Xcm, yZero)),
+                                fill=minusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
+                            im_drawer.line(
+                                xy=((Xcm, yZero), (Xc, Yc)),
+                                fill=plusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                     elif (Yc0-yZero)*(Yc-yZero) > 0:
                         if Yc < yZero:
-                            canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, Yc0), (Xc, Yc)), fill=plusColor,
+                                width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                         else:
-                            canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0,yZero-(Yc0-yZero)),
+                                    (Xc,yZero-(Yc-yZero))),
+                                fill=minusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                     else:
                         minYc = min(Yc-yZero, Yc0-yZero)
                         if minYc < 0:
-                            canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, Yc0), (Xc, Yc)),
+                                fill=plusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                         else:
-                            canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, yZero - (Yc0-yZero)),
+                                    (Xc, yZero - (Yc-yZero))),
+                                fill=minusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
 
         if not self.multipleInterval and INTERCROSS and self.dominanceChecked:
             plusColor = self.DOMINANCE_COLOR_POSITIVE
@@ -2024,42 +2413,88 @@ class DisplayMappingResults(object):
                         else:
                             Xcm = (yZero-Yc0)/((Yc-Yc0)/(Xc-Xc0)) +Xc0
                         if Yc0 < yZero:
-                            canvas.drawLine(Xc0, Yc0, Xcm, yZero, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
-                            canvas.drawLine(Xcm, yZero, Xc, yZero-(Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, Yc0), (Xcm, yZero)),
+                                fill=plusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
+                            im_drawer.line(
+                                xy=((Xcm, yZero), (Xc, yZero-(Yc-yZero))),
+                                fill=minusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                         else:
-                            canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xcm, yZero, color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
-                            canvas.drawLine(Xcm, yZero, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, yZero - (Yc0-yZero)), (Xcm, yZero)),
+                                fill=minusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
+                            im_drawer.line(
+                                xy=((Xcm, yZero), (Xc, Yc)),
+                                fill=plusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                     elif (Yc0-yZero)*(Yc-yZero) > 0:
                         if Yc < yZero:
-                            canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, Yc0), (Xc, Yc)),
+                                fill=plusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                         else:
-                            canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, yZero - (Yc0-yZero)),
+                                    (Xc, yZero - (Yc-yZero))),
+                                fill=minusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                     else:
                         minYc = min(Yc-yZero, Yc0-yZero)
                         if minYc < 0:
-                            canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, Yc0), (Xc, Yc)),
+                                fill=plusColor, width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
                         else:
-                            canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth))
+                            im_drawer.line(
+                                xy=((Xc0, yZero - (Yc0-yZero)),
+                                    (Xc, yZero - (Yc-yZero))), fill=minusColor,
+                                width=lineWidth
+                                #, clipX=(xLeftOffset, xLeftOffset + plotWidth)
+                            )
 
 
         ###draw additive scale
         if not self.multipleInterval and self.additiveChecked:
-            additiveScaleFont=pid.Font(ttf="verdana",size=16*zoom,bold=0)
+            additiveScaleFont=ImageFont.truetype(font=VERDANA_FILE,size=16*zoom)
             additiveScale = Plot.detScaleOld(0,additiveMax)
             additiveStep = (additiveScale[1]-additiveScale[0])/additiveScale[2]
             additiveAxisList = Plot.frange(0, additiveScale[1], additiveStep)
             addPlotScale = AdditiveHeightThresh/additiveMax
+            TEXT_Y_DISPLACEMENT = -8
 
             additiveAxisList.append(additiveScale[1])
             for item in additiveAxisList:
                 additiveY = yZero - item*addPlotScale
-                canvas.drawLine(xLeftOffset + plotWidth,additiveY,xLeftOffset+4+ plotWidth,additiveY,color=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom)
+                im_drawer.line(
+                    xy=((xLeftOffset + plotWidth,additiveY),
+                        (xLeftOffset+4+ plotWidth,additiveY)),
+                    fill=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom)
                 scaleStr = "%2.3f" % item
-                canvas.drawString(scaleStr,xLeftOffset + plotWidth +6,additiveY+5,font=additiveScaleFont,color=self.ADDITIVE_COLOR_POSITIVE)
+                im_drawer.text(
+                    text=scaleStr,
+                    xy=(xLeftOffset + plotWidth +6,additiveY+TEXT_Y_DISPLACEMENT),
+                    font=additiveScaleFont,fill=self.ADDITIVE_COLOR_POSITIVE)
 
-            canvas.drawLine(xLeftOffset+plotWidth,additiveY,xLeftOffset+plotWidth,yZero,color=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom)
+            im_drawer.line(
+                xy=((xLeftOffset+plotWidth,additiveY),
+                    (xLeftOffset+plotWidth,yZero)),
+                fill=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom)
 
-        canvas.drawLine(xLeftOffset, yZero, xLeftOffset, yTopOffset + 30*(zoom - 1), color=self.LRS_COLOR, width=1*zoom)  #the blue line running up the y axis
+        im_drawer.line(
+            xy=((xLeftOffset, yZero), (xLeftOffset, yTopOffset + 30*(zoom - 1))),
+            fill=self.LRS_COLOR, width=1*zoom)  #the blue line running up the y axis
 
 
     def drawGraphBackground(self, canvas, gifmap, offset= (80, 120, 80, 50), zoom = 1, startMb = None, endMb = None):
@@ -2067,6 +2502,7 @@ class DisplayMappingResults(object):
         ##multiple Chromosome view
         ##single Chromosome Physical
         ##single Chromosome Genetic
+        im_drawer = ImageDraw.Draw(canvas)
         xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset
         plotWidth = canvas.size[0] - xLeftOffset - xRightOffset
         plotHeight = canvas.size[1] - yTopOffset - yBottomOffset
@@ -2093,8 +2529,10 @@ class DisplayMappingResults(object):
                 else:
                     theBackColor = self.GRAPH_BACK_LIGHT_COLOR
                 i += 1
-                canvas.drawRect(startPix, yTopOffset, min(startPix+spacingAmt, xLeftOffset+plotWidth), \
-                        yBottom, edgeColor=theBackColor, fillColor=theBackColor)
+                im_drawer.rectangle(
+                    [(startPix, yTopOffset),
+                     (min(startPix+spacingAmt, xLeftOffset+plotWidth), yBottom)],
+                    outline=theBackColor, fill=theBackColor)
 
             drawRegionDistance = self.ChrLengthDistList[self.ChrList[self.selectedChr][1]]
             self.ChrLengthDistList = [drawRegionDistance]
@@ -2111,7 +2549,7 @@ class DisplayMappingResults(object):
                 chrFontZoom = 2
             else:
                 chrFontZoom = 1
-            chrLabelFont=pid.Font(ttf="verdana",size=24*chrFontZoom,bold=0)
+            chrLabelFont=ImageFont.truetype(font=VERDANA_FILE,size=24*chrFontZoom)
 
             for i, _chr in enumerate(self.genotype):
                 if (i % 2 == 0):
@@ -2120,14 +2558,19 @@ class DisplayMappingResults(object):
                     theBackColor = self.GRAPH_BACK_LIGHT_COLOR
 
                 #draw the shaded boxes and the sig/sug thick lines
-                canvas.drawRect(startPosX, yTopOffset, startPosX + self.ChrLengthDistList[i]*plotXScale, \
-                                yBottom, edgeColor=pid.gainsboro,fillColor=theBackColor)
+                im_drawer.rectangle(
+                    ((startPosX, yTopOffset),
+                     (startPosX + self.ChrLengthDistList[i]*plotXScale, yBottom)),
+                    outline=GAINSBORO,
+                    fill=theBackColor)
 
-                chrNameWidth = canvas.stringWidth(_chr.name, font=chrLabelFont)
+                chrNameWidth, chrNameHeight = im_drawer.textsize(_chr.name, font=chrLabelFont)
                 chrStartPix = startPosX + (self.ChrLengthDistList[i]*plotXScale -chrNameWidth)/2
                 chrEndPix = startPosX + (self.ChrLengthDistList[i]*plotXScale +chrNameWidth)/2
 
-                canvas.drawString(_chr.name, chrStartPix, yTopOffset + 20 ,font = chrLabelFont,color=pid.black)
+                TEXT_Y_DISPLACEMENT = 0
+                im_drawer.text(xy=(chrStartPix, yTopOffset + TEXT_Y_DISPLACEMENT),
+                               text=_chr.name, font=chrLabelFont, fill=BLACK)
                 COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20)
 
                 #add by NL 09-03-2010
@@ -2143,7 +2586,7 @@ class DisplayMappingResults(object):
         #########################################
         #      Permutation Graph
         #########################################
-        myCanvas = pid.PILCanvas(size=(500,300))
+        myCanvas = Image.new("RGBA", size=(500, 300))
         if 'lod_score' in self.qtlresults[0] and self.LRS_LOD == "LRS":
             perm_output = [value*4.61 for value in self.perm_output]
         elif 'lod_score' not in self.qtlresults[0] and self.LRS_LOD == "LOD":
@@ -2153,7 +2596,8 @@ class DisplayMappingResults(object):
 
         filename= webqtlUtil.genRandStr("Reg_")
         Plot.plotBar(myCanvas, perm_output, XLabel=self.LRS_LOD, YLabel='Frequency', title=' Histogram of Permutation Test')
-        myCanvas.save(GENERATED_IMAGE_DIR+filename, format='gif')
+        myCanvas.save("{}.gif".format(GENERATED_IMAGE_DIR+filename),
+                      format='gif')
 
         return filename
 
@@ -2379,4 +2823,4 @@ class DisplayMappingResults(object):
                     lCorr = lCorr[0]
                     break
         except: raise #lCorr = None
-        return lCorr
\ No newline at end of file
+        return lCorr
diff --git a/wqflask/wqflask/snp_browser/snp_browser.py b/wqflask/wqflask/snp_browser/snp_browser.py
index 73ab8798..1d28d76a 100644
--- a/wqflask/wqflask/snp_browser/snp_browser.py
+++ b/wqflask/wqflask/snp_browser/snp_browser.py
@@ -3,7 +3,7 @@ from __future__ import absolute_import, print_function, division
 from flask import Flask, g, url_for
 
 import string
-import piddle as pid
+from PIL import (Image)
 
 from utility.logger import getLogger
 logger = getLogger(__name__ )
@@ -629,7 +629,7 @@ class SnpBrowser(object):
 
         canvas_width = 900
         canvas_height = 200
-        snp_canvas = pid.PILCanvas(size=(canvas_width, canvas_height))
+        snp_canvas = Image.new("RGBA", size=(canvas_width, canvas_height))
         left_offset, right_offset, top_offset, bottom_offset = (30, 30, 40, 50)
         plot_width = canvas_width - left_offset - right_offset
         plot_height = canvas_height - top_offset - bottom_offset
diff --git a/wqflask/wqflask/static/fonts/README b/wqflask/wqflask/static/fonts/README
new file mode 100644
index 00000000..75a3e444
--- /dev/null
+++ b/wqflask/wqflask/static/fonts/README
@@ -0,0 +1 @@
+These fonts are used by pillow for 'interval mapping'
diff --git a/wqflask/wqflask/static/fonts/arial.ttf b/wqflask/wqflask/static/fonts/arial.ttf
new file mode 100644
index 00000000..bf0d4a95
--- /dev/null
+++ b/wqflask/wqflask/static/fonts/arial.ttf
Binary files differdiff --git a/wqflask/wqflask/static/fonts/courbd.ttf b/wqflask/wqflask/static/fonts/courbd.ttf
new file mode 100644
index 00000000..c8081467
--- /dev/null
+++ b/wqflask/wqflask/static/fonts/courbd.ttf
Binary files differdiff --git a/wqflask/wqflask/static/fonts/fnt_bs.ttf b/wqflask/wqflask/static/fonts/fnt_bs.ttf
new file mode 100644
index 00000000..712c38cf
--- /dev/null
+++ b/wqflask/wqflask/static/fonts/fnt_bs.ttf
Binary files differdiff --git a/wqflask/wqflask/static/fonts/tahoma.ttf b/wqflask/wqflask/static/fonts/tahoma.ttf
new file mode 100644
index 00000000..bb314be3
--- /dev/null
+++ b/wqflask/wqflask/static/fonts/tahoma.ttf
Binary files differdiff --git a/wqflask/wqflask/static/fonts/trebucbd.ttf b/wqflask/wqflask/static/fonts/trebucbd.ttf
new file mode 100644
index 00000000..1ab1ae0a
--- /dev/null
+++ b/wqflask/wqflask/static/fonts/trebucbd.ttf
Binary files differdiff --git a/wqflask/wqflask/static/fonts/verdana.ttf b/wqflask/wqflask/static/fonts/verdana.ttf
new file mode 100644
index 00000000..754a9b7b
--- /dev/null
+++ b/wqflask/wqflask/static/fonts/verdana.ttf
Binary files differdiff --git a/wqflask/wqflask/static/fonts/verdanab.ttf b/wqflask/wqflask/static/fonts/verdanab.ttf
new file mode 100644
index 00000000..1a99258f
--- /dev/null
+++ b/wqflask/wqflask/static/fonts/verdanab.ttf
Binary files differ