diff options
-rw-r--r-- | wqflask/utility/redis_tools.py | 18 | ||||
-rw-r--r-- | wqflask/wqflask/gsearch.py | 5 | ||||
-rw-r--r-- | wqflask/wqflask/marker_regression/display_mapping_results.py | 25 | ||||
-rw-r--r-- | wqflask/wqflask/marker_regression/rqtl_mapping.py | 18 | ||||
-rw-r--r-- | wqflask/wqflask/marker_regression/run_mapping.py | 20 | ||||
-rw-r--r-- | wqflask/wqflask/show_trait/export_trait_data.py | 30 | ||||
-rw-r--r-- | wqflask/wqflask/show_trait/show_trait.py | 88 | ||||
-rw-r--r-- | wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js | 19 | ||||
-rw-r--r-- | wqflask/wqflask/templates/collections/view.html | 8 | ||||
-rw-r--r-- | wqflask/wqflask/templates/correlation_page.html | 8 | ||||
-rw-r--r-- | wqflask/wqflask/templates/mapping_results.html | 4 | ||||
-rwxr-xr-x | wqflask/wqflask/templates/show_trait_mapping_tools.html | 24 | ||||
-rw-r--r-- | wqflask/wqflask/user_manager.py | 22 | ||||
-rw-r--r-- | wqflask/wqflask/views.py | 23 |
14 files changed, 250 insertions, 62 deletions
diff --git a/wqflask/utility/redis_tools.py b/wqflask/utility/redis_tools.py index 0754e16f..573f9945 100644 --- a/wqflask/utility/redis_tools.py +++ b/wqflask/utility/redis_tools.py @@ -78,3 +78,21 @@ def check_verification_code(code): else: return None flash("Invalid code: Password reset code does not exist or might have expired!", "error") + +def get_user_groups(user_id): + #ZS: Get the groups where a user is an admin or a member and return lists corresponding to those two sets of groups + admin_group_ids = [] #ZS: Group IDs where user is an admin + user_group_ids = [] #ZS: Group IDs where user is a regular user + groups_list = Redis.hgetall("groups") + for key in groups_list: + group_ob = json.loads(groups_list[key]) + group_admins = set(group_ob['admins']) + group_users = set(group_ob['users']) + if user_id in group_admins: + admin_group_ids.append(group_ob['id']) + elif user_id in group_users: + user_group_ids.append(group_ob['id']) + else: + continue + + return admin_group_ids, user_group_ids diff --git a/wqflask/wqflask/gsearch.py b/wqflask/wqflask/gsearch.py index 3d9b508a..04e3d578 100644 --- a/wqflask/wqflask/gsearch.py +++ b/wqflask/wqflask/gsearch.py @@ -75,7 +75,10 @@ class GSearch(object): this_trait['group'] = line[1] this_trait['tissue'] = line[2] this_trait['symbol'] = line[6] - this_trait['description'] = line[7].decode('utf-8', 'replace') + if line[7]: + this_trait['description'] = line[7].decode('utf-8', 'replace') + else: + this_trait['description'] = "N/A" this_trait['location_repr'] = 'N/A' if (line[8] != "NULL" and line[8] != "") and (line[9] != 0): this_trait['location_repr'] = 'Chr%s: %.6f' % (line[8], float(line[9])) diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 2a53b60e..f70bc555 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -265,14 +265,12 @@ class DisplayMappingResults(object): else: self.colorCollection = [self.LRS_COLOR] + self.dataset.group.genofile = self.genofile_string.split(":")[0] if self.mapping_method == "reaper" and self.manhattan_plot != True: self.genotype = self.dataset.group.read_genotype_file(use_reaper=True) else: self.genotype = self.dataset.group.read_genotype_file() - #if self.mapping_method == "rqtl_geno" and self.genotype.filler == True: - # self.genotype = self.genotype.read_rdata_output(self.qtlresults) - #Darwing Options try: if self.selectedChr > -1: @@ -1761,9 +1759,9 @@ class DisplayMappingResults(object): break if all_int: - max_lrs_width = canvas.stringWidth("%d" % LRS_LOD_Max, font=LRSScaleFont) + 30 + max_lrs_width = canvas.stringWidth("%d" % LRS_LOD_Max, font=LRSScaleFont) + 40 else: - max_lrs_width = canvas.stringWidth("%2.1f" % LRS_LOD_Max, font=LRSScaleFont) + 20 + max_lrs_width = canvas.stringWidth("%2.1f" % LRS_LOD_Max, font=LRSScaleFont) + 30 #draw the "LRS" or "LOD" string to the left of the axis canvas.drawString(self.LRS_LOD, xLeftOffset - max_lrs_width - 15*(zoom-1), \ @@ -1899,13 +1897,16 @@ class DisplayMappingResults(object): this_chr = str(self.ChrList[self.selectedChr][1]+1) if self.selectedChr == -1 or str(qtlresult['chr']) == this_chr: - if self.plotScale != "physic" and self.genotype.filler == True: - if self.selectedChr != -1: - start_cm = self.genotype[self.selectedChr - 1][0].cM - Xc = startPosX + (qtlresult['Mb'] - start_cm)*plotXScale - else: - start_cm = self.genotype[previous_chr_as_int][0].cM - Xc = startPosX + ((qtlresult['Mb']-start_cm-startMb)*plotXScale)*(((qtlresult['Mb']-start_cm-startMb)*plotXScale)/((qtlresult['Mb']-start_cm-startMb+self.GraphInterval)*plotXScale)) + if self.plotScale != "physic" and self.mapping_method == "reaper" and not self.manhattan_plot: + Xc = startPosX + (qtlresult['cM']-startMb)*plotXScale + if hasattr(self.genotype, "filler"): + if self.genotype.filler: + if self.selectedChr != -1: + start_cm = self.genotype[self.selectedChr - 1][0].cM + Xc = startPosX + (qtlresult['Mb'] - start_cm)*plotXScale + else: + start_cm = self.genotype[previous_chr_as_int][0].cM + Xc = startPosX + ((qtlresult['Mb']-start_cm-startMb)*plotXScale)*(((qtlresult['Mb']-start_cm-startMb)*plotXScale)/((qtlresult['Mb']-start_cm-startMb+self.GraphInterval)*plotXScale)) else: Xc = startPosX + (qtlresult['Mb']-startMb)*plotXScale diff --git a/wqflask/wqflask/marker_regression/rqtl_mapping.py b/wqflask/wqflask/marker_regression/rqtl_mapping.py index 152bb5be..ad3a4cb7 100644 --- a/wqflask/wqflask/marker_regression/rqtl_mapping.py +++ b/wqflask/wqflask/marker_regression/rqtl_mapping.py @@ -124,21 +124,18 @@ def generate_cross_from_geno(dataset): # TODO: Need to figure out why som ro.r(""" trim <- function( x ) { gsub("(^[[:space:]]+|[[:space:]]+$)", "", x) } - getGenoCode <- function(header, name = 'unk'){ mat = which(unlist(lapply(header,function(x){ length(grep(paste('@',name,sep=''), x)) })) == 1) return(trim(strsplit(header[mat],':')[[1]][2])) } - GENOtoCSVR <- function(genotypes = '%s', out = 'cross.csvr', phenotype = NULL, sex = NULL, verbose = FALSE){ header = readLines(genotypes, 40) # Assume a geno header is not longer than 40 lines toskip = which(unlist(lapply(header, function(x){ length(grep("Chr\t", x)) })) == 1)-1 # Major hack to skip the geno headers - type <- getGenoCode(header, 'type') if(type == '4-way'){ genocodes <- c('1','2','3','4') } else { - genocodes <- c(getGenoCode(header, 'mat'), getGenoCode(header, 'het'), getGenoCode(header, 'pat')) # Get the genotype codes + genocodes <- c(getGenoCode(header, 'mat'), getGenoCode(header, 'het'), getGenoCode(header, 'pat')) # Get the genotype codes } genodata <- read.csv(genotypes, sep='\t', skip=toskip, header=TRUE, na.strings=getGenoCode(header,'unk'), colClasses='character', comment.char = '#') cat('Genodata:', toskip, " ", dim(genodata), genocodes, '\n') @@ -149,17 +146,8 @@ def generate_cross_from_geno(dataset): # TODO: Need to figure out why som cbind(genodata[,c('Locus','Chr', 'cM')], genodata[, 5:ncol(genodata)])) # Genotypes write.table(outCSVR, file = out, row.names=FALSE, col.names=FALSE,quote=FALSE, sep=',') # Save it to a file require(qtl) - if(type == '4-way'){ - cat('Loading in as 4-WAY\n') - cross = read.cross(file=out, 'csvr', genotypes=genocodes, crosstype="4way", convertXdata=FALSE) # Load the created cross file using R/qtl read.cross - }else{ - cat('Loading in as normal\n') - cross = read.cross(file=out, 'csvr', genotypes=genocodes) # Load the created cross file using R/qtl read.cross - } - if(type == 'riset'){ - cat('Converting to RISELF\n') - cross <- convert2riself(cross) # If its a RIL, convert to a RIL in R/qtl - } + cross = read.cross(file=out, 'csvr', genotypes=genocodes) # Load the created cross file using R/qtl read.cross + if(type == 'riset') cross <- convert2riself(cross) # If its a RIL, convert to a RIL in R/qtl return(cross) } """ % (dataset.group.genofile)) diff --git a/wqflask/wqflask/marker_regression/run_mapping.py b/wqflask/wqflask/marker_regression/run_mapping.py index 589be702..5f7710ab 100644 --- a/wqflask/wqflask/marker_regression/run_mapping.py +++ b/wqflask/wqflask/marker_regression/run_mapping.py @@ -124,7 +124,7 @@ class RunMapping(object): self.samples.append(sample) self.vals.append(value) - self.num_vals = start_vars['num_vals'] + self.num_vals = len(self.vals) #ZS: Check if genotypes exist in the DB in order to create links for markers @@ -156,6 +156,8 @@ class RunMapping(object): self.transform = "" self.score_type = "LRS" #ZS: LRS or LOD self.mapping_scale = "physic" + if "mapping_scale" in start_vars: + self.mapping_scale = start_vars['mapping_scale'] self.num_perm = 0 self.perm_output = [] self.bootstrap_results = [] @@ -255,9 +257,9 @@ class RunMapping(object): #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, self.mapping_scale = rqtl_mapping.run_rqtl_geno(self.vals, self.samples, self.dataset, self.method, self.model, self.permCheck, self.num_perm, perm_strata, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan, self.covariates) + self.perm_output, self.suggestive, self.significant, results= rqtl_mapping.run_rqtl_geno(self.vals, self.samples, self.dataset, self.mapping_scale, self.method, self.model, self.permCheck, self.num_perm, perm_strata, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan, self.covariates) else: - results, self.mapping_scale = rqtl_mapping.run_rqtl_geno(self.vals, self.samples, self.dataset, self.method, self.model, self.permCheck, self.num_perm, perm_strata, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan, self.covariates) + results = rqtl_mapping.run_rqtl_geno(self.vals, self.samples, self.dataset, self.mapping_scale, self.method, self.model, self.permCheck, self.num_perm, perm_strata, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan, self.covariates) 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: @@ -429,7 +431,7 @@ class RunMapping(object): with Bench("Trimming Markers for Table"): self.trimmed_markers = trim_markers_for_table(results) - chr_lengths = get_chr_lengths(self.mapping_scale, self.dataset, self.qtl_results) + chr_lengths = get_chr_lengths(self.mapping_scale, self.mapping_method, self.dataset, self.qtl_results) #ZS: For zooming into genome browser, need to pass chromosome name instead of number if self.dataset.group.species == "mouse": @@ -643,7 +645,7 @@ def geno_db_exists(this_dataset): except: return "False" -def get_chr_lengths(mapping_scale, dataset, qtl_results): +def get_chr_lengths(mapping_scale, mapping_method, dataset, qtl_results): chr_lengths = [] if mapping_scale == "physic": for i, the_chr in enumerate(dataset.species.chromosomes.chromosomes): @@ -666,8 +668,12 @@ def get_chr_lengths(mapping_scale, dataset, qtl_results): this_chr = chr_as_num highest_pos = 0 else: - if float(result['Mb']) > highest_pos: - highest_pos = float(result['Mb']) + if mapping_method == "reaper": + if float(result['cM']) > highest_pos: + highest_pos = float(result['cM']) + else: + if float(result['Mb']) > highest_pos: + highest_pos = float(result['Mb']) return chr_lengths diff --git a/wqflask/wqflask/show_trait/export_trait_data.py b/wqflask/wqflask/show_trait/export_trait_data.py index 7ca4a4c0..107f87c6 100644 --- a/wqflask/wqflask/show_trait/export_trait_data.py +++ b/wqflask/wqflask/show_trait/export_trait_data.py @@ -4,11 +4,17 @@ import simplejson as json from pprint import pformat as pf +from base.trait import GeneralTrait +from base import data_set + def export_sample_table(targs): sample_data = json.loads(targs['export_data']) trait_name = targs['trait_display_name'] - final_sample_data = [] + + meta_data = get_export_metadata(targs['trait_id'], targs['dataset']) + + final_sample_data = meta_data for sample_group in ['primary_samples', 'other_samples']: for row in sample_data[sample_group]: @@ -18,6 +24,28 @@ def export_sample_table(targs): return trait_name, final_sample_data +def get_export_metadata(trait_id, dataset_name): + dataset = data_set.create_dataset(dataset_name) + this_trait = GeneralTrait(dataset=dataset, + name=trait_id, + cellid=None, + get_qtl_info=False) + + metadata = [] + if dataset.type == "Publish": + metadata.append(["Phenotype ID: " + trait_id]) + metadata.append(["Phenotype URL: " + "http://genenetwork.org/show_trait?trait_id=" + trait_id + "&dataset=" + dataset_name]) + metadata.append(["Group: " + dataset.group.name]) + metadata.append(["Phenotype: " + this_trait.description_display.replace(",", "\",\"")]) + metadata.append(["Authors: " + this_trait.authors]) + metadata.append(["Title: " + this_trait.title]) + metadata.append(["Journal: " + this_trait.journal]) + metadata.append(["Dataset Link: http://gn1.genenetwork.org/webqtl/main.py?FormID=sharinginfo&InfoPageName=" + dataset.name]) + metadata.append([]) + + return metadata + + def dict_to_sorted_list(dictionary): sorted_list = [item for item in dictionary.iteritems()] sorted_list = sorted(sorted_list, cmp=cmp_samples) diff --git a/wqflask/wqflask/show_trait/show_trait.py b/wqflask/wqflask/show_trait/show_trait.py index 8883e627..f73079f8 100644 --- a/wqflask/wqflask/show_trait/show_trait.py +++ b/wqflask/wqflask/show_trait/show_trait.py @@ -22,6 +22,7 @@ from base import webqtlConfig from base import webqtlCaseData from wqflask.show_trait.SampleList import SampleList from utility import webqtlUtil, Plot, Bunch, helper_functions +from utility.tools import locate_ignore_error from base.trait import GeneralTrait from base import data_set from db import webqtlDatabaseFunction @@ -170,6 +171,14 @@ class ShowTrait(object): self.genofiles = self.dataset.group.get_genofiles() + if "QTLReaper" or "R/qtl" in dataset.group.mapping_names: #ZS: No need to grab scales from .geno file unless it's using a mapping method that reads .geno files + if self.genofiles: + self.scales_in_geno = get_genotype_scales(self.genofiles) + else: + self.scales_in_geno = get_genotype_scales(self.dataset.group.name + ".geno") + else: + self.scales_in_geno = {} + self.has_num_cases = has_num_cases(self.this_trait) self.stats_table_width, self.trait_table_width = get_table_widths(self.sample_groups, self.has_num_cases) @@ -239,9 +248,12 @@ class ShowTrait(object): #hddn['control_marker'] = self.nearest_marker1+","+self.nearest_marker2 hddn['do_control'] = False hddn['maf'] = 0.05 + hddn['mapping_scale'] = "physic" hddn['compare_traits'] = [] hddn['export_data'] = "" hddn['export_format'] = "excel" + if len(self.scales_in_geno) < 2: + hddn['mapping_scale'] = self.scales_in_geno[self.scales_in_geno.keys()[0]][0] # We'll need access to this_trait and hddn in the Jinja2 Template, so we put it inside self self.hddn = hddn @@ -251,6 +263,7 @@ class ShowTrait(object): short_description = short_description, unit_type = trait_units, dataset_type = self.dataset.type, + scales_in_geno = self.scales_in_geno, data_scale = self.dataset.data_scale, sample_group_types = self.sample_group_types, sample_lists = sample_lists, @@ -597,4 +610,77 @@ def get_categorical_variables(this_trait, sample_list): if num_distinct < 10: categorical_var_list.append(sample_list.attributes[attribute].name) - return categorical_var_list
\ No newline at end of file + return categorical_var_list + +def get_genotype_scales(genofiles): + geno_scales = {} + if type(genofiles) is list: + for the_file in genofiles: + file_location = the_file['location'] + geno_scales[file_location] = get_scales_from_genofile(file_location) + else: + geno_scales[genofiles] = get_scales_from_genofile(genofiles) + + return geno_scales + +def get_scales_from_genofile(file_location): + geno_path = locate_ignore_error(file_location, 'genotype') + + if not geno_path: #ZS: This is just to allow the code to run when + return [["physic", "Mb"]] + cm_and_mb_cols_exist = True + cm_column = None + mb_column = None + with open(geno_path, "r") as geno_fh: + for i, line in enumerate(geno_fh): + if line[0] == "#" or line[0] == "@": + if "@scale" in line: #ZS: If the scale is made explicit in the metadata, use that + scale = line.split(":")[1].strip() + if scale == "morgan": + return [["morgan", "cM"]] + else: + return [["physic", "Mb"]] + else: + continue + if line[:3] == "Chr": + first_marker_line = i + 1 + if line.split("\t")[2].strip() == "cM": + cm_column = 2 + elif line.split("\t")[3].strip() == "cM": + cm_column = 3 + if line.split("\t")[2].strip() == "Mb": + mb_column = 2 + elif line.split("\t")[3].strip() == "Mb": + mb_column = 3 + break + + #ZS: This attempts to check whether the cM and Mb columns are 'real', since some .geno files have one column be a copy of the other column, or have one column that is all 0s + cm_all_zero = True + mb_all_zero = True + cm_mb_all_equal = True + for i, line in enumerate(geno_fh): + if first_marker_line <= i < first_marker_line + 10: #ZS: I'm assuming there won't be more than 10 markers where the position is listed as 0 + if cm_column: + cm_val = line.split("\t")[cm_column].strip() + if cm_val != "0": + cm_all_zero = False + if mb_column: + mb_val = line.split("\t")[mb_column].strip() + if mb_val != "0": + mb_all_zero = False + if cm_column and mb_column: + if cm_val != mb_val: + cm_mb_all_equal = False + else: + if i > first_marker_line + 10: + break + + #ZS: This assumes that both won't be all zero, since if that's the case mapping shouldn't be an option to begin with + if mb_all_zero: + return [["morgan", "cM"]] + elif cm_mb_all_equal: + return [["physic", "Mb"]] + elif cm_and_mb_cols_exist: + return [["physic", "Mb"], ["morgan", "cM"]] + else: + return [["physic", "Mb"]] diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js index 478ed87e..7176a0da 100644 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js @@ -165,6 +165,7 @@ url = "/loading"; $('input[name=method]').val("rqtl_geno"); $('input[name=selected_chr]').val($('#chr_rqtl_geno').val()); + $('input[name=mapping_scale]').val($('#scale_rqtl_geno').val()); $('input[name=genofile]').val($('#genofile_rqtl_geno').val()); $('input[name=num_perm]').val($('input[name=num_perm_rqtl_geno]').val()); $('input[name=categorical_vars]').val(js_data.categorical_vars) @@ -210,6 +211,7 @@ url = "/loading"; $('input[name=method]').val("reaper"); $('input[name=selected_chr]').val($('#chr_reaper').val()); + $('input[name=mapping_scale]').val($('#scale_reaper').val()); $('input[name=genofile]').val($('#genofile_reaper').val()); $('input[name=num_perm]').val($('input[name=num_perm_reaper]').val()); $('input[name=control_marker]').val($('input[name=control_reaper]').val()); @@ -289,4 +291,21 @@ return toggle_enable_disable("#suggestive_lrs"); }); + $('#genofile_rqtl_geno').change(function() { + geno_location = $(this).children("option:selected").val().split(":")[0] + $('#scale_rqtl_geno').empty() + the_scales = js_data.scales_in_geno[geno_location] + for (var i = 0; i < the_scales.length; i++){ + $('#scale_rqtl_geno').append($("<option></option>").attr("value", the_scales[i][0]).text(the_scales[i][1])); + } + }); + $('#genofile_reaper').change(function() { + geno_location = $(this).children("option:selected").val().split(":")[0] + $('#scale_reaper').empty() + the_scales = js_data.scales_in_geno[geno_location] + for (var i = 0; i < the_scales.length; i++){ + $('#scale_reaper').append($("<option></option>").attr("value", the_scales[i][0]).text(the_scales[i][1])); + } + }); + }).call(this); diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html index 6639f46a..1a622bb4 100644 --- a/wqflask/wqflask/templates/collections/view.html +++ b/wqflask/wqflask/templates/collections/view.html @@ -8,7 +8,7 @@ {% block content %} <!-- Start of body --> - <div class="container" style="min-width: 1250px;"> + <div class="container" style="min-width: 2050px;"> <h1> <span id="collection_name">{{ uc.name }}</span> <input type="text" name="new_collection_name" style="font-size: 20px; display: none; width: 500px;" class="form-control" placeholder="{{ uc.name }}"> @@ -122,9 +122,9 @@ </a> </TD> {% if this_trait.symbol %} - <TD data-export="{{ this_trait.symbol }}">{{ this_trait.symbol }}</TD> + <TD title="{{ this_trait.symbol }}" data-export="{{ this_trait.symbol }}">{% if this_trait.symbol|length > 20 %}{{ this_trait.symbol[:20] }}...{% else %}{{ this_trait.symbol }}{% endif %}</TD> {% elif this_trait.abbreviation %} - <TD data-export="{{ this_trait.abbreviation }}">{{ this_trait.abbreviation }}</TD> + <TD title="{{ this_trait.abbreviation }}" data-export="{{ this_trait.abbreviation }}">{% if this_trait.abbreviation|length > 20 %}{{ this_trait.abbreviation[:20] }}...{% else %}{{ this_trait.abbreviation }}{% endif %}</TD> {% else %} <TD data-export="N/A">N/A</TD> {% endif %} @@ -190,7 +190,7 @@ { "type": "natural", "width": 50 }, { "type": "natural" }, { "type": "natural", "width": 120 }, - { "type": "natural", "width": 120 }, + { "type": "natural" }, { "type": "natural" }, { "type": "natural", "width": 130 }, { "type": "natural", "width": 35 }, diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html index 03b03aa7..b73a6981 100644 --- a/wqflask/wqflask/templates/correlation_page.html +++ b/wqflask/wqflask/templates/correlation_page.html @@ -126,7 +126,7 @@ {% for trait in correlation_results %} <tr> <td><INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox" style="padding-right: 0px;" VALUE="{{ data_hmac('{}:{}'.format(trait.name, trait.dataset.name)) }}"></td> - <td data-export="{{ loop.index }}" style="padding-left: 8px; padding-right: 0px; padding-top: 4px; align: center;">{{ loop.index }}</td> + <td data-export="{{ loop.index }}" style="padding-left: 8px; padding-right: 0px; padding-top: 4px; align: right;">{{ loop.index }}</td> <td data-export="{{ trait.name }}"> <a href="{{ url_for('show_trait_page', trait_id = trait.name, @@ -159,6 +159,11 @@ <td data-export="{{ trait.LRS_location_repr }}" align="right">{{ trait.LRS_location_repr }}</td> <td data-export={% if trait.additive != "" %}"{{ '%0.3f' % trait.additive|float }}"{% else %}"N/A"{% endif %} align="right">{% if trait.additive != "" %}{{ '%0.3f' % trait.additive|float }}{% else %}N/A{% endif %}</td> {% elif target_dataset.type == "Publish" %} + {% if trait.abbreviation %} + <TD title="{{ trait.abbreviation }}" data-export="{{ trait.abbreviation }}">{% if trait.abbreviation|length > 20 %}{{ trait.abbreviation[:20] }}...{% else %}{{ trait.abbreviation }}{% endif %}</TD> + {% else %} + <TD data-export="{{ trait.abbreviation }}">N/A</TD> + {% endif %} <td data-export="{{ trait.description_display }}">{{ trait.description_display }}</td> <td data-export="{{ trait.authors }}">{{ trait.authors }}</td> <td data-export="{{ trait.pubmed_text }}"> @@ -398,6 +403,7 @@ { "type": "natural" }, { "type": "natural" }, { "type": "natural" }, + { "type": "natural" }, { "type": "natural", "width": "20%" }, { "type": "natural", "width": "12%" }, { "orderDataType": "dom-innertext" }, diff --git a/wqflask/wqflask/templates/mapping_results.html b/wqflask/wqflask/templates/mapping_results.html index 7e05be18..94ac0350 100644 --- a/wqflask/wqflask/templates/mapping_results.html +++ b/wqflask/wqflask/templates/mapping_results.html @@ -274,7 +274,11 @@ {% endif %} <td align="right">{{marker.chr}}</td> {% if plotScale != "physic" %} + {% if 'cM' in marker %} + <td align="right">{{ '%0.3f' | format(marker.cM|float) }}</td> + {% else %} <td align="right">{{ '%0.3f' | format(marker.Mb|float) }}</td> + {% endif %} {% else %} <td align="right">{{ '%0.6f' | format(marker.Mb|float) }}</td> {% endif %} diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html index 777d4a2d..a2416ced 100755 --- a/wqflask/wqflask/templates/show_trait_mapping_tools.html +++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html @@ -121,6 +121,16 @@ </div> {% if genofiles and genofiles|length>0 %} <div class="mapping_method_fields form-group"> + <label for="scale_select" style="text-align: right;" class="col-xs-3 control-label">Map Scale</label> + <div style="margin-left:20px;" class="col-xs-2 controls"> + <select id="scale_reaper" class="form-control" style="width: 80px;"> + {% for item in scales_in_geno[genofiles[0]['location']] %} + <option value="{{ item[0] }}">{{ item[1] }}</option> + {% endfor %} + </select> + </div> + </div> + <div class="mapping_method_fields form-group"> <label style="text-align: right;" for="genofiles" class="col-xs-3 control-label">Genotypes</label> <div style="margin-left:20px;" class="col-xs-4 controls"> <select id="genofile_reaper" class="form-control"> @@ -225,7 +235,17 @@ </select> </div> </div> - {% if genofiles and genofiles|length>0 %} + {% if genofiles and genofiles|length > 0 %} + <div class="mapping_method_fields form-group"> + <label for="scale_select" style="text-align: right;" class="col-xs-3 control-label">Map Scale</label> + <div style="margin-left:20px;" class="col-xs-2 controls"> + <select id="scale_rqtl_geno" class="form-control" style="width: 80px;"> + {% for item in scales_in_geno[genofiles[0]['location']] %} + <option value="{{ item[0] }}">{{ item[1] }}</option> + {% endfor %} + </select> + </div> + </div> <div class="mapping_method_fields form-group"> <label style="text-align:right;" for="genofiles" class="col-xs-3 control-label">Genotypes</label> <div style="margin-left:20px;" class="col-xs-4 controls"> @@ -379,7 +399,7 @@ <dt style="padding-top: 20px;">GEMMA</dt> <dd>Maps traits with correction for kinship among samples using a linear mixed model method, and also allows users to fit multiple covariates such as sex, age, treatment, and genetic markers (<a href="https://www.ncbi.nlm.nih.gov/pubmed/24531419">PMID: 2453419</a>, and <a href="https://github.com/genetics-statistics/GEMMA"> GitHub code</a>). GEMMA incorporates the Leave One Chromosome Out (LOCO) method to ensure that the correction for kinship does not remove useful genetic variance near each marker. Markers can be filtered to include only those with minor allele frequencies (MAF) above a threshold. The default MAF is 0.05.</dd> {% elif mapping_method == "R/qtl" %} - <dt style="margin-top: 20px;">R/qtl</dt> + <dt style="margin-top: 20px;">R/qtl (version 1.44.9</dt> <dd>The original R/qtl mapping package that supports classic experimental crosses including 4-parent F2 intercrosses (e.g., NIA ITP UM-HET3). R/qtl is ideal for populations that do not have complex kinship or admixture (<a href="https://www.ncbi.nlm.nih.gov/pubmed/12724300">PMID: 12724300</a>). Both R/qtl as implemented here, and R/qtl2 (<a href="https://www.ncbi.nlm.nih.gov/pubmed/30591514">PMID: 30591514</a>) are available as <a href="https://kbroman.org/pages/software.html">R suites</a>.</dd> {% elif mapping_method == "QTLReaper" %} <dt style="margin-top: 20px;">Haley-Knott Regression</dt> diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py index ce76e0e8..a871e91a 100644 --- a/wqflask/wqflask/user_manager.py +++ b/wqflask/wqflask/user_manager.py @@ -356,7 +356,7 @@ def get_cookie(): g.user_session = UserSession() g.cookie_session = AnonUser() -@app.after_request +#@app.after_request def set_cookie(response): if not request.cookies.get(g.cookie_session.cookie_name): response.set_cookie(g.cookie_session.cookie_name, g.cookie_session.cookie) @@ -538,7 +538,7 @@ def basic_info(): ip_address = request.remote_addr, user_agent = request.headers.get('User-Agent')) -@app.route("/manage/verify_email") +#@app.route("/manage/verify_email") def verify_email(): user = DecodeUser(VerificationEmail.key_prefix).user user.confirmed = json.dumps(basic_info(), sort_keys=True) @@ -552,7 +552,7 @@ def verify_email(): response.set_cookie(UserSession.cookie_name, session_id_signed) return response -@app.route("/n/password_reset", methods=['GET']) +#@app.route("/n/password_reset", methods=['GET']) def password_reset(): """Entry point after user clicks link in E-mail""" logger.debug("in password_reset request.url is:", request.url) @@ -576,7 +576,7 @@ def password_reset(): else: return redirect(url_for("login")) -@app.route("/n/password_reset_step2", methods=('POST',)) +#@app.route("/n/password_reset_step2", methods=('POST',)) def password_reset_step2(): """Handle confirmation E-mail for password reset""" logger.debug("in password_reset request.url is:", request.url) @@ -620,7 +620,7 @@ class DecodeUser(object): logger.debug("data is:", data) return model.User.query.get(data['id']) -@app.route("/n/login", methods=('GET', 'POST')) +#@app.route("/n/login", methods=('GET', 'POST')) def login(): lu = LoginUser() login_type = request.args.get("type") @@ -630,7 +630,7 @@ def login(): else: return lu.standard_login() -@app.route("/n/login/github_oauth2", methods=('GET', 'POST')) +#@app.route("/n/login/github_oauth2", methods=('GET', 'POST')) def github_oauth2(): from utility.tools import GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET code = request.args.get("code") @@ -661,7 +661,7 @@ def github_oauth2(): url = "/n/login?type=github&uid="+user_details["user_id"] return redirect(url) -@app.route("/n/login/orcid_oauth2", methods=('GET', 'POST')) +#@app.route("/n/login/orcid_oauth2", methods=('GET', 'POST')) def orcid_oauth2(): from uuid import uuid4 from utility.tools import ORCID_CLIENT_ID, ORCID_CLIENT_SECRET, ORCID_TOKEN_URL, ORCID_AUTH_URL @@ -841,7 +841,7 @@ class LoginUser(object): db_session.add(login_rec) db_session.commit() -@app.route("/n/logout") +#@app.route("/n/logout") def logout(): logger.debug("Logging out...") UserSession().delete_session() @@ -852,7 +852,7 @@ def logout(): return response -@app.route("/n/forgot_password", methods=['GET']) +#@app.route("/n/forgot_password", methods=['GET']) def forgot_password(): """Entry point for forgotten password""" print("ARGS: ", request.args) @@ -860,7 +860,7 @@ def forgot_password(): print("ERRORS: ", errors) return render_template("new_security/forgot_password.html", errors=errors) -@app.route("/n/forgot_password_submit", methods=('POST',)) +#@app.route("/n/forgot_password_submit", methods=('POST',)) def forgot_password_submit(): """When a forgotten password form is submitted we get here""" params = request.form @@ -945,7 +945,7 @@ def is_redis_available(): # return LoginUser().actual_login(user, assumed_by=assumed_by) -@app.route("/n/register", methods=('GET', 'POST')) +#@app.route("/n/register", methods=('GET', 'POST')) def register(): params = None errors = None diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py index 44752246..938570f3 100644 --- a/wqflask/wqflask/views.py +++ b/wqflask/wqflask/views.py @@ -40,7 +40,7 @@ from wqflask import update_search_results from wqflask import docs from wqflask import news from wqflask.submit_bnw import get_bnw_input -from base.data_set import DataSet # Used by YAML in marker_regression +from base.data_set import create_dataset, DataSet # Used by YAML in marker_regression from wqflask.show_trait import show_trait from wqflask.show_trait import export_trait_data from wqflask.heatmap import heatmap @@ -593,12 +593,21 @@ def loading_page(): if 'num_vals' in start_vars: num_vals = int(start_vars['num_vals']) else: - if 'primary_samples' in start_vars: - samples = start_vars['primary_samples'].split(",") - for sample in samples: - value = start_vars.get('value:' + sample) - if value != "x": - num_vals += 1 + dataset = create_dataset(start_vars['dataset']) + genofile_samplelist = [] + samples = start_vars['primary_samples'].split(",") + if 'genofile' in start_vars: + if start_vars['genofile'] != "": + genofile_string = start_vars['genofile'] + dataset.group.genofile = genofile_string.split(":")[0] + genofile_samples = run_mapping.get_genofile_samplelist(dataset) + if len(genofile_samples) > 1: + samples = genofile_samples + + for sample in samples: + value = start_vars.get('value:' + sample) + if value != "x": + num_vals += 1 start_vars['num_vals'] = num_vals start_vars['wanted_inputs'] = initial_start_vars['wanted_inputs'] |