From 7d1a681029e4efb73b4a0f07ac37c15764b15eb8 Mon Sep 17 00:00:00 2001 From: zsloan Date: Fri, 12 Oct 2018 15:57:48 +0000 Subject: Fixed issue that caused error when mapping single-chromosome, since a second reference to probeSetSearch wasn't removed --- wqflask/wqflask/marker_regression/marker_regression_gn1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wqflask/wqflask/marker_regression/marker_regression_gn1.py b/wqflask/wqflask/marker_regression/marker_regression_gn1.py index f7f3e08d..21dd897a 100644 --- a/wqflask/wqflask/marker_regression/marker_regression_gn1.py +++ b/wqflask/wqflask/marker_regression/marker_regression_gn1.py @@ -2153,7 +2153,7 @@ class MarkerRegression(object): else: this_row = [selectCheck.__str__(), str(tableIterationsCnt), - HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank").__str__() + " " + probeSetSearch.__str__(), + HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank").__str__(), HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank").__str__(), HT.Href("javascript:rangeView('%s', %f, %f)" % (str(chr_as_int), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), snpString, -- cgit v1.2.3 From 6a41599b218263bbe27726d1dbd0a3f4d2cf7ee6 Mon Sep 17 00:00:00 2001 From: zsloan Date: Mon, 15 Oct 2018 12:23:29 -0500 Subject: Updated instructions for running elasticsearch Since I know I'll forget otherwise, updated instructions on starting up ES--- doc/README.org | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/README.org b/doc/README.org index cc141098..100a76ca 100644 --- a/doc/README.org +++ b/doc/README.org @@ -259,9 +259,10 @@ if that works run genenetwork after setting SQL_URI to something like * Running ElasticSearch -In order to start up elasticsearch, change user to "elasticsearch" and use the following command: +In order to start up elasticsearch: +Penguin - change user to "elasticsearch" and use the following command: "env JAVA_HOME=/opt/jdk-9.0.4 /opt/elasticsearch-6.2.1/bin/elasticsearch" -: env JAVA_HOME=/opt/jdk-9.0.4 /opt/elasticsearch-6.2.1/bin/elasticsearch +New server - "systemctl restart elasticsearch" * Read more -- cgit v1.2.3 From aa7540a3f0c1c1d79bc130b6008a299d01cc732f Mon Sep 17 00:00:00 2001 From: zsloan Date: Mon, 15 Oct 2018 12:24:32 -0500 Subject: Added "as root" for instructions on running ES Forgot to add to change user to root during the last commit--- doc/README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README.org b/doc/README.org index 100a76ca..5dc9e994 100644 --- a/doc/README.org +++ b/doc/README.org @@ -262,7 +262,7 @@ if that works run genenetwork after setting SQL_URI to something like In order to start up elasticsearch: Penguin - change user to "elasticsearch" and use the following command: "env JAVA_HOME=/opt/jdk-9.0.4 /opt/elasticsearch-6.2.1/bin/elasticsearch" -New server - "systemctl restart elasticsearch" +New server - as root run "systemctl restart elasticsearch" * Read more -- cgit v1.2.3 From 9cfb01cab4bcf6bf87ff8f7bfcf603ed349fbd87 Mon Sep 17 00:00:00 2001 From: zsloan Date: Wed, 24 Oct 2018 17:23:18 +0000 Subject: - SNP Browser is mostly complete; just need to test more and add SNP density chart if results exceed some number (5000 on GN1) - Removed unnecessary options from the mode bar for the trait page Plotly figures and changed the default to highlight points the mouse is hovering over - Changed some file/function names related to mapping, which previously were erroneously named "marker_regression" --- wqflask/base/webqtlConfig.py | 4 + .../marker_regression/display_mapping_results.py | 2245 ++++++++++++++++++++ .../wqflask/marker_regression/marker_regression.py | 660 ------ .../marker_regression/marker_regression_gn1.py | 2245 -------------------- wqflask/wqflask/marker_regression/run_mapping.py | 660 ++++++ wqflask/wqflask/snp_browser/snp_browser.py | 341 ++- wqflask/wqflask/static/new/css/show_trait.css | 4 + wqflask/wqflask/static/new/css/snp_browser.css | 22 + .../static/new/javascript/draw_corr_scatterplot.js | 3 +- .../new/javascript/plotly_probability_plot.js | 3 +- .../wqflask/static/new/javascript/show_trait.js | 46 +- wqflask/wqflask/templates/base.html | 3 + wqflask/wqflask/templates/loading.html | 2 +- wqflask/wqflask/templates/mapping_results.html | 431 ++++ .../wqflask/templates/marker_regression_gn1.html | 431 ---- wqflask/wqflask/templates/snp_browser.html | 140 +- wqflask/wqflask/views.py | 44 +- 17 files changed, 3830 insertions(+), 3454 deletions(-) create mode 100644 wqflask/wqflask/marker_regression/display_mapping_results.py delete mode 100644 wqflask/wqflask/marker_regression/marker_regression.py delete mode 100644 wqflask/wqflask/marker_regression/marker_regression_gn1.py create mode 100644 wqflask/wqflask/marker_regression/run_mapping.py create mode 100644 wqflask/wqflask/static/new/css/snp_browser.css create mode 100644 wqflask/wqflask/templates/mapping_results.html delete mode 100644 wqflask/wqflask/templates/marker_regression_gn1.html diff --git a/wqflask/base/webqtlConfig.py b/wqflask/base/webqtlConfig.py index 4708bf0a..c9052c83 100644 --- a/wqflask/base/webqtlConfig.py +++ b/wqflask/base/webqtlConfig.py @@ -34,6 +34,10 @@ PUBMEDLINK_URL = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db= UCSC_BLAT = 'http://genome.ucsc.edu/cgi-bin/hgBlat?org=%s&db=%s&type=0&sort=0&output=0&userSeq=%s' UTHSC_BLAT = 'http://ucscbrowser.genenetwork.org/cgi-bin/hgBlat?org=%s&db=%s&type=0&sort=0&output=0&userSeq=%s' UTHSC_BLAT2 = 'http://ucscbrowserbeta.genenetwork.org/cgi-bin/hgBlat?org=%s&db=%s&type=0&sort=0&output=0&userSeq=%s' +GENOMEBROWSER_URL="https://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=%s" +NCBI_LOCUSID = "http://www.ncbi.nlm.nih.gov/gene?cmd=Retrieve&dopt=Graphics&list_uids=%s" +ENSEMBLETRANSCRIPT_URL="http://useast.ensembl.org/Mus_musculus/Transcript/Idhistory?t=%s" +DBSNP = 'http://www.ncbi.nlm.nih.gov/SNP/snp_ref.cgi?type=rs&rs=%s' # Temporary storage (note that this TMPDIR can be set as an # environment variable - use utility.tools.TEMPDIR when you diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py new file mode 100644 index 00000000..09646f57 --- /dev/null +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -0,0 +1,2245 @@ +# Copyright (C) University of Tennessee Health Science Center, Memphis, TN. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# This program is available from Source Forge: at GeneNetwork Project +# (sourceforge.net/projects/genenetwork/). +# +# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) +# at rwilliams@uthsc.edu and xzhou15@uthsc.edu +# +# +# +# This module is used by GeneNetwork project (www.genenetwork.org) +# +# Created by GeneNetwork Core Team 2010/08/10 +# +# Last updated by Zach 12/14/2010 + +import time +import string +from math import * +import piddle as pid +import sys,os +import cPickle +import httplib + +from flask import Flask, g + +from htmlgen import HTMLgen2 as HT + +from base import webqtlConfig +from base.GeneralObject import GeneralObject +from utility import webqtlUtil +from utility import helper_functions +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 + +import utility.logger +logger = utility.logger.getLogger(__name__ ) + +######################################### +# Inteval Mapping Plot Page +######################################### +class DisplayMappingResults(object): + cMGraphInterval = 5 + GRAPH_MIN_WIDTH = 900 + GRAPH_MAX_WIDTH = 10000 # Don't set this too high + GRAPH_DEFAULT_WIDTH = 1280 + MULT_GRAPH_DEFAULT_WIDTH = 2000 + MULT_GRAPH_MIN_WIDTH = 1400 + MULT_GRAPH_DEFAULT_WIDTH = 1600 + GRAPH_DEFAULT_HEIGHT = 600 + + + # Display order: + # UCSC BAND ========= + # ENSEMBL BAND -=-=-= + # ** GENES ********** + BAND_SPACING = 4 + + BAND_HEIGHT = 10 + BAND_HEIGHT = 10 + BAND_HEIGHT = 10 + + NUM_GENE_ROWS = 10 + EACH_GENE_HEIGHT = 6 # number of pixels tall, for each gene to display + EACH_GENE_ARROW_WIDTH = 5 + EACH_GENE_ARROW_SPACING = 14 + DRAW_DETAIL_MB = 4 + DRAW_UTR_LABELS_MB = 4 + + qmarkImg = HT.Image('/images/qmarkBoxBlue.gif', width=10, height=13, border=0, alt='Glossary') + # Note that "qmark.gif" is a similar, smaller, rounded-edges question mark. It doesn't look + # like the ones on the image, though, which is why we don't use it here. + + HELP_WINDOW_NAME = 'helpWind' + + ## BEGIN HaplotypeAnalyst + NR_INDIVIDUALS = 0 + ## END HaplotypeAnalyst + + ALEX_DEBUG_BOOL_PRINT_GENE_LIST = 1 + + kONE_MILLION = 1000000 + + LODFACTOR = 4.61 + + SNP_COLOR = pid.orange # Color for the SNP "seismograph" + TRANSCRIPT_LOCATION_COLOR = pid.mediumpurple + + BOOTSTRAP_BOX_COLOR = pid.yellow + LRS_COLOR = pid.HexColor(0x0000FF) + SIGNIFICANT_COLOR = pid.HexColor(0xEBC7C7) + SUGGESTIVE_COLOR = pid.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 + + ## BEGIN HaplotypeAnalyst + HAPLOTYPE_POSITIVE = pid.green + HAPLOTYPE_NEGATIVE = pid.red + HAPLOTYPE_HETEROZYGOUS = pid.blue + HAPLOTYPE_RECOMBINATION = pid.darkgray + ## END HaplotypeAnalyst + + TOP_RIGHT_INFO_COLOR = pid.black + + CLICKABLE_WEBQTL_REGION_COLOR = pid.HexColor(0xF5D3D3) + CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR = pid.HexColor(0xFCE9E9) + CLICKABLE_WEBQTL_TEXT_COLOR = pid.HexColor(0x912828) + + CLICKABLE_PHENOGEN_REGION_COLOR = pid.HexColor(0xA2FB94) + CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR = pid.HexColor(0xCEFEC7) + CLICKABLE_PHENOGEN_TEXT_COLOR = pid.HexColor(0x1FD504) + + CLICKABLE_UCSC_REGION_COLOR = pid.HexColor(0xDDDDEE) + CLICKABLE_UCSC_REGION_OUTLINE_COLOR = pid.HexColor(0xEDEDFF) + CLICKABLE_UCSC_TEXT_COLOR = pid.HexColor(0x333366) + + CLICKABLE_ENSEMBL_REGION_COLOR = pid.HexColor(0xEEEEDD) + CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR = pid.HexColor(0xFEFEEE) + CLICKABLE_ENSEMBL_TEXT_COLOR = pid.HexColor(0x555500) + + GRAPH_BACK_LIGHT_COLOR = pid.HexColor(0xFBFBFF) + GRAPH_BACK_DARK_COLOR = pid.HexColor(0xF1F1F9) + + HELP_PAGE_REF = '/glossary.html' + + def __init__(self, start_vars): + logger.info("Running qtlreaper") + + self.temp_uuid = start_vars['temp_uuid'] + + self.dataset = start_vars['dataset'] + self.this_trait = start_vars['this_trait'] + self.species = start_vars['species'] + if 'genofile_string' in start_vars: + self.genofile_string = start_vars['genofile_string'] + + self.geno_db_exists = start_vars['geno_db_exists'] + + #Needing for form submission when doing single chr mapping or remapping after changing options + self.samples = start_vars['samples'] + self.vals = start_vars['vals'] + self.mapping_method = start_vars['mapping_method'] + self.mapping_results_path = start_vars['mapping_results_path'] + if self.mapping_method == "rqtl_geno": + self.mapmethod_rqtl_geno = start_vars['method'] + self.mapmodel_rqtl_geno = start_vars['model'] + self.pair_scan = start_vars['pair_scan'] + + if self.mapping_method != "gemma" and self.mapping_method != "plink": + self.js_data = start_vars['js_data'] + self.trimmed_markers = start_vars['trimmed_markers'] #Top markers to display in table + + if self.dataset.group.species == "rat": + self._ucscDb = "rn3" + elif self.dataset.group.species == "mouse": + self._ucscDb = "mm9" + else: + self._ucscDb = "" + + ##################################### + # Options + ##################################### + #Mapping options + if start_vars['mapping_scale'] != "": + self.plotScale = start_vars['mapping_scale'] + else: + self.plotScale = "physic" + + self.manhattan_plot = start_vars['manhattan_plot'] + + if 'permCheck' in start_vars.keys(): + self.permChecked = start_vars['permCheck'] + else: + self.permChecked = False + if start_vars['num_perm'] > 0: + self.nperm = int(start_vars['num_perm']) + if self.permChecked: + self.perm_output = start_vars['perm_output'] + self.suggestive = start_vars['suggestive'] + self.significant = start_vars['significant'] + else: + self.nperm = 0 + + if 'bootCheck' in start_vars.keys(): + self.bootChecked = start_vars['bootCheck'] + else: + self.bootChecked = False + if 'num_bootstrap' in start_vars.keys(): + self.nboot = int(start_vars['num_bootstrap']) + else: + self.nboot = 0 + if 'bootstrap_results' in start_vars.keys(): + self.bootResult = start_vars['bootstrap_results'] + else: + self.bootResult = [] + + if 'do_control' in start_vars.keys(): + self.doControl = start_vars['do_control'] + else: + self.doControl = "false" + if 'control_marker' in start_vars.keys(): + self.controlLocus = start_vars['control_marker'] + else: + self.controlLocus = "" + if 'covariates' in start_vars.keys(): + self.covariates = start_vars['covariates'] + if 'maf' in start_vars.keys(): + self.maf = start_vars['maf'] + if 'use_loco' in start_vars.keys(): + self.use_loco = start_vars['use_loco'] + + self.selectedChr = int(start_vars['selected_chr']) + + self.strainlist = self.dataset.group.samplelist + self.genotype = self.dataset.group.read_genotype_file() + if self.mapping_method == "reaper" and self.manhattan_plot != True: + self.genotype = self.genotype.addinterval() + + #Darwing Options + try: + if self.selectedChr > -1: + self.graphWidth = min(self.GRAPH_MAX_WIDTH, max(self.GRAPH_MIN_WIDTH, int(start_vars['graphWidth']))) + else: + self.graphWidth = min(self.GRAPH_MAX_WIDTH, max(self.MULT_GRAPH_MIN_WIDTH, int(start_vars['graphWidth']))) + except: + if self.selectedChr > -1: + self.graphWidth = self.GRAPH_DEFAULT_WIDTH + else: + self.graphWidth = self.MULT_GRAPH_DEFAULT_WIDTH + +## BEGIN HaplotypeAnalyst + if 'haplotypeAnalystCheck' in start_vars.keys(): + self.haplotypeAnalystChecked = start_vars['haplotypeAnalystCheck'] + else: + self.haplotypeAnalystChecked = False +## END HaplotypeAnalyst + + self.graphHeight = self.GRAPH_DEFAULT_HEIGHT + self.dominanceChecked = False + if 'LRSCheck' in start_vars.keys(): + self.LRS_LOD = start_vars['LRSCheck'] + else: + self.LRS_LOD = start_vars['score_type'] + self.intervalAnalystChecked = True + self.draw2X = False + if 'additiveCheck' in start_vars.keys(): + self.additiveChecked = start_vars['additiveCheck'] + else: + self.additiveChecked = False + if 'viewLegend' in start_vars.keys(): + self.legendChecked = start_vars['viewLegend'] + else: + self.legendChecked = False + if 'showSNP' in start_vars.keys(): + self.SNPChecked = start_vars['showSNP'] + else: + self.SNPChecked = False + if 'showGenes' in start_vars.keys(): + self.geneChecked = start_vars['showGenes'] + else: + self.geneChecked = False + try: + self.startMb = float(start_vars['startMb']) + except: + self.startMb = -1 + try: + self.endMb = float(start_vars['endMb']) + except: + self.endMb = -1 + try: + self.lrsMax = float(start_vars['lrsMax']) + except: + self.lrsMax = 0 + + #Trait Infos + self.identification = "" + + ################################################################ + # Generate Chr list and Retrieve Length Information + ################################################################ + self.ChrList = [("All", -1)] + for i, indChr in enumerate(self.genotype): + self.ChrList.append((indChr.name, i)) + + + + self.ChrLengthMbList = g.db.execute(""" + Select + Length from Chr_Length, InbredSet + where + Chr_Length.SpeciesId = InbredSet.SpeciesId AND + InbredSet.Name = '%s' AND + Chr_Length.Name in (%s) + Order by + Chr_Length.OrderId + """ % (self.dataset.group.name, string.join(map(lambda X: "'%s'" % X[0], self.ChrList[1:]), ", "))) + + self.ChrLengthMbList = map(lambda x: x[0]/1000000.0, self.ChrLengthMbList) + self.ChrLengthMbSum = reduce(lambda x, y:x+y, self.ChrLengthMbList, 0.0) + if self.ChrLengthMbList: + self.MbGraphInterval = self.ChrLengthMbSum/(len(self.ChrLengthMbList)*12) #Empirical Mb interval + else: + self.MbGraphInterval = 1 + + self.ChrLengthCMList = [] + for i, _chr in enumerate(self.genotype): + self.ChrLengthCMList.append(_chr[-1].cM - _chr[0].cM) + self.ChrLengthCMSum = reduce(lambda x, y:x+y, self.ChrLengthCMList, 0.0) + + if self.plotScale == 'physic': + self.GraphInterval = self.MbGraphInterval #Mb + else: + self.GraphInterval = self.cMGraphInterval #cM + + self.traitList = [] + thisTrait = start_vars['this_trait'] + self.traitList.append(thisTrait) + +## BEGIN HaplotypeAnalyst +## count the amount of individuals to be plotted, and increase self.graphHeight + if self.haplotypeAnalystChecked and self.selectedChr > -1: + #thisTrait = self.traitList[0] + thisTrait = self.this_trait + _strains, _vals, _vars, _aliases = thisTrait.export_informative() + smd=[] + for ii, _val in enumerate(_vals): + temp = GeneralObject(name=_strains[ii], value=_val) + smd.append(temp) + samplelist = list(self.genotype.prgy) + for j,_geno in enumerate (self.genotype[0][1].genotype): + for item in smd: + if item.name == samplelist[j]: + self.NR_INDIVIDUALS = self.NR_INDIVIDUALS + 1 +# default: + self.graphHeight = self.graphHeight + 2 * (self.NR_INDIVIDUALS+10) * self.EACH_GENE_HEIGHT +## END HaplotypeAnalyst + + ################################################################ + # Calculations QTL goes here + ################################################################ + self.multipleInterval = len(self.traitList) > 1 + self.qtlresults = start_vars['qtl_results'] + + if self.multipleInterval: + self.colorCollection = Plot.colorSpectrum(len(self.qtlresults)) + else: + self.colorCollection = [self.LRS_COLOR] + + + ######################### + ## Get the sorting column + ######################### + RISet = self.dataset.group.name + if RISet in ('AXB', 'BXA', 'AXBXA'): + self.diffCol = ['B6J', 'A/J'] + elif RISet in ('BXD', 'BXD300', 'B6D2F2', 'BDF2-2005', 'BDF2-1999', 'BHHBF2'): + self.diffCol = ['B6J', 'D2J'] + elif RISet in ('CXB'): + self.diffCol = ['CBY', 'B6J'] + elif RISet in ('BXH', 'BHF2'): + self.diffCol = ['B6J', 'C3H'] + elif RISet in ('B6BTBRF2'): + self.diffCol = ['B6J', 'BTB'] + elif RISet in ('LXS'): + self.diffCol = ['ILS', 'ISS'] + else: + self.diffCol= [] + + for i, strain in enumerate(self.diffCol): + self.diffCol[i] = g.db.execute("select Id from Strain where Symbol = %s", strain).fetchone()[0] + + ################################################################ + # GeneCollection goes here + ################################################################ + if self.plotScale == 'physic' and self.selectedChr != -1: + #StartMb or EndMb + if self.startMb < 0 or self.endMb < 0: + self.startMb = 0 + self.endMb = self.ChrLengthMbList[self.selectedChr - 1] + + geneTable = "" + + self.geneCol = None + if self.plotScale == 'physic' and self.selectedChr > -1 and (self.intervalAnalystChecked or self.geneChecked): + # Draw the genes for this chromosome / region of this chromosome + webqtldatabase = self.dataset.name + + if self.dataset.group.species == "mouse": + if self.selectedChr == 20: + chrName = "X" + else: + chrName = self.selectedChr + self.geneCol = GeneUtil.loadGenes(chrName, self.diffCol, self.startMb, self.endMb, "mouse") + elif self.dataset.group.species == "rat": + if self.selectedChr == 21: + chrName = "X" + else: + chrName = self.selectedChr + self.geneCol = GeneUtil.loadGenes(chrName, self.diffCol, self.startMb, self.endMb, "rat") + + if self.geneCol and self.intervalAnalystChecked: + ####################################################################### + #Nick use GENEID as RefGene to get Literature Correlation Informations# + #For Interval Mapping, Literature Correlation isn't useful, so skip it# + #through set GENEID is None # + ####################################################################### + + GENEID = None + + self.geneTable(self.geneCol, GENEID) + + ################################################################ + # Plots goes here + ################################################################ + showLocusForm = "" + intCanvas = pid.PILCanvas(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') + 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)) + 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') + + ################################################################ + # Outputs goes here + ################################################################ + #this form is used for opening Locus page or trait page, only available for genetic mapping + if showLocusForm: + showLocusForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', + name=showLocusForm, submit=HT.Input(type='hidden')) + hddn = {'FormID':'showDatabase', 'ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_', 'RISet':fd.RISet, 'incparentsf1':'ON'} + for key in hddn.keys(): + showLocusForm.append(HT.Input(name=key, value=hddn[key], type='hidden')) + showLocusForm.append(intImg) + else: + showLocusForm = intImg + + if (self.permChecked and self.nperm > 0) and not (self.multipleInterval and 0 < self.nperm): + self.perm_filename = self.drawPermutationHistogram() + + ################################################################ + # footnote goes here + ################################################################ + btminfo = HT.Paragraph(Id="smallsize") #Small('More information about this graph is available here.') + + if self.traitList and self.traitList[0].dataset and self.traitList[0].dataset.type == 'Geno': + 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 = ""): + #calculating margins + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + if self.multipleInterval: + yTopOffset = max(80, yTopOffset) + else: + if self.legendChecked: + yTopOffset = max(80, yTopOffset) + else: + pass + + if self.plotScale != 'physic': + yBottomOffset = max(120, yBottomOffset) + fontZoom = zoom + if zoom == 2: + xLeftOffset += 20 + fontZoom = 1.5 + + xLeftOffset = int(xLeftOffset*fontZoom) + xRightOffset = int(xRightOffset*fontZoom) + yBottomOffset = int(yBottomOffset*fontZoom) + + cWidth = canvas.size[0] + cHeight = canvas.size[1] + plotWidth = cWidth - xLeftOffset - xRightOffset + plotHeight = cHeight - yTopOffset - yBottomOffset + + #Drawing Area Height + drawAreaHeight = plotHeight + if self.plotScale == 'physic' and self.selectedChr > -1: + if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": + drawAreaHeight -= 4*self.BAND_HEIGHT + 4*self.BAND_SPACING+ 10*zoom + else: + drawAreaHeight -= 3*self.BAND_HEIGHT + 3*self.BAND_SPACING+ 10*zoom + if self.geneChecked: + drawAreaHeight -= self.NUM_GENE_ROWS*self.EACH_GENE_HEIGHT + 3*self.BAND_SPACING + 10*zoom + else: + if self.selectedChr > -1: + drawAreaHeight -= 20 + else: + drawAreaHeight -= 30 + +## BEGIN HaplotypeAnalyst + if self.haplotypeAnalystChecked and self.selectedChr > -1: + drawAreaHeight -= self.EACH_GENE_HEIGHT * (self.NR_INDIVIDUALS+10) * 2 * zoom +## END HaplotypeAnalyst + + if zoom == 2: + drawAreaHeight -= 60 + + #Image map + gifmap = HT.Map(name = "WebQTLImageMap") + + newoffset = (xLeftOffset, xRightOffset, yTopOffset, yBottomOffset) + # Draw the alternating-color background first and get plotXScale + plotXScale = self.drawGraphBackground(canvas, gifmap, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb) + + #draw bootstap + if self.bootChecked and not self.multipleInterval and not self.manhattan_plot: + self.drawBootStrapResult(canvas, self.nboot, drawAreaHeight, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb) + + # Draw clickable region and gene band if selected + if self.plotScale == 'physic' and self.selectedChr > -1: + self.drawClickBand(canvas, gifmap, plotXScale, offset=newoffset, zoom = zoom, startMb=startMb, endMb = endMb) + if self.geneChecked and self.geneCol: + self.drawGeneBand(canvas, gifmap, plotXScale, offset=newoffset, zoom = zoom, startMb=startMb, endMb = endMb) + if self.SNPChecked: + self.drawSNPTrackNew(canvas, offset=newoffset, zoom = 2*zoom, startMb=startMb, endMb = endMb) +## BEGIN HaplotypeAnalyst + if self.haplotypeAnalystChecked: + self.drawHaplotypeBand(canvas, gifmap, plotXScale, offset=newoffset, zoom = zoom, startMb=startMb, endMb = endMb) +## END HaplotypeAnalyst + # Draw X axis + self.drawXAxis(canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset=newoffset, zoom = zoom, startMb=startMb, endMb = endMb) + # Draw QTL curve + self.drawQTL(canvas, drawAreaHeight, gifmap, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb) + + #draw legend + if self.multipleInterval: + self.drawMultiTraitName(fd, canvas, gifmap, showLocusForm, offset=newoffset) + elif self.legendChecked: + self.drawLegendPanel(canvas, offset=newoffset, zoom = zoom) + else: + pass + + #draw position, no need to use a separate function + self.drawProbeSetPosition(canvas, plotXScale, offset=newoffset, zoom = zoom) + + return gifmap + + def drawBootStrapResult(self, canvas, nboot, drawAreaHeight, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yZero = canvas.size[1] - yBottomOffset + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + + bootHeightThresh = drawAreaHeight*3/4 + + #break bootstrap result into groups + BootCoord = [] + i = 0 + startX = xLeftOffset + + if self.selectedChr == -1: #ZS: If viewing full genome/all chromosomes + for j, _chr in enumerate(self.genotype): + BootCoord.append( []) + for _locus in _chr: + if self.plotScale == 'physic': + Xc = startX + (_locus.Mb-self.startMb)*plotXScale + else: + Xc = startX + (_locus.cM-_chr[0].cM)*plotXScale + BootCoord[-1].append([Xc, self.bootResult[i]]) + i += 1 + startX += (self.ChrLengthDistList[j] + self.GraphInterval)*plotXScale + else: + for j, _chr in enumerate(self.genotype): + if _chr.name == self.ChrList[self.selectedChr][0]: + BootCoord.append( []) + for _locus in _chr: + if _chr.name == self.ChrList[self.selectedChr][0]: + if self.plotScale == 'physic': + Xc = startX + (_locus.Mb-startMb)*plotXScale + else: + Xc = startX + (_locus.cM-_chr[0].cM)*plotXScale + BootCoord[-1].append([Xc, self.bootResult[i]]) + i += 1 + + #reduce bootResult + if self.selectedChr > -1: + maxBootBar = 80.0 + else: + maxBootBar = 200.0 + stepBootStrap = plotWidth/maxBootBar + reducedBootCoord = [] + maxBootCount = 0 + + for BootChrCoord in BootCoord: + nBoot = len(BootChrCoord) + bootStartPixX = BootChrCoord[0][0] + bootCount = BootChrCoord[0][1] + for i in range(1, nBoot): + if BootChrCoord[i][0] - bootStartPixX < stepBootStrap: + bootCount += BootChrCoord[i][1] + continue + else: + if maxBootCount < bootCount: + maxBootCount = bootCount + # end if + reducedBootCoord.append([bootStartPixX, BootChrCoord[i][0], bootCount]) + bootStartPixX = BootChrCoord[i][0] + bootCount = BootChrCoord[i][1] + # end else + # end for + #add last piece + if BootChrCoord[-1][0] - bootStartPixX > stepBootStrap/2.0: + reducedBootCoord.append([bootStartPixX, BootChrCoord[-1][0], bootCount]) + else: + reducedBootCoord[-1][2] += bootCount + reducedBootCoord[-1][1] = BootChrCoord[-1][0] + # end else + if maxBootCount < reducedBootCoord[-1][2]: + maxBootCount = reducedBootCoord[-1][2] + # end if + for item in reducedBootCoord: + if item[2] > 0: + if item[0] < xLeftOffset: + item[0] = xLeftOffset + if item[0] > xLeftOffset+plotWidth: + item[0] = xLeftOffset+plotWidth + if item[1] < xLeftOffset: + item[1] = xLeftOffset + 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) + + ###draw boot scale + highestPercent = (maxBootCount*100.0)/nboot + bootScale = Plot.detScale(0, highestPercent) + bootScale = Plot.frange(bootScale[0], bootScale[1], bootScale[1]/bootScale[2]) + 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) + 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) + + if self.legendChecked: + startPosY = 30 + nCol = 2 + smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1) + 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) + + def drawProbeSetPosition(self, canvas, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + if len(self.traitList) != 1: + return + + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yZero = canvas.size[1] - yBottomOffset + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + + try: + Chr = self.traitList[0].chr + Mb = self.traitList[0].mb + except: + return + + previous_chr = 1 + previous_chr_as_int = 0 + if self.plotScale == "physic": + this_chr = str(self.ChrList[self.selectedChr][0]) + else: + this_chr = str(self.ChrList[self.selectedChr][1]+1) + + if self.plotScale == 'physic': + if self.selectedChr > -1: + if this_chr != Chr or Mb < self.startMb or Mb > self.endMb: + return + else: + locPixel = xLeftOffset + (Mb-self.startMb)*plotXScale + else: + locPixel = xLeftOffset + for i, _chr in enumerate(self.ChrList[1:]): + if _chr[0] != Chr: + locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale + else: + locPixel += Mb*plotXScale + break + else: + if self.selectedChr > -1: + for i, qtlresult in enumerate(self.qtlresults): + if qtlresult['chr'] != self.selectedChr: + continue + + if i==0 and qtlresult['Mb'] >= Mb: + locPixel=-1 + break + + #the trait's position is between two traits + if i > 0 and self.qtlresults[i-1]['Mb'] < Mb and qtlresult['Mb'] >= Mb: + locPixel = xLeftOffset + plotXScale*(self.qtlresults[i-1]['Mb']+(qtlresult['Mb']-self.qtlresults[i-1]['Mb'])*(Mb - self.qtlresults[i-1]['Mb'])/(qtlresult['Mb']-self.qtlresults[i-1]['Mb'])) + break + + #the trait's position is on the right of the last genotype + if i==len(self.qtlresults) and Mb>=qtlresult['Mb']: + locPixel = -1 + else: + locPixel = xLeftOffset + for i, _chr in enumerate(self.ChrList): + if i < (len(self.ChrList)-1): + if _chr != Chr: + locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale + else: + locPixel += (Mb*(_chr[-1].cM-_chr[0].cM)/self.ChrLengthCMList[i])*plotXScale + break + if locPixel >= 0 and self.plotScale == 'physic': + traitPixel = ((locPixel, yZero), (locPixel-6, yZero+12), (locPixel+6, yZero+12)) + canvas.drawPolygon(traitPixel, edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) + + if self.legendChecked: + startPosY = 15 + nCol = 2 + smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1) + if self.manhattan_plot: + leftOffset = xLeftOffset + else: + leftOffset = xLeftOffset+(nCol-1)*200*fontZoom + canvas.drawPolygon(((leftOffset+6, startPosY-6), (leftOffset, startPosY+6), (leftOffset+12, startPosY+6)), edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) + canvas.drawString("Sequence Site", (leftOffset+15), (startPosY+5), smallLabelFont, self.TOP_RIGHT_INFO_COLOR) + + def drawSNPTrackNew(self, canvas, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + if self.plotScale != 'physic' or self.selectedChr == -1 or not self.diffCol: + return + + SNP_HEIGHT_MODIFIER = 18.0 + + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yZero = canvas.size[1] - yBottomOffset + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + + drawSNPLocationY = yTopOffset + plotHeight + chrName = self.genotype[0].name + + stepMb = (endMb-startMb)/plotWidth + strainId1, strainId2 = self.diffCol + SNPCounts = [] + + while startMb= %2.6f AND Mb < %2.6f AND + StrainId1 = %d AND StrainId2 = %d + """ % (chrName, startMb, startMb+stepMb, strainId1, strainId2)).fetchone()[0] + SNPCounts.append(snp_count) + startMb += stepMb + + if (len(SNPCounts) > 0): + maxCount = max(SNPCounts) + 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) + + 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) + if len(self.qtlresults) >20 and self.selectedChr > -1: + rightShift = 20 + rightShiftStep = 60 + rectWidth = 10 + else: + rightShift = 40 + rightShiftStep = 80 + rectWidth = 15 + + for k, thisTrait in enumerate(self.traitList): + thisLRSColor = self.colorCollection[k] + kstep = k % 4 + if k!=0 and kstep==0: + if nameWidths: + rightShiftStep = max(nameWidths[-4:]) + rectWidth + 20 + rightShift += rightShiftStep + + name = thisTrait.displayName() + nameWidth = canvas.stringWidth(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) + 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) + Areas = HT.Area(shape='rect',coords=COORDS,href=HREF) + gifmap.areas.append(Areas) + + def drawLegendPanel(self, canvas, offset= (40, 120, 80, 10), zoom = 1): + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yZero = canvas.size[1] - yBottomOffset + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + + labelFont=pid.Font(ttf="trebuc",size=12*fontZoom, bold=1) + 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) + 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) + + 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) + + 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) + + 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 + if self.selectedChr == -1: + string1 = 'Mapping for Dataset: %s, mapping on All Chromosomes' % self.dataset.group.name + else: + string1 = 'Mapping for Dataset: %s, mapping on Chromosome %s' % (self.dataset.group.name, self.ChrList[self.selectedChr][0]) + + string3 = '' + if self.mapping_method == "gemma" or self.mapping_method == "gemma_bimbam": + if self.use_loco == "True": + string2 = 'Using GEMMA mapping method with LOCO and ' + else: + string2 = 'Using GEMMA mapping method with ' + if self.covariates != "": + string2 += 'the cofactors below:' + cofactor_names = ", ".join([covar.split(":")[0] for covar in self.covariates.split(",")]) + string3 = cofactor_names + else: + string2 += 'no cofactors' + elif self.mapping_method == "rqtl_plink" or self.mapping_method == "rqtl_geno": + string2 = 'Using R/qtl mapping method with ' + if self.controlLocus and self.doControl != "false": + string2 += '%s as control' % self.controlLocus + else: + string2 += 'no control for other QTLs' + elif self.mapping_method == "plink": + string2 = 'Using PLINK mapping method with no control for other QTLs' + else: + string2 = 'Using Haldane mapping function with ' + if self.controlLocus and self.doControl != "false": + string2 += '%s as control' % self.controlLocus + else: + string2 += 'no control for other QTLs' + + if self.this_trait.name: + if self.this_trait.symbol: + identification = "Trait ID: %s : %s : %s" % (self.this_trait.symbol, self.dataset.fullname, self.this_trait.name) + else: + identification = "Trait ID: %s : %s" % (self.dataset.fullname, self.this_trait.name) + 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) + if string3 != '': + canvas.drawString(string3,canvas.size[0] - xRightOffset-d,65*fontZoom,font=labelFont,color=labelColor) + + + def drawGeneBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + if self.plotScale != 'physic' or self.selectedChr == -1 or not self.geneCol: + return + + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yZero = canvas.size[1] - yBottomOffset + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + + yPaddingTop = yTopOffset + + for gIndex, theGO in enumerate(self.geneCol): + geneNCBILink = 'http://www.ncbi.nlm.nih.gov/gene?term=%s' + if self.dataset.group.species == "mouse": + txStart = theGO["TxStart"] + txEnd = theGO["TxEnd"] + geneLength = (txEnd - txStart)*1000.0 + tenPercentLength = geneLength*0.0001 + SNPdensity = theGO["snpCount"]/geneLength + + exonStarts = map(float, theGO['exonStarts'].split(",")[:-1]) + exonEnds = map(float, theGO['exonEnds'].split(",")[:-1]) + cdsStart = theGO['cdsStart'] + cdsEnd = theGO['cdsEnd'] + accession = theGO['NM_ID'] + geneSymbol = theGO["GeneSymbol"] + strand = theGO["Strand"] + exonCount = theGO["exonCount"] + + geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) + geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) #at least one pixel + + if (geneEndPix < xLeftOffset): + return; # this gene is not on the screen + elif (geneEndPix > xLeftOffset + plotWidth): + geneEndPix = xLeftOffset + plotWidth; # clip the last in-range gene + if (geneStartPix > xLeftOffset + plotWidth): + return; # we are outside the valid on-screen range, so stop drawing genes + elif (geneStartPix < xLeftOffset): + geneStartPix = xLeftOffset; # clip the first in-range gene + + #color the gene based on SNP density + #found earlier, needs to be recomputed as snps are added + #always apply colors now, even if SNP Track not checked - Zach 11/24/2010 + + densities=[1.0000000000000001e-05, 0.094094033555233408, 0.3306166377816987, 0.88246026851027781, 2.6690084029581951, 4.1, 61.0] + if SNPdensity < densities[0]: + myColor = pid.black + elif SNPdensity < densities[1]: + myColor = pid.purple + elif SNPdensity < densities[2]: + myColor = pid.darkblue + elif SNPdensity < densities[3]: + myColor = pid.darkgreen + elif SNPdensity < densities[4]: + myColor = pid.gold + elif SNPdensity < densities[5]: + myColor = pid.darkorange + else: + myColor = pid.darkred + + outlineColor = myColor + fillColor = myColor + + TITLE = "Gene: %s (%s)\nFrom %2.3f to %2.3f Mb (%s)\nNum. exons: %d." % (geneSymbol, accession, float(txStart), float(txEnd), strand, exonCount) + # NL: 06-02-2011 Rob required to change this link for gene related + HREF=geneNCBILink %geneSymbol + + elif self.dataset.group.species == "rat": + exonStarts = [] + exonEnds = [] + txStart = theGO["TxStart"] + txEnd = theGO["TxEnd"] + cdsStart = theGO["TxStart"] + cdsEnd = theGO["TxEnd"] + geneSymbol = theGO["GeneSymbol"] + strand = theGO["Strand"] + exonCount = 0 + + geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) + geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) #at least one pixel + + if (geneEndPix < xLeftOffset): + return; # this gene is not on the screen + elif (geneEndPix > xLeftOffset + plotWidth): + geneEndPix = xLeftOffset + plotWidth; # clip the last in-range gene + if (geneStartPix > xLeftOffset + plotWidth): + return; # we are outside the valid on-screen range, so stop drawing genes + elif (geneStartPix < xLeftOffset): + geneStartPix = xLeftOffset; # clip the first in-range gene + + outlineColor = pid.darkblue + fillColor = pid.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 + TITLE = "Gene: %s" % geneSymbol + + #Draw Genes + geneYLocation = yPaddingTop + (gIndex % self.NUM_GENE_ROWS) * self.EACH_GENE_HEIGHT*zoom + if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": + geneYLocation += 4*self.BAND_HEIGHT + 4*self.BAND_SPACING + else: + geneYLocation += 3*self.BAND_HEIGHT + 3*self.BAND_SPACING + + #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) + + #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) + + #draw the arrows + if geneEndPix - geneStartPix < 1: + genePixRange = 1 + else: + genePixRange = int(geneEndPix - geneStartPix) + for xCoord in range(0, genePixRange): + + 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) + 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) + + #draw the blocks for the exon regions + for i in range(0, len(exonStarts)): + exonStartPix = (exonStarts[i]-startMb)*plotXScale + xLeftOffset + exonEndPix = (exonEnds[i]-startMb)*plotXScale + xLeftOffset + if (exonStartPix < xLeftOffset): + exonStartPix = xLeftOffset + if (exonEndPix < xLeftOffset): + exonEndPix = xLeftOffset + if (exonEndPix > xLeftOffset + plotWidth): + 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) + + #draw gray blocks for 3' and 5' UTR blocks + if cdsStart and cdsEnd: + utrStartPix = (txStart-startMb)*plotXScale + xLeftOffset + utrEndPix = (cdsStart-startMb)*plotXScale + xLeftOffset + if (utrStartPix < xLeftOffset): + utrStartPix = xLeftOffset + if (utrEndPix < xLeftOffset): + utrEndPix = xLeftOffset + if (utrEndPix > xLeftOffset + plotWidth): + 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)) + + #the second UTR region + + utrStartPix = (cdsEnd-startMb)*plotXScale + xLeftOffset + utrEndPix = (txEnd-startMb)*plotXScale + xLeftOffset + if (utrStartPix < xLeftOffset): + utrStartPix = xLeftOffset + if (utrEndPix < xLeftOffset): + utrEndPix = xLeftOffset + if (utrEndPix > xLeftOffset + plotWidth): + 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)) + + #draw the genes as rectangles + else: + canvas.drawRect(geneStartPix, geneYLocation, geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom), edgeColor = outlineColor, fillColor = 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 + gifmap.areas.append(HT.Area(shape='rect',coords=COORDS,href=HREF, title=TITLE,target="_blank")) + +## BEGIN HaplotypeAnalyst + def drawHaplotypeBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + if self.plotScale != 'physic' or self.selectedChr == -1 or not self.geneCol: + return + + clickableRegionLabelFont=pid.Font(ttf="verdana", size=9, bold=0) + + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yZero = canvas.size[1] - yBottomOffset + fontZoom = zoom + + yPaddingTop = yTopOffset + + thisTrait = self.this_trait + _strains, _vals, _vars, _aliases = thisTrait.export_informative() + + smd=[] + for ii, _val in enumerate(_vals): + if _strains[ii] in self.dataset.group.samplelist: + temp = GeneralObject(name=_strains[ii], value=_val) + smd.append(temp) + + smd.sort(lambda A, B: cmp(A.value, B.value)) + smd.reverse() + + samplelist = list(self.genotype.prgy) + + oldgeneEndPix = -1 + #Initializing plotRight, error before + plotRight = xRightOffset + +#### find out PlotRight + for i, _locus in enumerate(self.genotype[0]): + txStart = self.genotype[0][i].Mb + txEnd = self.genotype[0][i].Mb + + geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) - 0 + geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) - 0 + + drawit = 1 + if (geneStartPix < xLeftOffset): + drawit = 0; + if (geneStartPix > xLeftOffset + plotWidth): + drawit = 0; + + if drawit == 1: + if self.genotype[0][i].name != " - " : + plotRight = geneEndPix + 4 + +#### end find out PlotRight + + firstGene = 1 + lastGene = 0 + + #Sets the length to the length of the strain list. Beforehand, "oldgeno = self.genotype[0][i].genotype" + #was the only place it was initialized, which worked as long as the very start (startMb = None/0) wasn't being mapped. + #Now there should always be some value set for "oldgeno" - Zach 12/14/2010 + oldgeno = [None]*len(self.strainlist) + + for i, _locus in enumerate(self.genotype[0]): + txStart = self.genotype[0][i].Mb + txEnd = self.genotype[0][i].Mb + + geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) - 0 + geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) + 0 + + if oldgeneEndPix >= xLeftOffset: + drawStart = oldgeneEndPix + 4 + else: + drawStart = xLeftOffset + 3 + + drawEnd = plotRight - 9 + + drawit = 1 + + if (geneStartPix < xLeftOffset): + if firstGene == 1: + drawit = 1 + else: + drawit = 0 + + elif (geneStartPix > (xLeftOffset + plotWidth - 3)): + if lastGene == 0: + drawit = 1 + drawEnd = xLeftOffset + plotWidth - 6 + lastGene = 1 + else: + break + + else: + firstGene = 0 + drawit = 1 + + if drawit == 1: + myColor = pid.darkblue + outlineColor = myColor + fillColor = myColor + + maxind=0 + + #Draw Genes + + geneYLocation = yPaddingTop + self.NUM_GENE_ROWS * (self.EACH_GENE_HEIGHT)*zoom + if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": + geneYLocation += 4*self.BAND_HEIGHT + 4*self.BAND_SPACING + else: + geneYLocation += 3*self.BAND_HEIGHT + 3*self.BAND_SPACING + + if self.genotype[0][i].name != " - " : + + if (firstGene == 1) and (lastGene != 1): + oldgeneEndPix = drawStart = xLeftOffset + oldgeno = self.genotype[0][i].genotype + continue + + for j,_geno in enumerate (self.genotype[0][i].genotype): + + plotbxd=0 + for item in smd: + if item.name == samplelist[j]: + plotbxd=1 + + if (plotbxd == 1): + ind = 0 + counter = 0 + for item in smd: + counter = counter + 1 + if item.name == samplelist[j]: + ind = counter + maxind=max(ind,maxind) + + # lines + if (oldgeno[j] == -1 and _geno == -1): + mylineColor = self.HAPLOTYPE_NEGATIVE + elif (oldgeno[j] == 1 and _geno == 1): + mylineColor = self.HAPLOTYPE_POSITIVE + elif (oldgeno[j] == 0 and _geno == 0): + mylineColor = self.HAPLOTYPE_HETEROZYGOUS + 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)) + + fillColor=pid.black + outlineColor=pid.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) + + + COORDS = "%d, %d, %d, %d" %(geneStartPix, geneYLocation+ind*self.EACH_GENE_HEIGHT, geneEndPix+1, (geneYLocation + ind*self.EACH_GENE_HEIGHT)) + TITLE = "Strain: %s, marker (%s) \n Position %2.3f Mb." % (samplelist[j], self.genotype[0][i].name, float(txStart)) + HREF = '' + gifmap.areas.append(HT.Area(shape='rect',coords=COORDS,href=HREF, title=TITLE)) + + # if there are no more markers in a chromosome, the plotRight value calculated above will be before the plotWidth + # resulting in some empty space on the right side of the plot area. This draws an "unknown" bar from plotRight to the edge. + 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)) + + + if lastGene == 0: + canvas.drawString("%s" % (self.genotype[0][i].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) + + oldgeneEndPix = geneEndPix; + oldgeno = self.genotype[0][i].genotype + firstGene = 0 + else: + lastGene = 0 + + for j, _geno in enumerate (self.genotype[0][1].genotype): + + plotbxd=0 + for item in smd: + if item.name == samplelist[j]: + plotbxd=1 + + if (plotbxd == 1): + + ind = 0 + counter = 0 + expr = 0 + for item in smd: + counter = counter + 1 + if item.name == samplelist[j]: + ind = counter + 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) + +## END HaplotypeAnalyst + + def drawClickBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + if self.plotScale != 'physic' or self.selectedChr == -1: + return + + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yZero = canvas.size[1] - yBottomOffset + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + + # only draw this many clickable regions (if you set it higher, you get more precision in clicking, + # 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) + 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. + + numBasesCurrentlyOnScreen = self.kONE_MILLION*abs(startMb - endMb) # Number of bases on screen now + flankingWidthInBases = int ( min( (float(numBasesCurrentlyOnScreen) / 2.0), (5*self.kONE_MILLION) ) ) + webqtlZoomWidth = numBasesCurrentlyOnScreen / 16.0 + # Flanking width should be such that we either zoom in to a 10 million base region, or we show the clicked region at the same scale as we are currently seeing. + + currentChromosome = self.genotype[0].name + i = 0 + + paddingTop = yTopOffset + if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": + phenogenPaddingTop = paddingTop + (self.BAND_HEIGHT + self.BAND_SPACING) + ucscPaddingTop = paddingTop + 2*(self.BAND_HEIGHT + self.BAND_SPACING) + ensemblPaddingTop = paddingTop + 3*(self.BAND_HEIGHT + self.BAND_SPACING) + else: + ucscPaddingTop = paddingTop + (self.BAND_HEIGHT + self.BAND_SPACING) + ensemblPaddingTop = paddingTop + 2*(self.BAND_HEIGHT + self.BAND_SPACING) + + if zoom == 1: + for pixel in range(xLeftOffset, xLeftOffset + plotWidth, pixelStep): + + calBase = self.kONE_MILLION*(startMb + (endMb-startMb)*(pixel-xLeftOffset-0.0)/plotWidth) + if pixel == (xLeftOffset + pixelStep*2): + logger.debug("CALBASE:", calBase) + logger.debug("FLANKING:", flankingWidthInBases) + + xBrowse1 = pixel + xBrowse2 = min(xLeftOffset + plotWidth, (pixel + pixelStep - 1)) + + WEBQTL_COORDS = "%d, %d, %d, %d" % (xBrowse1, paddingTop, xBrowse2, (paddingTop+self.BAND_HEIGHT)) + WEBQTL_HREF = "javascript:rangeView('%s', %f, %f)" % (self.selectedChr - 1, max(0, (calBase-webqtlZoomWidth))/1000000.0, (calBase+webqtlZoomWidth)/1000000.0) + + 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) + + 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)) + if self.dataset.group.species == "mouse": + PHENOGEN_HREF = "https://phenogen.ucdenver.edu/PhenoGen/gene.jsp?speciesCB=Mm&auto=Y&geneTxt=chr%s:%d-%d&genomeVer=mm10" % (self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases) + else: + PHENOGEN_HREF = "https://phenogen.ucdenver.edu/PhenoGen/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) + + UCSC_COORDS = "%d, %d, %d, %d" %(xBrowse1, ucscPaddingTop, xBrowse2, (ucscPaddingTop+self.BAND_HEIGHT)) + if self.dataset.group.species == "mouse": + UCSC_HREF = "http://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=chr%s:%d-%d&hgt.customText=%s/snp/chr%s" % (self._ucscDb, self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases, webqtlConfig.PORTADDR, self.selectedChr) + else: + 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) + + ENSEMBL_COORDS = "%d, %d, %d, %d" %(xBrowse1, ensemblPaddingTop, xBrowse2, (ensemblPaddingTop+self.BAND_HEIGHT)) + if self.dataset.group.species == "mouse": + ENSEMBL_HREF = "http://www.ensembl.org/Mus_musculus/contigview?highlight=&chr=%s&vc_start=%d&vc_end=%d&x=35&y=12" % (self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases) + else: + 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) + # 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) + 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) + + #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) + # 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) + # end of drawBrowserClickableRegions + pass + + def drawXAxis(self, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yZero = canvas.size[1] - yBottomOffset + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + + #Parameters + NUM_MINOR_TICKS = 5 # Number of minor ticks between major ticks + X_MAJOR_TICK_THICKNESS = 2 + 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) + xMajorTickHeight = 10 * zoom # How high the tick extends below the axis + xMinorTickHeight = 5*zoom + xAxisTickMarkColor = pid.black + xAxisLabelColor = pid.black + fontHeight = 12*fontZoom # How tall the font that we're using is + spacingFromLabelToAxis = 5 + + if self.plotScale == 'physic': + strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) + ###Physical single chromosome view + if self.selectedChr > -1: + XScale = Plot.detScale(startMb, endMb) + XStart, XEnd, XStep = XScale + if XStep < 8: + XStep *= 2 + spacingAmtX = spacingAmt = (XEnd-XStart)/XStep + + j = 0 + while abs(spacingAmtX -int(spacingAmtX)) >= spacingAmtX/100.0 and j < 6: + j += 1 + spacingAmtX *= 10 + + formatStr = '%%2.%df' % j + + for counter, _Mb in enumerate(Plot.frange(XStart, XEnd, spacingAmt / NUM_MINOR_TICKS)): + if _Mb < startMb or _Mb > endMb: + 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 + labelStr = str(formatStr % _Mb) # What Mbase location to put on the label + strWidth = canvas.stringWidth(labelStr, font=MBLabelFont) + drawStringXc = (Xc - (strWidth / 2.0)) + canvas.drawString(labelStr, drawStringXc, strYLoc, font=MBLabelFont, color=xAxisLabelColor, angle=0) + else: + canvas.drawLine(Xc, yZero, Xc, yZero+xMinorTickHeight, color=xAxisTickMarkColor, width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark + + ###Physical genome wide view + else: + distScale = 0 + startPosX = xLeftOffset + for i, distLen in enumerate(self.ChrLengthDistList): + if distScale == 0: #universal scale in whole genome mapping + if distLen > 75: + distScale = 25 + elif distLen > 30: + distScale = 10 + 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) + if j % 2 == 0: + canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=pid.black, font=MBLabelFont, 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) + pass + else: + strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) + 8 + ChrAInfo = [] + preLpos = -1 + distinctCount = 0.0 + + if self.selectedChr == -1: #ZS: If viewing full genome/all chromosomes + for i, _chr in enumerate(self.genotype): + thisChr = [] + Locus0CM = _chr[0].cM + nLoci = len(_chr) + if nLoci <= 8: + for _locus in _chr: + if _locus.name != ' - ': + if _locus.cM != preLpos: + distinctCount += 1 + preLpos = _locus.cM + thisChr.append([_locus.name, _locus.cM-Locus0CM]) + else: + for j in (0, nLoci/4, nLoci/2, nLoci*3/4, -1): + while _chr[j].name == ' - ': + j += 1 + if _chr[j].cM != preLpos: + distinctCount += 1 + preLpos = _chr[j].cM + thisChr.append([_chr[j].name, _chr[j].cM-Locus0CM]) + ChrAInfo.append(thisChr) + else: + for i, _chr in enumerate(self.genotype): + if _chr.name == self.ChrList[self.selectedChr][0]: + thisChr = [] + Locus0CM = _chr[0].cM + for _locus in _chr: + if _locus.name != ' - ': + if _locus.cM != preLpos: + distinctCount += 1 + preLpos = _locus.cM + thisChr.append([_locus.name, _locus.cM-Locus0CM]) + ChrAInfo.append(thisChr) + + stepA = (plotWidth+0.0)/distinctCount + + LRectWidth = 10 + LRectHeight = 3 + offsetA = -stepA + lineColor = pid.lightblue + startPosX = xLeftOffset + + for j, ChrInfo in enumerate(ChrAInfo): + preLpos = -1 + for i, item in enumerate(ChrInfo): + Lname,Lpos = item + if Lpos != preLpos: + offsetA += stepA + differ = 1 + else: + differ = 0 + preLpos = Lpos + Lpos *= plotXScale + if self.selectedChr > -1: + Zorder = i % 5 + 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 + 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) + 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") + #HREF="javascript:showDatabase3('%s','%s','%s','');" % (showLocusForm,fd.RISet+"Geno", Lname) + Areas=HT.Area(shape='rect', coords=COORDS, href=HREF, target="_blank", title="Locus : " + Lname) + gifmap.areas.append(Areas) + ##piddle bug + if j == 0: + canvas.drawLine(startPosX,yZero,startPosX,yZero+40, color=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) + + canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.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): + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + + INTERCROSS = (self.genotype.type=="intercross") + + LRSHeightThresh = drawAreaHeight + AdditiveHeightThresh = drawAreaHeight/2 + DominanceHeightThresh = drawAreaHeight/2 + + #draw the LRS scale + #We first determine whether or not we are using a sliding scale. + #If so, we need to compute the maximum LRS value to determine where the max y-value should be, and call this LRS_LOD_Max. + #LRSTop is then defined to be above the LRS_LOD_Max by enough to add one additional LRSScale increment. + #if we are using a set-scale, then we set LRSTop to be the user's value, and LRS_LOD_Max doesn't matter. + + #ZS: This is a mess, but I don't know a better way to account for different mapping methods returning results in different formats + the option to change between LRS and LOD + if self.lrsMax <= 0: #sliding scale + if "lrs_value" in self.qtlresults[0]: + LRS_LOD_Max = max([result['lrs_value'] for result in self.qtlresults]) + if self.LRS_LOD == "LOD" or self.LRS_LOD == "-log(p)": + LRS_LOD_Max = LRS_LOD_Max / self.LODFACTOR + if self.permChecked and self.nperm > 0 and not self.multipleInterval: + self.significant = min(self.significant / self.LODFACTOR, webqtlConfig.MAXLRS) + self.suggestive = min(self.suggestive / self.LODFACTOR, webqtlConfig.MAXLRS) + else: + if self.permChecked and self.nperm > 0 and not self.multipleInterval: + self.significant = min(self.significant, webqtlConfig.MAXLRS) + self.suggestive = min(self.suggestive, webqtlConfig.MAXLRS) + else: + pass + else: + LRS_LOD_Max = max([result['lod_score'] for result in self.qtlresults]) + if self.LRS_LOD == "LRS": + LRS_LOD_Max = LRS_LOD_Max * self.LODFACTOR + if self.permChecked and self.nperm > 0 and not self.multipleInterval: + self.significant = min(self.significant * self.LODFACTOR, webqtlConfig.MAXLRS) + self.suggestive = min(self.suggestive * self.LODFACTOR, webqtlConfig.MAXLRS) + else: + if self.permChecked and self.nperm > 0 and not self.multipleInterval: + self.significant = min(self.significant, webqtlConfig.MAXLRS) + self.suggestive = min(self.suggestive, webqtlConfig.MAXLRS) + else: + pass + + if self.permChecked and self.nperm > 0 and not self.multipleInterval: + LRS_LOD_Max = max(self.significant, LRS_LOD_Max) + else: + LRS_LOD_Max = 1.15*LRS_LOD_Max + + #genotype trait will give infinite LRS + LRS_LOD_Max = min(LRS_LOD_Max, webqtlConfig.MAXLRS) + else: + LRS_LOD_Max = self.lrsMax + + if LRS_LOD_Max > 100: + LRSScale = 20.0 + elif LRS_LOD_Max > 20: + LRSScale = 5.0 + elif LRS_LOD_Max > 7.5: + LRSScale = 2.5 + else: + LRSScale = 1.0 + + LRSAxisList = Plot.frange(LRSScale, LRS_LOD_Max, LRSScale) + #make sure the user's value appears on the y-axis + #update by NL 6-21-2011: round the LOD value to 100 when LRS_LOD_Max is equal to 460 + LRSAxisList.append(round(LRS_LOD_Max)) + + #draw the "LRS" or "LOD" string to the left of the axis + LRSScaleFont=pid.Font(ttf="verdana", size=16*zoom, bold=0) + LRSLODFont=pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0) + yZero = yTopOffset + plotHeight + + canvas.drawString(self.LRS_LOD, xLeftOffset - canvas.stringWidth("999.99", font=LRSScaleFont) - 15*(zoom-1), \ + yZero - 150 - 300*(zoom - 1), font=LRSLODFont, color=pid.black, angle=90) + + for item in LRSAxisList: + if LRS_LOD_Max == 0.0: + LRS_LOD_Max = 0.000001 + yLRS = yZero - (item/LRS_LOD_Max) * LRSHeightThresh + canvas.drawLine(xLeftOffset, yLRS, xLeftOffset - 4, yLRS, color=self.LRS_COLOR, width=1*zoom) + 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) + + if self.permChecked and self.nperm > 0 and not self.multipleInterval: + significantY = yZero - self.significant*LRSHeightThresh/LRS_LOD_Max + suggestiveY = yZero - self.suggestive*LRSHeightThresh/LRS_LOD_Max + startPosX = xLeftOffset + + #"Significant" and "Suggestive" Drawing Routine + # ======= Draw the thick lines for "Significant" and "Suggestive" ===== (crowell: I tried to make the SNPs draw over these lines, but piddle wouldn't have it...) + + #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)) + 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': + sugg_title = "Suggestive LRS = %0.2f" % self.suggestive + sig_title = "Significant LRS = %0.2f" % self.significant + else: + sugg_title = "Suggestive LOD = %0.2f" % (self.suggestive/4.61) + sig_title = "Significant LOD = %0.2f" % (self.significant/4.61) + Areas1 = HT.Area(shape='rect',coords=sugg_coords,title=sugg_title) + Areas2 = HT.Area(shape='rect',coords=sig_coords,title=sig_title) + gifmap.areas.append(Areas1) + gifmap.areas.append(Areas2) + + start_pos_x += (chr_length_dist+self.GraphInterval)*plotXScale + return start_pos_x + + for i, _chr in enumerate(self.genotype): + if self.selectedChr != -1: + if _chr.name == self.ChrList[self.selectedChr][0]: + startPosX = add_suggestive_significant_lines_and_legend(startPosX, self.ChrLengthDistList[0]) + break + else: + continue + else: + startPosX = add_suggestive_significant_lines_and_legend(startPosX, self.ChrLengthDistList[i]) + + if self.multipleInterval: + lrsEdgeWidth = 1 + else: + if self.additiveChecked: + additiveMax = max(map(lambda X : abs(X['additive']), self.qtlresults)) + lrsEdgeWidth = 2 + + if zoom == 2: + lrsEdgeWidth = 2 * lrsEdgeWidth + + LRSCoordXY = [] + AdditiveCoordXY = [] + DominanceCoordXY = [] + + symbolFont = pid.Font(ttf="fnt_bs", size=5,bold=0) #ZS: For Manhattan Plot + + previous_chr = 1 + previous_chr_as_int = 0 + lineWidth = 1 + oldStartPosX = 0 + startPosX = xLeftOffset + for i, qtlresult in enumerate(self.qtlresults): + m = 0 + 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)) + + if not self.multipleInterval and not self.manhattan_plot and self.additiveChecked: + plusColor = self.ADDITIVE_COLOR_POSITIVE + minusColor = self.ADDITIVE_COLOR_NEGATIVE + for k, aPoint in enumerate(AdditiveCoordXY): + if k > 0: + Xc0, Yc0 = AdditiveCoordXY[k-1] + Xc, Yc = aPoint + if (Yc0-yZero)*(Yc-yZero) < 0: + if Xc == Xc0: #genotype , locus distance is 0 + Xcm = Xc + 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)) + 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)) + elif (Yc0-yZero)*(Yc-yZero) > 0: + if Yc < yZero: + canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) + else: + minYc = min(Yc-yZero, Yc0-yZero) + if minYc < 0: + canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) + + LRSCoordXY = [] + AdditiveCoordXY = [] + previous_chr = qtlresult['chr'] + previous_chr_as_int += 1 + newStartPosX = (self.ChrLengthDistList[previous_chr_as_int - 1]+self.GraphInterval)*plotXScale + if newStartPosX != oldStartPosX: + startPosX += newStartPosX + oldStartPosX = newStartPosX + + #ZS: This is beause the chromosome value stored in qtlresult['chr'] can be (for example) either X or 20 depending upon the mapping method/scale used + if self.plotScale == "physic": + this_chr = str(self.ChrList[self.selectedChr][0]) + else: + this_chr = str(self.ChrList[self.selectedChr][1]+1) + if self.selectedChr == -1 or str(qtlresult['chr']) == this_chr: + Xc = startPosX + (qtlresult['Mb']-startMb)*plotXScale + # updated by NL 06-18-2011: + # fix the over limit LRS graph issue since genotype trait may give infinite LRS; + # for any lrs is over than 460(LRS max in this system), it will be reset to 460 + if 'lrs_value' in qtlresult: + if self.LRS_LOD == "LOD" or self.LRS_LOD == "-log(p)": + if qtlresult['lrs_value'] > 460 or qtlresult['lrs_value']=='inf': + Yc = yZero - webqtlConfig.MAXLRS*LRSHeightThresh/(LRS_LOD_Max*self.LODFACTOR) + else: + Yc = yZero - qtlresult['lrs_value']*LRSHeightThresh/(LRS_LOD_Max*self.LODFACTOR) + else: + if qtlresult['lrs_value'] > 460 or qtlresult['lrs_value']=='inf': + Yc = yZero - webqtlConfig.MAXLRS*LRSHeightThresh/LRS_LOD_Max + else: + Yc = yZero - qtlresult['lrs_value']*LRSHeightThresh/LRS_LOD_Max + else: + if qtlresult['lod_score'] > 100 or qtlresult['lod_score']=='inf': + Yc = yZero - webqtlConfig.MAXLRS*LRSHeightThresh/LRS_LOD_Max + else: + if self.LRS_LOD == "LRS": + Yc = yZero - qtlresult['lod_score']*self.LODFACTOR*LRSHeightThresh/LRS_LOD_Max + else: + Yc = yZero - qtlresult['lod_score']*LRSHeightThresh/LRS_LOD_Max + + if self.manhattan_plot == True: + point_color = pid.black + canvas.drawString("5", Xc-canvas.stringWidth("5",font=symbolFont)/2+1,Yc+2,color=point_color, font=symbolFont) + else: + LRSCoordXY.append((Xc, Yc)) + + if not self.multipleInterval and self.additiveChecked: + if additiveMax == 0.0: + additiveMax = 0.000001 + Yc = yZero - qtlresult['additive']*AdditiveHeightThresh/additiveMax + AdditiveCoordXY.append((Xc, Yc)) + + m += 1 + + if self.manhattan_plot != True: + canvas.drawPolygon(LRSCoordXY,edgeColor=thisLRSColor,closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + + if not self.multipleInterval and self.additiveChecked: + plusColor = self.ADDITIVE_COLOR_POSITIVE + minusColor = self.ADDITIVE_COLOR_NEGATIVE + for k, aPoint in enumerate(AdditiveCoordXY): + if k > 0: + Xc0, Yc0 = AdditiveCoordXY[k-1] + Xc, Yc = aPoint + if (Yc0-yZero)*(Yc-yZero) < 0: + if Xc == Xc0: #genotype , locus distance is 0 + Xcm = Xc + 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)) + 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)) + elif (Yc0-yZero)*(Yc-yZero) > 0: + if Yc < yZero: + canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) + else: + minYc = min(Yc-yZero, Yc0-yZero) + if minYc < 0: + canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) + + if not self.multipleInterval and INTERCROSS and self.dominanceChecked: + plusColor = self.DOMINANCE_COLOR_POSITIVE + minusColor = self.DOMINANCE_COLOR_NEGATIVE + for k, aPoint in enumerate(DominanceCoordXY): + if k > 0: + Xc0, Yc0 = DominanceCoordXY[k-1] + Xc, Yc = aPoint + if (Yc0-yZero)*(Yc-yZero) < 0: + if Xc == Xc0: #genotype , locus distance is 0 + Xcm = Xc + 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)) + 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)) + elif (Yc0-yZero)*(Yc-yZero) > 0: + if Yc < yZero: + canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) + else: + minYc = min(Yc-yZero, Yc0-yZero) + if minYc < 0: + canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) + + + ###draw additive scale + if not self.multipleInterval and self.additiveChecked: + additiveScaleFont=pid.Font(ttf="verdana",size=16*zoom,bold=0) + additiveScale = Plot.detScaleOld(0,additiveMax) + additiveStep = (additiveScale[1]-additiveScale[0])/additiveScale[2] + additiveAxisList = Plot.frange(0, additiveScale[1], additiveStep) + addPlotScale = AdditiveHeightThresh/additiveMax + + 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) + scaleStr = "%2.3f" % item + canvas.drawString(scaleStr,xLeftOffset + plotWidth +6,additiveY+5,font=additiveScaleFont,color=self.ADDITIVE_COLOR_POSITIVE) + + canvas.drawLine(xLeftOffset+plotWidth,additiveY,xLeftOffset+plotWidth,yZero,color=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 + + + def drawGraphBackground(self, canvas, gifmap, offset= (80, 120, 80, 50), zoom = 1, startMb = None, endMb = None): + ##conditions + ##multiple Chromosome view + ##single Chromosome Physical + ##single Chromosome Genetic + xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset + plotWidth = canvas.size[0] - xLeftOffset - xRightOffset + plotHeight = canvas.size[1] - yTopOffset - yBottomOffset + yBottom = yTopOffset+plotHeight + fontZoom = zoom + if zoom == 2: + fontZoom = 1.5 + yTopOffset += 30 + + #calculate plot scale + if self.plotScale != 'physic': + self.ChrLengthDistList = self.ChrLengthCMList + drawRegionDistance = self.ChrLengthCMSum + else: + self.ChrLengthDistList = self.ChrLengthMbList + drawRegionDistance = self.ChrLengthMbSum + + if self.selectedChr > -1: #single chromosome view + spacingAmt = plotWidth/13.5 + i = 0 + for startPix in Plot.frange(xLeftOffset, xLeftOffset+plotWidth, spacingAmt): + if (i % 2 == 0): + theBackColor = self.GRAPH_BACK_DARK_COLOR + else: + theBackColor = self.GRAPH_BACK_LIGHT_COLOR + i += 1 + canvas.drawRect(startPix, yTopOffset, min(startPix+spacingAmt, xLeftOffset+plotWidth), \ + yBottom, edgeColor=theBackColor, fillColor=theBackColor) + + drawRegionDistance = self.ChrLengthDistList[self.ChrList[self.selectedChr][1]] + self.ChrLengthDistList = [drawRegionDistance] + if self.plotScale == 'physic': + plotXScale = plotWidth / (endMb-startMb) + else: + plotXScale = plotWidth / drawRegionDistance + + else: #multiple chromosome view + plotXScale = plotWidth / ((len(self.genotype)-1)*self.GraphInterval + drawRegionDistance) + + startPosX = xLeftOffset + if fontZoom == 1.5: + chrFontZoom = 2 + else: + chrFontZoom = 1 + chrLabelFont=pid.Font(ttf="verdana",size=24*chrFontZoom,bold=0) + + for i, _chr in enumerate(self.genotype): + if (i % 2 == 0): + theBackColor = self.GRAPH_BACK_DARK_COLOR + else: + 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) + + chrNameWidth = canvas.stringWidth(_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) + COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20) + + #add by NL 09-03-2010 + HREF = "javascript:chrView(%d,%s);" % (i,self.ChrLengthMbList) + #HREF = "javascript:changeView(%d,%s);" % (i,self.ChrLengthMbList) + Areas = HT.Area(shape='rect',coords=COORDS,href=HREF) + gifmap.areas.append(Areas) + startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale + + return plotXScale + + def drawPermutationHistogram(self): + ######################################### + # Permutation Graph + ######################################### + myCanvas = pid.PILCanvas(size=(400,300)) + if 'lod_score' in self.qtlresults[0] and self.LRS_LOD == "LRS": + perm_output = [value*4.16 for value in self.perm_output] + elif 'lod_score' not in self.qtlresults[0] and self.LRS_LOD == "LOD": + perm_output = [value/4.16 for value in self.perm_output] + else: + perm_output = self.perm_output + + Plot.plotBar(myCanvas, perm_output, XLabel=self.LRS_LOD, YLabel='Frequency', title=' Histogram of Permutation Test') + filename= webqtlUtil.genRandStr("Reg_") + myCanvas.save(GENERATED_IMAGE_DIR+filename, format='gif') + + return filename + + def geneTable(self, geneCol, refGene=None): + if self.dataset.group.species == 'mouse' or self.dataset.group.species == 'rat': + self.gene_table_header = self.getGeneTableHeaderList(refGene=None) + self.gene_table_body = self.getGeneTableBody(geneCol, refGene=None) + else: + self.gene_table_header = None + self.gene_table_body = None + + def getGeneTableHeaderList(self, refGene=None): + + gene_table_header_list = [] + if self.dataset.group.species == "mouse": + if refGene: + gene_table_header_list = ["Index", + "Symbol", + "Mb Start", + "Length (Kb)", + "SNP Count", + "SNP Density", + "Avg Expr", + "Human Chr", + "Mb Start (hg19)", + "Literature Correlation", + "Gene Description"] + else: + gene_table_header_list = ["", + "Index", + "Symbol", + "Mb Start", + "Length (Kb)", + "SNP Count", + "SNP Density", + "Avg Expr", + "Human Chr", + "Mb Start (hg19)", + "Gene Description"] + elif self.dataset.group.species == "rat": + gene_table_header_list = ["", + "Index", + "Symbol", + "Mb Start", + "Length (Kb)", + "Avg Expr", + "Mouse Chr", + "Mb Start (mm9)", + "Human Chr", + "Mb Start (hg19)", + "Gene Description"] + + return gene_table_header_list + + def getGeneTableBody(self, geneCol, refGene=None): + gene_table_body = [] + + tableIterationsCnt = 0 + if self.dataset.group.species == "mouse": + for gIndex, theGO in enumerate(geneCol): + + tableIterationsCnt = tableIterationsCnt + 1 + + this_row = [] #container for the cells of each row + selectCheck = HT.Input(type="checkbox", name="searchResult", value=theGO["GeneSymbol"], Class="checkbox", onClick="highlight(this)") #checkbox for each row + + geneLength = (theGO["TxEnd"] - theGO["TxStart"])*1000.0 + tenPercentLength = geneLength*0.0001 + txStart = theGO["TxStart"] + txEnd = theGO["TxEnd"] + theGO["snpDensity"] = theGO["snpCount"]/geneLength + if self.ALEX_DEBUG_BOOL_PRINT_GENE_LIST: + geneIdString = 'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s' % theGO["GeneID"] + + if theGO["snpCount"]: + snpString = HT.Href(url="http://genenetwork.org/webqtl/main.py?FormID=snpBrowser&chr=%s&start=%s&end=%s&geneName=%s&s1=%d&s2=%d" % (theGO["Chromosome"], + theGO["TxStart"], theGO["TxEnd"], theGO["GeneSymbol"], self.diffCol[0], self.diffCol[1]), + text=theGO["snpCount"], target="_blank", Class="normalsize") + else: + snpString = 0 + + mouseStartString = "http://genome.ucsc.edu/cgi-bin/hgTracks?clade=vertebrate&org=Mouse&db=mm9&position=chr" + theGO["Chromosome"] + "%3A" + str(int(theGO["TxStart"] * 1000000.0)) + "-" + str(int(theGO["TxEnd"]*1000000.0)) +"&pix=620&Submit=submit" + + #the chromosomes for human 1 are 1qXX.XX + if theGO['humanGene']: + if theGO['humanGene']["TxStart"] == '': + humanStartDisplay = "" + else: + humanStartDisplay = "%0.6f" % theGO['humanGene']["TxStart"] + + humanChr = theGO['humanGene']["Chromosome"] + humanTxStart = theGO['humanGene']["TxStart"] + + humanStartString = "http://genome.ucsc.edu/cgi-bin/hgTracks?clade=vertebrate&org=Human&db=hg17&position=chr%s:%d-%d" % (humanChr, int(1000000*theGO['humanGene']["TxStart"]), int(1000000*theGO['humanGene']["TxEnd"])) + else: + humanStartString = humanChr = humanStartDisplay = "--" + + geneDescription = theGO["GeneDescription"] + if len(geneDescription) > 26: + geneDescription = geneDescription[:26]+"..." + + if theGO["snpDensity"] < 0.000001: + snpDensityStr = "0" + else: + snpDensityStr = "%0.6f" % theGO["snpDensity"] + + avgExpr = [] #theGO["avgExprVal"] + if avgExpr in ([], None): + avgExpr = "--" + else: + avgExpr = "%0.6f" % avgExpr + + # If we have a referenceGene then we will show the Literature Correlation + if theGO["Chromosome"] == "X": + chr_as_int = 19 + else: + chr_as_int = int(theGO["Chromosome"]) - 1 + if refGene: + literatureCorrelationString = str(self.getLiteratureCorrelation(self.cursor,refGene,theGO['GeneID']) or "N/A") + + this_row = [selectCheck.__str__(), + str(tableIterationsCnt), + HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank").__str__(), + HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank").__str__(), + HT.Href("javascript:rangeView('%s', %f, %f)" % (str(chr_as_int), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), + snpString, + snpDensityStr, + avgExpr, + humanChr, + HT.Href(humanStartString, humanStartDisplay, target="_blank").__str__(), + literatureCorrelationString, + geneDescription] + else: + this_row = [selectCheck.__str__(), + str(tableIterationsCnt), + HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank").__str__(), + HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank").__str__(), + HT.Href("javascript:rangeView('%s', %f, %f)" % (str(chr_as_int), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), + snpString, + snpDensityStr, + avgExpr, + humanChr, + HT.Href(humanStartString, humanStartDisplay, target="_blank").__str__(), + geneDescription] + + gene_table_body.append(this_row) + + elif self.dataset.group.species == 'rat': + for gIndex, theGO in enumerate(geneCol): + this_row = [] #container for the cells of each row + selectCheck = HT.Input(type="checkbox", name="searchResult", Class="checkbox", onClick="highlight(this)").__str__() #checkbox for each row + + webqtlSearch = HT.Href(os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)+"?cmd=sch&gene=%s&alias=1&species=rat" % theGO["GeneSymbol"], ">>", target="_blank").__str__() + + if theGO["GeneID"] != "": + geneSymbolNCBI = HT.Href("http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % theGO["GeneID"], theGO["GeneSymbol"], Class="normalsize", target="_blank").__str__() + else: + geneSymbolNCBI = theGO["GeneSymbol"] + + if theGO["Chromosome"] == "X": + chr_as_int = 20 + else: + chr_as_int = int(theGO["Chromosome"]) - 1 + + geneLength = (float(theGO["TxEnd"]) - float(theGO["TxStart"])) + geneLengthURL = "javascript:rangeView('%s', %f, %f)" % (theGO["Chromosome"], float(theGO["TxStart"])-(geneLength*0.1), float(theGO["TxEnd"])+(geneLength*0.1)) + + avgExprVal = [] + if avgExprVal != "" and avgExprVal: + avgExprVal = "%0.5f" % float(avgExprVal) + else: + avgExprVal = "" + + #Mouse Gene + if theGO['mouseGene']: + mouseChr = theGO['mouseGene']["Chromosome"] + mouseTxStart = theGO['mouseGene']["TxStart"] + else: + mouseChr = mouseTxStart = "" + + #the chromosomes for human 1 are 1qXX.XX + if theGO['humanGene']: + humanChr = theGO['humanGene']["Chromosome"] + humanTxStart = theGO['humanGene']["TxStart"] + else: + humanChr = humanTxStart = "" + + geneDesc = theGO["GeneDescription"] + if geneDesc == "---": + geneDesc = "" + + this_row = [selectCheck.__str__(), + str(gIndex+1), + webqtlSearch.__str__() + geneSymbolNCBI, + theGO["TxStart"], + HT.Href(geneLengthURL, "%0.3f" % (geneLength*1000.0)).__str__(), + avgExprVal, + mouseChr, + mouseTxStart, + humanChr, + humanTxStart, + geneDesc] + + gene_table_body.append(this_row) + + return gene_table_body + + def getLiteratureCorrelation(cursor,geneId1=None,geneId2=None): + if not geneId1 or not geneId2: + return None + if geneId1 == geneId2: + return 1.0 + geneId1 = str(geneId1) + geneId2 = str(geneId2) + lCorr = None + try: + query = 'SELECT Value FROM LCorrRamin3 WHERE GeneId1 = %s and GeneId2 = %s' + for x,y in [(geneId1,geneId2),(geneId2,geneId1)]: + cursor.execute(query,(x,y)) + lCorr = cursor.fetchone() + if lCorr: + lCorr = lCorr[0] + break + except: raise #lCorr = None + return lCorr \ No newline at end of file diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py deleted file mode 100644 index 17089c13..00000000 --- a/wqflask/wqflask/marker_regression/marker_regression.py +++ /dev/null @@ -1,660 +0,0 @@ -from __future__ import absolute_import, print_function, division - -from base.trait import GeneralTrait -from base import data_set #import create_dataset - -from pprint import pformat as pf - -import string -import math -import random -import sys -import datetime -import os -import collections -import uuid - -import rpy2.robjects as ro -import numpy as np - -import cPickle as pickle -import itertools - -import simplejson as json - -from redis import Redis -Redis = Redis() - -from flask import Flask, g - -from base.trait import GeneralTrait -from base import data_set -from base import species -from base import webqtlConfig -from utility import webqtlUtil -from utility import helper_functions -from utility import Plot, Bunch -from utility import temp_data -from utility.benchmark import Bench -from wqflask.marker_regression import gemma_mapping, rqtl_mapping, qtlreaper_mapping, plink_mapping - -from utility.tools import locate, locate_ignore_error, PYLMM_COMMAND, GEMMA_COMMAND, PLINK_COMMAND, TEMPDIR -from utility.external import shell -from base.webqtlConfig import TMPDIR, GENERATED_TEXT_DIR - -import utility.logger -logger = utility.logger.getLogger(__name__ ) - -class MarkerRegression(object): - - def __init__(self, start_vars, temp_uuid): - - helper_functions.get_species_dataset_trait(self, start_vars) - - self.temp_uuid = temp_uuid #needed to pass temp_uuid to gn1 mapping code (marker_regression_gn1.py) - - self.json_data = {} - self.json_data['lodnames'] = ['lod.hk'] - - self.samples = [] # Want only ones with values - self.vals = [] - - all_samples_ordered = self.dataset.group.all_samples_ordered() - primary_sample_names = list(all_samples_ordered) - - for sample in self.dataset.group.samplelist: - # sample is actually the name of an individual - in_trait_data = False - for item in self.this_trait.data: - if self.this_trait.data[item].name == sample: - value = start_vars['value:' + self.this_trait.data[item].name] - self.samples.append(self.this_trait.data[item].name) - self.vals.append(value) - in_trait_data = True - break - if not in_trait_data: - value = start_vars.get('value:' + sample) - if value: - self.samples.append(sample) - self.vals.append(value) - - #ZS: Check if genotypes exist in the DB in order to create links for markers - if "geno_db_exists" in start_vars: - self.geno_db_exists = start_vars['geno_db_exists'] - else: - try: - self.geno_db_exists = "True" - except: - self.geno_db_exists = "False" - - self.mapping_method = start_vars['method'] - if "results_path" in start_vars: - self.mapping_results_path = start_vars['results_path'] - else: - mapping_results_filename = self.dataset.group.name + "_" + ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6)) - self.mapping_results_path = "{}{}.csv".format(webqtlConfig.GENERATED_IMAGE_DIR, mapping_results_filename) - - if start_vars['manhattan_plot'] == "True": - self.manhattan_plot = True - else: - self.manhattan_plot = False - - self.maf = start_vars['maf'] # Minor allele frequency - if "use_loco" in start_vars: - self.use_loco = start_vars['use_loco'] - else: - self.use_loco = None - self.suggestive = "" - self.significant = "" - self.pair_scan = False # Initializing this since it is checked in views to determine which template to use - self.score_type = "LRS" #ZS: LRS or LOD - self.mapping_scale = "physic" - self.num_perm = 0 - self.perm_output = [] - self.bootstrap_results = [] - self.covariates = start_vars['covariates'] if "covariates" in start_vars else None - - #ZS: This is passed to GN1 code for single chr mapping - self.selected_chr = -1 - if "selected_chr" in start_vars: - if int(start_vars['selected_chr']) != -1: #ZS: Needs to be -1 if showing full map; there's probably a better way to fix this - self.selected_chr = int(start_vars['selected_chr']) + 1 - else: - self.selected_chr = int(start_vars['selected_chr']) - if "startMb" in start_vars: - self.startMb = start_vars['startMb'] - if "endMb" in start_vars: - self.endMb = start_vars['endMb'] - if "graphWidth" in start_vars: - self.graphWidth = start_vars['graphWidth'] - if "lrsMax" in start_vars: - self.lrsMax = start_vars['lrsMax'] - if "haplotypeAnalystCheck" in start_vars: - self.haplotypeAnalystCheck = start_vars['haplotypeAnalystCheck'] - if "startMb" in start_vars: #ZS: This is to ensure showGenes, Legend, etc are checked the first time you open the mapping page, since startMb will only not be set during the first load - if "permCheck" in start_vars: - self.permCheck = "ON" - else: - self.permCheck = False - self.num_perm = int(start_vars['num_perm']) - - self.LRSCheck = start_vars['LRSCheck'] - - if "showSNP" in start_vars: - self.showSNP = start_vars['showSNP'] - else: - self.showSNP = False - - if "showGenes" in start_vars: - self.showGenes = start_vars['showGenes'] - else: - self.showGenes = False - - if "viewLegend" in start_vars: - self.viewLegend = start_vars['viewLegend'] - else: - self.viewLegend = False - else: - try: - if int(start_vars['num_perm']) > 0: - self.num_perm = int(start_vars['num_perm']) - except: - self.num_perm = 0 - - if self.num_perm > 0: - self.permCheck = "ON" - else: - self.permCheck = False - self.showSNP = "ON" - self.showGenes = "ON" - self.viewLegend = "ON" - - if 'genofile' in start_vars: - if start_vars['genofile'] != "": - self.genofile_string = start_vars['genofile'] - self.dataset.group.genofile = self.genofile_string.split(":")[0] - self.dataset.group.get_markers() - if self.mapping_method == "gemma": - self.score_type = "-log(p)" - self.manhattan_plot = True - with Bench("Running GEMMA"): - marker_obs = gemma_mapping.run_gemma(self.dataset, self.samples, self.vals, self.covariates, self.use_loco, self.maf) - results = marker_obs - elif self.mapping_method == "rqtl_plink": - results = self.run_rqtl_plink() - elif self.mapping_method == "rqtl_geno": - self.score_type = "LOD" - self.mapping_scale = "morgan" - self.control_marker = start_vars['control_marker'] - self.do_control = start_vars['do_control'] - self.method = start_vars['mapmethod_rqtl_geno'] - self.model = start_vars['mapmodel_rqtl_geno'] - #if start_vars['pair_scan'] == "true": - # self.pair_scan = True - if self.permCheck and self.num_perm > 0: - self.perm_output, self.suggestive, self.significant, results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan) - else: - results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan) - elif self.mapping_method == "reaper": - if "startMb" in start_vars: #ZS: Check if first time page loaded, so it can default to ON - if "additiveCheck" in start_vars: - self.additiveCheck = start_vars['additiveCheck'] - else: - self.additiveCheck = False - - if "bootCheck" in start_vars: - self.bootCheck = "ON" - else: - self.bootCheck = False - self.num_bootstrap = int(start_vars['num_bootstrap']) - else: - self.additiveCheck = "ON" - try: - if int(start_vars['num_bootstrap']) > 0: - self.bootCheck = "ON" - self.num_bootstrap = int(start_vars['num_bootstrap']) - else: - self.bootCheck = False - self.num_bootstrap = 0 - except: - self.bootCheck = False - self.num_bootstrap = 0 - - self.control_marker = start_vars['control_marker'] - self.do_control = start_vars['do_control'] - logger.info("Running qtlreaper") - results, self.json_data, self.perm_output, self.suggestive, self.significant, self.bootstrap_results = qtlreaper_mapping.gen_reaper_results(self.this_trait, - self.dataset, - self.samples, - self.vals, - self.json_data, - self.num_perm, - self.bootCheck, - self.num_bootstrap, - self.do_control, - self.control_marker, - self.manhattan_plot) - elif self.mapping_method == "plink": - self.score_type = "-log(p)" - self.manhattan_plot = True - results = plink_mapping.run_plink(self.this_trait, self.dataset, self.species, self.vals, self.maf) - #results = self.run_plink() - elif self.mapping_method == "pylmm": - logger.debug("RUNNING PYLMM") - if self.num_perm > 0: - self.run_permutations(str(temp_uuid)) - results = self.gen_data(str(temp_uuid)) - else: - logger.debug("RUNNING NOTHING") - - if self.pair_scan == True: - self.qtl_results = [] - highest_chr = 1 #This is needed in order to convert the highest chr to X/Y - for marker in results: - if marker['chr1'] > 0 or marker['chr1'] == "X" or marker['chr1'] == "X/Y": - if marker['chr1'] > highest_chr or marker['chr1'] == "X" or marker['chr1'] == "X/Y": - highest_chr = marker['chr1'] - if 'lod_score' in marker.keys(): - self.qtl_results.append(marker) - - self.trimmed_markers = results - - for qtl in enumerate(self.qtl_results): - self.json_data['chr1'].append(str(qtl['chr1'])) - self.json_data['chr2'].append(str(qtl['chr2'])) - self.json_data['Mb'].append(qtl['Mb']) - self.json_data['markernames'].append(qtl['name']) - - self.js_data = dict( - json_data = self.json_data, - this_trait = self.this_trait.name, - data_set = self.dataset.name, - maf = self.maf, - manhattan_plot = self.manhattan_plot, - mapping_scale = self.mapping_scale, - qtl_results = self.qtl_results - ) - - else: - self.qtl_results = [] - highest_chr = 1 #This is needed in order to convert the highest chr to X/Y - for marker in results: - if marker['chr'] > 0 or marker['chr'] == "X" or marker['chr'] == "X/Y": - if marker['chr'] > highest_chr or marker['chr'] == "X" or marker['chr'] == "X/Y": - highest_chr = marker['chr'] - if ('lod_score' in marker.keys()) or ('lrs_value' in marker.keys()): - self.qtl_results.append(marker) - - with Bench("Exporting Results"): - export_mapping_results(self.dataset, self.this_trait, self.qtl_results, self.mapping_results_path, self.mapping_scale, self.score_type) - - with Bench("Trimming Markers for Figure"): - if len(self.qtl_results) > 30000: - self.qtl_results = trim_markers_for_figure(self.qtl_results) - - with Bench("Trimming Markers for Table"): - self.trimmed_markers = trim_markers_for_table(results) - - if self.mapping_method != "gemma": - self.json_data['chr'] = [] - self.json_data['pos'] = [] - self.json_data['lod.hk'] = [] - self.json_data['markernames'] = [] - - self.json_data['suggestive'] = self.suggestive - self.json_data['significant'] = self.significant - - #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary - for index, qtl in enumerate(self.qtl_results): - #if index<40: - # logger.debug("lod score is:", qtl['lod_score']) - if qtl['chr'] == highest_chr and highest_chr != "X" and highest_chr != "X/Y": - #logger.debug("changing to X") - self.json_data['chr'].append("X") - else: - self.json_data['chr'].append(str(qtl['chr'])) - self.json_data['pos'].append(qtl['Mb']) - if 'lrs_value' in qtl.keys(): - self.json_data['lod.hk'].append(str(qtl['lrs_value'])) - else: - self.json_data['lod.hk'].append(str(qtl['lod_score'])) - self.json_data['markernames'].append(qtl['name']) - - #Get chromosome lengths for drawing the interval map plot - chromosome_mb_lengths = {} - self.json_data['chrnames'] = [] - for key in self.species.chromosomes.chromosomes.keys(): - self.json_data['chrnames'].append([self.species.chromosomes.chromosomes[key].name, self.species.chromosomes.chromosomes[key].mb_length]) - chromosome_mb_lengths[key] = self.species.chromosomes.chromosomes[key].mb_length - - self.js_data = dict( - result_score_type = self.score_type, - json_data = self.json_data, - this_trait = self.this_trait.name, - data_set = self.dataset.name, - maf = self.maf, - manhattan_plot = self.manhattan_plot, - mapping_scale = self.mapping_scale, - chromosomes = chromosome_mb_lengths, - qtl_results = self.qtl_results, - num_perm = self.num_perm, - perm_results = self.perm_output, - ) - - def run_rqtl_plink(self): - # os.chdir("") never do this inside a webserver!! - - output_filename = webqtlUtil.genRandStr("%s_%s_"%(self.dataset.group.name, self.this_trait.name)) - - plink_mapping.gen_pheno_txt_file_plink(self.this_trait, self.dataset, self.vals, pheno_filename = output_filename) - - rqtl_command = './plink --noweb --ped %s.ped --no-fid --no-parents --no-sex --no-pheno --map %s.map --pheno %s/%s.txt --pheno-name %s --maf %s --missing-phenotype -9999 --out %s%s --assoc ' % (self.dataset.group.name, self.dataset.group.name, TMPDIR, plink_output_filename, self.this_trait.name, self.maf, TMPDIR, plink_output_filename) - - os.system(rqtl_command) - - count, p_values = self.parse_rqtl_output(plink_output_filename) - - def run_permutations(self, temp_uuid): - """Runs permutations and gets significant and suggestive LOD scores""" - - top_lod_scores = [] - - #logger.debug("self.num_perm:", self.num_perm) - - for permutation in range(self.num_perm): - - pheno_vector = np.array([val == "x" and np.nan or float(val) for val in self.vals]) - np.random.shuffle(pheno_vector) - - key = "pylmm:input:" + temp_uuid - - if self.dataset.group.species == "human": - p_values, t_stats = self.gen_human_results(pheno_vector, key, temp_uuid) - else: - genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers] - - no_val_samples = self.identify_empty_samples() - trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples) - - genotype_matrix = np.array(trimmed_genotype_data).T - - params = dict(pheno_vector = pheno_vector.tolist(), - genotype_matrix = genotype_matrix.tolist(), - restricted_max_likelihood = True, - refit = False, - temp_uuid = temp_uuid, - - # meta data - timestamp = datetime.datetime.now().isoformat(), - ) - - json_params = json.dumps(params) - Redis.set(key, json_params) - Redis.expire(key, 60*60) - - command = PYLMM_COMMAND+' --key {} --species {}'.format(key,"other") - shell(command) - - json_results = Redis.blpop("pylmm:results:" + temp_uuid, 45*60) - results = json.loads(json_results[1]) - p_values = [float(result) for result in results['p_values']] - - lowest_p_value = 1 - for p_value in p_values: - if p_value < lowest_p_value: - lowest_p_value = p_value - - #logger.debug("lowest_p_value:", lowest_p_value) - top_lod_scores.append(-math.log10(lowest_p_value)) - - #logger.debug("top_lod_scores:", top_lod_scores) - - self.suggestive = np.percentile(top_lod_scores, 67) - self.significant = np.percentile(top_lod_scores, 95) - - def gen_data(self, temp_uuid): - """Generates p-values for each marker""" - - logger.debug("self.vals is:", self.vals) - pheno_vector = np.array([(val == "x" or val == "") and np.nan or float(val) for val in self.vals]) - - #lmm_uuid = str(uuid.uuid4()) - - key = "pylmm:input:" + temp_uuid - logger.debug("key is:", pf(key)) - #with Bench("Loading cache"): - # result = Redis.get(key) - - if self.dataset.group.species == "human": - p_values, t_stats = self.gen_human_results(pheno_vector, key, temp_uuid) - - else: - logger.debug("NOW CWD IS:", os.getcwd()) - genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers] - - no_val_samples = self.identify_empty_samples() - trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples) - - genotype_matrix = np.array(genotype_data).T - - #logger.debug("pheno_vector: ", pf(pheno_vector)) - #logger.debug("genotype_matrix: ", pf(genotype_matrix)) - #logger.debug("genotype_matrix.shape: ", pf(genotype_matrix.shape)) - - #params = {"pheno_vector": pheno_vector, - # "genotype_matrix": genotype_matrix, - # "restricted_max_likelihood": True, - # "refit": False, - # "temp_data": tempdata} - - # logger.debug("genotype_matrix:", str(genotype_matrix.tolist())) - # logger.debug("pheno_vector:", str(pheno_vector.tolist())) - - params = dict(pheno_vector = pheno_vector.tolist(), - genotype_matrix = genotype_matrix.tolist(), - restricted_max_likelihood = True, - refit = False, - temp_uuid = temp_uuid, - - # meta data - timestamp = datetime.datetime.now().isoformat(), - ) - - json_params = json.dumps(params) - #logger.debug("json_params:", json_params) - Redis.set(key, json_params) - Redis.expire(key, 60*60) - logger.debug("before printing command") - - command = PYLMM_COMMAND + ' --key {} --species {}'.format(key, "other") - logger.debug("command is:", command) - logger.debug("after printing command") - - shell(command) - - #t_stats, p_values = lmm.run(key) - #lmm.run(key) - - json_results = Redis.blpop("pylmm:results:" + temp_uuid, 45*60) - results = json.loads(json_results[1]) - p_values = [float(result) for result in results['p_values']] - t_stats = results['t_stats'] - - #t_stats, p_values = lmm.run( - # pheno_vector, - # genotype_matrix, - # restricted_max_likelihood=True, - # refit=False, - # temp_data=tempdata - #) - #logger.debug("p_values:", p_values) - - self.dataset.group.markers.add_pvalues(p_values) - - return self.dataset.group.markers.markers - - def gen_human_results(self, pheno_vector, key, temp_uuid): - file_base = locate(self.dataset.group.name,"mapping") - - plink_input = input.plink(file_base, type='b') - input_file_name = os.path.join(webqtlConfig.SNP_PATH, self.dataset.group.name + ".snps.gz") - - pheno_vector = pheno_vector.reshape((len(pheno_vector), 1)) - covariate_matrix = np.ones((pheno_vector.shape[0],1)) - kinship_matrix = np.fromfile(open(file_base + '.kin','r'),sep=" ") - kinship_matrix.resize((len(plink_input.indivs),len(plink_input.indivs))) - - logger.debug("Before creating params") - - params = dict(pheno_vector = pheno_vector.tolist(), - covariate_matrix = covariate_matrix.tolist(), - input_file_name = input_file_name, - kinship_matrix = kinship_matrix.tolist(), - refit = False, - temp_uuid = temp_uuid, - - # meta data - timestamp = datetime.datetime.now().isoformat(), - ) - - logger.debug("After creating params") - - json_params = json.dumps(params) - Redis.set(key, json_params) - Redis.expire(key, 60*60) - - logger.debug("Before creating the command") - - command = PYLMM_COMMAND+' --key {} --species {}'.format(key, "human") - - logger.debug("command is:", command) - - os.system(command) - - json_results = Redis.blpop("pylmm:results:" + temp_uuid, 45*60) - results = json.loads(json_results[1]) - t_stats = results['t_stats'] - p_values = results['p_values'] - - - #p_values, t_stats = lmm.run_human(key) - - #p_values, t_stats = lmm.run_human( - # pheno_vector, - # covariate_matrix, - # input_file_name, - # kinship_matrix, - # loading_progress=tempdata - # ) - - return p_values, t_stats - - def identify_empty_samples(self): - no_val_samples = [] - for sample_count, val in enumerate(self.vals): - if val == "x": - no_val_samples.append(sample_count) - return no_val_samples - - def trim_genotypes(self, genotype_data, no_value_samples): - trimmed_genotype_data = [] - for marker in genotype_data: - new_genotypes = [] - for item_count, genotype in enumerate(marker): - if item_count in no_value_samples: - continue - try: - genotype = float(genotype) - except ValueError: - genotype = np.nan - pass - new_genotypes.append(genotype) - trimmed_genotype_data.append(new_genotypes) - return trimmed_genotype_data - -def export_mapping_results(dataset, trait, markers, results_path, mapping_scale, score_type): - with open(results_path, "w+") as output_file: - output_file.write("Population: " + dataset.group.species.title() + " " + dataset.group.name + "\n") - output_file.write("Data Set: " + dataset.fullname + "\n") - if dataset.type == "ProbeSet": - output_file.write("Gene Symbol: " + trait.symbol + "\n") - output_file.write("Location: " + str(trait.chr) + " @ " + str(trait.mb) + " Mb\n") - output_file.write("\n") - output_file.write("Name,Chr,") - if mapping_scale == "physic": - output_file.write("Mb," + score_type) - else: - output_file.write("Cm," + score_type) - if "additive" in markers[0].keys(): - output_file.write(",Additive") - if "dominance" in markers[0].keys(): - output_file.write(",Dominance") - output_file.write("\n") - for i, marker in enumerate(markers): - output_file.write(marker['name'] + "," + str(marker['chr']) + "," + str(marker['Mb']) + ",") - if "lod_score" in marker.keys(): - output_file.write(str(marker['lod_score'])) - else: - output_file.write(str(marker['lrs_value'])) - if "additive" in marker.keys(): - output_file.write("," + str(marker['additive'])) - if "dominance" in marker.keys(): - output_file.write("," + str(marker['dominance'])) - if i < (len(markers) - 1): - output_file.write("\n") - -def trim_markers_for_figure(markers): - if 'lod_score' in markers[0].keys(): - score_type = 'lod_score' - else: - score_type = 'lrs_value' - - filtered_markers = [] - low_counter = 0 - med_counter = 0 - high_counter = 0 - for marker in markers: - if score_type == 'lod_score': - if marker[score_type] < 1: - if low_counter % 20 == 0: - filtered_markers.append(marker) - low_counter += 1 - elif 1 <= marker[score_type] < 2: - if med_counter % 10 == 0: - filtered_markers.append(marker) - med_counter += 1 - elif 2 <= marker[score_type] <= 3: - if high_counter % 2 == 0: - filtered_markers.append(marker) - high_counter += 1 - else: - filtered_markers.append(marker) - else: - if marker[score_type] < 4.16: - if low_counter % 20 == 0: - filtered_markers.append(marker) - low_counter += 1 - elif 4.16 <= marker[score_type] < (2*4.16): - if med_counter % 10 == 0: - filtered_markers.append(marker) - med_counter += 1 - elif (2*4.16) <= marker[score_type] <= (3*4.16): - if high_counter % 2 == 0: - filtered_markers.append(marker) - high_counter += 1 - else: - filtered_markers.append(marker) - return filtered_markers - -def trim_markers_for_table(markers): - if 'lod_score' in markers[0].keys(): - sorted_markers = sorted(markers, key=lambda k: k['lod_score'], reverse=True) - else: - sorted_markers = sorted(markers, key=lambda k: k['lrs_value'], reverse=True) - - #ZS: So we end up with a list of just 200 markers - if len(sorted_markers) >= 200: - trimmed_sorted_markers = sorted_markers[:200] - return trimmed_sorted_markers - else: - return sorted_markers \ No newline at end of file diff --git a/wqflask/wqflask/marker_regression/marker_regression_gn1.py b/wqflask/wqflask/marker_regression/marker_regression_gn1.py deleted file mode 100644 index 21dd897a..00000000 --- a/wqflask/wqflask/marker_regression/marker_regression_gn1.py +++ /dev/null @@ -1,2245 +0,0 @@ -# Copyright (C) University of Tennessee Health Science Center, Memphis, TN. -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero General Public License -# as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU Affero General Public License for more details. -# -# This program is available from Source Forge: at GeneNetwork Project -# (sourceforge.net/projects/genenetwork/). -# -# Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) -# at rwilliams@uthsc.edu and xzhou15@uthsc.edu -# -# -# -# This module is used by GeneNetwork project (www.genenetwork.org) -# -# Created by GeneNetwork Core Team 2010/08/10 -# -# Last updated by Zach 12/14/2010 - -import time -import string -from math import * -import piddle as pid -import sys,os -import cPickle -import httplib - -from flask import Flask, g - -from htmlgen import HTMLgen2 as HT - -from base import webqtlConfig -from base.GeneralObject import GeneralObject -from utility import webqtlUtil -from utility import helper_functions -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 - -import utility.logger -logger = utility.logger.getLogger(__name__ ) - -######################################### -# Inteval Mapping Plot Page -######################################### -class MarkerRegression(object): - cMGraphInterval = 5 - GRAPH_MIN_WIDTH = 900 - GRAPH_MAX_WIDTH = 10000 # Don't set this too high - GRAPH_DEFAULT_WIDTH = 1280 - MULT_GRAPH_DEFAULT_WIDTH = 2000 - MULT_GRAPH_MIN_WIDTH = 1400 - MULT_GRAPH_DEFAULT_WIDTH = 1600 - GRAPH_DEFAULT_HEIGHT = 600 - - - # Display order: - # UCSC BAND ========= - # ENSEMBL BAND -=-=-= - # ** GENES ********** - BAND_SPACING = 4 - - BAND_HEIGHT = 10 - BAND_HEIGHT = 10 - BAND_HEIGHT = 10 - - NUM_GENE_ROWS = 10 - EACH_GENE_HEIGHT = 6 # number of pixels tall, for each gene to display - EACH_GENE_ARROW_WIDTH = 5 - EACH_GENE_ARROW_SPACING = 14 - DRAW_DETAIL_MB = 4 - DRAW_UTR_LABELS_MB = 4 - - qmarkImg = HT.Image('/images/qmarkBoxBlue.gif', width=10, height=13, border=0, alt='Glossary') - # Note that "qmark.gif" is a similar, smaller, rounded-edges question mark. It doesn't look - # like the ones on the image, though, which is why we don't use it here. - - HELP_WINDOW_NAME = 'helpWind' - - ## BEGIN HaplotypeAnalyst - NR_INDIVIDUALS = 0 - ## END HaplotypeAnalyst - - ALEX_DEBUG_BOOL_PRINT_GENE_LIST = 1 - - kONE_MILLION = 1000000 - - LODFACTOR = 4.61 - - SNP_COLOR = pid.orange # Color for the SNP "seismograph" - TRANSCRIPT_LOCATION_COLOR = pid.mediumpurple - - BOOTSTRAP_BOX_COLOR = pid.yellow - LRS_COLOR = pid.HexColor(0x0000FF) - SIGNIFICANT_COLOR = pid.HexColor(0xEBC7C7) - SUGGESTIVE_COLOR = pid.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 - - ## BEGIN HaplotypeAnalyst - HAPLOTYPE_POSITIVE = pid.green - HAPLOTYPE_NEGATIVE = pid.red - HAPLOTYPE_HETEROZYGOUS = pid.blue - HAPLOTYPE_RECOMBINATION = pid.darkgray - ## END HaplotypeAnalyst - - TOP_RIGHT_INFO_COLOR = pid.black - - CLICKABLE_WEBQTL_REGION_COLOR = pid.HexColor(0xF5D3D3) - CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR = pid.HexColor(0xFCE9E9) - CLICKABLE_WEBQTL_TEXT_COLOR = pid.HexColor(0x912828) - - CLICKABLE_PHENOGEN_REGION_COLOR = pid.HexColor(0xA2FB94) - CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR = pid.HexColor(0xCEFEC7) - CLICKABLE_PHENOGEN_TEXT_COLOR = pid.HexColor(0x1FD504) - - CLICKABLE_UCSC_REGION_COLOR = pid.HexColor(0xDDDDEE) - CLICKABLE_UCSC_REGION_OUTLINE_COLOR = pid.HexColor(0xEDEDFF) - CLICKABLE_UCSC_TEXT_COLOR = pid.HexColor(0x333366) - - CLICKABLE_ENSEMBL_REGION_COLOR = pid.HexColor(0xEEEEDD) - CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR = pid.HexColor(0xFEFEEE) - CLICKABLE_ENSEMBL_TEXT_COLOR = pid.HexColor(0x555500) - - GRAPH_BACK_LIGHT_COLOR = pid.HexColor(0xFBFBFF) - GRAPH_BACK_DARK_COLOR = pid.HexColor(0xF1F1F9) - - HELP_PAGE_REF = '/glossary.html' - - def __init__(self, start_vars): - logger.info("Running qtlreaper") - - self.temp_uuid = start_vars['temp_uuid'] - - self.dataset = start_vars['dataset'] - self.this_trait = start_vars['this_trait'] - self.species = start_vars['species'] - if 'genofile_string' in start_vars: - self.genofile_string = start_vars['genofile_string'] - - self.geno_db_exists = start_vars['geno_db_exists'] - - #Needing for form submission when doing single chr mapping or remapping after changing options - self.samples = start_vars['samples'] - self.vals = start_vars['vals'] - self.mapping_method = start_vars['mapping_method'] - self.mapping_results_path = start_vars['mapping_results_path'] - if self.mapping_method == "rqtl_geno": - self.mapmethod_rqtl_geno = start_vars['method'] - self.mapmodel_rqtl_geno = start_vars['model'] - self.pair_scan = start_vars['pair_scan'] - - if self.mapping_method != "gemma" and self.mapping_method != "plink": - self.js_data = start_vars['js_data'] - self.trimmed_markers = start_vars['trimmed_markers'] #Top markers to display in table - - if self.dataset.group.species == "rat": - self._ucscDb = "rn3" - elif self.dataset.group.species == "mouse": - self._ucscDb = "mm9" - else: - self._ucscDb = "" - - ##################################### - # Options - ##################################### - #Mapping options - if start_vars['mapping_scale'] != "": - self.plotScale = start_vars['mapping_scale'] - else: - self.plotScale = "physic" - - self.manhattan_plot = start_vars['manhattan_plot'] - - if 'permCheck' in start_vars.keys(): - self.permChecked = start_vars['permCheck'] - else: - self.permChecked = False - if start_vars['num_perm'] > 0: - self.nperm = int(start_vars['num_perm']) - if self.permChecked: - self.perm_output = start_vars['perm_output'] - self.suggestive = start_vars['suggestive'] - self.significant = start_vars['significant'] - else: - self.nperm = 0 - - if 'bootCheck' in start_vars.keys(): - self.bootChecked = start_vars['bootCheck'] - else: - self.bootChecked = False - if 'num_bootstrap' in start_vars.keys(): - self.nboot = int(start_vars['num_bootstrap']) - else: - self.nboot = 0 - if 'bootstrap_results' in start_vars.keys(): - self.bootResult = start_vars['bootstrap_results'] - else: - self.bootResult = [] - - if 'do_control' in start_vars.keys(): - self.doControl = start_vars['do_control'] - else: - self.doControl = "false" - if 'control_marker' in start_vars.keys(): - self.controlLocus = start_vars['control_marker'] - else: - self.controlLocus = "" - if 'covariates' in start_vars.keys(): - self.covariates = start_vars['covariates'] - if 'maf' in start_vars.keys(): - self.maf = start_vars['maf'] - if 'use_loco' in start_vars.keys(): - self.use_loco = start_vars['use_loco'] - - self.selectedChr = int(start_vars['selected_chr']) - - self.strainlist = self.dataset.group.samplelist - self.genotype = self.dataset.group.read_genotype_file() - if self.mapping_method == "reaper" and self.manhattan_plot != True: - self.genotype = self.genotype.addinterval() - - #Darwing Options - try: - if self.selectedChr > -1: - self.graphWidth = min(self.GRAPH_MAX_WIDTH, max(self.GRAPH_MIN_WIDTH, int(start_vars['graphWidth']))) - else: - self.graphWidth = min(self.GRAPH_MAX_WIDTH, max(self.MULT_GRAPH_MIN_WIDTH, int(start_vars['graphWidth']))) - except: - if self.selectedChr > -1: - self.graphWidth = self.GRAPH_DEFAULT_WIDTH - else: - self.graphWidth = self.MULT_GRAPH_DEFAULT_WIDTH - -## BEGIN HaplotypeAnalyst - if 'haplotypeAnalystCheck' in start_vars.keys(): - self.haplotypeAnalystChecked = start_vars['haplotypeAnalystCheck'] - else: - self.haplotypeAnalystChecked = False -## END HaplotypeAnalyst - - self.graphHeight = self.GRAPH_DEFAULT_HEIGHT - self.dominanceChecked = False - if 'LRSCheck' in start_vars.keys(): - self.LRS_LOD = start_vars['LRSCheck'] - else: - self.LRS_LOD = start_vars['score_type'] - self.intervalAnalystChecked = True - self.draw2X = False - if 'additiveCheck' in start_vars.keys(): - self.additiveChecked = start_vars['additiveCheck'] - else: - self.additiveChecked = False - if 'viewLegend' in start_vars.keys(): - self.legendChecked = start_vars['viewLegend'] - else: - self.legendChecked = False - if 'showSNP' in start_vars.keys(): - self.SNPChecked = start_vars['showSNP'] - else: - self.SNPChecked = False - if 'showGenes' in start_vars.keys(): - self.geneChecked = start_vars['showGenes'] - else: - self.geneChecked = False - try: - self.startMb = float(start_vars['startMb']) - except: - self.startMb = -1 - try: - self.endMb = float(start_vars['endMb']) - except: - self.endMb = -1 - try: - self.lrsMax = float(start_vars['lrsMax']) - except: - self.lrsMax = 0 - - #Trait Infos - self.identification = "" - - ################################################################ - # Generate Chr list and Retrieve Length Information - ################################################################ - self.ChrList = [("All", -1)] - for i, indChr in enumerate(self.genotype): - self.ChrList.append((indChr.name, i)) - - - - self.ChrLengthMbList = g.db.execute(""" - Select - Length from Chr_Length, InbredSet - where - Chr_Length.SpeciesId = InbredSet.SpeciesId AND - InbredSet.Name = '%s' AND - Chr_Length.Name in (%s) - Order by - Chr_Length.OrderId - """ % (self.dataset.group.name, string.join(map(lambda X: "'%s'" % X[0], self.ChrList[1:]), ", "))) - - self.ChrLengthMbList = map(lambda x: x[0]/1000000.0, self.ChrLengthMbList) - self.ChrLengthMbSum = reduce(lambda x, y:x+y, self.ChrLengthMbList, 0.0) - if self.ChrLengthMbList: - self.MbGraphInterval = self.ChrLengthMbSum/(len(self.ChrLengthMbList)*12) #Empirical Mb interval - else: - self.MbGraphInterval = 1 - - self.ChrLengthCMList = [] - for i, _chr in enumerate(self.genotype): - self.ChrLengthCMList.append(_chr[-1].cM - _chr[0].cM) - self.ChrLengthCMSum = reduce(lambda x, y:x+y, self.ChrLengthCMList, 0.0) - - if self.plotScale == 'physic': - self.GraphInterval = self.MbGraphInterval #Mb - else: - self.GraphInterval = self.cMGraphInterval #cM - - self.traitList = [] - thisTrait = start_vars['this_trait'] - self.traitList.append(thisTrait) - -## BEGIN HaplotypeAnalyst -## count the amount of individuals to be plotted, and increase self.graphHeight - if self.haplotypeAnalystChecked and self.selectedChr > -1: - #thisTrait = self.traitList[0] - thisTrait = self.this_trait - _strains, _vals, _vars, _aliases = thisTrait.export_informative() - smd=[] - for ii, _val in enumerate(_vals): - temp = GeneralObject(name=_strains[ii], value=_val) - smd.append(temp) - samplelist = list(self.genotype.prgy) - for j,_geno in enumerate (self.genotype[0][1].genotype): - for item in smd: - if item.name == samplelist[j]: - self.NR_INDIVIDUALS = self.NR_INDIVIDUALS + 1 -# default: - self.graphHeight = self.graphHeight + 2 * (self.NR_INDIVIDUALS+10) * self.EACH_GENE_HEIGHT -## END HaplotypeAnalyst - - ################################################################ - # Calculations QTL goes here - ################################################################ - self.multipleInterval = len(self.traitList) > 1 - self.qtlresults = start_vars['qtl_results'] - - if self.multipleInterval: - self.colorCollection = Plot.colorSpectrum(len(self.qtlresults)) - else: - self.colorCollection = [self.LRS_COLOR] - - - ######################### - ## Get the sorting column - ######################### - RISet = self.dataset.group.name - if RISet in ('AXB', 'BXA', 'AXBXA'): - self.diffCol = ['B6J', 'A/J'] - elif RISet in ('BXD', 'BXD300', 'B6D2F2', 'BDF2-2005', 'BDF2-1999', 'BHHBF2'): - self.diffCol = ['B6J', 'D2J'] - elif RISet in ('CXB'): - self.diffCol = ['CBY', 'B6J'] - elif RISet in ('BXH', 'BHF2'): - self.diffCol = ['B6J', 'C3H'] - elif RISet in ('B6BTBRF2'): - self.diffCol = ['B6J', 'BTB'] - elif RISet in ('LXS'): - self.diffCol = ['ILS', 'ISS'] - else: - self.diffCol= [] - - for i, strain in enumerate(self.diffCol): - self.diffCol[i] = g.db.execute("select Id from Strain where Symbol = %s", strain).fetchone()[0] - - ################################################################ - # GeneCollection goes here - ################################################################ - if self.plotScale == 'physic' and self.selectedChr != -1: - #StartMb or EndMb - if self.startMb < 0 or self.endMb < 0: - self.startMb = 0 - self.endMb = self.ChrLengthMbList[self.selectedChr - 1] - - geneTable = "" - - self.geneCol = None - if self.plotScale == 'physic' and self.selectedChr > -1 and (self.intervalAnalystChecked or self.geneChecked): - # Draw the genes for this chromosome / region of this chromosome - webqtldatabase = self.dataset.name - - if self.dataset.group.species == "mouse": - if self.selectedChr == 20: - chrName = "X" - else: - chrName = self.selectedChr - self.geneCol = GeneUtil.loadGenes(chrName, self.diffCol, self.startMb, self.endMb, "mouse") - elif self.dataset.group.species == "rat": - if self.selectedChr == 21: - chrName = "X" - else: - chrName = self.selectedChr - self.geneCol = GeneUtil.loadGenes(chrName, self.diffCol, self.startMb, self.endMb, "rat") - - if self.geneCol and self.intervalAnalystChecked: - ####################################################################### - #Nick use GENEID as RefGene to get Literature Correlation Informations# - #For Interval Mapping, Literature Correlation isn't useful, so skip it# - #through set GENEID is None # - ####################################################################### - - GENEID = None - - self.geneTable(self.geneCol, GENEID) - - ################################################################ - # Plots goes here - ################################################################ - showLocusForm = "" - intCanvas = pid.PILCanvas(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') - 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)) - 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') - - ################################################################ - # Outputs goes here - ################################################################ - #this form is used for opening Locus page or trait page, only available for genetic mapping - if showLocusForm: - showLocusForm = HT.Form(cgi= os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE), enctype='multipart/form-data', - name=showLocusForm, submit=HT.Input(type='hidden')) - hddn = {'FormID':'showDatabase', 'ProbeSetID':'_','database':fd.RISet+"Geno",'CellID':'_', 'RISet':fd.RISet, 'incparentsf1':'ON'} - for key in hddn.keys(): - showLocusForm.append(HT.Input(name=key, value=hddn[key], type='hidden')) - showLocusForm.append(intImg) - else: - showLocusForm = intImg - - if (self.permChecked and self.nperm > 0) and not (self.multipleInterval and 0 < self.nperm): - self.perm_filename = self.drawPermutationHistogram() - - ################################################################ - # footnote goes here - ################################################################ - btminfo = HT.Paragraph(Id="smallsize") #Small('More information about this graph is available here.') - - if self.traitList and self.traitList[0].dataset and self.traitList[0].dataset.type == 'Geno': - 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 = ""): - #calculating margins - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - if self.multipleInterval: - yTopOffset = max(80, yTopOffset) - else: - if self.legendChecked: - yTopOffset = max(80, yTopOffset) - else: - pass - - if self.plotScale != 'physic': - yBottomOffset = max(120, yBottomOffset) - fontZoom = zoom - if zoom == 2: - xLeftOffset += 20 - fontZoom = 1.5 - - xLeftOffset = int(xLeftOffset*fontZoom) - xRightOffset = int(xRightOffset*fontZoom) - yBottomOffset = int(yBottomOffset*fontZoom) - - cWidth = canvas.size[0] - cHeight = canvas.size[1] - plotWidth = cWidth - xLeftOffset - xRightOffset - plotHeight = cHeight - yTopOffset - yBottomOffset - - #Drawing Area Height - drawAreaHeight = plotHeight - if self.plotScale == 'physic' and self.selectedChr > -1: - if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": - drawAreaHeight -= 4*self.BAND_HEIGHT + 4*self.BAND_SPACING+ 10*zoom - else: - drawAreaHeight -= 3*self.BAND_HEIGHT + 3*self.BAND_SPACING+ 10*zoom - if self.geneChecked: - drawAreaHeight -= self.NUM_GENE_ROWS*self.EACH_GENE_HEIGHT + 3*self.BAND_SPACING + 10*zoom - else: - if self.selectedChr > -1: - drawAreaHeight -= 20 - else: - drawAreaHeight -= 30 - -## BEGIN HaplotypeAnalyst - if self.haplotypeAnalystChecked and self.selectedChr > -1: - drawAreaHeight -= self.EACH_GENE_HEIGHT * (self.NR_INDIVIDUALS+10) * 2 * zoom -## END HaplotypeAnalyst - - if zoom == 2: - drawAreaHeight -= 60 - - #Image map - gifmap = HT.Map(name = "WebQTLImageMap") - - newoffset = (xLeftOffset, xRightOffset, yTopOffset, yBottomOffset) - # Draw the alternating-color background first and get plotXScale - plotXScale = self.drawGraphBackground(canvas, gifmap, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb) - - #draw bootstap - if self.bootChecked and not self.multipleInterval and not self.manhattan_plot: - self.drawBootStrapResult(canvas, self.nboot, drawAreaHeight, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb) - - # Draw clickable region and gene band if selected - if self.plotScale == 'physic' and self.selectedChr > -1: - self.drawClickBand(canvas, gifmap, plotXScale, offset=newoffset, zoom = zoom, startMb=startMb, endMb = endMb) - if self.geneChecked and self.geneCol: - self.drawGeneBand(canvas, gifmap, plotXScale, offset=newoffset, zoom = zoom, startMb=startMb, endMb = endMb) - if self.SNPChecked: - self.drawSNPTrackNew(canvas, offset=newoffset, zoom = 2*zoom, startMb=startMb, endMb = endMb) -## BEGIN HaplotypeAnalyst - if self.haplotypeAnalystChecked: - self.drawHaplotypeBand(canvas, gifmap, plotXScale, offset=newoffset, zoom = zoom, startMb=startMb, endMb = endMb) -## END HaplotypeAnalyst - # Draw X axis - self.drawXAxis(canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset=newoffset, zoom = zoom, startMb=startMb, endMb = endMb) - # Draw QTL curve - self.drawQTL(canvas, drawAreaHeight, gifmap, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb) - - #draw legend - if self.multipleInterval: - self.drawMultiTraitName(fd, canvas, gifmap, showLocusForm, offset=newoffset) - elif self.legendChecked: - self.drawLegendPanel(canvas, offset=newoffset, zoom = zoom) - else: - pass - - #draw position, no need to use a separate function - self.drawProbeSetPosition(canvas, plotXScale, offset=newoffset, zoom = zoom) - - return gifmap - - def drawBootStrapResult(self, canvas, nboot, drawAreaHeight, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yZero = canvas.size[1] - yBottomOffset - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - - bootHeightThresh = drawAreaHeight*3/4 - - #break bootstrap result into groups - BootCoord = [] - i = 0 - startX = xLeftOffset - - if self.selectedChr == -1: #ZS: If viewing full genome/all chromosomes - for j, _chr in enumerate(self.genotype): - BootCoord.append( []) - for _locus in _chr: - if self.plotScale == 'physic': - Xc = startX + (_locus.Mb-self.startMb)*plotXScale - else: - Xc = startX + (_locus.cM-_chr[0].cM)*plotXScale - BootCoord[-1].append([Xc, self.bootResult[i]]) - i += 1 - startX += (self.ChrLengthDistList[j] + self.GraphInterval)*plotXScale - else: - for j, _chr in enumerate(self.genotype): - if _chr.name == self.ChrList[self.selectedChr][0]: - BootCoord.append( []) - for _locus in _chr: - if _chr.name == self.ChrList[self.selectedChr][0]: - if self.plotScale == 'physic': - Xc = startX + (_locus.Mb-startMb)*plotXScale - else: - Xc = startX + (_locus.cM-_chr[0].cM)*plotXScale - BootCoord[-1].append([Xc, self.bootResult[i]]) - i += 1 - - #reduce bootResult - if self.selectedChr > -1: - maxBootBar = 80.0 - else: - maxBootBar = 200.0 - stepBootStrap = plotWidth/maxBootBar - reducedBootCoord = [] - maxBootCount = 0 - - for BootChrCoord in BootCoord: - nBoot = len(BootChrCoord) - bootStartPixX = BootChrCoord[0][0] - bootCount = BootChrCoord[0][1] - for i in range(1, nBoot): - if BootChrCoord[i][0] - bootStartPixX < stepBootStrap: - bootCount += BootChrCoord[i][1] - continue - else: - if maxBootCount < bootCount: - maxBootCount = bootCount - # end if - reducedBootCoord.append([bootStartPixX, BootChrCoord[i][0], bootCount]) - bootStartPixX = BootChrCoord[i][0] - bootCount = BootChrCoord[i][1] - # end else - # end for - #add last piece - if BootChrCoord[-1][0] - bootStartPixX > stepBootStrap/2.0: - reducedBootCoord.append([bootStartPixX, BootChrCoord[-1][0], bootCount]) - else: - reducedBootCoord[-1][2] += bootCount - reducedBootCoord[-1][1] = BootChrCoord[-1][0] - # end else - if maxBootCount < reducedBootCoord[-1][2]: - maxBootCount = reducedBootCoord[-1][2] - # end if - for item in reducedBootCoord: - if item[2] > 0: - if item[0] < xLeftOffset: - item[0] = xLeftOffset - if item[0] > xLeftOffset+plotWidth: - item[0] = xLeftOffset+plotWidth - if item[1] < xLeftOffset: - item[1] = xLeftOffset - 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) - - ###draw boot scale - highestPercent = (maxBootCount*100.0)/nboot - bootScale = Plot.detScale(0, highestPercent) - bootScale = Plot.frange(bootScale[0], bootScale[1], bootScale[1]/bootScale[2]) - 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) - 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) - - if self.legendChecked: - startPosY = 30 - nCol = 2 - smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1) - 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) - - def drawProbeSetPosition(self, canvas, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): - if len(self.traitList) != 1: - return - - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yZero = canvas.size[1] - yBottomOffset - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - - try: - Chr = self.traitList[0].chr - Mb = self.traitList[0].mb - except: - return - - previous_chr = 1 - previous_chr_as_int = 0 - if self.plotScale == "physic": - this_chr = str(self.ChrList[self.selectedChr][0]) - else: - this_chr = str(self.ChrList[self.selectedChr][1]+1) - - if self.plotScale == 'physic': - if self.selectedChr > -1: - if this_chr != Chr or Mb < self.startMb or Mb > self.endMb: - return - else: - locPixel = xLeftOffset + (Mb-self.startMb)*plotXScale - else: - locPixel = xLeftOffset - for i, _chr in enumerate(self.ChrList[1:]): - if _chr[0] != Chr: - locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale - else: - locPixel += Mb*plotXScale - break - else: - if self.selectedChr > -1: - for i, qtlresult in enumerate(self.qtlresults): - if qtlresult['chr'] != self.selectedChr: - continue - - if i==0 and qtlresult['Mb'] >= Mb: - locPixel=-1 - break - - #the trait's position is between two traits - if i > 0 and self.qtlresults[i-1]['Mb'] < Mb and qtlresult['Mb'] >= Mb: - locPixel = xLeftOffset + plotXScale*(self.qtlresults[i-1]['Mb']+(qtlresult['Mb']-self.qtlresults[i-1]['Mb'])*(Mb - self.qtlresults[i-1]['Mb'])/(qtlresult['Mb']-self.qtlresults[i-1]['Mb'])) - break - - #the trait's position is on the right of the last genotype - if i==len(self.qtlresults) and Mb>=qtlresult['Mb']: - locPixel = -1 - else: - locPixel = xLeftOffset - for i, _chr in enumerate(self.ChrList): - if i < (len(self.ChrList)-1): - if _chr != Chr: - locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale - else: - locPixel += (Mb*(_chr[-1].cM-_chr[0].cM)/self.ChrLengthCMList[i])*plotXScale - break - if locPixel >= 0 and self.plotScale == 'physic': - traitPixel = ((locPixel, yZero), (locPixel-6, yZero+12), (locPixel+6, yZero+12)) - canvas.drawPolygon(traitPixel, edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) - - if self.legendChecked: - startPosY = 15 - nCol = 2 - smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1) - if self.manhattan_plot: - leftOffset = xLeftOffset - else: - leftOffset = xLeftOffset+(nCol-1)*200*fontZoom - canvas.drawPolygon(((leftOffset+6, startPosY-6), (leftOffset, startPosY+6), (leftOffset+12, startPosY+6)), edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) - canvas.drawString("Sequence Site", (leftOffset+15), (startPosY+5), smallLabelFont, self.TOP_RIGHT_INFO_COLOR) - - def drawSNPTrackNew(self, canvas, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): - if self.plotScale != 'physic' or self.selectedChr == -1 or not self.diffCol: - return - - SNP_HEIGHT_MODIFIER = 18.0 - - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yZero = canvas.size[1] - yBottomOffset - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - - drawSNPLocationY = yTopOffset + plotHeight - chrName = self.genotype[0].name - - stepMb = (endMb-startMb)/plotWidth - strainId1, strainId2 = self.diffCol - SNPCounts = [] - - while startMb= %2.6f AND Mb < %2.6f AND - StrainId1 = %d AND StrainId2 = %d - """ % (chrName, startMb, startMb+stepMb, strainId1, strainId2)).fetchone()[0] - SNPCounts.append(snp_count) - startMb += stepMb - - if (len(SNPCounts) > 0): - maxCount = max(SNPCounts) - 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) - - 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) - if len(self.qtlresults) >20 and self.selectedChr > -1: - rightShift = 20 - rightShiftStep = 60 - rectWidth = 10 - else: - rightShift = 40 - rightShiftStep = 80 - rectWidth = 15 - - for k, thisTrait in enumerate(self.traitList): - thisLRSColor = self.colorCollection[k] - kstep = k % 4 - if k!=0 and kstep==0: - if nameWidths: - rightShiftStep = max(nameWidths[-4:]) + rectWidth + 20 - rightShift += rightShiftStep - - name = thisTrait.displayName() - nameWidth = canvas.stringWidth(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) - 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) - Areas = HT.Area(shape='rect',coords=COORDS,href=HREF) - gifmap.areas.append(Areas) - - def drawLegendPanel(self, canvas, offset= (40, 120, 80, 10), zoom = 1): - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yZero = canvas.size[1] - yBottomOffset - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - - labelFont=pid.Font(ttf="trebuc",size=12*fontZoom, bold=1) - 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) - 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) - - 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) - - 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) - - 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 - if self.selectedChr == -1: - string1 = 'Mapping for Dataset: %s, mapping on All Chromosomes' % self.dataset.group.name - else: - string1 = 'Mapping for Dataset: %s, mapping on Chromosome %s' % (self.dataset.group.name, self.ChrList[self.selectedChr][0]) - - string3 = '' - if self.mapping_method == "gemma" or self.mapping_method == "gemma_bimbam": - if self.use_loco == "True": - string2 = 'Using GEMMA mapping method with LOCO and ' - else: - string2 = 'Using GEMMA mapping method with ' - if self.covariates != "": - string2 += 'the cofactors below:' - cofactor_names = ", ".join([covar.split(":")[0] for covar in self.covariates.split(",")]) - string3 = cofactor_names - else: - string2 += 'no cofactors' - elif self.mapping_method == "rqtl_plink" or self.mapping_method == "rqtl_geno": - string2 = 'Using R/qtl mapping method with ' - if self.controlLocus and self.doControl != "false": - string2 += '%s as control' % self.controlLocus - else: - string2 += 'no control for other QTLs' - elif self.mapping_method == "plink": - string2 = 'Using PLINK mapping method with no control for other QTLs' - else: - string2 = 'Using Haldane mapping function with ' - if self.controlLocus and self.doControl != "false": - string2 += '%s as control' % self.controlLocus - else: - string2 += 'no control for other QTLs' - - if self.this_trait.name: - if self.this_trait.symbol: - identification = "Trait ID: %s : %s : %s" % (self.this_trait.symbol, self.dataset.fullname, self.this_trait.name) - else: - identification = "Trait ID: %s : %s" % (self.dataset.fullname, self.this_trait.name) - 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) - if string3 != '': - canvas.drawString(string3,canvas.size[0] - xRightOffset-d,65*fontZoom,font=labelFont,color=labelColor) - - - def drawGeneBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): - if self.plotScale != 'physic' or self.selectedChr == -1 or not self.geneCol: - return - - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yZero = canvas.size[1] - yBottomOffset - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - - yPaddingTop = yTopOffset - - for gIndex, theGO in enumerate(self.geneCol): - geneNCBILink = 'http://www.ncbi.nlm.nih.gov/gene?term=%s' - if self.dataset.group.species == "mouse": - txStart = theGO["TxStart"] - txEnd = theGO["TxEnd"] - geneLength = (txEnd - txStart)*1000.0 - tenPercentLength = geneLength*0.0001 - SNPdensity = theGO["snpCount"]/geneLength - - exonStarts = map(float, theGO['exonStarts'].split(",")[:-1]) - exonEnds = map(float, theGO['exonEnds'].split(",")[:-1]) - cdsStart = theGO['cdsStart'] - cdsEnd = theGO['cdsEnd'] - accession = theGO['NM_ID'] - geneSymbol = theGO["GeneSymbol"] - strand = theGO["Strand"] - exonCount = theGO["exonCount"] - - geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) - geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) #at least one pixel - - if (geneEndPix < xLeftOffset): - return; # this gene is not on the screen - elif (geneEndPix > xLeftOffset + plotWidth): - geneEndPix = xLeftOffset + plotWidth; # clip the last in-range gene - if (geneStartPix > xLeftOffset + plotWidth): - return; # we are outside the valid on-screen range, so stop drawing genes - elif (geneStartPix < xLeftOffset): - geneStartPix = xLeftOffset; # clip the first in-range gene - - #color the gene based on SNP density - #found earlier, needs to be recomputed as snps are added - #always apply colors now, even if SNP Track not checked - Zach 11/24/2010 - - densities=[1.0000000000000001e-05, 0.094094033555233408, 0.3306166377816987, 0.88246026851027781, 2.6690084029581951, 4.1, 61.0] - if SNPdensity < densities[0]: - myColor = pid.black - elif SNPdensity < densities[1]: - myColor = pid.purple - elif SNPdensity < densities[2]: - myColor = pid.darkblue - elif SNPdensity < densities[3]: - myColor = pid.darkgreen - elif SNPdensity < densities[4]: - myColor = pid.gold - elif SNPdensity < densities[5]: - myColor = pid.darkorange - else: - myColor = pid.darkred - - outlineColor = myColor - fillColor = myColor - - TITLE = "Gene: %s (%s)\nFrom %2.3f to %2.3f Mb (%s)\nNum. exons: %d." % (geneSymbol, accession, float(txStart), float(txEnd), strand, exonCount) - # NL: 06-02-2011 Rob required to change this link for gene related - HREF=geneNCBILink %geneSymbol - - elif self.dataset.group.species == "rat": - exonStarts = [] - exonEnds = [] - txStart = theGO["TxStart"] - txEnd = theGO["TxEnd"] - cdsStart = theGO["TxStart"] - cdsEnd = theGO["TxEnd"] - geneSymbol = theGO["GeneSymbol"] - strand = theGO["Strand"] - exonCount = 0 - - geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) - geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) #at least one pixel - - if (geneEndPix < xLeftOffset): - return; # this gene is not on the screen - elif (geneEndPix > xLeftOffset + plotWidth): - geneEndPix = xLeftOffset + plotWidth; # clip the last in-range gene - if (geneStartPix > xLeftOffset + plotWidth): - return; # we are outside the valid on-screen range, so stop drawing genes - elif (geneStartPix < xLeftOffset): - geneStartPix = xLeftOffset; # clip the first in-range gene - - outlineColor = pid.darkblue - fillColor = pid.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 - TITLE = "Gene: %s" % geneSymbol - - #Draw Genes - geneYLocation = yPaddingTop + (gIndex % self.NUM_GENE_ROWS) * self.EACH_GENE_HEIGHT*zoom - if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": - geneYLocation += 4*self.BAND_HEIGHT + 4*self.BAND_SPACING - else: - geneYLocation += 3*self.BAND_HEIGHT + 3*self.BAND_SPACING - - #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) - - #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) - - #draw the arrows - if geneEndPix - geneStartPix < 1: - genePixRange = 1 - else: - genePixRange = int(geneEndPix - geneStartPix) - for xCoord in range(0, genePixRange): - - 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) - 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) - - #draw the blocks for the exon regions - for i in range(0, len(exonStarts)): - exonStartPix = (exonStarts[i]-startMb)*plotXScale + xLeftOffset - exonEndPix = (exonEnds[i]-startMb)*plotXScale + xLeftOffset - if (exonStartPix < xLeftOffset): - exonStartPix = xLeftOffset - if (exonEndPix < xLeftOffset): - exonEndPix = xLeftOffset - if (exonEndPix > xLeftOffset + plotWidth): - 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) - - #draw gray blocks for 3' and 5' UTR blocks - if cdsStart and cdsEnd: - utrStartPix = (txStart-startMb)*plotXScale + xLeftOffset - utrEndPix = (cdsStart-startMb)*plotXScale + xLeftOffset - if (utrStartPix < xLeftOffset): - utrStartPix = xLeftOffset - if (utrEndPix < xLeftOffset): - utrEndPix = xLeftOffset - if (utrEndPix > xLeftOffset + plotWidth): - 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)) - - #the second UTR region - - utrStartPix = (cdsEnd-startMb)*plotXScale + xLeftOffset - utrEndPix = (txEnd-startMb)*plotXScale + xLeftOffset - if (utrStartPix < xLeftOffset): - utrStartPix = xLeftOffset - if (utrEndPix < xLeftOffset): - utrEndPix = xLeftOffset - if (utrEndPix > xLeftOffset + plotWidth): - 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)) - - #draw the genes as rectangles - else: - canvas.drawRect(geneStartPix, geneYLocation, geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom), edgeColor = outlineColor, fillColor = 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 - gifmap.areas.append(HT.Area(shape='rect',coords=COORDS,href=HREF, title=TITLE,target="_blank")) - -## BEGIN HaplotypeAnalyst - def drawHaplotypeBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): - if self.plotScale != 'physic' or self.selectedChr == -1 or not self.geneCol: - return - - clickableRegionLabelFont=pid.Font(ttf="verdana", size=9, bold=0) - - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yZero = canvas.size[1] - yBottomOffset - fontZoom = zoom - - yPaddingTop = yTopOffset - - thisTrait = self.this_trait - _strains, _vals, _vars, _aliases = thisTrait.export_informative() - - smd=[] - for ii, _val in enumerate(_vals): - if _strains[ii] in self.dataset.group.samplelist: - temp = GeneralObject(name=_strains[ii], value=_val) - smd.append(temp) - - smd.sort(lambda A, B: cmp(A.value, B.value)) - smd.reverse() - - samplelist = list(self.genotype.prgy) - - oldgeneEndPix = -1 - #Initializing plotRight, error before - plotRight = xRightOffset - -#### find out PlotRight - for i, _locus in enumerate(self.genotype[0]): - txStart = self.genotype[0][i].Mb - txEnd = self.genotype[0][i].Mb - - geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) - 0 - geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) - 0 - - drawit = 1 - if (geneStartPix < xLeftOffset): - drawit = 0; - if (geneStartPix > xLeftOffset + plotWidth): - drawit = 0; - - if drawit == 1: - if self.genotype[0][i].name != " - " : - plotRight = geneEndPix + 4 - -#### end find out PlotRight - - firstGene = 1 - lastGene = 0 - - #Sets the length to the length of the strain list. Beforehand, "oldgeno = self.genotype[0][i].genotype" - #was the only place it was initialized, which worked as long as the very start (startMb = None/0) wasn't being mapped. - #Now there should always be some value set for "oldgeno" - Zach 12/14/2010 - oldgeno = [None]*len(self.strainlist) - - for i, _locus in enumerate(self.genotype[0]): - txStart = self.genotype[0][i].Mb - txEnd = self.genotype[0][i].Mb - - geneStartPix = xLeftOffset + plotXScale*(float(txStart) - startMb) - 0 - geneEndPix = xLeftOffset + plotXScale*(float(txEnd) - startMb) + 0 - - if oldgeneEndPix >= xLeftOffset: - drawStart = oldgeneEndPix + 4 - else: - drawStart = xLeftOffset + 3 - - drawEnd = plotRight - 9 - - drawit = 1 - - if (geneStartPix < xLeftOffset): - if firstGene == 1: - drawit = 1 - else: - drawit = 0 - - elif (geneStartPix > (xLeftOffset + plotWidth - 3)): - if lastGene == 0: - drawit = 1 - drawEnd = xLeftOffset + plotWidth - 6 - lastGene = 1 - else: - break - - else: - firstGene = 0 - drawit = 1 - - if drawit == 1: - myColor = pid.darkblue - outlineColor = myColor - fillColor = myColor - - maxind=0 - - #Draw Genes - - geneYLocation = yPaddingTop + self.NUM_GENE_ROWS * (self.EACH_GENE_HEIGHT)*zoom - if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": - geneYLocation += 4*self.BAND_HEIGHT + 4*self.BAND_SPACING - else: - geneYLocation += 3*self.BAND_HEIGHT + 3*self.BAND_SPACING - - if self.genotype[0][i].name != " - " : - - if (firstGene == 1) and (lastGene != 1): - oldgeneEndPix = drawStart = xLeftOffset - oldgeno = self.genotype[0][i].genotype - continue - - for j,_geno in enumerate (self.genotype[0][i].genotype): - - plotbxd=0 - for item in smd: - if item.name == samplelist[j]: - plotbxd=1 - - if (plotbxd == 1): - ind = 0 - counter = 0 - for item in smd: - counter = counter + 1 - if item.name == samplelist[j]: - ind = counter - maxind=max(ind,maxind) - - # lines - if (oldgeno[j] == -1 and _geno == -1): - mylineColor = self.HAPLOTYPE_NEGATIVE - elif (oldgeno[j] == 1 and _geno == 1): - mylineColor = self.HAPLOTYPE_POSITIVE - elif (oldgeno[j] == 0 and _geno == 0): - mylineColor = self.HAPLOTYPE_HETEROZYGOUS - 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)) - - fillColor=pid.black - outlineColor=pid.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) - - - COORDS = "%d, %d, %d, %d" %(geneStartPix, geneYLocation+ind*self.EACH_GENE_HEIGHT, geneEndPix+1, (geneYLocation + ind*self.EACH_GENE_HEIGHT)) - TITLE = "Strain: %s, marker (%s) \n Position %2.3f Mb." % (samplelist[j], self.genotype[0][i].name, float(txStart)) - HREF = '' - gifmap.areas.append(HT.Area(shape='rect',coords=COORDS,href=HREF, title=TITLE)) - - # if there are no more markers in a chromosome, the plotRight value calculated above will be before the plotWidth - # resulting in some empty space on the right side of the plot area. This draws an "unknown" bar from plotRight to the edge. - 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)) - - - if lastGene == 0: - canvas.drawString("%s" % (self.genotype[0][i].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) - - oldgeneEndPix = geneEndPix; - oldgeno = self.genotype[0][i].genotype - firstGene = 0 - else: - lastGene = 0 - - for j, _geno in enumerate (self.genotype[0][1].genotype): - - plotbxd=0 - for item in smd: - if item.name == samplelist[j]: - plotbxd=1 - - if (plotbxd == 1): - - ind = 0 - counter = 0 - expr = 0 - for item in smd: - counter = counter + 1 - if item.name == samplelist[j]: - ind = counter - 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) - -## END HaplotypeAnalyst - - def drawClickBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): - if self.plotScale != 'physic' or self.selectedChr == -1: - return - - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yZero = canvas.size[1] - yBottomOffset - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - - # only draw this many clickable regions (if you set it higher, you get more precision in clicking, - # 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) - 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. - - numBasesCurrentlyOnScreen = self.kONE_MILLION*abs(startMb - endMb) # Number of bases on screen now - flankingWidthInBases = int ( min( (float(numBasesCurrentlyOnScreen) / 2.0), (5*self.kONE_MILLION) ) ) - webqtlZoomWidth = numBasesCurrentlyOnScreen / 16.0 - # Flanking width should be such that we either zoom in to a 10 million base region, or we show the clicked region at the same scale as we are currently seeing. - - currentChromosome = self.genotype[0].name - i = 0 - - paddingTop = yTopOffset - if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": - phenogenPaddingTop = paddingTop + (self.BAND_HEIGHT + self.BAND_SPACING) - ucscPaddingTop = paddingTop + 2*(self.BAND_HEIGHT + self.BAND_SPACING) - ensemblPaddingTop = paddingTop + 3*(self.BAND_HEIGHT + self.BAND_SPACING) - else: - ucscPaddingTop = paddingTop + (self.BAND_HEIGHT + self.BAND_SPACING) - ensemblPaddingTop = paddingTop + 2*(self.BAND_HEIGHT + self.BAND_SPACING) - - if zoom == 1: - for pixel in range(xLeftOffset, xLeftOffset + plotWidth, pixelStep): - - calBase = self.kONE_MILLION*(startMb + (endMb-startMb)*(pixel-xLeftOffset-0.0)/plotWidth) - if pixel == (xLeftOffset + pixelStep*2): - logger.debug("CALBASE:", calBase) - logger.debug("FLANKING:", flankingWidthInBases) - - xBrowse1 = pixel - xBrowse2 = min(xLeftOffset + plotWidth, (pixel + pixelStep - 1)) - - WEBQTL_COORDS = "%d, %d, %d, %d" % (xBrowse1, paddingTop, xBrowse2, (paddingTop+self.BAND_HEIGHT)) - WEBQTL_HREF = "javascript:rangeView('%s', %f, %f)" % (self.selectedChr - 1, max(0, (calBase-webqtlZoomWidth))/1000000.0, (calBase+webqtlZoomWidth)/1000000.0) - - 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) - - 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)) - if self.dataset.group.species == "mouse": - PHENOGEN_HREF = "https://phenogen.ucdenver.edu/PhenoGen/gene.jsp?speciesCB=Mm&auto=Y&geneTxt=chr%s:%d-%d&genomeVer=mm10" % (self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases) - else: - PHENOGEN_HREF = "https://phenogen.ucdenver.edu/PhenoGen/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) - - UCSC_COORDS = "%d, %d, %d, %d" %(xBrowse1, ucscPaddingTop, xBrowse2, (ucscPaddingTop+self.BAND_HEIGHT)) - if self.dataset.group.species == "mouse": - UCSC_HREF = "http://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=chr%s:%d-%d&hgt.customText=%s/snp/chr%s" % (self._ucscDb, self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases, webqtlConfig.PORTADDR, self.selectedChr) - else: - 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) - - ENSEMBL_COORDS = "%d, %d, %d, %d" %(xBrowse1, ensemblPaddingTop, xBrowse2, (ensemblPaddingTop+self.BAND_HEIGHT)) - if self.dataset.group.species == "mouse": - ENSEMBL_HREF = "http://www.ensembl.org/Mus_musculus/contigview?highlight=&chr=%s&vc_start=%d&vc_end=%d&x=35&y=12" % (self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases) - else: - 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) - # 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) - 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) - - #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) - # 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) - # end of drawBrowserClickableRegions - pass - - def drawXAxis(self, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yZero = canvas.size[1] - yBottomOffset - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - - #Parameters - NUM_MINOR_TICKS = 5 # Number of minor ticks between major ticks - X_MAJOR_TICK_THICKNESS = 2 - 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) - xMajorTickHeight = 10 * zoom # How high the tick extends below the axis - xMinorTickHeight = 5*zoom - xAxisTickMarkColor = pid.black - xAxisLabelColor = pid.black - fontHeight = 12*fontZoom # How tall the font that we're using is - spacingFromLabelToAxis = 5 - - if self.plotScale == 'physic': - strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) - ###Physical single chromosome view - if self.selectedChr > -1: - XScale = Plot.detScale(startMb, endMb) - XStart, XEnd, XStep = XScale - if XStep < 8: - XStep *= 2 - spacingAmtX = spacingAmt = (XEnd-XStart)/XStep - - j = 0 - while abs(spacingAmtX -int(spacingAmtX)) >= spacingAmtX/100.0 and j < 6: - j += 1 - spacingAmtX *= 10 - - formatStr = '%%2.%df' % j - - for counter, _Mb in enumerate(Plot.frange(XStart, XEnd, spacingAmt / NUM_MINOR_TICKS)): - if _Mb < startMb or _Mb > endMb: - 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 - labelStr = str(formatStr % _Mb) # What Mbase location to put on the label - strWidth = canvas.stringWidth(labelStr, font=MBLabelFont) - drawStringXc = (Xc - (strWidth / 2.0)) - canvas.drawString(labelStr, drawStringXc, strYLoc, font=MBLabelFont, color=xAxisLabelColor, angle=0) - else: - canvas.drawLine(Xc, yZero, Xc, yZero+xMinorTickHeight, color=xAxisTickMarkColor, width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark - - ###Physical genome wide view - else: - distScale = 0 - startPosX = xLeftOffset - for i, distLen in enumerate(self.ChrLengthDistList): - if distScale == 0: #universal scale in whole genome mapping - if distLen > 75: - distScale = 25 - elif distLen > 30: - distScale = 10 - 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) - if j % 2 == 0: - canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=pid.black, font=MBLabelFont, 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) - pass - else: - strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) + 8 - ChrAInfo = [] - preLpos = -1 - distinctCount = 0.0 - - if self.selectedChr == -1: #ZS: If viewing full genome/all chromosomes - for i, _chr in enumerate(self.genotype): - thisChr = [] - Locus0CM = _chr[0].cM - nLoci = len(_chr) - if nLoci <= 8: - for _locus in _chr: - if _locus.name != ' - ': - if _locus.cM != preLpos: - distinctCount += 1 - preLpos = _locus.cM - thisChr.append([_locus.name, _locus.cM-Locus0CM]) - else: - for j in (0, nLoci/4, nLoci/2, nLoci*3/4, -1): - while _chr[j].name == ' - ': - j += 1 - if _chr[j].cM != preLpos: - distinctCount += 1 - preLpos = _chr[j].cM - thisChr.append([_chr[j].name, _chr[j].cM-Locus0CM]) - ChrAInfo.append(thisChr) - else: - for i, _chr in enumerate(self.genotype): - if _chr.name == self.ChrList[self.selectedChr][0]: - thisChr = [] - Locus0CM = _chr[0].cM - for _locus in _chr: - if _locus.name != ' - ': - if _locus.cM != preLpos: - distinctCount += 1 - preLpos = _locus.cM - thisChr.append([_locus.name, _locus.cM-Locus0CM]) - ChrAInfo.append(thisChr) - - stepA = (plotWidth+0.0)/distinctCount - - LRectWidth = 10 - LRectHeight = 3 - offsetA = -stepA - lineColor = pid.lightblue - startPosX = xLeftOffset - - for j, ChrInfo in enumerate(ChrAInfo): - preLpos = -1 - for i, item in enumerate(ChrInfo): - Lname,Lpos = item - if Lpos != preLpos: - offsetA += stepA - differ = 1 - else: - differ = 0 - preLpos = Lpos - Lpos *= plotXScale - if self.selectedChr > -1: - Zorder = i % 5 - 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 - 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) - 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") - #HREF="javascript:showDatabase3('%s','%s','%s','');" % (showLocusForm,fd.RISet+"Geno", Lname) - Areas=HT.Area(shape='rect', coords=COORDS, href=HREF, target="_blank", title="Locus : " + Lname) - gifmap.areas.append(Areas) - ##piddle bug - if j == 0: - canvas.drawLine(startPosX,yZero,startPosX,yZero+40, color=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) - - canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.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): - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - - INTERCROSS = (self.genotype.type=="intercross") - - LRSHeightThresh = drawAreaHeight - AdditiveHeightThresh = drawAreaHeight/2 - DominanceHeightThresh = drawAreaHeight/2 - - #draw the LRS scale - #We first determine whether or not we are using a sliding scale. - #If so, we need to compute the maximum LRS value to determine where the max y-value should be, and call this LRS_LOD_Max. - #LRSTop is then defined to be above the LRS_LOD_Max by enough to add one additional LRSScale increment. - #if we are using a set-scale, then we set LRSTop to be the user's value, and LRS_LOD_Max doesn't matter. - - #ZS: This is a mess, but I don't know a better way to account for different mapping methods returning results in different formats + the option to change between LRS and LOD - if self.lrsMax <= 0: #sliding scale - if "lrs_value" in self.qtlresults[0]: - LRS_LOD_Max = max([result['lrs_value'] for result in self.qtlresults]) - if self.LRS_LOD == "LOD" or self.LRS_LOD == "-log(p)": - LRS_LOD_Max = LRS_LOD_Max / self.LODFACTOR - if self.permChecked and self.nperm > 0 and not self.multipleInterval: - self.significant = min(self.significant / self.LODFACTOR, webqtlConfig.MAXLRS) - self.suggestive = min(self.suggestive / self.LODFACTOR, webqtlConfig.MAXLRS) - else: - if self.permChecked and self.nperm > 0 and not self.multipleInterval: - self.significant = min(self.significant, webqtlConfig.MAXLRS) - self.suggestive = min(self.suggestive, webqtlConfig.MAXLRS) - else: - pass - else: - LRS_LOD_Max = max([result['lod_score'] for result in self.qtlresults]) - if self.LRS_LOD == "LRS": - LRS_LOD_Max = LRS_LOD_Max * self.LODFACTOR - if self.permChecked and self.nperm > 0 and not self.multipleInterval: - self.significant = min(self.significant * self.LODFACTOR, webqtlConfig.MAXLRS) - self.suggestive = min(self.suggestive * self.LODFACTOR, webqtlConfig.MAXLRS) - else: - if self.permChecked and self.nperm > 0 and not self.multipleInterval: - self.significant = min(self.significant, webqtlConfig.MAXLRS) - self.suggestive = min(self.suggestive, webqtlConfig.MAXLRS) - else: - pass - - if self.permChecked and self.nperm > 0 and not self.multipleInterval: - LRS_LOD_Max = max(self.significant, LRS_LOD_Max) - else: - LRS_LOD_Max = 1.15*LRS_LOD_Max - - #genotype trait will give infinite LRS - LRS_LOD_Max = min(LRS_LOD_Max, webqtlConfig.MAXLRS) - else: - LRS_LOD_Max = self.lrsMax - - if LRS_LOD_Max > 100: - LRSScale = 20.0 - elif LRS_LOD_Max > 20: - LRSScale = 5.0 - elif LRS_LOD_Max > 7.5: - LRSScale = 2.5 - else: - LRSScale = 1.0 - - LRSAxisList = Plot.frange(LRSScale, LRS_LOD_Max, LRSScale) - #make sure the user's value appears on the y-axis - #update by NL 6-21-2011: round the LOD value to 100 when LRS_LOD_Max is equal to 460 - LRSAxisList.append(round(LRS_LOD_Max)) - - #draw the "LRS" or "LOD" string to the left of the axis - LRSScaleFont=pid.Font(ttf="verdana", size=16*zoom, bold=0) - LRSLODFont=pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0) - yZero = yTopOffset + plotHeight - - canvas.drawString(self.LRS_LOD, xLeftOffset - canvas.stringWidth("999.99", font=LRSScaleFont) - 15*(zoom-1), \ - yZero - 150 - 300*(zoom - 1), font=LRSLODFont, color=pid.black, angle=90) - - for item in LRSAxisList: - if LRS_LOD_Max == 0.0: - LRS_LOD_Max = 0.000001 - yLRS = yZero - (item/LRS_LOD_Max) * LRSHeightThresh - canvas.drawLine(xLeftOffset, yLRS, xLeftOffset - 4, yLRS, color=self.LRS_COLOR, width=1*zoom) - 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) - - if self.permChecked and self.nperm > 0 and not self.multipleInterval: - significantY = yZero - self.significant*LRSHeightThresh/LRS_LOD_Max - suggestiveY = yZero - self.suggestive*LRSHeightThresh/LRS_LOD_Max - startPosX = xLeftOffset - - #"Significant" and "Suggestive" Drawing Routine - # ======= Draw the thick lines for "Significant" and "Suggestive" ===== (crowell: I tried to make the SNPs draw over these lines, but piddle wouldn't have it...) - - #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)) - 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': - sugg_title = "Suggestive LRS = %0.2f" % self.suggestive - sig_title = "Significant LRS = %0.2f" % self.significant - else: - sugg_title = "Suggestive LOD = %0.2f" % (self.suggestive/4.61) - sig_title = "Significant LOD = %0.2f" % (self.significant/4.61) - Areas1 = HT.Area(shape='rect',coords=sugg_coords,title=sugg_title) - Areas2 = HT.Area(shape='rect',coords=sig_coords,title=sig_title) - gifmap.areas.append(Areas1) - gifmap.areas.append(Areas2) - - start_pos_x += (chr_length_dist+self.GraphInterval)*plotXScale - return start_pos_x - - for i, _chr in enumerate(self.genotype): - if self.selectedChr != -1: - if _chr.name == self.ChrList[self.selectedChr][0]: - startPosX = add_suggestive_significant_lines_and_legend(startPosX, self.ChrLengthDistList[0]) - break - else: - continue - else: - startPosX = add_suggestive_significant_lines_and_legend(startPosX, self.ChrLengthDistList[i]) - - if self.multipleInterval: - lrsEdgeWidth = 1 - else: - if self.additiveChecked: - additiveMax = max(map(lambda X : abs(X['additive']), self.qtlresults)) - lrsEdgeWidth = 2 - - if zoom == 2: - lrsEdgeWidth = 2 * lrsEdgeWidth - - LRSCoordXY = [] - AdditiveCoordXY = [] - DominanceCoordXY = [] - - symbolFont = pid.Font(ttf="fnt_bs", size=5,bold=0) #ZS: For Manhattan Plot - - previous_chr = 1 - previous_chr_as_int = 0 - lineWidth = 1 - oldStartPosX = 0 - startPosX = xLeftOffset - for i, qtlresult in enumerate(self.qtlresults): - m = 0 - 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)) - - if not self.multipleInterval and not self.manhattan_plot and self.additiveChecked: - plusColor = self.ADDITIVE_COLOR_POSITIVE - minusColor = self.ADDITIVE_COLOR_NEGATIVE - for k, aPoint in enumerate(AdditiveCoordXY): - if k > 0: - Xc0, Yc0 = AdditiveCoordXY[k-1] - Xc, Yc = aPoint - if (Yc0-yZero)*(Yc-yZero) < 0: - if Xc == Xc0: #genotype , locus distance is 0 - Xcm = Xc - 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)) - 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)) - elif (Yc0-yZero)*(Yc-yZero) > 0: - if Yc < yZero: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) - else: - minYc = min(Yc-yZero, Yc0-yZero) - if minYc < 0: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) - - LRSCoordXY = [] - AdditiveCoordXY = [] - previous_chr = qtlresult['chr'] - previous_chr_as_int += 1 - newStartPosX = (self.ChrLengthDistList[previous_chr_as_int - 1]+self.GraphInterval)*plotXScale - if newStartPosX != oldStartPosX: - startPosX += newStartPosX - oldStartPosX = newStartPosX - - #ZS: This is beause the chromosome value stored in qtlresult['chr'] can be (for example) either X or 20 depending upon the mapping method/scale used - if self.plotScale == "physic": - this_chr = str(self.ChrList[self.selectedChr][0]) - else: - this_chr = str(self.ChrList[self.selectedChr][1]+1) - if self.selectedChr == -1 or str(qtlresult['chr']) == this_chr: - Xc = startPosX + (qtlresult['Mb']-startMb)*plotXScale - # updated by NL 06-18-2011: - # fix the over limit LRS graph issue since genotype trait may give infinite LRS; - # for any lrs is over than 460(LRS max in this system), it will be reset to 460 - if 'lrs_value' in qtlresult: - if self.LRS_LOD == "LOD" or self.LRS_LOD == "-log(p)": - if qtlresult['lrs_value'] > 460 or qtlresult['lrs_value']=='inf': - Yc = yZero - webqtlConfig.MAXLRS*LRSHeightThresh/(LRS_LOD_Max*self.LODFACTOR) - else: - Yc = yZero - qtlresult['lrs_value']*LRSHeightThresh/(LRS_LOD_Max*self.LODFACTOR) - else: - if qtlresult['lrs_value'] > 460 or qtlresult['lrs_value']=='inf': - Yc = yZero - webqtlConfig.MAXLRS*LRSHeightThresh/LRS_LOD_Max - else: - Yc = yZero - qtlresult['lrs_value']*LRSHeightThresh/LRS_LOD_Max - else: - if qtlresult['lod_score'] > 100 or qtlresult['lod_score']=='inf': - Yc = yZero - webqtlConfig.MAXLRS*LRSHeightThresh/LRS_LOD_Max - else: - if self.LRS_LOD == "LRS": - Yc = yZero - qtlresult['lod_score']*self.LODFACTOR*LRSHeightThresh/LRS_LOD_Max - else: - Yc = yZero - qtlresult['lod_score']*LRSHeightThresh/LRS_LOD_Max - - if self.manhattan_plot == True: - point_color = pid.black - canvas.drawString("5", Xc-canvas.stringWidth("5",font=symbolFont)/2+1,Yc+2,color=point_color, font=symbolFont) - else: - LRSCoordXY.append((Xc, Yc)) - - if not self.multipleInterval and self.additiveChecked: - if additiveMax == 0.0: - additiveMax = 0.000001 - Yc = yZero - qtlresult['additive']*AdditiveHeightThresh/additiveMax - AdditiveCoordXY.append((Xc, Yc)) - - m += 1 - - if self.manhattan_plot != True: - canvas.drawPolygon(LRSCoordXY,edgeColor=thisLRSColor,closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) - - if not self.multipleInterval and self.additiveChecked: - plusColor = self.ADDITIVE_COLOR_POSITIVE - minusColor = self.ADDITIVE_COLOR_NEGATIVE - for k, aPoint in enumerate(AdditiveCoordXY): - if k > 0: - Xc0, Yc0 = AdditiveCoordXY[k-1] - Xc, Yc = aPoint - if (Yc0-yZero)*(Yc-yZero) < 0: - if Xc == Xc0: #genotype , locus distance is 0 - Xcm = Xc - 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)) - 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)) - elif (Yc0-yZero)*(Yc-yZero) > 0: - if Yc < yZero: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) - else: - minYc = min(Yc-yZero, Yc0-yZero) - if minYc < 0: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) - - if not self.multipleInterval and INTERCROSS and self.dominanceChecked: - plusColor = self.DOMINANCE_COLOR_POSITIVE - minusColor = self.DOMINANCE_COLOR_NEGATIVE - for k, aPoint in enumerate(DominanceCoordXY): - if k > 0: - Xc0, Yc0 = DominanceCoordXY[k-1] - Xc, Yc = aPoint - if (Yc0-yZero)*(Yc-yZero) < 0: - if Xc == Xc0: #genotype , locus distance is 0 - Xcm = Xc - 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)) - 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)) - elif (Yc0-yZero)*(Yc-yZero) > 0: - if Yc < yZero: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) - else: - minYc = min(Yc-yZero, Yc0-yZero) - if minYc < 0: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=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)) - - - ###draw additive scale - if not self.multipleInterval and self.additiveChecked: - additiveScaleFont=pid.Font(ttf="verdana",size=16*zoom,bold=0) - additiveScale = Plot.detScaleOld(0,additiveMax) - additiveStep = (additiveScale[1]-additiveScale[0])/additiveScale[2] - additiveAxisList = Plot.frange(0, additiveScale[1], additiveStep) - addPlotScale = AdditiveHeightThresh/additiveMax - - 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) - scaleStr = "%2.3f" % item - canvas.drawString(scaleStr,xLeftOffset + plotWidth +6,additiveY+5,font=additiveScaleFont,color=self.ADDITIVE_COLOR_POSITIVE) - - canvas.drawLine(xLeftOffset+plotWidth,additiveY,xLeftOffset+plotWidth,yZero,color=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 - - - def drawGraphBackground(self, canvas, gifmap, offset= (80, 120, 80, 50), zoom = 1, startMb = None, endMb = None): - ##conditions - ##multiple Chromosome view - ##single Chromosome Physical - ##single Chromosome Genetic - xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset - plotWidth = canvas.size[0] - xLeftOffset - xRightOffset - plotHeight = canvas.size[1] - yTopOffset - yBottomOffset - yBottom = yTopOffset+plotHeight - fontZoom = zoom - if zoom == 2: - fontZoom = 1.5 - yTopOffset += 30 - - #calculate plot scale - if self.plotScale != 'physic': - self.ChrLengthDistList = self.ChrLengthCMList - drawRegionDistance = self.ChrLengthCMSum - else: - self.ChrLengthDistList = self.ChrLengthMbList - drawRegionDistance = self.ChrLengthMbSum - - if self.selectedChr > -1: #single chromosome view - spacingAmt = plotWidth/13.5 - i = 0 - for startPix in Plot.frange(xLeftOffset, xLeftOffset+plotWidth, spacingAmt): - if (i % 2 == 0): - theBackColor = self.GRAPH_BACK_DARK_COLOR - else: - theBackColor = self.GRAPH_BACK_LIGHT_COLOR - i += 1 - canvas.drawRect(startPix, yTopOffset, min(startPix+spacingAmt, xLeftOffset+plotWidth), \ - yBottom, edgeColor=theBackColor, fillColor=theBackColor) - - drawRegionDistance = self.ChrLengthDistList[self.ChrList[self.selectedChr][1]] - self.ChrLengthDistList = [drawRegionDistance] - if self.plotScale == 'physic': - plotXScale = plotWidth / (endMb-startMb) - else: - plotXScale = plotWidth / drawRegionDistance - - else: #multiple chromosome view - plotXScale = plotWidth / ((len(self.genotype)-1)*self.GraphInterval + drawRegionDistance) - - startPosX = xLeftOffset - if fontZoom == 1.5: - chrFontZoom = 2 - else: - chrFontZoom = 1 - chrLabelFont=pid.Font(ttf="verdana",size=24*chrFontZoom,bold=0) - - for i, _chr in enumerate(self.genotype): - if (i % 2 == 0): - theBackColor = self.GRAPH_BACK_DARK_COLOR - else: - 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) - - chrNameWidth = canvas.stringWidth(_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) - COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20) - - #add by NL 09-03-2010 - HREF = "javascript:chrView(%d,%s);" % (i,self.ChrLengthMbList) - #HREF = "javascript:changeView(%d,%s);" % (i,self.ChrLengthMbList) - Areas = HT.Area(shape='rect',coords=COORDS,href=HREF) - gifmap.areas.append(Areas) - startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale - - return plotXScale - - def drawPermutationHistogram(self): - ######################################### - # Permutation Graph - ######################################### - myCanvas = pid.PILCanvas(size=(400,300)) - if 'lod_score' in self.qtlresults[0] and self.LRS_LOD == "LRS": - perm_output = [value*4.16 for value in self.perm_output] - elif 'lod_score' not in self.qtlresults[0] and self.LRS_LOD == "LOD": - perm_output = [value/4.16 for value in self.perm_output] - else: - perm_output = self.perm_output - - Plot.plotBar(myCanvas, perm_output, XLabel=self.LRS_LOD, YLabel='Frequency', title=' Histogram of Permutation Test') - filename= webqtlUtil.genRandStr("Reg_") - myCanvas.save(GENERATED_IMAGE_DIR+filename, format='gif') - - return filename - - def geneTable(self, geneCol, refGene=None): - if self.dataset.group.species == 'mouse' or self.dataset.group.species == 'rat': - self.gene_table_header = self.getGeneTableHeaderList(refGene=None) - self.gene_table_body = self.getGeneTableBody(geneCol, refGene=None) - else: - self.gene_table_header = None - self.gene_table_body = None - - def getGeneTableHeaderList(self, refGene=None): - - gene_table_header_list = [] - if self.dataset.group.species == "mouse": - if refGene: - gene_table_header_list = ["Index", - "Symbol", - "Mb Start", - "Length (Kb)", - "SNP Count", - "SNP Density", - "Avg Expr", - "Human Chr", - "Mb Start (hg19)", - "Literature Correlation", - "Gene Description"] - else: - gene_table_header_list = ["", - "Index", - "Symbol", - "Mb Start", - "Length (Kb)", - "SNP Count", - "SNP Density", - "Avg Expr", - "Human Chr", - "Mb Start (hg19)", - "Gene Description"] - elif self.dataset.group.species == "rat": - gene_table_header_list = ["", - "Index", - "Symbol", - "Mb Start", - "Length (Kb)", - "Avg Expr", - "Mouse Chr", - "Mb Start (mm9)", - "Human Chr", - "Mb Start (hg19)", - "Gene Description"] - - return gene_table_header_list - - def getGeneTableBody(self, geneCol, refGene=None): - gene_table_body = [] - - tableIterationsCnt = 0 - if self.dataset.group.species == "mouse": - for gIndex, theGO in enumerate(geneCol): - - tableIterationsCnt = tableIterationsCnt + 1 - - this_row = [] #container for the cells of each row - selectCheck = HT.Input(type="checkbox", name="searchResult", value=theGO["GeneSymbol"], Class="checkbox", onClick="highlight(this)") #checkbox for each row - - geneLength = (theGO["TxEnd"] - theGO["TxStart"])*1000.0 - tenPercentLength = geneLength*0.0001 - txStart = theGO["TxStart"] - txEnd = theGO["TxEnd"] - theGO["snpDensity"] = theGO["snpCount"]/geneLength - if self.ALEX_DEBUG_BOOL_PRINT_GENE_LIST: - geneIdString = 'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s' % theGO["GeneID"] - - if theGO["snpCount"]: - snpString = HT.Href(url="http://genenetwork.org/webqtl/main.py?FormID=snpBrowser&chr=%s&start=%s&end=%s&geneName=%s&s1=%d&s2=%d" % (theGO["Chromosome"], - theGO["TxStart"], theGO["TxEnd"], theGO["GeneSymbol"], self.diffCol[0], self.diffCol[1]), - text=theGO["snpCount"], target="_blank", Class="normalsize") - else: - snpString = 0 - - mouseStartString = "http://genome.ucsc.edu/cgi-bin/hgTracks?clade=vertebrate&org=Mouse&db=mm9&position=chr" + theGO["Chromosome"] + "%3A" + str(int(theGO["TxStart"] * 1000000.0)) + "-" + str(int(theGO["TxEnd"]*1000000.0)) +"&pix=620&Submit=submit" - - #the chromosomes for human 1 are 1qXX.XX - if theGO['humanGene']: - if theGO['humanGene']["TxStart"] == '': - humanStartDisplay = "" - else: - humanStartDisplay = "%0.6f" % theGO['humanGene']["TxStart"] - - humanChr = theGO['humanGene']["Chromosome"] - humanTxStart = theGO['humanGene']["TxStart"] - - humanStartString = "http://genome.ucsc.edu/cgi-bin/hgTracks?clade=vertebrate&org=Human&db=hg17&position=chr%s:%d-%d" % (humanChr, int(1000000*theGO['humanGene']["TxStart"]), int(1000000*theGO['humanGene']["TxEnd"])) - else: - humanStartString = humanChr = humanStartDisplay = "--" - - geneDescription = theGO["GeneDescription"] - if len(geneDescription) > 26: - geneDescription = geneDescription[:26]+"..." - - if theGO["snpDensity"] < 0.000001: - snpDensityStr = "0" - else: - snpDensityStr = "%0.6f" % theGO["snpDensity"] - - avgExpr = [] #theGO["avgExprVal"] - if avgExpr in ([], None): - avgExpr = "--" - else: - avgExpr = "%0.6f" % avgExpr - - # If we have a referenceGene then we will show the Literature Correlation - if theGO["Chromosome"] == "X": - chr_as_int = 19 - else: - chr_as_int = int(theGO["Chromosome"]) - 1 - if refGene: - literatureCorrelationString = str(self.getLiteratureCorrelation(self.cursor,refGene,theGO['GeneID']) or "N/A") - - this_row = [selectCheck.__str__(), - str(tableIterationsCnt), - HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank").__str__(), - HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank").__str__(), - HT.Href("javascript:rangeView('%s', %f, %f)" % (str(chr_as_int), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), - snpString, - snpDensityStr, - avgExpr, - humanChr, - HT.Href(humanStartString, humanStartDisplay, target="_blank").__str__(), - literatureCorrelationString, - geneDescription] - else: - this_row = [selectCheck.__str__(), - str(tableIterationsCnt), - HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank").__str__(), - HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank").__str__(), - HT.Href("javascript:rangeView('%s', %f, %f)" % (str(chr_as_int), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), - snpString, - snpDensityStr, - avgExpr, - humanChr, - HT.Href(humanStartString, humanStartDisplay, target="_blank").__str__(), - geneDescription] - - gene_table_body.append(this_row) - - elif self.dataset.group.species == 'rat': - for gIndex, theGO in enumerate(geneCol): - this_row = [] #container for the cells of each row - selectCheck = HT.Input(type="checkbox", name="searchResult", Class="checkbox", onClick="highlight(this)").__str__() #checkbox for each row - - webqtlSearch = HT.Href(os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)+"?cmd=sch&gene=%s&alias=1&species=rat" % theGO["GeneSymbol"], ">>", target="_blank").__str__() - - if theGO["GeneID"] != "": - geneSymbolNCBI = HT.Href("http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % theGO["GeneID"], theGO["GeneSymbol"], Class="normalsize", target="_blank").__str__() - else: - geneSymbolNCBI = theGO["GeneSymbol"] - - if theGO["Chromosome"] == "X": - chr_as_int = 20 - else: - chr_as_int = int(theGO["Chromosome"]) - 1 - - geneLength = (float(theGO["TxEnd"]) - float(theGO["TxStart"])) - geneLengthURL = "javascript:rangeView('%s', %f, %f)" % (theGO["Chromosome"], float(theGO["TxStart"])-(geneLength*0.1), float(theGO["TxEnd"])+(geneLength*0.1)) - - avgExprVal = [] - if avgExprVal != "" and avgExprVal: - avgExprVal = "%0.5f" % float(avgExprVal) - else: - avgExprVal = "" - - #Mouse Gene - if theGO['mouseGene']: - mouseChr = theGO['mouseGene']["Chromosome"] - mouseTxStart = theGO['mouseGene']["TxStart"] - else: - mouseChr = mouseTxStart = "" - - #the chromosomes for human 1 are 1qXX.XX - if theGO['humanGene']: - humanChr = theGO['humanGene']["Chromosome"] - humanTxStart = theGO['humanGene']["TxStart"] - else: - humanChr = humanTxStart = "" - - geneDesc = theGO["GeneDescription"] - if geneDesc == "---": - geneDesc = "" - - this_row = [selectCheck.__str__(), - str(gIndex+1), - webqtlSearch.__str__() + geneSymbolNCBI, - theGO["TxStart"], - HT.Href(geneLengthURL, "%0.3f" % (geneLength*1000.0)).__str__(), - avgExprVal, - mouseChr, - mouseTxStart, - humanChr, - humanTxStart, - geneDesc] - - gene_table_body.append(this_row) - - return gene_table_body - - def getLiteratureCorrelation(cursor,geneId1=None,geneId2=None): - if not geneId1 or not geneId2: - return None - if geneId1 == geneId2: - return 1.0 - geneId1 = str(geneId1) - geneId2 = str(geneId2) - lCorr = None - try: - query = 'SELECT Value FROM LCorrRamin3 WHERE GeneId1 = %s and GeneId2 = %s' - for x,y in [(geneId1,geneId2),(geneId2,geneId1)]: - cursor.execute(query,(x,y)) - lCorr = cursor.fetchone() - if lCorr: - lCorr = lCorr[0] - break - except: raise #lCorr = None - return lCorr \ No newline at end of file diff --git a/wqflask/wqflask/marker_regression/run_mapping.py b/wqflask/wqflask/marker_regression/run_mapping.py new file mode 100644 index 00000000..b604b467 --- /dev/null +++ b/wqflask/wqflask/marker_regression/run_mapping.py @@ -0,0 +1,660 @@ +from __future__ import absolute_import, print_function, division + +from base.trait import GeneralTrait +from base import data_set #import create_dataset + +from pprint import pformat as pf + +import string +import math +import random +import sys +import datetime +import os +import collections +import uuid + +import rpy2.robjects as ro +import numpy as np + +import cPickle as pickle +import itertools + +import simplejson as json + +from redis import Redis +Redis = Redis() + +from flask import Flask, g + +from base.trait import GeneralTrait +from base import data_set +from base import species +from base import webqtlConfig +from utility import webqtlUtil +from utility import helper_functions +from utility import Plot, Bunch +from utility import temp_data +from utility.benchmark import Bench +from wqflask.marker_regression import gemma_mapping, rqtl_mapping, qtlreaper_mapping, plink_mapping + +from utility.tools import locate, locate_ignore_error, PYLMM_COMMAND, GEMMA_COMMAND, PLINK_COMMAND, TEMPDIR +from utility.external import shell +from base.webqtlConfig import TMPDIR, GENERATED_TEXT_DIR + +import utility.logger +logger = utility.logger.getLogger(__name__ ) + +class RunMapping(object): + + def __init__(self, start_vars, temp_uuid): + + helper_functions.get_species_dataset_trait(self, start_vars) + + self.temp_uuid = temp_uuid #needed to pass temp_uuid to gn1 mapping code (marker_regression_gn1.py) + + self.json_data = {} + self.json_data['lodnames'] = ['lod.hk'] + + self.samples = [] # Want only ones with values + self.vals = [] + + all_samples_ordered = self.dataset.group.all_samples_ordered() + primary_sample_names = list(all_samples_ordered) + + for sample in self.dataset.group.samplelist: + # sample is actually the name of an individual + in_trait_data = False + for item in self.this_trait.data: + if self.this_trait.data[item].name == sample: + value = start_vars['value:' + self.this_trait.data[item].name] + self.samples.append(self.this_trait.data[item].name) + self.vals.append(value) + in_trait_data = True + break + if not in_trait_data: + value = start_vars.get('value:' + sample) + if value: + self.samples.append(sample) + self.vals.append(value) + + #ZS: Check if genotypes exist in the DB in order to create links for markers + if "geno_db_exists" in start_vars: + self.geno_db_exists = start_vars['geno_db_exists'] + else: + try: + self.geno_db_exists = "True" + except: + self.geno_db_exists = "False" + + self.mapping_method = start_vars['method'] + if "results_path" in start_vars: + self.mapping_results_path = start_vars['results_path'] + else: + mapping_results_filename = self.dataset.group.name + "_" + ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6)) + self.mapping_results_path = "{}{}.csv".format(webqtlConfig.GENERATED_IMAGE_DIR, mapping_results_filename) + + if start_vars['manhattan_plot'] == "True": + self.manhattan_plot = True + else: + self.manhattan_plot = False + + self.maf = start_vars['maf'] # Minor allele frequency + if "use_loco" in start_vars: + self.use_loco = start_vars['use_loco'] + else: + self.use_loco = None + self.suggestive = "" + self.significant = "" + self.pair_scan = False # Initializing this since it is checked in views to determine which template to use + self.score_type = "LRS" #ZS: LRS or LOD + self.mapping_scale = "physic" + self.num_perm = 0 + self.perm_output = [] + self.bootstrap_results = [] + self.covariates = start_vars['covariates'] if "covariates" in start_vars else None + + #ZS: This is passed to GN1 code for single chr mapping + self.selected_chr = -1 + if "selected_chr" in start_vars: + if int(start_vars['selected_chr']) != -1: #ZS: Needs to be -1 if showing full map; there's probably a better way to fix this + self.selected_chr = int(start_vars['selected_chr']) + 1 + else: + self.selected_chr = int(start_vars['selected_chr']) + if "startMb" in start_vars: + self.startMb = start_vars['startMb'] + if "endMb" in start_vars: + self.endMb = start_vars['endMb'] + if "graphWidth" in start_vars: + self.graphWidth = start_vars['graphWidth'] + if "lrsMax" in start_vars: + self.lrsMax = start_vars['lrsMax'] + if "haplotypeAnalystCheck" in start_vars: + self.haplotypeAnalystCheck = start_vars['haplotypeAnalystCheck'] + if "startMb" in start_vars: #ZS: This is to ensure showGenes, Legend, etc are checked the first time you open the mapping page, since startMb will only not be set during the first load + if "permCheck" in start_vars: + self.permCheck = "ON" + else: + self.permCheck = False + self.num_perm = int(start_vars['num_perm']) + + self.LRSCheck = start_vars['LRSCheck'] + + if "showSNP" in start_vars: + self.showSNP = start_vars['showSNP'] + else: + self.showSNP = False + + if "showGenes" in start_vars: + self.showGenes = start_vars['showGenes'] + else: + self.showGenes = False + + if "viewLegend" in start_vars: + self.viewLegend = start_vars['viewLegend'] + else: + self.viewLegend = False + else: + try: + if int(start_vars['num_perm']) > 0: + self.num_perm = int(start_vars['num_perm']) + except: + self.num_perm = 0 + + if self.num_perm > 0: + self.permCheck = "ON" + else: + self.permCheck = False + self.showSNP = "ON" + self.showGenes = "ON" + self.viewLegend = "ON" + + if 'genofile' in start_vars: + if start_vars['genofile'] != "": + self.genofile_string = start_vars['genofile'] + self.dataset.group.genofile = self.genofile_string.split(":")[0] + self.dataset.group.get_markers() + if self.mapping_method == "gemma": + self.score_type = "-log(p)" + self.manhattan_plot = True + with Bench("Running GEMMA"): + marker_obs = gemma_mapping.run_gemma(self.dataset, self.samples, self.vals, self.covariates, self.use_loco, self.maf) + results = marker_obs + elif self.mapping_method == "rqtl_plink": + results = self.run_rqtl_plink() + elif self.mapping_method == "rqtl_geno": + self.score_type = "LOD" + self.mapping_scale = "morgan" + self.control_marker = start_vars['control_marker'] + self.do_control = start_vars['do_control'] + self.method = start_vars['mapmethod_rqtl_geno'] + self.model = start_vars['mapmodel_rqtl_geno'] + #if start_vars['pair_scan'] == "true": + # self.pair_scan = True + if self.permCheck and self.num_perm > 0: + self.perm_output, self.suggestive, self.significant, results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan) + else: + results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan) + elif self.mapping_method == "reaper": + if "startMb" in start_vars: #ZS: Check if first time page loaded, so it can default to ON + if "additiveCheck" in start_vars: + self.additiveCheck = start_vars['additiveCheck'] + else: + self.additiveCheck = False + + if "bootCheck" in start_vars: + self.bootCheck = "ON" + else: + self.bootCheck = False + self.num_bootstrap = int(start_vars['num_bootstrap']) + else: + self.additiveCheck = "ON" + try: + if int(start_vars['num_bootstrap']) > 0: + self.bootCheck = "ON" + self.num_bootstrap = int(start_vars['num_bootstrap']) + else: + self.bootCheck = False + self.num_bootstrap = 0 + except: + self.bootCheck = False + self.num_bootstrap = 0 + + self.control_marker = start_vars['control_marker'] + self.do_control = start_vars['do_control'] + logger.info("Running qtlreaper") + results, self.json_data, self.perm_output, self.suggestive, self.significant, self.bootstrap_results = qtlreaper_mapping.gen_reaper_results(self.this_trait, + self.dataset, + self.samples, + self.vals, + self.json_data, + self.num_perm, + self.bootCheck, + self.num_bootstrap, + self.do_control, + self.control_marker, + self.manhattan_plot) + elif self.mapping_method == "plink": + self.score_type = "-log(p)" + self.manhattan_plot = True + results = plink_mapping.run_plink(self.this_trait, self.dataset, self.species, self.vals, self.maf) + #results = self.run_plink() + elif self.mapping_method == "pylmm": + logger.debug("RUNNING PYLMM") + if self.num_perm > 0: + self.run_permutations(str(temp_uuid)) + results = self.gen_data(str(temp_uuid)) + else: + logger.debug("RUNNING NOTHING") + + if self.pair_scan == True: + self.qtl_results = [] + highest_chr = 1 #This is needed in order to convert the highest chr to X/Y + for marker in results: + if marker['chr1'] > 0 or marker['chr1'] == "X" or marker['chr1'] == "X/Y": + if marker['chr1'] > highest_chr or marker['chr1'] == "X" or marker['chr1'] == "X/Y": + highest_chr = marker['chr1'] + if 'lod_score' in marker.keys(): + self.qtl_results.append(marker) + + self.trimmed_markers = results + + for qtl in enumerate(self.qtl_results): + self.json_data['chr1'].append(str(qtl['chr1'])) + self.json_data['chr2'].append(str(qtl['chr2'])) + self.json_data['Mb'].append(qtl['Mb']) + self.json_data['markernames'].append(qtl['name']) + + self.js_data = dict( + json_data = self.json_data, + this_trait = self.this_trait.name, + data_set = self.dataset.name, + maf = self.maf, + manhattan_plot = self.manhattan_plot, + mapping_scale = self.mapping_scale, + qtl_results = self.qtl_results + ) + + else: + self.qtl_results = [] + highest_chr = 1 #This is needed in order to convert the highest chr to X/Y + for marker in results: + if marker['chr'] > 0 or marker['chr'] == "X" or marker['chr'] == "X/Y": + if marker['chr'] > highest_chr or marker['chr'] == "X" or marker['chr'] == "X/Y": + highest_chr = marker['chr'] + if ('lod_score' in marker.keys()) or ('lrs_value' in marker.keys()): + self.qtl_results.append(marker) + + with Bench("Exporting Results"): + export_mapping_results(self.dataset, self.this_trait, self.qtl_results, self.mapping_results_path, self.mapping_scale, self.score_type) + + with Bench("Trimming Markers for Figure"): + if len(self.qtl_results) > 30000: + self.qtl_results = trim_markers_for_figure(self.qtl_results) + + with Bench("Trimming Markers for Table"): + self.trimmed_markers = trim_markers_for_table(results) + + if self.mapping_method != "gemma": + self.json_data['chr'] = [] + self.json_data['pos'] = [] + self.json_data['lod.hk'] = [] + self.json_data['markernames'] = [] + + self.json_data['suggestive'] = self.suggestive + self.json_data['significant'] = self.significant + + #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary + for index, qtl in enumerate(self.qtl_results): + #if index<40: + # logger.debug("lod score is:", qtl['lod_score']) + if qtl['chr'] == highest_chr and highest_chr != "X" and highest_chr != "X/Y": + #logger.debug("changing to X") + self.json_data['chr'].append("X") + else: + self.json_data['chr'].append(str(qtl['chr'])) + self.json_data['pos'].append(qtl['Mb']) + if 'lrs_value' in qtl.keys(): + self.json_data['lod.hk'].append(str(qtl['lrs_value'])) + else: + self.json_data['lod.hk'].append(str(qtl['lod_score'])) + self.json_data['markernames'].append(qtl['name']) + + #Get chromosome lengths for drawing the interval map plot + chromosome_mb_lengths = {} + self.json_data['chrnames'] = [] + for key in self.species.chromosomes.chromosomes.keys(): + self.json_data['chrnames'].append([self.species.chromosomes.chromosomes[key].name, self.species.chromosomes.chromosomes[key].mb_length]) + chromosome_mb_lengths[key] = self.species.chromosomes.chromosomes[key].mb_length + + self.js_data = dict( + result_score_type = self.score_type, + json_data = self.json_data, + this_trait = self.this_trait.name, + data_set = self.dataset.name, + maf = self.maf, + manhattan_plot = self.manhattan_plot, + mapping_scale = self.mapping_scale, + chromosomes = chromosome_mb_lengths, + qtl_results = self.qtl_results, + num_perm = self.num_perm, + perm_results = self.perm_output, + ) + + def run_rqtl_plink(self): + # os.chdir("") never do this inside a webserver!! + + output_filename = webqtlUtil.genRandStr("%s_%s_"%(self.dataset.group.name, self.this_trait.name)) + + plink_mapping.gen_pheno_txt_file_plink(self.this_trait, self.dataset, self.vals, pheno_filename = output_filename) + + rqtl_command = './plink --noweb --ped %s.ped --no-fid --no-parents --no-sex --no-pheno --map %s.map --pheno %s/%s.txt --pheno-name %s --maf %s --missing-phenotype -9999 --out %s%s --assoc ' % (self.dataset.group.name, self.dataset.group.name, TMPDIR, plink_output_filename, self.this_trait.name, self.maf, TMPDIR, plink_output_filename) + + os.system(rqtl_command) + + count, p_values = self.parse_rqtl_output(plink_output_filename) + + def run_permutations(self, temp_uuid): + """Runs permutations and gets significant and suggestive LOD scores""" + + top_lod_scores = [] + + #logger.debug("self.num_perm:", self.num_perm) + + for permutation in range(self.num_perm): + + pheno_vector = np.array([val == "x" and np.nan or float(val) for val in self.vals]) + np.random.shuffle(pheno_vector) + + key = "pylmm:input:" + temp_uuid + + if self.dataset.group.species == "human": + p_values, t_stats = self.gen_human_results(pheno_vector, key, temp_uuid) + else: + genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers] + + no_val_samples = self.identify_empty_samples() + trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples) + + genotype_matrix = np.array(trimmed_genotype_data).T + + params = dict(pheno_vector = pheno_vector.tolist(), + genotype_matrix = genotype_matrix.tolist(), + restricted_max_likelihood = True, + refit = False, + temp_uuid = temp_uuid, + + # meta data + timestamp = datetime.datetime.now().isoformat(), + ) + + json_params = json.dumps(params) + Redis.set(key, json_params) + Redis.expire(key, 60*60) + + command = PYLMM_COMMAND+' --key {} --species {}'.format(key,"other") + shell(command) + + json_results = Redis.blpop("pylmm:results:" + temp_uuid, 45*60) + results = json.loads(json_results[1]) + p_values = [float(result) for result in results['p_values']] + + lowest_p_value = 1 + for p_value in p_values: + if p_value < lowest_p_value: + lowest_p_value = p_value + + #logger.debug("lowest_p_value:", lowest_p_value) + top_lod_scores.append(-math.log10(lowest_p_value)) + + #logger.debug("top_lod_scores:", top_lod_scores) + + self.suggestive = np.percentile(top_lod_scores, 67) + self.significant = np.percentile(top_lod_scores, 95) + + def gen_data(self, temp_uuid): + """Generates p-values for each marker""" + + logger.debug("self.vals is:", self.vals) + pheno_vector = np.array([(val == "x" or val == "") and np.nan or float(val) for val in self.vals]) + + #lmm_uuid = str(uuid.uuid4()) + + key = "pylmm:input:" + temp_uuid + logger.debug("key is:", pf(key)) + #with Bench("Loading cache"): + # result = Redis.get(key) + + if self.dataset.group.species == "human": + p_values, t_stats = self.gen_human_results(pheno_vector, key, temp_uuid) + + else: + logger.debug("NOW CWD IS:", os.getcwd()) + genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers] + + no_val_samples = self.identify_empty_samples() + trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples) + + genotype_matrix = np.array(genotype_data).T + + #logger.debug("pheno_vector: ", pf(pheno_vector)) + #logger.debug("genotype_matrix: ", pf(genotype_matrix)) + #logger.debug("genotype_matrix.shape: ", pf(genotype_matrix.shape)) + + #params = {"pheno_vector": pheno_vector, + # "genotype_matrix": genotype_matrix, + # "restricted_max_likelihood": True, + # "refit": False, + # "temp_data": tempdata} + + # logger.debug("genotype_matrix:", str(genotype_matrix.tolist())) + # logger.debug("pheno_vector:", str(pheno_vector.tolist())) + + params = dict(pheno_vector = pheno_vector.tolist(), + genotype_matrix = genotype_matrix.tolist(), + restricted_max_likelihood = True, + refit = False, + temp_uuid = temp_uuid, + + # meta data + timestamp = datetime.datetime.now().isoformat(), + ) + + json_params = json.dumps(params) + #logger.debug("json_params:", json_params) + Redis.set(key, json_params) + Redis.expire(key, 60*60) + logger.debug("before printing command") + + command = PYLMM_COMMAND + ' --key {} --species {}'.format(key, "other") + logger.debug("command is:", command) + logger.debug("after printing command") + + shell(command) + + #t_stats, p_values = lmm.run(key) + #lmm.run(key) + + json_results = Redis.blpop("pylmm:results:" + temp_uuid, 45*60) + results = json.loads(json_results[1]) + p_values = [float(result) for result in results['p_values']] + t_stats = results['t_stats'] + + #t_stats, p_values = lmm.run( + # pheno_vector, + # genotype_matrix, + # restricted_max_likelihood=True, + # refit=False, + # temp_data=tempdata + #) + #logger.debug("p_values:", p_values) + + self.dataset.group.markers.add_pvalues(p_values) + + return self.dataset.group.markers.markers + + def gen_human_results(self, pheno_vector, key, temp_uuid): + file_base = locate(self.dataset.group.name,"mapping") + + plink_input = input.plink(file_base, type='b') + input_file_name = os.path.join(webqtlConfig.SNP_PATH, self.dataset.group.name + ".snps.gz") + + pheno_vector = pheno_vector.reshape((len(pheno_vector), 1)) + covariate_matrix = np.ones((pheno_vector.shape[0],1)) + kinship_matrix = np.fromfile(open(file_base + '.kin','r'),sep=" ") + kinship_matrix.resize((len(plink_input.indivs),len(plink_input.indivs))) + + logger.debug("Before creating params") + + params = dict(pheno_vector = pheno_vector.tolist(), + covariate_matrix = covariate_matrix.tolist(), + input_file_name = input_file_name, + kinship_matrix = kinship_matrix.tolist(), + refit = False, + temp_uuid = temp_uuid, + + # meta data + timestamp = datetime.datetime.now().isoformat(), + ) + + logger.debug("After creating params") + + json_params = json.dumps(params) + Redis.set(key, json_params) + Redis.expire(key, 60*60) + + logger.debug("Before creating the command") + + command = PYLMM_COMMAND+' --key {} --species {}'.format(key, "human") + + logger.debug("command is:", command) + + os.system(command) + + json_results = Redis.blpop("pylmm:results:" + temp_uuid, 45*60) + results = json.loads(json_results[1]) + t_stats = results['t_stats'] + p_values = results['p_values'] + + + #p_values, t_stats = lmm.run_human(key) + + #p_values, t_stats = lmm.run_human( + # pheno_vector, + # covariate_matrix, + # input_file_name, + # kinship_matrix, + # loading_progress=tempdata + # ) + + return p_values, t_stats + + def identify_empty_samples(self): + no_val_samples = [] + for sample_count, val in enumerate(self.vals): + if val == "x": + no_val_samples.append(sample_count) + return no_val_samples + + def trim_genotypes(self, genotype_data, no_value_samples): + trimmed_genotype_data = [] + for marker in genotype_data: + new_genotypes = [] + for item_count, genotype in enumerate(marker): + if item_count in no_value_samples: + continue + try: + genotype = float(genotype) + except ValueError: + genotype = np.nan + pass + new_genotypes.append(genotype) + trimmed_genotype_data.append(new_genotypes) + return trimmed_genotype_data + +def export_mapping_results(dataset, trait, markers, results_path, mapping_scale, score_type): + with open(results_path, "w+") as output_file: + output_file.write("Population: " + dataset.group.species.title() + " " + dataset.group.name + "\n") + output_file.write("Data Set: " + dataset.fullname + "\n") + if dataset.type == "ProbeSet": + output_file.write("Gene Symbol: " + trait.symbol + "\n") + output_file.write("Location: " + str(trait.chr) + " @ " + str(trait.mb) + " Mb\n") + output_file.write("\n") + output_file.write("Name,Chr,") + if mapping_scale == "physic": + output_file.write("Mb," + score_type) + else: + output_file.write("Cm," + score_type) + if "additive" in markers[0].keys(): + output_file.write(",Additive") + if "dominance" in markers[0].keys(): + output_file.write(",Dominance") + output_file.write("\n") + for i, marker in enumerate(markers): + output_file.write(marker['name'] + "," + str(marker['chr']) + "," + str(marker['Mb']) + ",") + if "lod_score" in marker.keys(): + output_file.write(str(marker['lod_score'])) + else: + output_file.write(str(marker['lrs_value'])) + if "additive" in marker.keys(): + output_file.write("," + str(marker['additive'])) + if "dominance" in marker.keys(): + output_file.write("," + str(marker['dominance'])) + if i < (len(markers) - 1): + output_file.write("\n") + +def trim_markers_for_figure(markers): + if 'lod_score' in markers[0].keys(): + score_type = 'lod_score' + else: + score_type = 'lrs_value' + + filtered_markers = [] + low_counter = 0 + med_counter = 0 + high_counter = 0 + for marker in markers: + if score_type == 'lod_score': + if marker[score_type] < 1: + if low_counter % 20 == 0: + filtered_markers.append(marker) + low_counter += 1 + elif 1 <= marker[score_type] < 2: + if med_counter % 10 == 0: + filtered_markers.append(marker) + med_counter += 1 + elif 2 <= marker[score_type] <= 3: + if high_counter % 2 == 0: + filtered_markers.append(marker) + high_counter += 1 + else: + filtered_markers.append(marker) + else: + if marker[score_type] < 4.16: + if low_counter % 20 == 0: + filtered_markers.append(marker) + low_counter += 1 + elif 4.16 <= marker[score_type] < (2*4.16): + if med_counter % 10 == 0: + filtered_markers.append(marker) + med_counter += 1 + elif (2*4.16) <= marker[score_type] <= (3*4.16): + if high_counter % 2 == 0: + filtered_markers.append(marker) + high_counter += 1 + else: + filtered_markers.append(marker) + return filtered_markers + +def trim_markers_for_table(markers): + if 'lod_score' in markers[0].keys(): + sorted_markers = sorted(markers, key=lambda k: k['lod_score'], reverse=True) + else: + sorted_markers = sorted(markers, key=lambda k: k['lrs_value'], reverse=True) + + #ZS: So we end up with a list of just 200 markers + if len(sorted_markers) >= 200: + trimmed_sorted_markers = sorted_markers[:200] + return trimmed_sorted_markers + else: + return sorted_markers \ No newline at end of file diff --git a/wqflask/wqflask/snp_browser/snp_browser.py b/wqflask/wqflask/snp_browser/snp_browser.py index df68d4a0..393b8507 100644 --- a/wqflask/wqflask/snp_browser/snp_browser.py +++ b/wqflask/wqflask/snp_browser/snp_browser.py @@ -8,21 +8,27 @@ from utility.logger import getLogger logger = getLogger(__name__ ) from base import species +from base import webqtlConfig class SnpBrowser(object): MAXSNPRETURN = 5000 def __init__(self, start_vars): - self.strain_list = get_browser_sample_list() + self.strain_lists = get_browser_sample_lists() self.initialize_parameters(start_vars) if self.first_run == "false": if self.limit_strains == "true": self.header_fields = get_header_list(self.variant_type, self.chosen_strains) else: - self.header_fields = get_header_list(self.variant_type, self.strain_list) - self.filtered_results = self.get_table_results() + self.header_fields = get_header_list(self.variant_type, self.strain_lists, self.species_name) + self.filtered_results = self.get_browser_results() + + if len(self.filtered_results) <= 5000: + self.table_rows = self.get_table_rows() + else: + self.table_rows = [] def initialize_parameters(self, start_vars): self.first_run = "true" @@ -39,7 +45,7 @@ class SnpBrowser(object): self.species_id = 0 #Using this to indicate "All Species" #ZS: Currently this is just assuming mouse for determining the chromosomes. - # This logic may have to change depending upon what other species are added or how we want to deal with an "All Species" option + # This logic may have to change depending upon what other species are added self.chr_list = [] species_ob = species.TheSpecies(species_name="Mouse") for key in species_ob.chromosomes.chromosomes: @@ -61,7 +67,14 @@ class SnpBrowser(object): self.limit_strains = "true" else: self.limit_strains = "false" - self.chosen_strains = start_vars['chosen_strains'].split(",") + self.chosen_strains_mouse = start_vars['chosen_strains_mouse'].split(",") + self.chosen_strains_rat = start_vars['chosen_strains_rat'].split(",") + + if self.species_id == 1: + self.chosen_strains = self.chosen_strains_mouse + elif self.species_id == 2: + self.chosen_strains = self.chosen_strains_rat + self.domain = start_vars['domain'] self.function = start_vars['function'] self.source = start_vars['source'] @@ -89,15 +102,19 @@ class SnpBrowser(object): self.limit_strains = "true" - self.chosen_strains = ["C57BL/6J", - "DBA/2J", - "A/J", - "129S1/SvImJ", - "NOD/ShiLtJ", - "NZO/HlLtJ", - "WSB/EiJ", - "PWK/PhJ", - "CAST/EiJ"] + self.chosen_strains_mouse = ["C57BL/6J", + "DBA/2J", + "A/J", + "129S1/SvImJ", + "NOD/ShiLtJ", + "NZO/HlLtJ", + "WSB/EiJ", + "PWK/PhJ", + "CAST/EiJ"] + self.chosen_strains_rat = ["F344"] + self.chosen_strains_all = self.chosen_strains_mouse + self.chosen_strains_rat + + self.chosen_strains = self.chosen_strains_mouse self.domain = "All" self.function = "All" @@ -108,11 +125,14 @@ class SnpBrowser(object): self.redundant = "false" self.diff_alleles = "true" - def get_table_results(self): + def get_browser_results(self): self.snp_list = None if self.gene_name != "": - query = "SELECT geneSymbol, chromosome, txStart, txEnd FROM GeneList WHERE SpeciesId = %s AND geneSymbol = %s" % (self.species_id, self.gene_name) + if self.species_id != 0: + query = "SELECT geneSymbol, chromosome, txStart, txEnd FROM GeneList WHERE SpeciesId = %s AND geneSymbol = '%s'" % (self.species_id, self.gene_name) + else: + query = "SELECT geneSymbol, chromosome, txStart, txEnd FROM GeneList WHERE geneSymbol = '%s'" % (self.gene_name) result = g.db.execute(query).fetchone() if result: self.gene_name, self.chr, self.start_mb, self.end_mb = result @@ -120,9 +140,12 @@ class SnpBrowser(object): result_snp = None if self.variant_type == "SNP": if self.gene_name[:2] == "rs": - query = "SELECT Id, Chromosome, Position, Position+0.000001 FROM SnpAll WHERE Rs = %s" % self.gene_name + query = "SELECT Id, Chromosome, Position, Position+0.000001 FROM SnpAll WHERE Rs = '%s'" % self.gene_name else: - query = "SELECT Id, Chromosome, Position, Position+0.000001 ForM SnpAll where SpeciesId = %s AND SnpName = %s" % (self.species_id, self.gene_name) + if self.species_id != 0: + query = "SELECT Id, Chromosome, Position, Position+0.000001 ForM SnpAll where SpeciesId = %s AND SnpName = '%s'" % (self.species_id, self.gene_name) + else: + query = "SELECT Id, Chromosome, Position, Position+0.000001 ForM SnpAll where SnpName = '%s'" % (self.gene_name) result_snp = g.db.execute(query).fetchall() if result_snp: self.snp_list = [item[0] for item in result_snp] @@ -133,7 +156,10 @@ class SnpBrowser(object): return elif self.variant_type == "InDel": if self.gene_name[0] == "I": - query = "SELECT Id, Chromosome, Mb_start, Mb_end FROM IndelAll WHERE SpeciesId = %s AND Name = %s" % (self.species_id, self.gene_name) + if self.species_id != 0: + query = "SELECT Id, Chromosome, Mb_start, Mb_end FROM IndelAll WHERE SpeciesId = %s AND Name = '%s'" % (self.species_id, self.gene_name) + else: + query = "SELECT Id, Chromosome, Mb_start, Mb_end FROM IndelAll WHERE Name = '%s'" % (self.gene_name) result_snp = g.db.execute(query).fetchall() if result_snp: self.snp_list = [item[0] for item in result_snp] @@ -144,29 +170,59 @@ class SnpBrowser(object): return if self.variant_type == "SNP": - query = """ + mouse_query = """ SELECT - a.*, b.* + a.*, b.* FROM - SnpAll a, SnpPattern b + SnpAll a, SnpPattern b WHERE - a.SpeciesId = %s AND a.Chromosome = '%s' AND - a.Position >= %.6f AND a.Position < %.6f AND - a.Id = b.SnpId + a.SpeciesId = %s AND a.Chromosome = '%s' AND + a.Position >= %.6f AND a.Position < %.6f AND + a.Id = b.SnpId ORDER BY a.Position """ % (self.species_id, self.chr, self.start_mb, self.end_mb) - elif self.variant_type == "InDel": - query = """ + + rat_query = """ SELECT - DISTINCT a.Name, a.Chromosome, a.SourceId, a.Mb_start, a.Mb_end, a.Strand, a.Type, a.Size, a.InDelSequence, b.Name + a.*, b.* FROM - IndelAll a, SnpSource b + SnpAll a, RatSnpPattern b WHERE + a.SpeciesId = %s AND a.Chromosome = '%s' AND + a.Position >= %.6f AND a.Position < %.6f AND + a.Id = b.SnpId + ORDER BY a.Position + """ % (self.species_id, self.chr, self.start_mb, self.end_mb) + if self.species_id == 1: + query = mouse_query + elif self.species_id == 2: + query = rat_query + + elif self.variant_type == "InDel": + if species_id != 0: + query = """ + SELECT + DISTINCT a.Name, a.Chromosome, a.SourceId, a.Mb_start, a.Mb_end, a.Strand, a.Type, a.Size, a.InDelSequence, b.Name + FROM + IndelAll a, SnpSource b + WHERE a.SpeciesId = '%s' AND a.Chromosome = '%s' AND a.Mb_start >= %2.6f AND a.Mb_start < (%2.6f+.0010) AND b.Id = a.SourceId - ORDER BY a.Mb_start - """ % (self.species_id, self.chr, self.start_mb, self.end_mb) + ORDER BY a.Mb_start + """ % (self.species_id, self.chr, self.start_mb, self.end_mb) + else: + query = """ + SELECT + DISTINCT a.Name, a.Chromosome, a.SourceId, a.Mb_start, a.Mb_end, a.Strand, a.Type, a.Size, a.InDelSequence, b.Name + FROM + IndelAll a, SnpSource b + WHERE + a.Chromosome = '%s' AND + a.Mb_start >= %2.6f AND a.Mb_start < (%2.6f+.0010) AND + b.Id = a.SourceId + ORDER BY a.Mb_start + """ % (self.chr, self.start_mb, self.end_mb) results_all = g.db.execute(query).fetchall() @@ -179,7 +235,7 @@ class SnpBrowser(object): if self.limit_strains == "true" and len(self.chosen_strains) > 0: for item in self.chosen_strains: - index = self.strain_list.index(item) + index = self.strain_lists[self.species_name.lower()].index(item) strain_index_list.append(index) for seq, result in enumerate(results): @@ -189,11 +245,17 @@ class SnpBrowser(object): display_strains = [] snp_id, species_id, snp_name, rs, chr, mb, mb_2016, alleles, snp_source, conservation_score = result[:10] effect_list = result[10:26] - self.allele_list = result[27:] + if self.species_id == 1: + self.allele_list = result[27:] + elif self.species_id == 2: + self.allele_list = result[28:] if self.limit_strains == "true" and len(self.chosen_strains) > 0: for index in strain_index_list: - display_strains.append(result[27+index]) + if self.species_id == 1: + display_strains.append(result[27+index]) + elif self.species_id == 2: + display_strains.append(result[28+index]) self.allele_list = display_strains effect_info_dict = get_effect_info(effect_list) @@ -266,6 +328,150 @@ class SnpBrowser(object): return filtered_results + def get_table_rows(self): + """ Take results and put them into the order and format necessary for the tables rows """ + + if self.variant_type == "SNP": + gene_name_list = [] + for item in self.filtered_results: + if item[5] and item[5] != "": + gene_name = item[5][1] + # eliminate duplicate gene_name + if gene_name and (gene_name not in gene_name_list): + gene_name_list.append(gene_name) + if len(gene_name_list) > 0: + gene_id_name_dict = get_gene_id_name_dict(gene_name_list) + + the_rows = [] + for result in self.filtered_results: + this_row = [] + if self.variant_type == "SNP": + snp_name, rs, chr, mb, alleles, gene, transcript, exon, domain, function, function_details, snp_source, conservation_score, snp_id = result[:14] + allele_value_list = result[14:] + if rs: + snp_url = webqtlConfig.DBSNP % (rs) + snp_name = rs + else: + rs = "" + start_bp = int(mb*1000000 - 100) + end_bp = int(mb*1000000 + 100) + position_info = "chr%s:%d-%d" % (chr, start_bp, end_bp) + if self.species_id == 2: + snp_url = webqtlConfig.GENOMEBROWSER_URL % ("rn6", position_info) + else: + snp_url = webqtlConfig.GENOMEBROWSER_URL % ("mm10", position_info) + + mb = float(mb) + mb_formatted = "%2.6f" % mb + + if snp_source == "Sanger/UCLA": + source_url_1 = "http://www.sanger.ac.uk/resources/mouse/genomes/" + source_url_2 = "http://mouse.cs.ucla.edu/mousehapmap/beta/wellcome.html" + source_urls = [source_url_1, source_url_2] + else: + source_urls = [] + + if not conservation_score: + conservation_score = "" + + if gene: + gene_name = gene[1] + # if gene_name has related gene_id, use gene_id for NCBI search + if (gene_name in gene_id_name_dict) and (gene_id_name_dict[gene_name] != None and gene_id_name_dict[gene_name] != ""): + gene_id = gene_id_name_dict[gene[1]] + gene_link = webqtlConfig.NCBI_LOCUSID % gene_id + else: + gene_link = "http://www.ncbi.nln.nih.gov/entrez/query.fcgi?CMD=search&DB=gene&term=%s" % gene_name + else: + gene_name = "" + gene_link = "" + + if transcript: + transcript_link = webqtlConfig.ENSEMBLETRANSCRIPT_URL % (transcript) + else: + transcript_link = "" + + if exon: + exon = exon[1] # exon[0] is exon_id, exon[1] is exon_rank + else: + exon = "1" + + if domain: + domain_1 = domain[0] + domain_2 = domain[1] + if domain_1 == "Exon": + domain_1 = domain_1 + " " + exon + + function_list = [] + if function_details: + function_list = string.split(string.strip(function_details), ",") + function_list = map(string.strip, function_list) + function_list[0] = function_list[0].title() + function_details = ", ".join(item for item in function_list) + function_details = function_details.replace("_", " ") + function_details = function_details.replace("/", " -> ") + if function_details == "Biotype: Protein Coding": + function_details = function_details + ", Coding Region Unknown" + + #[snp_href, chr, mb_formatted, alleles, snp_source_cell, conservation_score, gene_name_cell, transcript_href, exon, domain_1, domain_2, function, function_details] + + base_color_dict = {"A": "#C33232", "C": "#1569C7", "T": "#CFCF32", "G": "#32C332", + "t": "#FF6", "c": "#5CB3FF", "a": "#F66", "g": "#CF9", ":": "#FFFFFF", "-": "#FFFFFF", "?": "#FFFFFF"} + + + the_bases = [] + for j, item in enumerate(allele_value_list): + if item: + this_base = [item, base_color_dict[item]] + else: + this_base = "" + + the_bases.append(this_base) + + this_row = { + "rs": rs, + "snp_url": snp_url, + "snp_name": snp_name, + "chr": chr, + "mb_formatted": mb_formatted, + "alleles": alleles, + "snp_source": snp_source, + "source_urls": source_urls, + "conservation_score": conservation_score, + "gene_name": gene_name, + "gene_link": gene_link, + "transcript": transcript, + "transcript_link": transcript_link, + "exon": exon, + "domain_1": domain_1, + "domain_2": domain_2, + "function": function, + "function_details": function_details, + "allele_value_list": the_bases + } + + elif self.variant_type == "InDel": + indel_name, indel_chr, indel_mb_s, indel_mb_e, indel_strand, indel_type, indel_size, indel_sequence, source_name = result + this_row = { + "indel_name": indel_name, + "indel_chr": indel_chr, + "indel_mb_s": indel_mb_s, + "indel_mb_e": indel_mb_e, + "indel_strand": indel_strand, + "indel_type": indel_type, + "indel_size": indel_size, + "indel_sequence": indel_sequence, + "source_name": source_name + } + #this_row = [indel_name, indel_chr, indel_mb_s, indel_mb_e, indel_strand, indel_type, indel_size, indel_sequence, source_name] + else: + this_row = {} + + the_rows.append(this_row) + + return the_rows + + def include_record(self, domain, function, snp_source, conservation_score): """ Decide whether to add this record """ @@ -304,7 +510,10 @@ class SnpBrowser(object): function_satisfied = False else: function_satisfied = False - if function.startswith(self.function): + if self.function != "All": + if function.startswith(self.function): + function_satisfied = True + else: function_satisfied = True else: if self.function != "All": @@ -358,23 +567,39 @@ class SnpBrowser(object): return domain_satisfied and function_satisfied and source_satisfied and score_satisfied and different_alleles_satisfied -def get_browser_sample_list(species_id=1): - sample_list = [] +def get_browser_sample_lists(species_id=1): + strain_lists = {} + mouse_strain_list = [] query = "SHOW COLUMNS FROM SnpPattern;" results = g.db.execute(query).fetchall(); for result in results[1:]: - sample_list.append(result[0]) + mouse_strain_list.append(result[0]) + + rat_strain_list = [] + query = "SHOW COLUMNS FROM RatSnpPattern;" + results = g.db.execute(query).fetchall(); + for result in results[2:]: + rat_strain_list.append(result[0]) + + strain_lists['mouse'] = mouse_strain_list + strain_lists['rat'] = rat_strain_list - return sample_list + return strain_lists -def get_header_list(variant_type, strain_list): +def get_header_list(variant_type, strains, species = None): + if species == "Mouse": + strain_list = strains['mouse'] + elif species == "Rat": + strain_list = strains['rat'] + else: + strain_list = strains + + header_fields = [] if variant_type == "SNP": - header_fields = ['Index', 'SNP ID', 'Chr', 'Mb', 'Alleles', 'Source', 'ConScore', 'Gene', 'Transcript', 'Exon', 'Domain 1', 'Domain 2', 'Function', 'Details'] - header_fields.extend(strain_list) + header_fields.append(['Index', 'SNP ID', 'Chr', 'Mb', 'Alleles', 'Source', 'ConScore', 'Gene', 'Transcript', 'Exon', 'Domain 1', 'Domain 2', 'Function', 'Details']) + header_fields.append(strain_list) elif variant_type == "InDel": header_fields = ['Index', 'ID', 'Type', 'InDel Chr', 'Mb Start', 'Mb End', 'Strand', 'Size', 'Sequence', 'Source'] - else: - header_fields = [] return header_fields @@ -454,7 +679,7 @@ def get_effect_info(effect_list): effect_detail_list = get_effect_details_by_category(effect_name='Splice Site', effect_value=splice_site) effect_info_dict[domain] = effect_detail_list if nonsplice_site: - domain = "Downstream" + domain = "Nonsplice Site" effect_detail_list = get_effect_details_by_category(effect_name='Nonsplice Site', effect_value=nonsplice_site) effect_info_dict[domain] = effect_detail_list # get gene, transcript_list, and exon info @@ -498,3 +723,29 @@ def get_effect_info(effect_list): effect_info_dict[domain] = effect_detail_list return effect_info_dict + +def get_gene_id_name_dict(gene_name_list): + gene_id_name_dict = {} + if len(gene_name_list) == 0: + return "" + gene_name_str_list = ["'" + gene_name + "'" for gene_name in gene_name_list] + gene_name_str = string.join(gene_name_str_list, ",") + + query = """ + SELECT + geneId, geneSymbol + FROM + GeneList + WHERE + SpeciesId = 1 AND geneSymbol in (%s) + """ % gene_name_str + + results = g.db.execute(query).fetchall() + + if len(results) > 0: + for item in results: + gene_id_name_dict[item[1]] = item[0] + else: + pass + + return gene_id_name_dict diff --git a/wqflask/wqflask/static/new/css/show_trait.css b/wqflask/wqflask/static/new/css/show_trait.css index 1e9fd4df..135a7643 100644 --- a/wqflask/wqflask/static/new/css/show_trait.css +++ b/wqflask/wqflask/static/new/css/show_trait.css @@ -8,4 +8,8 @@ tr .outlier { div.sample_group { overflow: auto; # needed because it contains float dataTable wrapper +} + +.js-plotly-plot .plotly .modebar { + left: 100px; } \ No newline at end of file diff --git a/wqflask/wqflask/static/new/css/snp_browser.css b/wqflask/wqflask/static/new/css/snp_browser.css new file mode 100644 index 00000000..c1adaf20 --- /dev/null +++ b/wqflask/wqflask/static/new/css/snp_browser.css @@ -0,0 +1,22 @@ +.form_group { + margin-bottom 5px; +} + +table.dataTable thead th { + vertical-align: bottom; +} + +table.dataTable thead .sorting, +table.dataTable thead .sorting_asc, +table.dataTable thead .sorting_desc, +table.dataTable thead .sorting_asc_disabled, +table.dataTable thead .sorting_desc_disabled { + background-repeat: no-repeat; + background-position: bottom right; +} + +table.dataTable thead th{ + border-right: 1px solid white; + color: white; + background-color: royalblue; +} \ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot.js b/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot.js index be0b96a1..a74c99d3 100644 --- a/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot.js +++ b/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot.js @@ -23,7 +23,8 @@ var layout = { visible: true, linecolor: 'black', linewidth: 1, - } + }, + hovermode: "closest" } cofactor1_dict = {} diff --git a/wqflask/wqflask/static/new/javascript/plotly_probability_plot.js b/wqflask/wqflask/static/new/javascript/plotly_probability_plot.js index ad06ff6a..1585b0ad 100644 --- a/wqflask/wqflask/static/new/javascript/plotly_probability_plot.js +++ b/wqflask/wqflask/static/new/javascript/plotly_probability_plot.js @@ -183,7 +183,8 @@ visible: true, linecolor: 'black', linewidth: 1, - } + }, + hovermode: "closest" } var primary_trace = { diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js index a0a98437..a3edd0e6 100644 --- a/wqflask/wqflask/static/new/javascript/show_trait.js +++ b/wqflask/wqflask/static/new/javascript/show_trait.js @@ -776,6 +776,12 @@ sample_group_list = [js_data.sample_group_types['samples_primary']] } + // Define Plotly Options (for the options bar at the top of each figure) + + root.modebar_options = { + modeBarButtonsToRemove:['hoverClosest', 'hoverCompare', 'hoverClosestCartesian', 'hoverCompareCartesian', 'lasso2d', 'toggleSpikelines'] + } + // Bar Chart root.errors_exist = get_sample_errors(sample_lists[0])[1] @@ -822,7 +828,13 @@ range_bottom = 0 } } - if (get_sample_vals(sample_lists[0]).length < 256) { + + total_sample_count = 0 + for (i = 0, i < sample_lists.length; i++) { + total_sample_count += get_sample_vals(sample_lists[i]).length + } + + if (total_sample_count < 256) { bar_chart_width = 25 * get_sample_vals(sample_lists[0]).length var layout = { @@ -839,7 +851,7 @@ } }; root.bar_layout = layout - Plotly.newPlot('bar_chart', root.bar_data, root.bar_layout) + Plotly.newPlot('bar_chart', root.bar_data, root.bar_layout, root.modebar_options) } if (full_sample_lists.length > 1) { @@ -947,14 +959,14 @@ data: box_data, layout: root.box_layout } - Plotly.newPlot('box_plot', obj); + Plotly.newPlot('box_plot', obj, root.modebar_options); // Violin Plot if (full_sample_lists.length > 1) { root.violin_layout = { title: "Violin Plot", - xaxis: { + yaxis: { range: [range_bottom, range_top], zeroline: false }, @@ -963,12 +975,12 @@ margin: { l: 50, r: 30, - t: 30, + t: 80, b: 80 } }; var trace1 = { - x: get_sample_vals(full_sample_lists[2]), + y: get_sample_vals(full_sample_lists[2]), type: 'violin', points: 'none', box: { @@ -981,10 +993,10 @@ visible: true }, name: sample_group_list[2], - y0: sample_group_list[2] + x0: sample_group_list[2] } var trace2 = { - x: get_sample_vals(full_sample_lists[1]), + y: get_sample_vals(full_sample_lists[1]), type: 'violin', points: 'none', box: { @@ -997,10 +1009,10 @@ visible: true }, name: sample_group_list[1], - y0: sample_group_list[1] + x0: sample_group_list[1] } var trace3 = { - x: get_sample_vals(full_sample_lists[0]), + y: get_sample_vals(full_sample_lists[0]), type: 'violin', points: 'none', box: { @@ -1013,13 +1025,13 @@ visible: true }, name: sample_group_list[0], - y0: sample_group_list[0] + x0: sample_group_list[0] } violin_data = [trace1, trace2, trace3] } else { root.violin_layout = { title: "Violin Plot", - xaxis: { + yaxis: { range: [range_bottom, range_top], zeroline: false }, @@ -1028,13 +1040,13 @@ margin: { l: 50, r: 30, - t: 30, + t: 80, b: 80 } }; violin_data = [ { - x: get_sample_vals(full_sample_lists[0]), + y: get_sample_vals(full_sample_lists[0]), type: 'violin', points: 'none', box: { @@ -1047,7 +1059,7 @@ visible: true }, name: sample_group_list[0], - y0: sample_group_list[0] + x0: sample_group_list[0] } ] } @@ -1057,7 +1069,7 @@ layout: root.violin_layout } - Plotly.plot('violin_plot', obj) + Plotly.plot('violin_plot', obj, root.modebar_options) // Histogram var hist_trace = { @@ -1077,7 +1089,7 @@ b: 60 } }; - Plotly.newPlot('histogram', data, layout) + Plotly.newPlot('histogram', data, layout, root.modebar_options) update_histogram_width() diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html index 3df4c81a..81c04db5 100644 --- a/wqflask/wqflask/templates/base.html +++ b/wqflask/wqflask/templates/base.html @@ -51,6 +51,9 @@ {% endif %} +
  • + SNP Browser +
  • Help
  • diff --git a/wqflask/wqflask/templates/loading.html b/wqflask/wqflask/templates/loading.html index 43488c75..99fa4a89 100644 --- a/wqflask/wqflask/templates/loading.html +++ b/wqflask/wqflask/templates/loading.html @@ -1,6 +1,6 @@ Loading Mapping Results -
    + {% for key, value in start_vars.iteritems() %} {% endfor %} diff --git a/wqflask/wqflask/templates/mapping_results.html b/wqflask/wqflask/templates/mapping_results.html new file mode 100644 index 00000000..5fb2c95e --- /dev/null +++ b/wqflask/wqflask/templates/mapping_results.html @@ -0,0 +1,431 @@ +{% extends "base.html" %} +{% block title %}Mapping Results{% endblock %} +{% block css %} + + + + + +{% endblock %} +{% from "base_macro.html" import header %} +{% block content %} +
    + + + + + + + + + {% for sample in samples %} + + {% endfor %} + + + + + + + + + + + + + + +
    +
    +

    Map Viewer: Whole Genome


    + Population: {{ dataset.group.species|capitalize }} {{ dataset.group.name }}
    + Database: {{ dataset.fullname }}
    + {% if dataset.type == "ProbeSet" %}Trait ID:{% else %}Record ID:{% endif %} {{ this_trait.name }}
    + {% if dataset.type == "ProbeSet" %} + Gene Symbol: {{ this_trait.symbol }}
    + Location: Chr {{ this_trait.chr }} @ {{ this_trait.mb }} Mb
    + {% endif %} + {% if genofile_string is defined %} + Genotypes: {{ genofile_string.split(":")[1] }} + {% endif %} +
    +
    + Download Full Results +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + +
    Chr:  +   + +
    View:  + to +
    Units:  + + + + ? + +
    + units on the y-axis (0 for default) +
    Width:  + pixels (minimum=900) +
    +
    +
    + {% if (mapping_method == "reaper" or mapping_method == "rqtl_geno") and nperm > 0 %} + Permutation Test + + ? + +
    + {% endif %} + {% if mapping_method == "reaper" and nboot > 0 %} + Bootstrap Test + + ? + +
    + {% endif %} + {% if mapping_method == "reaper" %} + Allele Effects + + ? + +
    + {% endif %} + SNP Track + + ? + + * +
    + Gene Track *
    + {% if plotScale != "morgan" and mapping_method != "gemma" and mapping_method != "plink" %} + Haplotype Analyst *
    + {% endif %} + Legend +
    +
    + * only apply to single chromosome physical mapping +
    +
    +
    + +
    + +
    +
    +
    + {{ gifmap|safe }} + + {% if additiveChecked|upper == "ON" %} +
    + A positive additive coefficient (green line) indicates that {{ dataset.group.parlist[1] }} alleles increase trait values. In contrast, a negative additive coefficient (orange line) indicates that {{ dataset.group.parlist[0] }} alleles increase trait values. + {% endif %} + {% if nperm > 0 and permChecked == "ON" %} +

    + +

    + Total of {{ nperm }} permutations  Download Permutation Results +
    + {% endif %} +
    +
    + {% if mapping_method != "gemma" and mapping_method != "plink" %} +
    +
    +
    +
    +
    + {% endif %} +
    +
    + + + {% if selectedChr == -1 %} +
    +

    Mapping Statistics

    +
    + + + + +
    +
    +
    + + + + + + + + + {% if plotScale != "physic" %} + + {% else %} + + {% endif %} + {% if 'additive' in trimmed_markers[0] %} + + {% endif %} + {% if 'dominance' in trimmed_markers[0] and dataset.group.genetic_type != "riset" %} + + {% endif %} + + + + {% for marker in trimmed_markers %} + + + + + {% if LRS_LOD == "LOD" or LRS_LOD == "-log(p)" %} + {% if 'lod_score' in marker %} + + {% else %} + + {% endif %} + {% else %} + {% if 'lod_score' in marker %} + + {% else %} + + {% endif %} + {% endif %} + + {% if plotScale != "physic" %} + + {% else %} + + {% endif %} + {% if 'additive' in marker %} + + {% endif %} + {% if 'dominance' in marker and dataset.group.genetic_type != "riset" %} + + {% endif %} + + {% endfor %} + +
    RowLocus{{ LRS_LOD }}ChrcMMbAdd EffDom Eff
    + + {{ loop.index }}{% if geno_db_exists == "True" %}{{ marker.name }}{% else %}{{ marker.name }}{% endif %}{{ '%0.2f' | format(marker.lod_score|float) }}{{ '%0.2f' | format(marker.lrs_value|float / 4.16) }}{{ '%0.2f' | format(marker.lod_score|float * 4.16) }}{{ '%0.2f' | format(marker.lrs_value|float) }}{{marker.chr}}{{ '%0.3f' | format(marker.Mb|float) }}{{ '%0.6f' | format(marker.Mb|float) }}{{ '%0.3f' | format(marker.additive|float) }}{{ '%0.2f' | format(marker.dominance|float) }}
    +
    +
    + {% elif selectedChr != -1 and plotScale =="physic" and (dataset.group.species == 'mouse' or dataset.group.species == 'rat') %} +
    +

    Interval Analyst

    +
    + + + + {% for header in gene_table_header %} + + {% endfor %} + + + + {% for row in gene_table_body %} + + {% for n in range(row|length) %} + + {% endfor %} + + {% endfor %} + +
    {{ header|safe }}
    {{ row[n]|safe }}
    +
    +
    + {% endif %} +
    + + + +{% endblock %} + +{% block js %} + + + + + + + + + + + + {% if mapping_method != "gemma" and mapping_method != "plink" %} + + {% endif %} + + + {% if mapping_method != "gemma" and mapping_method != "plink" %} + + + + + {% endif %} + + + +{% endblock %} + diff --git a/wqflask/wqflask/templates/marker_regression_gn1.html b/wqflask/wqflask/templates/marker_regression_gn1.html deleted file mode 100644 index fd083983..00000000 --- a/wqflask/wqflask/templates/marker_regression_gn1.html +++ /dev/null @@ -1,431 +0,0 @@ -{% extends "base.html" %} -{% block title %}Mapping Results{% endblock %} -{% block css %} - - - - - -{% endblock %} -{% from "base_macro.html" import header %} -{% block content %} -
    -
    - - - - - - - - {% for sample in samples %} - - {% endfor %} - - - - - - - - - - - - - - -
    -
    -

    Map Viewer: Whole Genome


    - Population: {{ dataset.group.species|capitalize }} {{ dataset.group.name }}
    - Database: {{ dataset.fullname }}
    - {% if dataset.type == "ProbeSet" %}Trait ID:{% else %}Record ID:{% endif %} {{ this_trait.name }}
    - {% if dataset.type == "ProbeSet" %} - Gene Symbol: {{ this_trait.symbol }}
    - Location: Chr {{ this_trait.chr }} @ {{ this_trait.mb }} Mb
    - {% endif %} - {% if genofile_string is defined %} - Genotypes: {{ genofile_string.split(":")[1] }} - {% endif %} -
    -
    - Download Full Results -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - -
    Chr:  -   - -
    View:  - to -
    Units:  - - - - ? - -
    - units on the y-axis (0 for default) -
    Width:  - pixels (minimum=900) -
    -
    -
    - {% if (mapping_method == "reaper" or mapping_method == "rqtl_geno") and nperm > 0 %} - Permutation Test - - ? - -
    - {% endif %} - {% if mapping_method == "reaper" and nboot > 0 %} - Bootstrap Test - - ? - -
    - {% endif %} - {% if mapping_method == "reaper" %} - Allele Effects - - ? - -
    - {% endif %} - SNP Track - - ? - - * -
    - Gene Track *
    - {% if plotScale != "morgan" and mapping_method != "gemma" and mapping_method != "plink" %} - Haplotype Analyst *
    - {% endif %} - Legend -
    -
    - * only apply to single chromosome physical mapping -
    -
    -
    - -
    - -
    -
    -
    - {{ gifmap|safe }} - - {% if additiveChecked|upper == "ON" %} -
    - A positive additive coefficient (green line) indicates that {{ dataset.group.parlist[1] }} alleles increase trait values. In contrast, a negative additive coefficient (orange line) indicates that {{ dataset.group.parlist[0] }} alleles increase trait values. - {% endif %} - {% if nperm > 0 and permChecked == "ON" %} -

    - -

    - Total of {{ nperm }} permutations  Download Permutation Results -
    - {% endif %} -
    -
    - {% if mapping_method != "gemma" and mapping_method != "plink" %} -
    -
    -
    -
    -
    - {% endif %} -
    -
    - -
    - {% if selectedChr == -1 %} -
    -

    Mapping Statistics

    -
    - - - - -
    -
    -
    - - - - - - - - - {% if plotScale != "physic" %} - - {% else %} - - {% endif %} - {% if 'additive' in trimmed_markers[0] %} - - {% endif %} - {% if 'dominance' in trimmed_markers[0] and dataset.group.genetic_type != "riset" %} - - {% endif %} - - - - {% for marker in trimmed_markers %} - - - - - {% if LRS_LOD == "LOD" or LRS_LOD == "-log(p)" %} - {% if 'lod_score' in marker %} - - {% else %} - - {% endif %} - {% else %} - {% if 'lod_score' in marker %} - - {% else %} - - {% endif %} - {% endif %} - - {% if plotScale != "physic" %} - - {% else %} - - {% endif %} - {% if 'additive' in marker %} - - {% endif %} - {% if 'dominance' in marker and dataset.group.genetic_type != "riset" %} - - {% endif %} - - {% endfor %} - -
    RowLocus{{ LRS_LOD }}ChrcMMbAdd EffDom Eff
    - - {{ loop.index }}{% if geno_db_exists == "True" %}{{ marker.name }}{% else %}{{ marker.name }}{% endif %}{{ '%0.2f' | format(marker.lod_score|float) }}{{ '%0.2f' | format(marker.lrs_value|float / 4.16) }}{{ '%0.2f' | format(marker.lod_score|float * 4.16) }}{{ '%0.2f' | format(marker.lrs_value|float) }}{{marker.chr}}{{ '%0.3f' | format(marker.Mb|float) }}{{ '%0.6f' | format(marker.Mb|float) }}{{ '%0.3f' | format(marker.additive|float) }}{{ '%0.2f' | format(marker.dominance|float) }}
    -
    -
    - {% elif selectedChr != -1 and plotScale =="physic" and (dataset.group.species == 'mouse' or dataset.group.species == 'rat') %} -
    -

    Interval Analyst

    -
    - - - - {% for header in gene_table_header %} - - {% endfor %} - - - - {% for row in gene_table_body %} - - {% for n in range(row|length) %} - - {% endfor %} - - {% endfor %} - -
    {{ header|safe }}
    {{ row[n]|safe }}
    -
    -
    - {% endif %} -
    - - - -{% endblock %} - -{% block js %} - - - - - - - - - - - - {% if mapping_method != "gemma" and mapping_method != "plink" %} - - {% endif %} - - - {% if mapping_method != "gemma" and mapping_method != "plink" %} - - - - - {% endif %} - - - -{% endblock %} - diff --git a/wqflask/wqflask/templates/snp_browser.html b/wqflask/wqflask/templates/snp_browser.html index cbce1449..578bd2fc 100644 --- a/wqflask/wqflask/templates/snp_browser.html +++ b/wqflask/wqflask/templates/snp_browser.html @@ -9,9 +9,10 @@

    Variant Browser Info

    -
    +
    - + +
    @@ -25,17 +26,16 @@
    - + +
    - +
    @@ -75,15 +75,16 @@
    - + {% if species_name == "Mouse" %} + {% for strain in strain_lists['mouse'] %} {% endfor %} - - - - + {% elif species_name == "Rat" %} + {% for strain in strain_lists['rat'] %} + + {% endfor %} + {% endif %}
    @@ -177,32 +178,57 @@
    +
    {% if filtered_results is defined %} - + {% if filtered_results|length > 5000 %} + There are more than 5000 results. Consider limiting your search to a smaller range. + {% else %} +
    + {% if header_fields|length == 2 %} + {% for header in header_fields[0] %} + + {% endfor %} + {% for strain in header_fields[1] %} + + {% endfor %} + {% else %} {% for header in header_fields %} {% endfor %} + {% endif %} - {% for result in filtered_results %} + {% for row in table_rows %} - {% for item in result %} - {% if loop.index > 1 %} - - {% endif %} + + + + + + + + + + + + + + {% for item in row.allele_value_list %} + {% endfor %} {% endfor %}
    {{ header }}{% for letter in strain %}
    {{ letter }}
    {% endfor %}
    {{ header }}
    {{ loop.index }}{{ item }}{% if row.rs != "" %}{{ row.snp_name }}{% else %}{{ row.snp_name }}{% endif %}{{ row.chr }}{{ row.mb_formatted }}{{ row.alleles }}{% if row.snp_source == "Sanger/UCLA" %}Sanger/UCLA{% else %}{{ row.snp_source }}{% endif %}{{ row.conservation_score }}{% if row.gene_name != "" %}{{ row.gene_name }}
    NCBI{% else %}{% endif %}
    {{ row.transcript }}{{ row.exon }}{{ row.domain_1 }}{{ row.domain_2 }}{{ row.function }}{{ row.function_details }}{{ item[0] }}
    + {% endif %} {% endif %} - +
    {% endblock %} @@ -213,6 +239,18 @@ {% if filtered_results is defined %} $("#results_table").DataTable( { + {% if variant_type == "SNP" %} + "columnDefs": [ { + "targets": [0, {% for n in range(15, 15 + allele_list|length) %}, {{ n }}{% endfor %}], + "orderable": false + } ], + {% else %} + "columnDefs": [ { + "targets": 0, + "orderable": false + } ], + {% endif %} + "order": [[1, "asc" ]], "sDom": "tir", "iDisplayLength": -1, "autoWidth": true, @@ -220,14 +258,74 @@ }); {% endif %} + $("#species_select").change(function() { + this_species = $(this).val(); + $("#strain_select").empty() + $("#chosen_strains_select").empty() + + if (this_species == "Mouse") { + {% for strain in strain_lists["mouse"] %} + var option = $('').attr("value", "{{ strain }}").text("{{ strain }}"); + $("select[name=strains]").append(option); + {% endfor %} + + chosen_strains = $("input[name=chosen_strains_mouse]").val().split(",") + } else if (this_species == "Rat") { + {% for strain in strain_lists["rat"] %} + var option = $('').attr("value", "{{ strain }}").text("{{ strain }}"); + $("select[name=strains]").append(option); + {% endfor %} + + chosen_strains = $("input[name=chosen_strains_rat]").val().split(",") + } + + for (i=0; i < chosen_strains.length; i++) { + var option = $('').attr("value", chosen_strains[i]).text(chosen_strains[i]); + $("#chosen_strains_select").append(option) + } + }); + $("input[name=add_strain]").click(function() { var selected_strain = $("select[name=strains] option:selected").val(); $("#chosen_strains_select").append(""); + + var current_species = $("#species_select").val(); + if (current_species == "Mouse") { + stored_strains = $("input[name=chosen_strains_mouse]").val().split(",") + stored_strains.push(selected_strain) + $("input[name=chosen_strains_mouse]").val(stored_strains.join(",")) + } else if (current_species == "Rat") { + stored_strains = $("input[name=chosen_strains_rat]").val().split(",") + stored_strains.push(selected_strain) + $("input[name=chosen_strains_rat]").val(stored_strains.join(",")) + } }); $("input[name=remove_strain]").click(function() { var selected_strain = $("#chosen_strains_select option:selected").val(); $("#chosen_strains_select option[value='" + selected_strain + "']").remove(); + + var current_species = $("#species_select").val(); + + if (current_species == "Mouse") { + stored_strains = $("input[name=chosen_strains_mouse]").val().split(",") + for (i=0; i < stored_strains.length; i++) { + if (stored_strains[i] == selected_strain) { + stored_strains.splice(i, 1); + break; + } + } + $("input[name=chosen_strains_mouse]").val(stored_strains.join(",")) + } else if (current_species == "Rat") { + stored_strains = $("input[name=chosen_strains_rat]").val().split(",") + for (i=0; i < stored_strains.length; i++) { + if (stored_strains[i] == selected_strain) { + stored_strains.splice(i, 1); + break; + } + } + $("input[name=chosen_strains_rat]").val(stored_strains.join(",")) + } }); $("#snp_browser_form").submit(function() { diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py index fdb80040..27e6eed1 100644 --- a/wqflask/wqflask/views.py +++ b/wqflask/wqflask/views.py @@ -44,8 +44,8 @@ from wqflask.show_trait import show_trait from wqflask.show_trait import export_trait_data from wqflask.heatmap import heatmap from wqflask.comparison_bar_chart import comparison_bar_chart -from wqflask.marker_regression import marker_regression -from wqflask.marker_regression import marker_regression_gn1 +from wqflask.marker_regression import run_mapping +from wqflask.marker_regression import display_mapping_results from wqflask.network_graph import network_graph from wqflask.correlation import show_corr_results from wqflask.correlation_matrix import show_corr_matrix @@ -551,10 +551,10 @@ def loading_page(): return rendered_template -@app.route("/marker_regression", methods=('POST',)) -def marker_regression_page(): +@app.route("/run_mapping", methods=('POST',)) +def mapping_results_page(): initial_start_vars = request.form - logger.debug("Marker regression called with initial_start_vars:", initial_start_vars.items()) + logger.debug("Mapping called with initial_start_vars:", initial_start_vars.items()) logger.info(request.url) temp_uuid = initial_start_vars['temp_uuid'] wanted = ( @@ -585,6 +585,7 @@ def marker_regression_page(): 'control_marker', 'control_marker_db', 'do_control', + 'genofile', 'genofile_string', 'pair_scan', 'startMb', @@ -606,10 +607,10 @@ def marker_regression_page(): for key, value in initial_start_vars.iteritems(): if key in wanted or key.startswith(('value:')): start_vars[key] = value - logger.debug("Marker regression called with start_vars:", start_vars) + logger.debug("Mapping called with start_vars:", start_vars) version = "v3" - key = "marker_regression:{}:".format(version) + json.dumps(start_vars, sort_keys=True) + key = "mapping_results:{}:".format(version) + json.dumps(start_vars, sort_keys=True) logger.info("key is:", pf(key)) with Bench("Loading cache"): result = None # Just for testing @@ -625,8 +626,8 @@ def marker_regression_page(): result = pickle.loads(result) else: logger.info("Cache miss!!!") - with Bench("Total time in MarkerRegression"): - template_vars = marker_regression.MarkerRegression(start_vars, temp_uuid) + with Bench("Total time in RunMapping"): + template_vars = run_mapping.RunMapping(start_vars, temp_uuid) if template_vars.mapping_method != "gemma" and template_vars.mapping_method != "plink": template_vars.js_data = json.dumps(template_vars.js_data, @@ -648,10 +649,7 @@ def marker_regression_page(): result['pair_scan_array'] = bytesarray rendered_template = render_template("pair_scan_results.html", **result) else: - #for item in template_vars.__dict__.keys(): - # logger.info(" ---**--- {}: {}".format(type(template_vars.__dict__[item]), item)) - - gn1_template_vars = marker_regression_gn1.MarkerRegression(result).__dict__ + gn1_template_vars = display_mapping_results.DisplayMappingResults(result).__dict__ #pickled_result = pickle.dumps(result, pickle.HIGHEST_PROTOCOL) #logger.info("pickled result length:", len(pickled_result)) #Redis.set(key, pickled_result) @@ -660,24 +658,7 @@ def marker_regression_page(): with Bench("Rendering template"): if (gn1_template_vars['mapping_method'] == "gemma") or (gn1_template_vars['mapping_method'] == "plink"): gn1_template_vars.pop('qtlresults', None) - print("TEMPLATE KEYS:", list(gn1_template_vars.keys())) - rendered_template = render_template("marker_regression_gn1.html", **gn1_template_vars) - - # with Bench("Rendering template"): - # if result['pair_scan'] == True: - # img_path = result['pair_scan_filename'] - # logger.info("img_path:", img_path) - # initial_start_vars = request.form - # logger.info("initial_start_vars:", initial_start_vars) - # imgfile = open(TEMPDIR + '/' + img_path, 'rb') - # imgdata = imgfile.read() - # imgB64 = imgdata.encode("base64") - # bytesarray = array.array('B', imgB64) - # result['pair_scan_array'] = bytesarray - # rendered_template = render_template("pair_scan_results.html", **result) - # else: - # rendered_template = render_template("marker_regression.html", **result) - # rendered_template = render_template("marker_regression_gn1.html", **gn1_template_vars) + rendered_template = render_template("mapping_results.html", **gn1_template_vars) return rendered_template @@ -693,7 +674,6 @@ def export_mapping_results(): return response - @app.route("/export", methods = ('POST',)) def export(): logger.info("request.form:", request.form) -- cgit v1.2.3 From f5bc311907ede5e2cce9539554453f846debd9ae Mon Sep 17 00:00:00 2001 From: zsloan Date: Thu, 1 Nov 2018 19:41:26 +0000 Subject: Updated the way snpbrowser initializes parameters, in preparation for drawing SNP density chart when results exceed a certain value, plus a couple minor fixes Changed the header bar to put a few items under the "Help" option, since previously the header was too long and would go to a second line when the browser window width was smaller Changed dataset info link on trait page to same as one on search page Changed the mapping default to non-LOCO for the time being, until it is faster --- wqflask/wqflask/snp_browser/snp_browser.py | 177 ++++++++++++--------- wqflask/wqflask/static/new/css/main.css | 45 ++++-- .../new/javascript/dataset_menu_structure.json | 111 ++++++------- .../new/javascript/dataset_select_menu_orig.js | 2 +- .../wqflask/static/new/javascript/show_trait.js | 6 +- wqflask/wqflask/templates/base.html | 35 ++-- wqflask/wqflask/templates/show_trait_details.html | 2 +- .../templates/show_trait_mapping_tools.html | 4 +- wqflask/wqflask/templates/snp_browser.html | 5 +- 9 files changed, 217 insertions(+), 170 deletions(-) diff --git a/wqflask/wqflask/snp_browser/snp_browser.py b/wqflask/wqflask/snp_browser/snp_browser.py index 393b8507..0e999ba2 100644 --- a/wqflask/wqflask/snp_browser/snp_browser.py +++ b/wqflask/wqflask/snp_browser/snp_browser.py @@ -1,8 +1,11 @@ from __future__ import absolute_import, print_function, division -from flask import Flask, g +from flask import Flask, g, url_for + +from htmlgen import HTMLgen2 as HT import string +import piddle as pid from utility.logger import getLogger logger = getLogger(__name__ ) @@ -31,99 +34,110 @@ class SnpBrowser(object): self.table_rows = [] def initialize_parameters(self, start_vars): - self.first_run = "true" - self.allele_list = [] - if 'variant' in start_vars: #ZS: Check if not first time loaded (if it has form input) + if 'first_run' in start_vars: self.first_run = "false" + else: + self.first_run = "true" + self.allele_list = [] + + self.variant_type = "SNP" + if 'variant' in start_vars: self.variant_type = start_vars['variant'] + + self.species_name = "Mouse" + self.species_id = 1 + if 'species' in start_vars: self.species_name = start_vars['species'] - if self.species_name.capitalize() == "Mouse": - self.species_id = 1 - elif self.species_name.capitalize() == "Rat": + if self.species_name.capitalize() == "Rat": self.species_id = 2 + + species_ob = species.TheSpecies(species_name=self.species_name) + + self.chr_list = [] + for key in species_ob.chromosomes.chromosomes: + self.chr_list.append(species_ob.chromosomes.chromosomes[key].name) + + if self.first_run == "true": + self.chr = "19" + self.start_mb = 30.1 + self.end_mb = 30.12 + else: + if 'gene_name' in start_vars: + if start_vars['gene_name'] != "": + self.gene_name = start_vars['gene_name'] + else: + self.gene_name = "" + self.chr = start_vars['chr'] + try: + self.start_mb = float(start_vars['start_mb']) + self.end_mb = float(start_vars['end_mb']) + except: + self.start_mb = 0.0 + self.end_mb = 0.0 else: - self.species_id = 0 #Using this to indicate "All Species" - - #ZS: Currently this is just assuming mouse for determining the chromosomes. - # This logic may have to change depending upon what other species are added - self.chr_list = [] - species_ob = species.TheSpecies(species_name="Mouse") - for key in species_ob.chromosomes.chromosomes: - self.chr_list.append(species_ob.chromosomes.chromosomes[key].name) - - if start_vars['gene_name'] != "": - self.gene_name = start_vars['gene_name'] - else: - self.gene_name = "" - self.chr = start_vars['chr'] try: + self.chr = start_vars['chr'] self.start_mb = float(start_vars['start_mb']) self.end_mb = float(start_vars['end_mb']) except: + self.chr = "1" self.start_mb = 0.0 self.end_mb = 0.0 - if 'limit_strains' in start_vars: - self.limit_strains = "true" - else: + self.limit_strains = "true" + if self.first_run == "false": + if 'limit_strains' not in start_vars: self.limit_strains = "false" + else: + if start_vars['limit_strains'] == "false": + self.limit_strains = "false" + + self.chosen_strains_mouse = ["C57BL/6J", + "DBA/2J", + "A/J", + "129S1/SvImJ", + "NOD/ShiLtJ", + "NZO/HlLtJ", + "WSB/EiJ", + "PWK/PhJ", + "CAST/EiJ"] + self.chosen_strains_rat = ["BN", "F344"] + if 'chosen_strains_mouse' in start_vars: self.chosen_strains_mouse = start_vars['chosen_strains_mouse'].split(",") + if 'chosen_strains_rat' in start_vars: self.chosen_strains_rat = start_vars['chosen_strains_rat'].split(",") - if self.species_id == 1: - self.chosen_strains = self.chosen_strains_mouse - elif self.species_id == 2: - self.chosen_strains = self.chosen_strains_rat + if self.species_id == 1: + self.chosen_strains = self.chosen_strains_mouse + else: + self.chosen_strains = self.chosen_strains_rat + self.domain = "All" + if 'domain' in start_vars: self.domain = start_vars['domain'] + self.function = "All" + if 'function' in start_vars: self.function = start_vars['function'] + self.source = "All" + if 'source' in start_vars: self.source = start_vars['source'] + self.criteria = ">=" + if 'criteria' in start_vars: self.criteria = start_vars['criteria'] + self.score = 0.0 + if 'score' in start_vars: self.score = start_vars['score'] - self.redundant = "false" - self.diff_alleles = "false" - if 'redundant' in start_vars: - self.redundant = "true" - if 'diff_alleles' in start_vars: - self.diff_alleles = "true" - - else: #ZS: Default values - self.variant_type = "SNP" - self.species_name = "Mouse" - species_ob = species.TheSpecies(species_name=self.species_name) - self.chr_list = [] - for key in species_ob.chromosomes.chromosomes: - self.chr_list.append(species_ob.chromosomes.chromosomes[key].name) - - self.chr = "19" - self.start_mb = 30.1 - self.end_mb = 30.12 - - self.limit_strains = "true" - - self.chosen_strains_mouse = ["C57BL/6J", - "DBA/2J", - "A/J", - "129S1/SvImJ", - "NOD/ShiLtJ", - "NZO/HlLtJ", - "WSB/EiJ", - "PWK/PhJ", - "CAST/EiJ"] - self.chosen_strains_rat = ["F344"] - self.chosen_strains_all = self.chosen_strains_mouse + self.chosen_strains_rat - - self.chosen_strains = self.chosen_strains_mouse - - self.domain = "All" - self.function = "All" - self.source = "All" - self.criteria = ">=" - self.score = 0.0 - - self.redundant = "false" - self.diff_alleles = "true" + self.redundant = "false" + if self.first_run == "false" and 'redundant' in start_vars: + self.redundant = "true" + self.diff_alleles = "true" + if self.first_run == "false": + if 'diff_alleles' not in start_vars: + self.diff_alleles = "false" + else: + if start_vars['diff_alleles'] == "false": + self.diff_alleles = "false" def get_browser_results(self): self.snp_list = None @@ -567,6 +581,27 @@ class SnpBrowser(object): return domain_satisfied and function_satisfied and source_satisfied and score_satisfied and different_alleles_satisfied + def snp_density_map(self, query, results): + + canvas_width = 900 + canvas_height = 200 + snp_canvas = pid.PILCanvas(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 + y_zero = top_offset + plot_height/2 + + x_scale = plot_width/(self.end_mb - self.start_mb) + + #draw clickable image map + #gifmap = HT.Map + n_click = 80.0 + click_step = plot_width/n_click + click_mb_step = (self.end_mb - self.start_mb)/n_click + + #for i in range(n_click): + # href = url_for('snp_browser', first_run="false", chosen_strains_mouse=self.chosen_strains_mouse, chosen_strains_rat=self.chosen_strains_rat, variant=self.variant_type, species=self.species_name, gene_name=self.gene_name, chr=self.chr, start_mb=self.start_mb, end_mb=self.end_mb, limit_strains=self.limit_strains, domain=self.domain, function=self.function, criteria=self.criteria, score=self.score, diff_alleles=self.diff_alleles) + def get_browser_sample_lists(species_id=1): strain_lists = {} mouse_strain_list = [] diff --git a/wqflask/wqflask/static/new/css/main.css b/wqflask/wqflask/static/new/css/main.css index 880395a7..097cd997 100644 --- a/wqflask/wqflask/static/new/css/main.css +++ b/wqflask/wqflask/static/new/css/main.css @@ -1,11 +1,36 @@ -.security_box { - padding-left: 30px; - padding-right: 30px; -} - -ol { - font-family: Arial; - font-weight: bold; - font-size: 16px; - color: #000082 +@media (max-width: 10px) { + .navbar-header { + float: none; + } + .navbar-toggle { + display: block; + } + .navbar-collapse { + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.1); + } + .navbar-collapse.collapse { + display: none!important; + } + .navbar-nav { + float: none!important; + margin: 7.5px -15px; + } + .navbar-nav>li { + float: none; + } + .navbar-nav>li>a { + padding-top: 10px; + padding-bottom: 10px; + } + .navbar-text { + float: none; + margin: 15px 0; + } + .navbar-collapse.collapse.in { + display: block!important; + } + .collapsing { + overflow: hidden!important; + } } \ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json b/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json index 1c6791c4..9c806a7f 100644 --- a/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json +++ b/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json @@ -2590,21 +2590,6 @@ ] ], "Liver mRNA": [ - [ - "858", - "EPFLMouseLiverHFDRMA0818", - "EPFL/LISP BXD HFD Liver Affy Mouse Gene 1.0 ST (Aug18) RMA" - ], - [ - "852", - "NIA-AgBXD-Liv_HFD-0818", - "NIA Aging BXD HFD Liver Affy Clariom S Gene Level (Aug18) RMA **" - ], - [ - "857", - "EPFLMouseLiverCDHFDRMA0818", - "EPFL/LISP BXD CD+HFD Liver Affy Mouse Gene 1.0 ST (Aug18) RMA" - ], [ "859", "EPFLMouseLiverCDRMA0818", @@ -2625,6 +2610,21 @@ "UCLA_BXD_Liv_Jan16", "UCLA BXD Liver Affy M430 2.0 (Jan16) RMA" ], + [ + "858", + "EPFLMouseLiverHFDRMA0818", + "EPFL/LISP BXD HFD Liver Affy Mouse Gene 1.0 ST (Aug18) RMA" + ], + [ + "852", + "NIA-AgBXD-Liv_HFD-0818", + "NIA Aging BXD HFD Liver Affy Clariom S Gene Level (Aug18) RMA **" + ], + [ + "857", + "EPFLMouseLiverCDHFDRMA0818", + "EPFL/LISP BXD CD+HFD Liver Affy Mouse Gene 1.0 ST (Aug18) RMA" + ], [ "430", "EPFLMouseLiverRMA0413", @@ -2640,6 +2640,11 @@ "EPFLMouseLiverCDRMA0413", "EPFL/LISP BXD CD Liver Affy Mouse Gene 1.0 ST (Apr13) RMA" ], + [ + "433", + "EPFLMouseLiverBothExRMA0413", + "EPFL/LISP BXD CD+HFD Liver Affy Mouse Gene 1.0 ST (Apr13) RMA Exon Level" + ], [ "849", "EPFLMouseLiverCDEx0413", @@ -2650,11 +2655,6 @@ "EPFLMouseLiverHFCEx0413", "EPFL/LISP BXD HFC Liver Affy Mouse Gene 1.0 ST (Apr13) RMA Exon Level" ], - [ - "433", - "EPFLMouseLiverBothExRMA0413", - "EPFL/LISP BXD CD+HFD Liver Affy Mouse Gene 1.0 ST (Apr13) RMA Exon Level" - ], [ "700", "UTHSC-VGX_MmBXDHepatocytesRMA1014", @@ -3671,6 +3671,11 @@ }, "Retina-RGC-Rheaume": { "Retina Single-cell RNA-Seq": [ + [ + "866", + "UConn-RGC-RSeq_log2-0918", + "UConn-Rheaume Retina RGC (Sep18) scRNA-Seq Log2" + ], [ "865", "UConn-RGC-RSeq_r-0918", @@ -3680,11 +3685,6 @@ "867", "UConn-RGC-RSeq_s-0918", "UConn-Rheaume Retina RGC (Sep18) scRNA-Seq Siamak" - ], - [ - "866", - "UConn-RGC-RSeq_log2-0918", - "UConn-Rheaume Retina RGC (Sep18) scRNA-Seq Log2" ] ] }, @@ -3712,16 +3712,18 @@ }, "rat": { "HSNIH-Palmer": { + "Infralimbic Cortex mRNA": [ + [ + "861", + "HSNIH-Rat-IL-RSeq-0818", + "HSNIH-Palmer Infralimbic Cortex RNA-Seq (Aug18) rlog" + ] + ], "Lateral Habenula mRNA": [ [ "862", "HSNIH-Rat-LHB-RSeq-0818", "HSNIH-Palmer Lateral Habenula RNA-Seq (Aug18) rlog" - ], - [ - "870", - "HSNIH-Rat-LHB-RSeqlog2-0818", - "HSNIH-Palmer Lateral Habenula RNA-Seq (Aug18) log2" ] ], "Nucleus Accumbens mRNA": [ @@ -3729,11 +3731,13 @@ "860", "HSNIH-Rat-Acbc-RSeq-0818", "HSNIH-Palmer Nucleus Accumbens Core RNA-Seq (Aug18) rlog" - ], + ] + ], + "Orbitofrontal Cortex mRNA": [ [ - "868", - "HSNIH-Rat-Acbc-RSeqlog2-0818", - "HSNIH-Palmer Nucleus Accumbens Core RNA-Seq (Aug18) log2" + "864", + "HSNIH-Rat-VoLo-RSeq-0818", + "HSNIH-Palmer Orbitofrontal Cortex RNA-Seq (Aug18) rlog" ] ], "Phenotypes": [ @@ -3743,32 +3747,7 @@ "HSNIH-Palmer Phenotypes" ] ], - "Prefrontal Cortex mRNA": [ - [ - "869", - "HSNIH-Rat-IL-RSeqlog2-0818", - "HSNIH-Palmer Infralimbic Cortex RNA-Seq (Aug18) log2" - ], - [ - "872", - "HSNIH-Rat-VoLo-RSeqlog2-0818", - "HSNIH-Palmer Orbitofrontal Cortex RNA-Seq (Aug18) log2" - ], - [ - "861", - "HSNIH-Rat-IL-RSeq-0818", - "HSNIH-Palmer Infralimbic Cortex RNA-Seq (Aug18) rlog" - ], - [ - "864", - "HSNIH-Rat-VoLo-RSeq-0818", - "HSNIH-Palmer Orbitofrontal Cortex RNA-Seq (Aug18) rlog" - ], - [ - "871", - "HSNIH-Rat-PL-RSeqlog2-0818", - "HSNIH-Palmer Prelimbic Cortex RNA-Seq (Aug18) log2" - ], + "Prelimbic Cortex mRNA": [ [ "863", "HSNIH-Rat-PL-RSeq-0818", @@ -5531,6 +5510,10 @@ "Phenotypes", "Phenotypes" ], + [ + "Infralimbic Cortex mRNA", + "Infralimbic Cortex mRNA" + ], [ "Lateral Habenula mRNA", "Lateral Habenula mRNA" @@ -5540,8 +5523,12 @@ "Nucleus Accumbens mRNA" ], [ - "Prefrontal Cortex mRNA", - "Prefrontal Cortex mRNA" + "Orbitofrontal Cortex mRNA", + "Orbitofrontal Cortex mRNA" + ], + [ + "Prelimbic Cortex mRNA", + "Prelimbic Cortex mRNA" ] ], "HSNIH-RGSMC": [ diff --git a/wqflask/wqflask/static/new/javascript/dataset_select_menu_orig.js b/wqflask/wqflask/static/new/javascript/dataset_select_menu_orig.js index d5ce6f84..3f123d6f 100644 --- a/wqflask/wqflask/static/new/javascript/dataset_select_menu_orig.js +++ b/wqflask/wqflask/static/new/javascript/dataset_select_menu_orig.js @@ -94,7 +94,7 @@ $(function() { })(this)); open_window = function(url, name) { var options; - options = "menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=1,directories=1,width=900"; + options = "menubar=yes,toolbar=yes,titlebar=yes,location=yes,resizable=yes,status=yes,scrollbars=yes,directories=yes,width=900"; return open(url, name, options).focus(); }; group_info = function() { diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js index a3edd0e6..c1b0cef9 100644 --- a/wqflask/wqflask/static/new/javascript/show_trait.js +++ b/wqflask/wqflask/static/new/javascript/show_trait.js @@ -829,8 +829,10 @@ } } + root.chart_range = [range_bottom, range_top] + total_sample_count = 0 - for (i = 0, i < sample_lists.length; i++) { + for (i = 0, i < sample_lists.length; i++;) { total_sample_count += get_sample_vals(sample_lists[i]).length } @@ -839,7 +841,7 @@ var layout = { yaxis: { - range: [range_bottom, range_top], + range: root.chart_range, }, width: bar_chart_width, height: 600, diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html index 81c04db5..3d03f3b9 100644 --- a/wqflask/wqflask/templates/base.html +++ b/wqflask/wqflask/templates/base.html @@ -22,17 +22,22 @@ -