From 0b25ab1565faf3824d591c545dfe71dbd28c38ee Mon Sep 17 00:00:00 2001 From: Lei Yan Date: Tue, 4 Apr 2017 18:23:57 +0000 Subject: Change scatterplot title font size --- wqflask/wqflask/static/new/javascript/scatterplot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wqflask/wqflask/static/new/javascript/scatterplot.js b/wqflask/wqflask/static/new/javascript/scatterplot.js index de7b7906..d7f2a4a5 100644 --- a/wqflask/wqflask/static/new/javascript/scatterplot.js +++ b/wqflask/wqflask/static/new/javascript/scatterplot.js @@ -166,7 +166,7 @@ scatterplot = function() { maxx = xlim[1]; yticks = yticks != null ? yticks : ys.ticks(nyticks); xticks = xticks != null ? xticks : xs.ticks(nxticks); - titlegrp = g.append("g").attr("class", "title").append("text").attr("x", margin.left + width / 2).attr("y", margin.top - titlepos).style("fill", "black").style("font-size", "28px").text(title); + titlegrp = g.append("g").attr("class", "title").append("text").attr("x", margin.left + width / 2).attr("y", margin.top - titlepos).style("fill", "black").style("font-size", "24px").text(title); xaxis = g.append("g").attr("class", "x axis"); xaxis.selectAll("empty").data(xticks).enter().append("line").attr("x1", function(d) { return xscale(d); -- cgit v1.2.3 From 0408cc61181eaeda95bd1f60f76dc5798e315663 Mon Sep 17 00:00:00 2001 From: zsloan Date: Wed, 5 Apr 2017 15:37:29 +0000 Subject: - Temporary traits can be created, viewed, and added to collections - Correct PCA trait data is created but can't be saved yet - Added inner margins by increasing xDomain and yDomain of probability plot on trait page - Increased X/Y-axis label font size - Turned "processes" to 0 on runserver.py for PROD setting, since it doesn't work with threading - Improved appearance of correlation page table - Added links to github to index page - Removed js_data from GEMMA/PLINK mapping results, since it isn't used for those - Removed "Tissue" from trait page for phenotype traits --- wqflask/base/data_set.py | 35 +- wqflask/base/trait.py | 16 +- wqflask/base/webqtlConfig.py | 2 +- wqflask/runserver.py | 2 +- wqflask/wqflask/collect.py | 18 +- wqflask/wqflask/correlation/show_corr_results.py | 9 +- .../wqflask/correlation_matrix/show_corr_matrix.py | 87 +- wqflask/wqflask/marker_regression/gemma_mapping.py | 12 +- .../wqflask/marker_regression/marker_regression.py | 98 +- .../marker_regression/marker_regression_gn1.py | 63 +- wqflask/wqflask/marker_regression/plink_mapping.py | 35 +- wqflask/wqflask/show_trait/SampleList.py | 19 +- wqflask/wqflask/show_trait/show_trait.py | 174 +-- .../static/new/javascript/draw_probability_plot.js | 10 +- .../wqflask/static/new/javascript/show_trait.js | 2 +- wqflask/wqflask/static/new/packages/nvd3/nv.d3.css | 1188 ++++++++++---------- wqflask/wqflask/templates/correlation_page.html | 125 +- wqflask/wqflask/templates/index_page_orig.html | 12 +- .../wqflask/templates/marker_regression_gn1.html | 14 +- wqflask/wqflask/templates/show_trait.html | 4 +- wqflask/wqflask/templates/show_trait_details.html | 2 + .../templates/show_trait_mapping_tools.html | 7 +- wqflask/wqflask/templates/submit_trait.html | 2 +- wqflask/wqflask/views.py | 33 +- 24 files changed, 1081 insertions(+), 888 deletions(-) diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py index 54dd3c4b..7f08135f 100644 --- a/wqflask/base/data_set.py +++ b/wqflask/base/data_set.py @@ -61,14 +61,17 @@ logger = getLogger(__name__ ) # Each subclass will add to this DS_NAME_MAP = {} -def create_dataset(dataset_name, dataset_type = None, get_samplelist = True): +def create_dataset(dataset_name, dataset_type = None, get_samplelist = True, group_name = None): if not dataset_type: dataset_type = Dataset_Getter(dataset_name) logger.debug("dataset_type", dataset_type) dataset_ob = DS_NAME_MAP[dataset_type] dataset_class = globals()[dataset_ob] - return dataset_class(dataset_name, get_samplelist) + if dataset_type == "Temp": + return dataset_class(dataset_name, get_samplelist, group_name) + else: + return dataset_class(dataset_name, get_samplelist) class Dataset_Types(object): @@ -261,10 +264,13 @@ class DatasetGroup(object): has multiple datasets associated with it. """ - def __init__(self, dataset): + def __init__(self, dataset, name=None): """This sets self.group and self.group_id""" #logger.debug("DATASET NAME2:", dataset.name) - self.name, self.id, self.genetic_type = fetchone(dataset.query_for_group) + if name == None: + self.name, self.id, self.genetic_type = fetchone(dataset.query_for_group) + else: + self.name, self.id, self.genetic_type = fetchone("SELECT InbredSet.Name, InbredSet.Id, InbredSet.GeneticType FROM InbredSet where Name='%s'" % name) if self.name == 'BXD300': self.name = "BXD" @@ -304,7 +310,7 @@ class DatasetGroup(object): elif mapping_id == "2": mapping_names = ["GEMMA"] elif mapping_id == "4": - mapping_names = ["PLINK"] + mapping_names = ["GEMMA", "PLINK"] else: mapping_names = [] @@ -319,9 +325,7 @@ class DatasetGroup(object): def check_plink_gemma(): if flat_file_exists("mapping"): MAPPING_PATH = flat_files("mapping")+"/" - if (os.path.isfile(MAPPING_PATH+self.name+".bed") and - (os.path.isfile(MAPPING_PATH+self.name+".map") or - os.path.isfile(MAPPING_PATH+self.name+".bim"))): + if os.path.isfile(MAPPING_PATH+self.name+".bed"): return True return False @@ -481,7 +485,7 @@ class DataSet(object): """ - def __init__(self, name, get_samplelist = True): + def __init__(self, name, get_samplelist = True, group_name = None): assert name, "Need a name" self.name = name @@ -493,11 +497,12 @@ class DataSet(object): self.setup() - self.check_confidentiality() - - self.retrieve_other_names() - - self.group = DatasetGroup(self) # sets self.group and self.group_id and gets genotype + if self.type == "Temp": #Need to supply group name as input if temp trait + self.group = DatasetGroup(self, group_name) # sets self.group and self.group_id and gets genotype + else: + self.check_confidentiality() + self.retrieve_other_names() + self.group = DatasetGroup(self) # sets self.group and self.group_id and gets genotype if get_samplelist == True: self.group.get_samplelist() self.species = species.TheSpecies(self) @@ -1156,6 +1161,8 @@ class MrnaAssayDataSet(DataSet): class TempDataSet(DataSet): '''Temporary user-generated data set''' + DS_NAME_MAP['Temp'] = 'TempDataSet' + def setup(self): self.search_fields = ['name', 'description'] diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py index bf87e879..e22a51e4 100644 --- a/wqflask/base/trait.py +++ b/wqflask/base/trait.py @@ -62,6 +62,11 @@ class GeneralTrait(object): self.strand_probe = None self.symbol = None + self.LRS_score_repr = "N/A" + self.LRS_score_value = 0 + self.LRS_location_repr = "N/A" + self.LRS_location_value = 1000000 + if kw.get('fullname'): name2 = value.split("::") if len(name2) == 2: @@ -72,9 +77,10 @@ class GeneralTrait(object): # Todo: These two lines are necessary most of the time, but perhaps not all of the time # So we could add a simple if statement to short-circuit this if necessary - self = retrieve_trait_info(self, self.dataset, get_qtl_info=get_qtl_info) - if get_sample_info != False: - self = retrieve_sample_data(self, self.dataset) + if self.dataset.type != "Temp": + self = retrieve_trait_info(self, self.dataset, get_qtl_info=get_qtl_info) + if get_sample_info != False: + self = retrieve_sample_data(self, self.dataset) def get_name(self): @@ -315,12 +321,12 @@ def get_sample_data(): # #return jsonable_sample_data -def jsonable(trait, dataset_name): +def jsonable(trait): """Return a dict suitable for using as json Actual turning into json doesn't happen here though""" - dataset = create_dataset(dataset_name) + dataset = create_dataset(dataset_name = trait.dataset.name, dataset_type = trait.dataset.type, group_name = trait.dataset.group.name) if dataset.type == "ProbeSet": return dict(name=trait.name, diff --git a/wqflask/base/webqtlConfig.py b/wqflask/base/webqtlConfig.py index e5f10edf..1e47e183 100644 --- a/wqflask/base/webqtlConfig.py +++ b/wqflask/base/webqtlConfig.py @@ -65,7 +65,7 @@ ENSEMBLETRANSCRIPT_URL="http://useast.ensembl.org/Mus_musculus/Lucene/Details?sp # want to reach this base dir assert_writable_dir(TEMPDIR) -TMPDIR = mk_dir(TEMPDIR+'/gn2/') +TMPDIR = mk_dir(TEMPDIR+'gn2') assert_writable_dir(TMPDIR) CACHEDIR = mk_dir(TMPDIR+'/cache/') diff --git a/wqflask/runserver.py b/wqflask/runserver.py index 0342b7ad..a6ae28af 100644 --- a/wqflask/runserver.py +++ b/wqflask/runserver.py @@ -50,5 +50,5 @@ else: # staging/production modes debug=False, use_debugger=False, threaded=True, - processes=8, + processes=0, use_reloader=True) diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py index ba555094..478dbcaa 100644 --- a/wqflask/wqflask/collect.py +++ b/wqflask/wqflask/collect.py @@ -203,7 +203,8 @@ def process_traits(unprocessed_traits): data, _separator, hmac = trait.rpartition(':') data = data.strip() assert hmac==user_manager.actual_hmac_creation(data), "Data tampering?" - traits.add (str(data)) + traits.add(str(data)) + return traits def report_change(len_before, len_now): @@ -244,7 +245,6 @@ def collections_new(): if "sign_in" in params: return redirect(url_for('login')) - if "create_new" in params: print("in create_new") collection_name = params['new_collection'] @@ -376,13 +376,17 @@ def view_collection(): for atrait in traits: name, dataset_name = atrait.split(':') - dataset = create_dataset(dataset_name) - - trait_ob = trait.GeneralTrait(name=name, dataset=dataset) - trait_ob = trait.retrieve_trait_info(trait_ob, dataset, get_qtl_info=True) + if dataset_name == "Temp": + group = name.split("_")[2] + dataset = create_dataset(dataset_name, dataset_type = "Temp", group_name = group) + trait_ob = trait.GeneralTrait(name=name, dataset=dataset) + else: + dataset = create_dataset(dataset_name) + trait_ob = trait.GeneralTrait(name=name, dataset=dataset) + trait_ob = trait.retrieve_trait_info(trait_ob, dataset, get_qtl_info=True) trait_obs.append(trait_ob) - json_version.append(trait.jsonable(trait_ob, dataset_name)) + json_version.append(trait.jsonable(trait_ob)) if "uc_id" in params: collection_info = dict(trait_obs=trait_obs, diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py index cc21d1bf..7957e643 100644 --- a/wqflask/wqflask/correlation/show_corr_results.py +++ b/wqflask/wqflask/correlation/show_corr_results.py @@ -96,7 +96,14 @@ class CorrelationResults(object): print("TESTING...") with Bench("Doing correlations"): - helper_functions.get_species_dataset_trait(self, start_vars) + if start_vars['dataset'] == "Temp": + self.dataset = data_set.create_dataset(dataset_name = "Temp", dataset_type = "Temp", group_name = start_vars['group']) + self.trait_id = "Temp" + self.this_trait = GeneralTrait(dataset=self.dataset, + name=self.trait_id, + cellid=None) + else: + helper_functions.get_species_dataset_trait(self, start_vars) self.dataset.group.read_genotype_file() diff --git a/wqflask/wqflask/correlation_matrix/show_corr_matrix.py b/wqflask/wqflask/correlation_matrix/show_corr_matrix.py index 630980c7..95a5f6a6 100644 --- a/wqflask/wqflask/correlation_matrix/show_corr_matrix.py +++ b/wqflask/wqflask/correlation_matrix/show_corr_matrix.py @@ -33,6 +33,9 @@ import math import collections import resource +import numarray +import numarray.linear_algebra as la +import numpy as np import scipy from rpy2.robjects.packages import importr @@ -91,31 +94,40 @@ class CorrelationMatrix(object): this_trait_vals.append('') self.sample_data.append(this_trait_vals) + if len(this_trait_vals) < len(self.trait_list): #Shouldn't do PCA if there are more traits than observations/samples + return False + self.lowest_overlap = 8 #ZS: Variable set to the lowest overlapping samples in order to notify user, or 8, whichever is lower (since 8 is when we want to display warning) self.corr_results = [] self.pca_corr_results = [] + self.trait_data_array = [] for trait_db in self.trait_list: this_trait = trait_db[0] this_db = trait_db[1] - this_db_samples = this_db.group.samplelist + this_db_samples = this_db.group.all_samples_ordered() this_sample_data = this_trait.data + this_trait_vals = [] + for index, sample in enumerate(this_db_samples): + if (sample in this_sample_data): + sample_value = this_sample_data[sample].value + this_trait_vals.append(sample_value) + self.trait_data_array.append(this_trait_vals) + corr_result_row = [] pca_corr_result_row = [] is_spearman = False #ZS: To determine if it's above or below the diagonal for target in self.trait_list: target_trait = target[0] target_db = target[1] - target_samples = target_db.group.samplelist - + target_samples = target_db.group.all_samples_ordered() target_sample_data = target_trait.data this_trait_vals = [] target_vals = [] for index, sample in enumerate(target_samples): - if (sample in this_sample_data) and (sample in target_sample_data): sample_value = this_sample_data[sample].value target_sample_value = target_sample_data[sample].value @@ -144,13 +156,14 @@ class CorrelationMatrix(object): self.corr_results.append(corr_result_row) self.pca_corr_results.append(pca_corr_result_row) - print("corr_results:", pf(self.corr_results)) + corr_result_eigen = la.eigenvectors(numarray.array(self.pca_corr_results)) + corr_eigen_value, corr_eigen_vectors = sortEigenVectors(corr_result_eigen) groups = [] for sample in self.all_sample_list: groups.append(1) - pca = self.calculate_pca(self.pca_corr_results, range(len(self.traits))) + pca = self.calculate_pca(range(len(self.traits)), corr_eigen_value, corr_eigen_vectors) self.loadings_array = self.process_loadings() @@ -180,31 +193,34 @@ class CorrelationMatrix(object): #print("trait_list:", self.trait_list) - def calculate_pca(self, corr_results, cols): + def calculate_pca(self, cols, corr_eigen_value, corr_eigen_vectors): base = importr('base') stats = importr('stats') - print("checking:", pf(stats.rnorm(100))) - corr_results_to_list = robjects.FloatVector([item for sublist in corr_results for item in sublist]) - print("corr_results:", pf(corr_results_to_list)) + corr_results_to_list = robjects.FloatVector([item for sublist in self.pca_corr_results for item in sublist]) m = robjects.r.matrix(corr_results_to_list, nrow=len(cols)) eigen = base.eigen(m) - print("eigen:", eigen) pca = stats.princomp(m, cor = "TRUE") - print("pca:", pca) self.loadings = pca.rx('loadings') self.scores = pca.rx('scores') self.scale = pca.rx('scale') - print("scores:", pca.rx('scores')) - print("scale:", pca.rx('scale')) + trait_array = zScore(self.trait_data_array) + trait_array = np.array(trait_array) + trait_array_vectors = np.dot(corr_eigen_vectors, trait_array) + + pca_traits = [] + for i, vector in enumerate(trait_array_vectors): + if corr_eigen_value[i-1] < 100.0/len(self.trait_list): + pca_traits.append(vector*-1.0) + + print("pca_traits:", pca_traits) return pca def process_loadings(self): loadings_array = [] loadings_row = [] - print("before loop:", self.loadings[0]) for i in range(len(self.trait_list)): loadings_row = [] if len(self.trait_list) > 2: @@ -215,6 +231,45 @@ class CorrelationMatrix(object): position = i + len(self.trait_list)*j loadings_row.append(self.loadings[0][position]) loadings_array.append(loadings_row) - print("loadings:", loadings_array) return loadings_array +def zScore(trait_data_array): + NN = len(trait_data_array[0]) + if NN < 10: + return trait_data_array + else: + i = 0 + for data in trait_data_array: + N = len(data) + S = reduce(lambda x,y: x+y, data, 0.) + SS = reduce(lambda x,y: x+y*y, data, 0.) + mean = S/N + var = SS - S*S/N + stdev = math.sqrt(var/(N-1)) + if stdev == 0: + stdev = 1e-100 + data2 = map(lambda x:(x-mean)/stdev,data) + trait_data_array[i] = data2 + i += 1 + return trait_data_array + +def sortEigenVectors(vector): + try: + eigenValues = vector[0].tolist() + eigenVectors = vector[1].tolist() + combines = [] + i = 0 + for item in eigenValues: + combines.append([eigenValues[i],eigenVectors[i]]) + i += 1 + combines.sort(webqtlUtil.cmpEigenValue) + A = [] + B = [] + for item in combines: + A.append(item[0]) + B.append(item[1]) + sum = reduce(lambda x,y: x+y, A, 0.0) + A = map(lambda x:x*100.0/sum, A) + return [A,B] + except: + return [] \ No newline at end of file diff --git a/wqflask/wqflask/marker_regression/gemma_mapping.py b/wqflask/wqflask/marker_regression/gemma_mapping.py index 3bde61cd..6e2cb972 100644 --- a/wqflask/wqflask/marker_regression/gemma_mapping.py +++ b/wqflask/wqflask/marker_regression/gemma_mapping.py @@ -1,22 +1,22 @@ import os, math from base import webqtlConfig -from utility.tools import flat_files, GEMMA_COMMAND, GEMMA_RESULTS_PATH +from utility.tools import flat_files, GEMMA_COMMAND def run_gemma(this_dataset, samples, vals): """Generates p-values for each marker using GEMMA""" print("INSIDE GEMMA_MAPPING") - gen_pheno_txt_file(this_dataset, samples, vals) + gen_pheno_txt_file(this_dataset, vals) # use GEMMA_RUN in the next one, create a unique temp file - gemma_command = GEMMA_COMMAND + ' -bfile %s/%s -k %s/%s.sXX.txt -lmm 1 -outdir %s/output -o %s_output' % (flat_files('mapping'), + gemma_command = GEMMA_COMMAND + ' -bfile %s/%s -k %s/%s.sXX.txt -lmm 1 -maf 0.1 -outdir %s -o %s_output' % (flat_files('mapping'), this_dataset.group.name, flat_files('mapping'), this_dataset.group.name, - GEMMA_RESULTS_PATH, + webqtlConfig.GENERATED_IMAGE_DIR, this_dataset.group.name) print("gemma_command:" + gemma_command) @@ -26,7 +26,7 @@ def run_gemma(this_dataset, samples, vals): return marker_obs -def gen_pheno_txt_file(this_dataset, samples, vals): +def gen_pheno_txt_file(this_dataset, vals): """Generates phenotype file for GEMMA""" current_file_data = [] @@ -47,7 +47,7 @@ def parse_gemma_output(this_dataset): included_markers = [] p_values = [] marker_obs = [] - with open("{}/output/{}_output.assoc.txt".format(GEMMA_RESULTS_PATH, this_dataset.group.name)) as output_file: + with open("{}{}_output.assoc.txt".format(webqtlConfig.GENERATED_IMAGE_DIR, this_dataset.group.name)) as output_file: for line in output_file: if line.startswith("chr"): continue diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py index b1d2f811..87532445 100644 --- a/wqflask/wqflask/marker_regression/marker_regression.py +++ b/wqflask/wqflask/marker_regression/marker_regression.py @@ -211,6 +211,8 @@ class MarkerRegression(object): 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": @@ -263,52 +265,53 @@ class MarkerRegression(object): self.trimmed_markers = trim_markers_for_table(results) - 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 - - # logger.debug("json_data:", self.json_data) - - 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, - ) + 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 + + # logger.debug("json_data:", self.json_data) + + 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!! @@ -599,8 +602,7 @@ def trim_markers_for_table(markers): #ZS: So we end up with a list of just 200 markers if len(sorted_markers) >= 200: - trimming_factor = 200 / len(sorted_markers) - trimmed_sorted_markers = sorted_markers[:int(len(sorted_markers) * trimming_factor)] + trimmed_sorted_markers = sorted_markers[:200] return trimmed_sorted_markers else: return sorted_markers diff --git a/wqflask/wqflask/marker_regression/marker_regression_gn1.py b/wqflask/wqflask/marker_regression/marker_regression_gn1.py index 392ad745..49959a74 100644 --- a/wqflask/wqflask/marker_regression/marker_regression_gn1.py +++ b/wqflask/wqflask/marker_regression/marker_regression_gn1.py @@ -181,7 +181,8 @@ class MarkerRegression(object): self.mapmodel_rqtl_geno = start_vars['model'] self.pair_scan = start_vars['pair_scan'] - self.js_data = start_vars['js_data'] + 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 #ZS: Think I can just get all this from dataset object now @@ -564,7 +565,6 @@ class MarkerRegression(object): gifmap = self.plotIntMapping(intCanvas, startMb = self.startMb, endMb = self.endMb, showLocusForm= showLocusForm) self.gifmap = gifmap.__str__() - #print("GIFMAP:", gifmap.__str__()) self.filename= webqtlUtil.genRandStr("Itvl_") intCanvas.save(os.path.join(webqtlConfig.GENERATED_IMAGE_DIR, self.filename), format='jpeg') @@ -847,8 +847,7 @@ class MarkerRegression(object): pass #draw position, no need to use a separate function - if self.genotype.Mbmap: - self.drawProbeSetPosition(canvas, plotXScale, offset=newoffset, zoom = zoom) + self.drawProbeSetPosition(canvas, plotXScale, offset=newoffset, zoom = zoom) return gifmap @@ -1010,35 +1009,34 @@ class MarkerRegression(object): locPixel = xLeftOffset + (Mb-self.startMb)*plotXScale else: locPixel = xLeftOffset - for i, _chr in enumerate(self.genotype): - if _chr.name != Chr: - locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale + for i, _chr in enumerate(self.ChrList[1:]): + if _chr[0] != Chr: + locPixel += (self.ChrLengthDistList[i-1] + self.GraphInterval)*plotXScale else: locPixel += Mb*plotXScale break else: if self.selectedChr > -1: - if self.genotype[0].name != Chr: - return - else: - for i, _locus in enumerate(self.genotype[0]): - #the trait's position is on the left of the first genotype - if i==0 and _locus.Mb >= Mb: - locPixel=-1 - break + for i, qtlresult in enumerate(self.qtlresults): + if qtlresult['Chr'] != self.selectedChr: + continue - #the trait's position is between two traits - if i > 0 and self.genotype[0][i-1].Mb < Mb and _locus.Mb >= Mb: - locPixel = xLeftOffset + plotXScale*(self.genotype[0][i-1].cM+(_locus.cM-self.genotype[0][i-1].cM)*(Mb -self.genotype[0][i-1].Mb)/(_locus.Mb-self.genotype[0][i-1].Mb)) - break + 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]['cM']+(qtlresult['cM']-self.qtlresults[i-1]['cM'])*(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.genotype[0]) and Mb>=_locus.Mb: - locPixel = -1 + #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.genotype): - if _chr.name != Chr: + for i, _chr in enumerate(self.ChrList): + if _chr != Chr: locPixel += (self.ChrLengthDistList[i] + self.GraphInterval)*plotXScale else: locPixel += (Mb*(_chr[-1].cM-_chr[0].cM)/self.ChrLengthCMList[i])*plotXScale @@ -1190,13 +1188,16 @@ class MarkerRegression(object): else: if self.mapping_method == "gemma": string2 = 'Using GEMMA mapping method with 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 no control for other QTLs' - d = 4+ max(canvas.stringWidth(string1,font=labelFont),canvas.stringWidth(string2,font=labelFont)) if self.this_trait.name: 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) @@ -1915,7 +1916,7 @@ class MarkerRegression(object): 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": + 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) @@ -2118,7 +2119,7 @@ class MarkerRegression(object): # 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": + 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: @@ -2143,7 +2144,11 @@ class MarkerRegression(object): # Yc = yZero - qtlresult['lrs_value']*LRSHeightThresh/LRS_LOD_Max if self.manhattan_plot == True: - canvas.drawString("5", Xc-canvas.stringWidth("5",font=symbolFont)/2+1,Yc+2,color=pid.black, font=symbolFont) + if previous_chr_as_int % 2 == 1: + point_color = pid.grey + else: + 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)) diff --git a/wqflask/wqflask/marker_regression/plink_mapping.py b/wqflask/wqflask/marker_regression/plink_mapping.py index b457b9a0..3d31da1a 100644 --- a/wqflask/wqflask/marker_regression/plink_mapping.py +++ b/wqflask/wqflask/marker_regression/plink_mapping.py @@ -3,7 +3,7 @@ import os from base.webqtlConfig import TMPDIR from utility import webqtlUtil -from utility.tools import PLINK_COMMAND +from utility.tools import flat_files, PLINK_COMMAND import utility.logger logger = utility.logger.getLogger(__name__ ) @@ -11,12 +11,11 @@ logger = utility.logger.getLogger(__name__ ) def run_plink(this_trait, dataset, species, vals, maf): plink_output_filename = webqtlUtil.genRandStr("%s_%s_"%(dataset.group.name, this_trait.name)) - gen_pheno_txt_file_plink(this_trait, dataset, vals, pheno_filename = plink_output_filename) + gen_pheno_txt_file(dataset, vals) + #gen_pheno_txt_file_plink(this_trait, dataset, vals, pheno_filename = plink_output_filename) - plink_command = PLINK_COMMAND + ' --noweb --ped %s/%s.ped --no-fid --no-parents --no-sex --no-pheno --map %s/%s.map --pheno %s%s.txt --pheno-name %s --maf %s --missing-phenotype -9999 --out %s%s --assoc ' % ( - PLINK_PATH, dataset.group.name, PLINK_PATH, dataset.group.name, - TMPDIR, plink_output_filename, this_trait.name, maf, TMPDIR, - plink_output_filename) + plink_command = PLINK_COMMAND + ' --noweb --bfile %s/%s --no-fid --no-parents --no-sex --maf %s --missing-phenotype -9 --out %s/%s --assoc ' % ( + flat_files('mapping'), dataset.group.name, maf, TMPDIR, plink_output_filename) logger.debug("plink_command:", plink_command) os.system(plink_command) @@ -29,11 +28,27 @@ def run_plink(this_trait, dataset, species, vals, maf): # self.dataset.group.markers.markers.remove(marker) # #del self.dataset.group.markers.markers[marker] - logger.debug("p_values:", pf(p_values)) + logger.debug("p_values:", p_values) dataset.group.markers.add_pvalues(p_values) return dataset.group.markers.markers +def gen_pheno_txt_file(this_dataset, vals): + """Generates phenotype file for GEMMA/PLINK""" + + current_file_data = [] + with open("{}/{}.fam".format(flat_files('mapping'), this_dataset.group.name), "r") as outfile: + for i, line in enumerate(outfile): + split_line = line.split() + current_file_data.append(split_line) + + with open("{}/{}.fam".format(flat_files('mapping'), this_dataset.group.name), "w") as outfile: + for i, line in enumerate(current_file_data): + if vals[i] == "x": + this_val = -9 + else: + this_val = vals[i] + outfile.write(line[1] + " " + line[1] + " " + line[2] + " " + line[3] + " " + line[4] + " " + str(this_val) + "\n") def gen_pheno_txt_file_plink(this_trait, dataset, vals, pheno_filename = ''): ped_sample_list = get_samples_from_ped_file(dataset) @@ -71,7 +86,7 @@ def gen_pheno_txt_file_plink(this_trait, dataset, vals, pheno_filename = ''): # get strain name from ped file in order def get_samples_from_ped_file(dataset): - ped_file= open("{}/{}.ped".format(PLINK_PATH, dataset.group.name),"r") + ped_file= open("{}{}.ped".format(flat_files('mapping'), dataset.group.name),"r") line = ped_file.readline() sample_list=[] @@ -89,9 +104,9 @@ def get_samples_from_ped_file(dataset): def parse_plink_output(output_filename, species): plink_results={} - threshold_p_value = 0.01 + threshold_p_value = 1 - result_fp = open("%s%s.qassoc"% (TMPDIR, output_filename), "rb") + result_fp = open("%s/%s.qassoc"% (TMPDIR, output_filename), "rb") header_line = result_fp.readline()# read header line line = result_fp.readline() diff --git a/wqflask/wqflask/show_trait/SampleList.py b/wqflask/wqflask/show_trait/SampleList.py index 7e7503d4..6d84a960 100644 --- a/wqflask/wqflask/show_trait/SampleList.py +++ b/wqflask/wqflask/show_trait/SampleList.py @@ -32,7 +32,6 @@ class SampleList(object): self.sample_attribute_values = {} self.get_attributes() - # logger.debug("camera: attributes are:", pf(self.attributes)) if self.this_trait and self.dataset and self.dataset.type == 'ProbeSet': self.get_extra_attribute_values() @@ -40,12 +39,18 @@ class SampleList(object): for counter, sample_name in enumerate(sample_names, 1): sample_name = sample_name.replace("_2nd_", "") - #ZS - If there's no value for the sample/strain, create the sample object (so samples with no value are still displayed in the table) - try: - sample = self.this_trait.data[sample_name] - except KeyError: - logger.debug("No sample %s, let's create it now" % sample_name) - sample = webqtlCaseData.webqtlCaseData(sample_name) + if type(self.this_trait) is list: #ZS: self.this_trait will be a list if it is a Temp trait + if counter <= len(self.this_trait) and self.this_trait[counter-1] != 'X': + sample = webqtlCaseData.webqtlCaseData(name=sample_name, value=float(self.this_trait[counter-1])) + else: + sample = webqtlCaseData.webqtlCaseData(name=sample_name) + else: + #ZS - If there's no value for the sample/strain, create the sample object (so samples with no value are still displayed in the table) + try: + sample = self.this_trait.data[sample_name] + except KeyError: + logger.debug("No sample %s, let's create it now" % sample_name) + sample = webqtlCaseData.webqtlCaseData(name=sample_name) #sampleNameAdd = '' #if fd.RISet == 'AXBXA' and sampleName in ('AXB18/19/20','AXB13/14','BXA8/17'): diff --git a/wqflask/wqflask/show_trait/show_trait.py b/wqflask/wqflask/show_trait/show_trait.py index 5d55ebe1..b2dfc4ac 100644 --- a/wqflask/wqflask/show_trait/show_trait.py +++ b/wqflask/wqflask/show_trait/show_trait.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, print_function, division import string import os +import datetime import cPickle import uuid import json as json @@ -9,6 +10,9 @@ import json as json from collections import OrderedDict +import redis +Redis = redis.StrictRedis() + from flask import Flask, g from htmlgen import HTMLgen2 as HT @@ -42,16 +46,33 @@ class ShowTrait(object): def __init__(self, kw): logger.debug("in ShowTrait, kw are:", kw) - if kw['trait_id'] != None: + if 'trait_id' in kw and kw['dataset'] != "Temp": self.temp_trait = False self.trait_id = kw['trait_id'] helper_functions.get_species_dataset_trait(self, kw) - else: + elif 'group' in kw: self.temp_trait = True - self.trait_vals = kw['trait_paste'].split() - self.temp_group = kw['group'] + self.trait_id = "Temp_"+kw['species']+ "_" + kw['group'] + "_" + datetime.datetime.now().strftime("%m%d%H%M%S") self.temp_species = kw['species'] - #self.create_temp_trait() + self.temp_group = kw['group'] + self.dataset = data_set.create_dataset(dataset_name = "Temp", dataset_type = "Temp", group_name = self.temp_group) + self.this_trait = GeneralTrait(dataset=self.dataset, + name=self.trait_id, + cellid=None) + self.trait_vals = kw['trait_paste'].split() + + # Put values in Redis so they can be looked up later if added to a collection + Redis.set(self.trait_id, kw['trait_paste']) + else: + self.temp_trait = True + self.trait_id = kw['trait_id'] + self.temp_species = self.trait_id.split("_")[1] + self.temp_group = self.trait_id.split("_")[2] + self.dataset = data_set.create_dataset(dataset_name = "Temp", dataset_type = "Temp", group_name = self.temp_group) + self.this_trait = GeneralTrait(dataset=self.dataset, + name=self.trait_id, + cellid=None) + self.trait_vals = Redis.get(self.trait_id).split() #self.dataset.group.read_genotype_file() @@ -64,17 +85,17 @@ class ShowTrait(object): self.build_correlation_tools() #Get nearest marker for composite mapping + if not self.temp_trait: + if hasattr(self.this_trait, 'locus_chr') and self.this_trait.locus_chr != "" and self.dataset.type != "Geno" and self.dataset.type != "Publish": + self.nearest_marker = get_nearest_marker(self.this_trait, self.dataset) + #self.nearest_marker1 = get_nearest_marker(self.this_trait, self.dataset)[0] + #self.nearest_marker2 = get_nearest_marker(self.this_trait, self.dataset)[1] + else: + self.nearest_marker = "" + #self.nearest_marker1 = "" + #self.nearest_marker2 = "" - if hasattr(self.this_trait, 'locus_chr') and self.this_trait.locus_chr != "" and self.dataset.type != "Geno" and self.dataset.type != "Publish": - self.nearest_marker = get_nearest_marker(self.this_trait, self.dataset) - #self.nearest_marker1 = get_nearest_marker(self.this_trait, self.dataset)[0] - #self.nearest_marker2 = get_nearest_marker(self.this_trait, self.dataset)[1] - else: - self.nearest_marker = "" - #self.nearest_marker1 = "" - #self.nearest_marker2 = "" - - self.make_sample_lists(self.this_trait) + self.make_sample_lists() # Todo: Add back in the ones we actually need from below, as we discover we need them hddn = OrderedDict() @@ -84,17 +105,22 @@ class ShowTrait(object): hddn['trait_id'] = self.trait_id hddn['dataset'] = self.dataset.name + hddn['temp_trait'] = False + if self.temp_trait: + hddn['temp_trait'] = True + hddn['group'] = self.temp_group + hddn['species'] = self.temp_species hddn['use_outliers'] = False hddn['method'] = "pylmm" hddn['mapping_display_all'] = True hddn['suggestive'] = 0 hddn['num_perm'] = 0 hddn['manhattan_plot'] = "" - if hasattr(self.this_trait, 'locus_chr') and self.this_trait.locus_chr != "" and self.dataset.type != "Geno" and self.dataset.type != "Publish": - hddn['control_marker'] = self.nearest_marker - #hddn['control_marker'] = self.nearest_marker1+","+self.nearest_marker2 - else: - hddn['control_marker'] = "" + hddn['control_marker'] = "" + if not self.temp_trait: + if hasattr(self.this_trait, 'locus_chr') and self.this_trait.locus_chr != "" and self.dataset.type != "Geno" and self.dataset.type != "Publish": + hddn['control_marker'] = self.nearest_marker + #hddn['control_marker'] = self.nearest_marker1+","+self.nearest_marker2 hddn['do_control'] = False hddn['maf'] = 0.01 hddn['compare_traits'] = [] @@ -118,11 +144,12 @@ class ShowTrait(object): self.trait_table_width = get_trait_table_width(self.sample_groups) - if self.this_trait.symbol: - trait_symbol = self.this_trait.symbol - else: - trait_symbol = None - js_data = dict(trait_id = self.this_trait.name, + trait_symbol = None + if not self.temp_trait: + if self.this_trait.symbol: + trait_symbol = self.this_trait.symbol + + js_data = dict(trait_id = self.trait_id, trait_symbol = trait_symbol, dataset_type = self.dataset.type, data_scale = self.dataset.data_scale, @@ -149,7 +176,7 @@ class ShowTrait(object): else: return False - self.genofiles = get_genofiles(self.this_trait) + self.genofiles = get_genofiles(self.dataset) self.use_plink_gemma = check_plink_gemma() self.use_pylmm_rqtl = check_pylmm_rqtl() @@ -173,8 +200,8 @@ class ShowTrait(object): dataset_menu = data_set.datasets(this_group, self.dataset.group) dataset_menu_selected = None if len(dataset_menu): - if self.this_trait and self.this_trait.dataset: - dataset_menu_selected = self.this_trait.dataset.name + if self.dataset: + dataset_menu_selected = self.dataset.name return_results_menu = (100, 200, 500, 1000, 2000, 5000, 10000, 15000, 20000) return_results_menu_selected = 500 @@ -185,52 +212,57 @@ class ShowTrait(object): return_results_menu_selected = return_results_menu_selected,) - def make_sample_lists(self, this_trait): + def make_sample_lists(self): all_samples_ordered = self.dataset.group.all_samples_ordered() primary_sample_names = list(all_samples_ordered) - other_sample_names = [] - for sample in this_trait.data.keys(): - if (this_trait.data[sample].name2 in primary_sample_names) and (this_trait.data[sample].name not in primary_sample_names): - primary_sample_names.append(this_trait.data[sample].name) - primary_sample_names.remove(this_trait.data[sample].name2) - elif sample not in all_samples_ordered: - all_samples_ordered.append(sample) - other_sample_names.append(sample) - - if self.dataset.group.species == "human": - primary_sample_names += other_sample_names - - primary_samples = SampleList(dataset = self.dataset, - sample_names=primary_sample_names, - this_trait=this_trait, - sample_group_type='primary', - header="%s Only" % (self.dataset.group.name)) - logger.debug("primary_samples is: ", pf(primary_samples)) - - logger.debug("other_sample_names2:", other_sample_names) - if other_sample_names and self.dataset.group.species != "human" and self.dataset.group.name != "CFW": - parent_f1_samples = None - if self.dataset.group.parlist and self.dataset.group.f1list: - parent_f1_samples = self.dataset.group.parlist + self.dataset.group.f1list - - other_sample_names.sort() #Sort other samples - if parent_f1_samples: - other_sample_names = parent_f1_samples + other_sample_names - - logger.debug("other_sample_names:", other_sample_names) - - other_samples = SampleList(dataset=self.dataset, - sample_names=other_sample_names, - this_trait=this_trait, - sample_group_type='other', - header="Non-%s" % (self.dataset.group.name)) - - self.sample_groups = (primary_samples, other_samples) + if not self.temp_trait: + other_sample_names = [] + for sample in self.this_trait.data.keys(): + if (self.this_trait.data[sample].name2 in primary_sample_names) and (self.this_trait.data[sample].name not in primary_sample_names): + primary_sample_names.append(self.this_trait.data[sample].name) + primary_sample_names.remove(self.this_trait.data[sample].name2) + elif sample not in all_samples_ordered: + all_samples_ordered.append(sample) + other_sample_names.append(sample) + + if self.dataset.group.species == "human": + primary_sample_names += other_sample_names + + primary_samples = SampleList(dataset = self.dataset, + sample_names=primary_sample_names, + this_trait=self.this_trait, + sample_group_type='primary', + header="%s Only" % (self.dataset.group.name)) + + if other_sample_names and self.dataset.group.species != "human" and self.dataset.group.name != "CFW": + parent_f1_samples = None + if self.dataset.group.parlist and self.dataset.group.f1list: + parent_f1_samples = self.dataset.group.parlist + self.dataset.group.f1list + + other_sample_names.sort() #Sort other samples + if parent_f1_samples: + other_sample_names = parent_f1_samples + other_sample_names + + logger.debug("other_sample_names:", other_sample_names) + + other_samples = SampleList(dataset=self.dataset, + sample_names=other_sample_names, + this_trait=self.this_trait, + sample_group_type='other', + header="Non-%s" % (self.dataset.group.name)) + + self.sample_groups = (primary_samples, other_samples) + else: + self.sample_groups = (primary_samples,) else: + primary_samples = SampleList(dataset = self.dataset, + sample_names=primary_sample_names, + this_trait=self.trait_vals, + sample_group_type='primary', + header="%s Only" % (self.dataset.group.name)) self.sample_groups = (primary_samples,) - #TODO: Figure out why this if statement is written this way - Zach #if (other_sample_names or (fd.f1list and this_trait.data.has_key(fd.f1list[0])) # or (fd.f1list and this_trait.data.has_key(fd.f1list[1]))): @@ -261,8 +293,8 @@ def get_nearest_marker(this_trait, this_db): return result[0][0] #return result[0][0], result[1][0] -def get_genofiles(this_trait): - jsonfile = "%s/%s.json" % (webqtlConfig.GENODIR, this_trait.dataset.group.name) +def get_genofiles(this_dataset): + jsonfile = "%s/%s.json" % (webqtlConfig.GENODIR, this_dataset.group.name) try: f = open(jsonfile) except: @@ -271,7 +303,7 @@ def get_genofiles(this_trait): return jsondata['genofile'] def get_trait_table_width(sample_groups): - table_width = 20 + table_width = 25 if sample_groups[0].se_exists(): table_width += 15 if (table_width + len(sample_groups[0].attributes)*10) > 100: diff --git a/wqflask/wqflask/static/new/javascript/draw_probability_plot.js b/wqflask/wqflask/static/new/javascript/draw_probability_plot.js index e5787564..f23dad0c 100644 --- a/wqflask/wqflask/static/new/javascript/draw_probability_plot.js +++ b/wqflask/wqflask/static/new/javascript/draw_probability_plot.js @@ -45,7 +45,7 @@ chart = nv.models.scatterChart().width(w).height(h).showLegend(true).color(d3.scale.category10().range()); chart.pointRange([50, 50]); chart.legend.updateState(false); - chart.xAxis.axisLabel("Expected Z score").tickFormat(d3.format('.02f')); + chart.xAxis.axisLabel("Expected Z score").axisLabelDistance(20).tickFormat(d3.format('.02f')); chart.tooltipContent(function(obj) { return '' + obj.point.name + ''; }); @@ -78,13 +78,19 @@ } return results; })(); - chart.yAxis.axisLabel("Trait value").tickFormat(d3.format('.0'+max_decimals.toString()+'f')); + //ZS: 0.1 indicates buffer, increase to increase buffer + y_domain = [sorted_values[0] - (sorted_values.slice(-1)[0] - sorted_values[0])*0.1, sorted_values.slice(-1)[0] + (sorted_values.slice(-1)[0] - sorted_values[0])*0.1] + chart.yDomain(y_domain) + chart.yAxis.axisLabel("Trait value").axisLabelDistance(10).tickFormat(d3.format('.0'+max_decimals.toString()+'f')); sw_result = ShapiroWilkW(sorted_values); W = sw_result.w.toFixed(3); pvalue = sw_result.p.toFixed(3); pvalue_str = pvalue > 0.05 ? pvalue.toString() : "" + pvalue + ""; test_str = "Shapiro-Wilk test statistic is " + W + " (p = " + pvalue_str + ")"; z_scores = get_z_scores(sorted_values.length); + //ZS: 0.1 indicates buffer, increase to increase buffer + x_domain = [z_scores[0] - (z_scores.slice(-1)[0] - z_scores[0])*0.1, z_scores.slice(-1)[0] + (z_scores.slice(-1)[0] - z_scores[0])*0.1] + chart.xDomain(x_domain) slope = jStat.stdev(sorted_values); intercept = jStat.mean(sorted_values); make_data = function(group_name) { diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js index 8223a38c..bb1af326 100644 --- a/wqflask/wqflask/static/new/javascript/show_trait.js +++ b/wqflask/wqflask/static/new/javascript/show_trait.js @@ -195,7 +195,7 @@ } row_line = ""; if (row.url != null) { - row_line += "" + row.pretty + ""; + row_line += "" + row.pretty + ""; } else { row_line += "" + row.pretty + ""; } diff --git a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.css b/wqflask/wqflask/static/new/packages/nvd3/nv.d3.css index 694b9218..593d3889 100644 --- a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.css +++ b/wqflask/wqflask/static/new/packages/nvd3/nv.d3.css @@ -1,96 +1,96 @@ /* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-05-25 */ -.nvd3 .nv-axis { - pointer-events:none; - opacity: 1; -} - -.nvd3 .nv-axis path { - fill: none; - stroke: #000; - stroke-opacity: .75; - shape-rendering: crispEdges; -} - -.nvd3 .nv-axis path.domain { - stroke-opacity: .75; -} - -.nvd3 .nv-axis.nv-x path.domain { - stroke-opacity: 1; -} - -.nvd3 .nv-axis line { - fill: none; - stroke: #e5e5e5; - shape-rendering: crispEdges; -} - -.nvd3 .nv-axis .zero line, - /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { - stroke-opacity: .75; -} - -.nvd3 .nv-axis .nv-axisMaxMin text { - font-weight: bold; -} - -.nvd3 .x .nv-axis .nv-axisMaxMin text, -.nvd3 .x2 .nv-axis .nv-axisMaxMin text, -.nvd3 .x3 .nv-axis .nv-axisMaxMin text { - text-anchor: middle -} - -.nvd3 .nv-axis.nv-disabled { - opacity: 0; -} - -.nvd3 .nv-bars rect { - fill-opacity: .75; - - transition: fill-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear; -} - -.nvd3 .nv-bars rect.hover { - fill-opacity: 1; -} - -.nvd3 .nv-bars .hover rect { - fill: lightblue; -} - -.nvd3 .nv-bars text { - fill: rgba(0,0,0,0); -} - -.nvd3 .nv-bars .hover text { - fill: rgba(0,0,0,1); -} - -.nvd3 .nv-multibar .nv-groups rect, -.nvd3 .nv-multibarHorizontal .nv-groups rect, -.nvd3 .nv-discretebar .nv-groups rect { - stroke-opacity: 0; - - transition: fill-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear; -} - -.nvd3 .nv-multibar .nv-groups rect:hover, -.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, -.nvd3 .nv-candlestickBar .nv-ticks rect:hover, -.nvd3 .nv-discretebar .nv-groups rect:hover { - fill-opacity: 1; -} - -.nvd3 .nv-discretebar .nv-groups text, -.nvd3 .nv-multibarHorizontal .nv-groups text { - font-weight: bold; - fill: rgba(0,0,0,1); - stroke: rgba(0,0,0,0); -} +.nvd3 .nv-axis { + pointer-events:none; + opacity: 1; +} + +.nvd3 .nv-axis path { + fill: none; + stroke: #000; + stroke-opacity: .75; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis path.domain { + stroke-opacity: .75; +} + +.nvd3 .nv-axis.nv-x path.domain { + stroke-opacity: 1; +} + +.nvd3 .nv-axis line { + fill: none; + stroke: #e5e5e5; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis .zero line, + /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { + stroke-opacity: .75; +} + +.nvd3 .nv-axis .nv-axisMaxMin text { + font-weight: bold; +} + +.nvd3 .x .nv-axis .nv-axisMaxMin text, +.nvd3 .x2 .nv-axis .nv-axisMaxMin text, +.nvd3 .x3 .nv-axis .nv-axisMaxMin text { + text-anchor: middle +} + +.nvd3 .nv-axis.nv-disabled { + opacity: 0; +} + +.nvd3 .nv-bars rect { + fill-opacity: .75; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-bars rect.hover { + fill-opacity: 1; +} + +.nvd3 .nv-bars .hover rect { + fill: lightblue; +} + +.nvd3 .nv-bars text { + fill: rgba(0,0,0,0); +} + +.nvd3 .nv-bars .hover text { + fill: rgba(0,0,0,1); +} + +.nvd3 .nv-multibar .nv-groups rect, +.nvd3 .nv-multibarHorizontal .nv-groups rect, +.nvd3 .nv-discretebar .nv-groups rect { + stroke-opacity: 0; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-multibar .nv-groups rect:hover, +.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, +.nvd3 .nv-candlestickBar .nv-ticks rect:hover, +.nvd3 .nv-discretebar .nv-groups rect:hover { + fill-opacity: 1; +} + +.nvd3 .nv-discretebar .nv-groups text, +.nvd3 .nv-multibarHorizontal .nv-groups text { + font-weight: bold; + fill: rgba(0,0,0,1); + stroke: rgba(0,0,0,0); +} /* boxplot CSS */ .nvd3 .nv-boxplot circle { @@ -112,57 +112,57 @@ .nv-boxplot-tick:hover { stroke-width: 2.5px; } -/* bullet */ -.nvd3.nv-bullet { font: 10px sans-serif; } -.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } -.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } -.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } -.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } -.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } -.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } -.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } -.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } -.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } -.nvd3.nv-bullet .nv-subtitle { fill: #999; } - - -.nvd3.nv-bullet .nv-range { - fill: #bababa; - fill-opacity: .4; -} -.nvd3.nv-bullet .nv-range:hover { - fill-opacity: .7; -} - -.nvd3.nv-candlestickBar .nv-ticks .nv-tick { - stroke-width: 1px; -} - -.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover { - stroke-width: 2px; -} - -.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect { - stroke: #2ca02c; - fill: #2ca02c; -} - -.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect { - stroke: #d62728; - fill: #d62728; -} - -.with-transitions .nv-candlestickBar .nv-ticks .nv-tick { - transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -} - -.nvd3.nv-candlestickBar .nv-ticks line { - stroke: #333; -} - +/* bullet */ +.nvd3.nv-bullet { font: 10px sans-serif; } +.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } +.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } +.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } +.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } +.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } +.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } +.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } +.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } +.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } +.nvd3.nv-bullet .nv-subtitle { fill: #999; } + + +.nvd3.nv-bullet .nv-range { + fill: #bababa; + fill-opacity: .4; +} +.nvd3.nv-bullet .nv-range:hover { + fill-opacity: .7; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect { + stroke: #d62728; + fill: #d62728; +} + +.with-transitions .nv-candlestickBar .nv-ticks .nv-tick { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-candlestickBar .nv-ticks line { + stroke: #333; +} + .nvd3 .nv-legend .nv-disabled rect { /*fill-opacity: 0;*/ @@ -187,455 +187,455 @@ opacity: 0; } -/* line plus bar */ -.nvd3.nv-linePlusBar .nv-bar rect { - fill-opacity: .75; -} - -.nvd3.nv-linePlusBar .nv-bar rect:hover { - fill-opacity: 1; -} -.nvd3 .nv-groups path.nv-line { - fill: none; -} - -.nvd3 .nv-groups path.nv-area { - stroke: none; -} - -.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { - fill-opacity: 0; - stroke-opacity: 0; -} - -.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { - fill-opacity: .5 !important; - stroke-opacity: .5 !important; -} - - -.with-transitions .nvd3 .nv-groups .nv-point { - transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -} - -.nvd3.nv-scatter .nv-groups .nv-point.hover, -.nvd3 .nv-groups .nv-point.hover { - stroke-width: 7px; - fill-opacity: .95 !important; - stroke-opacity: .95 !important; -} - - -.nvd3 .nv-point-paths path { - stroke: #aaa; - stroke-opacity: 0; - fill: #eee; - fill-opacity: 0; -} - - - -.nvd3 .nv-indexLine { - cursor: ew-resize; -} - -/******************** - * SVG CSS - */ - -/******************** - Default CSS for an svg element nvd3 used -*/ -svg.nvd3-svg { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -ms-user-select: none; - -moz-user-select: none; - user-select: none; - display: block; - width:100%; - height:100%; -} - -/******************** - Box shadow and border radius styling -*/ -.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { - -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); - box-shadow: 0 5px 10px rgba(0,0,0,.2); - - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - - -.nvd3 text { - font: normal 12px Arial; -} - -.nvd3 .title { - font: bold 14px Arial; -} - -.nvd3 .nv-background { - fill: white; - fill-opacity: 0; -} - -.nvd3.nv-noData { - font-size: 18px; - font-weight: bold; -} - - -/********** -* Brush -*/ - -.nv-brush .extent { - fill-opacity: .125; - shape-rendering: crispEdges; -} - -.nv-brush .resize path { - fill: #eee; - stroke: #666; -} - - -/********** -* Legend -*/ - -.nvd3 .nv-legend .nv-series { - cursor: pointer; -} - -.nvd3 .nv-legend .nv-disabled circle { - fill-opacity: 0; -} - -/* focus */ -.nvd3 .nv-brush .extent { - fill-opacity: 0 !important; -} - -.nvd3 .nv-brushBackground rect { - stroke: #000; - stroke-width: .4; - fill: #fff; - fill-opacity: .7; -} - - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick { - stroke-width: 1px; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { - stroke-width: 2px; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { - stroke: #2ca02c; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { - stroke: #d62728; -} - - -.nvd3 .background path { - fill: none; - stroke: #EEE; - stroke-opacity: .4; - shape-rendering: crispEdges; -} - -.nvd3 .foreground path { - fill: none; - stroke-opacity: .7; -} - -.nvd3 .nv-parallelCoordinates-brush .extent -{ - fill: #fff; - fill-opacity: .6; - stroke: gray; - shape-rendering: crispEdges; -} - -.nvd3 .nv-parallelCoordinates .hover { - fill-opacity: 1; - stroke-width: 3px; -} - - -.nvd3 .missingValuesline line { - fill: none; - stroke: black; - stroke-width: 1; - stroke-opacity: 1; - stroke-dasharray: 5, 5; -} -.nvd3.nv-pie path { - stroke-opacity: 0; - transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -} - -.nvd3.nv-pie .nv-pie-title { - font-size: 24px; - fill: rgba(19, 196, 249, 0.59); -} - -.nvd3.nv-pie .nv-slice text { - stroke: #000; - stroke-width: 0; -} - -.nvd3.nv-pie path { - stroke: #fff; - stroke-width: 1px; - stroke-opacity: 1; -} - -.nvd3.nv-pie .hover path { - fill-opacity: .7; -} -.nvd3.nv-pie .nv-label { - pointer-events: none; -} -.nvd3.nv-pie .nv-label rect { - fill-opacity: 0; - stroke-opacity: 0; -} - -/* scatter */ -.nvd3 .nv-groups .nv-point.hover { - stroke-width: 20px; - stroke-opacity: .5; -} - -.nvd3 .nv-scatter .nv-point.hover { - fill-opacity: 1; -} -.nv-noninteractive { - pointer-events: none; -} - -.nv-distx, .nv-disty { - pointer-events: none; -} - -/* sparkline */ -.nvd3.nv-sparkline path { - fill: none; -} - -.nvd3.nv-sparklineplus g.nv-hoverValue { - pointer-events: none; -} - -.nvd3.nv-sparklineplus .nv-hoverValue line { - stroke: #333; - stroke-width: 1.5px; -} - -.nvd3.nv-sparklineplus, -.nvd3.nv-sparklineplus g { - pointer-events: all; -} - -.nvd3 .nv-hoverArea { - fill-opacity: 0; - stroke-opacity: 0; -} - -.nvd3.nv-sparklineplus .nv-xValue, -.nvd3.nv-sparklineplus .nv-yValue { - stroke-width: 0; - font-size: .9em; - font-weight: normal; -} - -.nvd3.nv-sparklineplus .nv-yValue { - stroke: #f66; -} - -.nvd3.nv-sparklineplus .nv-maxValue { - stroke: #2ca02c; - fill: #2ca02c; -} - -.nvd3.nv-sparklineplus .nv-minValue { - stroke: #d62728; - fill: #d62728; -} - -.nvd3.nv-sparklineplus .nv-currentValue { - font-weight: bold; - font-size: 1.1em; -} -/* stacked area */ -.nvd3.nv-stackedarea path.nv-area { - fill-opacity: .7; - stroke-opacity: 0; - transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; -} - -.nvd3.nv-stackedarea path.nv-area.hover { - fill-opacity: .9; -} - - -.nvd3.nv-stackedarea .nv-groups .nv-point { - stroke-opacity: 0; - fill-opacity: 0; -} - - -.nvtooltip { - position: absolute; - background-color: rgba(255,255,255,1.0); - color: rgba(0,0,0,1.0); - padding: 1px; - border: 1px solid rgba(0,0,0,.2); - z-index: 10000; - display: block; - - font-family: Arial; - font-size: 13px; - text-align: left; - pointer-events: none; - - white-space: nowrap; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.nvtooltip { - background: rgba(255,255,255, 0.8); - border: 1px solid rgba(0,0,0,0.5); - border-radius: 4px; -} - -/*Give tooltips that old fade in transition by - putting a "with-transitions" class on the container div. -*/ -.nvtooltip.with-transitions, .with-transitions .nvtooltip { - transition: opacity 50ms linear; - -moz-transition: opacity 50ms linear; - -webkit-transition: opacity 50ms linear; - - transition-delay: 200ms; - -moz-transition-delay: 200ms; - -webkit-transition-delay: 200ms; -} - -.nvtooltip.x-nvtooltip, -.nvtooltip.y-nvtooltip { - padding: 8px; -} - -.nvtooltip h3 { - margin: 0; - padding: 4px 14px; - line-height: 18px; - font-weight: normal; - background-color: rgba(247,247,247,0.75); - color: rgba(0,0,0,1.0); - text-align: center; - - border-bottom: 1px solid #ebebeb; - - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 5px 5px 0 0; -} - -.nvtooltip p { - margin: 0; - padding: 5px 14px; - text-align: center; -} - -.nvtooltip span { - display: inline-block; - margin: 2px 0; -} - -.nvtooltip table { - margin: 6px; - border-spacing:0; -} - - -.nvtooltip table td { - padding: 2px 9px 2px 0; - vertical-align: middle; -} - -.nvtooltip table td.key { - font-weight:normal; -} -.nvtooltip table td.value { - text-align: right; - font-weight: bold; -} - -.nvtooltip table tr.highlight td { - padding: 1px 9px 1px 0; - border-bottom-style: solid; - border-bottom-width: 1px; - border-top-style: solid; - border-top-width: 1px; -} - -.nvtooltip table td.legend-color-guide div { - width: 8px; - height: 8px; - vertical-align: middle; -} - -.nvtooltip table td.legend-color-guide div { - width: 12px; - height: 12px; - border: 1px solid #999; -} - -.nvtooltip .footer { - padding: 3px; - text-align: center; -} - -.nvtooltip-pending-removal { - pointer-events: none; - display: none; -} - - -/**** -Interactive Layer -*/ -.nvd3 .nv-interactiveGuideLine { - pointer-events:none; -} -.nvd3 line.nv-guideline { - stroke: #ccc; +/* line plus bar */ +.nvd3.nv-linePlusBar .nv-bar rect { + fill-opacity: .75; +} + +.nvd3.nv-linePlusBar .nv-bar rect:hover { + fill-opacity: 1; +} +.nvd3 .nv-groups path.nv-line { + fill: none; +} + +.nvd3 .nv-groups path.nv-area { + stroke: none; +} + +.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { + fill-opacity: .5 !important; + stroke-opacity: .5 !important; +} + + +.with-transitions .nvd3 .nv-groups .nv-point { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-scatter .nv-groups .nv-point.hover, +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 7px; + fill-opacity: .95 !important; + stroke-opacity: .95 !important; +} + + +.nvd3 .nv-point-paths path { + stroke: #aaa; + stroke-opacity: 0; + fill: #eee; + fill-opacity: 0; +} + + + +.nvd3 .nv-indexLine { + cursor: ew-resize; +} + +/******************** + * SVG CSS + */ + +/******************** + Default CSS for an svg element nvd3 used +*/ +svg.nvd3-svg { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -ms-user-select: none; + -moz-user-select: none; + user-select: none; + display: block; + width:100%; + height:100%; +} + +/******************** + Box shadow and border radius styling +*/ +.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + + +.nvd3 text { + font: normal 14px Arial; +} + +.nvd3 .title { + font: bold 14px Arial; +} + +.nvd3 .nv-background { + fill: white; + fill-opacity: 0; +} + +.nvd3.nv-noData { + font-size: 18px; + font-weight: bold; +} + + +/********** +* Brush +*/ + +.nv-brush .extent { + fill-opacity: .125; + shape-rendering: crispEdges; +} + +.nv-brush .resize path { + fill: #eee; + stroke: #666; +} + + +/********** +* Legend +*/ + +.nvd3 .nv-legend .nv-series { + cursor: pointer; +} + +.nvd3 .nv-legend .nv-disabled circle { + fill-opacity: 0; +} + +/* focus */ +.nvd3 .nv-brush .extent { + fill-opacity: 0 !important; +} + +.nvd3 .nv-brushBackground rect { + stroke: #000; + stroke-width: .4; + fill: #fff; + fill-opacity: .7; +} + + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { + stroke: #2ca02c; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { + stroke: #d62728; +} + + +.nvd3 .background path { + fill: none; + stroke: #EEE; + stroke-opacity: .4; + shape-rendering: crispEdges; +} + +.nvd3 .foreground path { + fill: none; + stroke-opacity: .7; +} + +.nvd3 .nv-parallelCoordinates-brush .extent +{ + fill: #fff; + fill-opacity: .6; + stroke: gray; + shape-rendering: crispEdges; +} + +.nvd3 .nv-parallelCoordinates .hover { + fill-opacity: 1; + stroke-width: 3px; +} + + +.nvd3 .missingValuesline line { + fill: none; + stroke: black; + stroke-width: 1; + stroke-opacity: 1; + stroke-dasharray: 5, 5; +} +.nvd3.nv-pie path { + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-pie .nv-pie-title { + font-size: 24px; + fill: rgba(19, 196, 249, 0.59); +} + +.nvd3.nv-pie .nv-slice text { + stroke: #000; + stroke-width: 0; +} + +.nvd3.nv-pie path { + stroke: #fff; + stroke-width: 1px; + stroke-opacity: 1; +} + +.nvd3.nv-pie .hover path { + fill-opacity: .7; +} +.nvd3.nv-pie .nv-label { + pointer-events: none; +} +.nvd3.nv-pie .nv-label rect { + fill-opacity: 0; + stroke-opacity: 0; +} + +/* scatter */ +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 20px; + stroke-opacity: .5; +} + +.nvd3 .nv-scatter .nv-point.hover { + fill-opacity: 1; +} +.nv-noninteractive { + pointer-events: none; +} + +.nv-distx, .nv-disty { + pointer-events: none; +} + +/* sparkline */ +.nvd3.nv-sparkline path { + fill: none; +} + +.nvd3.nv-sparklineplus g.nv-hoverValue { + pointer-events: none; +} + +.nvd3.nv-sparklineplus .nv-hoverValue line { + stroke: #333; + stroke-width: 1.5px; +} + +.nvd3.nv-sparklineplus, +.nvd3.nv-sparklineplus g { + pointer-events: all; +} + +.nvd3 .nv-hoverArea { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-sparklineplus .nv-xValue, +.nvd3.nv-sparklineplus .nv-yValue { + stroke-width: 0; + font-size: .9em; + font-weight: normal; +} + +.nvd3.nv-sparklineplus .nv-yValue { + stroke: #f66; +} + +.nvd3.nv-sparklineplus .nv-maxValue { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-sparklineplus .nv-minValue { + stroke: #d62728; + fill: #d62728; +} + +.nvd3.nv-sparklineplus .nv-currentValue { + font-weight: bold; + font-size: 1.1em; +} +/* stacked area */ +.nvd3.nv-stackedarea path.nv-area { + fill-opacity: .7; + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; +} + +.nvd3.nv-stackedarea path.nv-area.hover { + fill-opacity: .9; +} + + +.nvd3.nv-stackedarea .nv-groups .nv-point { + stroke-opacity: 0; + fill-opacity: 0; +} + + +.nvtooltip { + position: absolute; + background-color: rgba(255,255,255,1.0); + color: rgba(0,0,0,1.0); + padding: 1px; + border: 1px solid rgba(0,0,0,.2); + z-index: 10000; + display: block; + + font-family: Arial; + font-size: 13px; + text-align: left; + pointer-events: none; + + white-space: nowrap; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.nvtooltip { + background: rgba(255,255,255, 0.8); + border: 1px solid rgba(0,0,0,0.5); + border-radius: 4px; +} + +/*Give tooltips that old fade in transition by + putting a "with-transitions" class on the container div. +*/ +.nvtooltip.with-transitions, .with-transitions .nvtooltip { + transition: opacity 50ms linear; + -moz-transition: opacity 50ms linear; + -webkit-transition: opacity 50ms linear; + + transition-delay: 200ms; + -moz-transition-delay: 200ms; + -webkit-transition-delay: 200ms; +} + +.nvtooltip.x-nvtooltip, +.nvtooltip.y-nvtooltip { + padding: 8px; +} + +.nvtooltip h3 { + margin: 0; + padding: 4px 14px; + line-height: 18px; + font-weight: normal; + background-color: rgba(247,247,247,0.75); + color: rgba(0,0,0,1.0); + text-align: center; + + border-bottom: 1px solid #ebebeb; + + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.nvtooltip p { + margin: 0; + padding: 5px 14px; + text-align: center; +} + +.nvtooltip span { + display: inline-block; + margin: 2px 0; +} + +.nvtooltip table { + margin: 6px; + border-spacing:0; +} + + +.nvtooltip table td { + padding: 2px 9px 2px 0; + vertical-align: middle; +} + +.nvtooltip table td.key { + font-weight:normal; +} +.nvtooltip table td.value { + text-align: right; + font-weight: bold; +} + +.nvtooltip table tr.highlight td { + padding: 1px 9px 1px 0; + border-bottom-style: solid; + border-bottom-width: 1px; + border-top-style: solid; + border-top-width: 1px; +} + +.nvtooltip table td.legend-color-guide div { + width: 8px; + height: 8px; + vertical-align: middle; +} + +.nvtooltip table td.legend-color-guide div { + width: 12px; + height: 12px; + border: 1px solid #999; +} + +.nvtooltip .footer { + padding: 3px; + text-align: center; +} + +.nvtooltip-pending-removal { + pointer-events: none; + display: none; +} + + +/**** +Interactive Layer +*/ +.nvd3 .nv-interactiveGuideLine { + pointer-events:none; +} +.nvd3 line.nv-guideline { + stroke: #ccc; } \ No newline at end of file diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html index cedb65a1..3bde7dc7 100644 --- a/wqflask/wqflask/templates/correlation_page.html +++ b/wqflask/wqflask/templates/correlation_page.html @@ -32,65 +32,65 @@

-
+
- + {% for header in target_dataset.header_fields %} {% if header == 'Year' %} - + {% elif header == 'Max LRS' %} - + {% elif header == 'Max LRS Location' %} - + {% elif header == 'Location' %} - + {% elif header == 'Mean' %} - + {% elif header == 'Additive Effect' %} - + {% elif header == 'Index' %} - + {% elif header == 'N' %} - + {% else %} - + {% endif %} {% endfor %} {% if target_dataset.type == "ProbeSet" %} {% if corr_method == 'pearson' %} - - - - - + + + + + {% else %} - - - - - + + + + + {% endif %} {% elif target_dataset.type == "Publish" %} {% if corr_method == 'pearson' %} - - - + + + {% else %} - - - + + + {% endif %} {% elif target_dataset.type == "Geno" %} {% if corr_method == 'pearson' %} - - - + + + {% else %} - - - + + + {% endif %} {% endif %} @@ -99,7 +99,7 @@ {% for trait in correlation_results %} - + - - - - - - + + + + + + {% if trait.lit_corr == "" or trait.lit_corr == 0.000 %} - + {% else %} - + {% endif %} {% if trait.tissue_corr == "" or trait.tissue_corr == 0.000 %} - + {% else %} - + {% endif %} {% elif target_dataset.type == "Publish" %} @@ -138,17 +138,17 @@ {{ trait.pubmed_text }} - - - - - - + + + + + + {% elif target_dataset.type == "Geno" %} - - - - + + + + {% endif %} {% endfor %} @@ -278,6 +278,13 @@ { "type": "natural" }, { "type": "natural" } ], + "createdRow": function ( row, data, index ) { + $('td', row).eq(4).attr('title', $('td', row).eq(4).text()); + if ($('td', row).eq(4).text().length > 60) { + $('td', row).eq(4).text($('td', row).eq(4).text().substring(0, 60)); + $('td', row).eq(4).text($('td', row).eq(4).text() + '...') + } + }, "order": [[12, "asc" ]], "sDom": "Btir", "autoWidth": false, @@ -287,7 +294,6 @@ } ); var table = $('#trait_table').DataTable(); - new $.fn.dataTable.FixedHeader( table ); {% elif target_dataset.type == "Publish" %} $('#trait_table').dataTable( { @@ -311,7 +317,7 @@ { "type": "natural" }, { "type": "natural" }, { "type": "natural", "width": "25%" }, - { "type": "natural", "width": "10%" }, + { "type": "natural", "width": "15%" }, { "type": "natural" }, { "type": "natural" }, { "type": "natural" }, @@ -320,6 +326,13 @@ { "type": "natural" }, { "type": "scientific" } ], + "createdRow": function ( row, data, index ) { + $('td', row).eq(4).attr('title', $('td', row).eq(4).text()); + if ($('td', row).eq(4).text().length > 60) { + $('td', row).eq(4).text($('td', row).eq(4).text().substring(0, 60)); + $('td', row).eq(4).text($('td', row).eq(4).text() + '...') + } + }, "order": [[11, "asc" ]], "sDom": "Btir", "autoWidth": false, diff --git a/wqflask/wqflask/templates/index_page_orig.html b/wqflask/wqflask/templates/index_page_orig.html index 1694eae5..72ced084 100755 --- a/wqflask/wqflask/templates/index_page_orig.html +++ b/wqflask/wqflask/templates/index_page_orig.html @@ -173,6 +173,16 @@
+
+ + +
- {% if mapping_method != "gemma" %} + {% if mapping_method != "gemma" and mapping_method != "plink" %}
@@ -277,11 +277,13 @@ + {% if mapping_method != "gemma" and mapping_method != "plink" %} + {% endif %} - {% if mapping_method != "gemma" %} + {% if mapping_method != "gemma" and mapping_method != "plink" %} @@ -385,6 +387,7 @@ return $('#marker_regression_form').submit(); }; + {% if mapping_method != "gemma" and mapping_method != "plink" %} export_perm_data = function() { var num_perm, perm_data; num_perm = js_data.num_perm @@ -393,7 +396,8 @@ $('input[name=perm_results]').val(json_perm_data); $('#marker_regression_form').attr('action', '/export_perm_data'); return $('#marker_regression_form').submit(); - }; + } + {% endif %} diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html index 772c4314..56b6cc62 100644 --- a/wqflask/wqflask/templates/show_trait.html +++ b/wqflask/wqflask/templates/show_trait.html @@ -17,7 +17,9 @@ {% block content %} diff --git a/wqflask/wqflask/templates/submit_trait.html b/wqflask/wqflask/templates/submit_trait.html index 2529a4f4..8d624ffd 100644 --- a/wqflask/wqflask/templates/submit_trait.html +++ b/wqflask/wqflask/templates/submit_trait.html @@ -2,7 +2,7 @@ {% block title %}Trait Submission{% endblock %} {% block content %} -
+
{{ flash_me() }} diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py index ab6c433d..39f4a686 100644 --- a/wqflask/wqflask/views.py +++ b/wqflask/wqflask/views.py @@ -389,6 +389,20 @@ def export_perm_data(): mimetype='text/csv', headers={"Content-Disposition":"attachment;filename=perm_data.csv"}) +@app.route("/show_temp_trait", methods=('POST',)) +def show_temp_trait_page(): + template_vars = show_trait.ShowTrait(request.form) + #logger.info("js_data before dump:", template_vars.js_data) + template_vars.js_data = json.dumps(template_vars.js_data, + default=json_default_handler, + indent=" ") + # Sorting the keys messes up the ordered dictionary, so don't do that + #sort_keys=True) + + #logger.info("js_data after dump:", template_vars.js_data) + #logger.info("show_trait template_vars:", pf(template_vars.__dict__)) + return render_template("show_trait.html", **template_vars.__dict__) + @app.route("/show_trait") def show_trait_page(): template_vars = show_trait.ShowTrait(request.args) @@ -575,9 +589,10 @@ def marker_regression_page(): with Bench("Total time in MarkerRegression"): template_vars = marker_regression.MarkerRegression(start_vars, temp_uuid) - template_vars.js_data = json.dumps(template_vars.js_data, - default=json_default_handler, - indent=" ") + if template_vars.mapping_method != "gemma" and template_vars.mapping_method != "plink": + template_vars.js_data = json.dumps(template_vars.js_data, + default=json_default_handler, + indent=" ") result = template_vars.__dict__ @@ -598,13 +613,15 @@ def marker_regression_page(): # logger.info(" ---**--- {}: {}".format(type(template_vars.__dict__[item]), item)) gn1_template_vars = marker_regression_gn1.MarkerRegression(result).__dict__ - - pickled_result = pickle.dumps(result, pickle.HIGHEST_PROTOCOL) - logger.info("pickled result length:", len(pickled_result)) - Redis.set(key, pickled_result) - Redis.expire(key, 1*60) + #pickled_result = pickle.dumps(result, pickle.HIGHEST_PROTOCOL) + #logger.info("pickled result length:", len(pickled_result)) + #Redis.set(key, pickled_result) + #Redis.expire(key, 1*60) 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"): -- cgit v1.2.3 From f419b8bc824303009817ad9d52e1452b870b0039 Mon Sep 17 00:00:00 2001 From: zsloan Date: Wed, 5 Apr 2017 15:51:20 +0000 Subject: Added images directory with various gifs, etc --- wqflask/wqflask/static/new/images/a1.gif | Bin 0 -> 430 bytes wqflask/wqflask/static/new/images/arrowdown.gif | Bin 0 -> 844 bytes wqflask/wqflask/static/new/images/step1.gif | Bin 0 -> 758 bytes wqflask/wqflask/static/new/images/step2.gif | Bin 0 -> 826 bytes wqflask/wqflask/static/new/images/step3.gif | Bin 0 -> 818 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 wqflask/wqflask/static/new/images/a1.gif create mode 100644 wqflask/wqflask/static/new/images/arrowdown.gif create mode 100644 wqflask/wqflask/static/new/images/step1.gif create mode 100644 wqflask/wqflask/static/new/images/step2.gif create mode 100644 wqflask/wqflask/static/new/images/step3.gif diff --git a/wqflask/wqflask/static/new/images/a1.gif b/wqflask/wqflask/static/new/images/a1.gif new file mode 100644 index 00000000..283921a0 Binary files /dev/null and b/wqflask/wqflask/static/new/images/a1.gif differ diff --git a/wqflask/wqflask/static/new/images/arrowdown.gif b/wqflask/wqflask/static/new/images/arrowdown.gif new file mode 100644 index 00000000..577e5476 Binary files /dev/null and b/wqflask/wqflask/static/new/images/arrowdown.gif differ diff --git a/wqflask/wqflask/static/new/images/step1.gif b/wqflask/wqflask/static/new/images/step1.gif new file mode 100644 index 00000000..42d2bc7d Binary files /dev/null and b/wqflask/wqflask/static/new/images/step1.gif differ diff --git a/wqflask/wqflask/static/new/images/step2.gif b/wqflask/wqflask/static/new/images/step2.gif new file mode 100644 index 00000000..b3dca656 Binary files /dev/null and b/wqflask/wqflask/static/new/images/step2.gif differ diff --git a/wqflask/wqflask/static/new/images/step3.gif b/wqflask/wqflask/static/new/images/step3.gif new file mode 100644 index 00000000..0e0c7ea2 Binary files /dev/null and b/wqflask/wqflask/static/new/images/step3.gif differ -- cgit v1.2.3 From 2c94097c49eedff1def1fb7d53572f290b8fe7d1 Mon Sep 17 00:00:00 2001 From: zsloan Date: Mon, 17 Apr 2017 22:24:40 +0000 Subject: Added option to remove collections from collection list page Improved appearance of search result and collection tables --- wqflask/base/data_set.py | 2 +- wqflask/wqflask/collect.py | 19 +++-- .../packages/DataTables/css/jquery.dataTables.css | 15 ++-- wqflask/wqflask/templates/collections/list.html | 60 +++++++++++---- wqflask/wqflask/templates/collections/view.html | 86 ++++++++++++---------- wqflask/wqflask/templates/search_result_page.html | 27 +++---- 6 files changed, 130 insertions(+), 79 deletions(-) diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py index 7f08135f..4959457a 100644 --- a/wqflask/base/data_set.py +++ b/wqflask/base/data_set.py @@ -893,7 +893,7 @@ class GenotypeDataSet(DataSet): def retrieve_sample_data(self, trait): query = """ SELECT - Strain.Name, GenoData.value, GenoSE.error, GenoData.Id, Sample.Name2 + Strain.Name, GenoData.value, GenoSE.error, GenoData.Id, Strain.Name2 FROM (GenoData, GenoFreeze, Strain, Geno, GenoXRef) left join GenoSE on diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py index 478dbcaa..2f6c3a96 100644 --- a/wqflask/wqflask/collect.py +++ b/wqflask/wqflask/collect.py @@ -335,12 +335,19 @@ def delete_collection(): print("params:", params) if g.user_session.logged_in: uc_id = params['uc_id'] - uc = model.UserCollection.query.get(uc_id) - # Todo: For now having the id is good enough since it's so unique - # But might want to check ownership in the future - collection_name = uc.name - db_session.delete(uc) - db_session.commit() + if len(uc_id.split(":")) > 1: + for this_uc_id in uc_id.split(":"): + uc = model.UserCollection.query.get(this_uc_id) + collection_name = uc.name + db_session.delete(uc) + db_session.commit() + else: + uc = model.UserCollection.query.get(uc_id) + # Todo: For now having the id is good enough since it's so unique + # But might want to check ownership in the future + collection_name = uc.name + db_session.delete(uc) + db_session.commit() else: collection_name = params['collection_name'] user_manager.AnonUser().delete_collection(collection_name) diff --git a/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css b/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css index 40e58ac8..ab7420a6 100644 --- a/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css +++ b/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css @@ -14,6 +14,9 @@ table.dataTable { * Body styles */ } +td.highlight { + background-color: whitesmoke !important; +} table.dataTable thead th, table.dataTable tfoot th { font-weight: bold; @@ -25,8 +28,8 @@ table.dataTable thead td { background-color: #ffffff; border-collapse: collapse; border-bottom: #cccccc 2px solid; - padding: 0; - //padding: 10px 18px 10px 0px; + //padding: 0; + padding: 10px 18px 4px 10px; //border-bottom: 1px solid #111; } table.dataTable thead th:active, @@ -39,8 +42,8 @@ table.dataTable tfoot td { color: #000000; background-color: #ffffff; border-collapse: collapse; - padding: 0; - //padding: 10px 18px 6px 18px; + //padding: 0; + padding: 10px 18px 6px 18px; //border-top: 1px solid #111; } table.dataTable thead .sorting, @@ -76,12 +79,12 @@ table.dataTable tbody tr { background-color: #ffffff; } table.dataTable tbody tr.selected { - background-color: #ffff99; + background-color: #abb9d3; } table.dataTable tbody th, table.dataTable tbody td { font: 12px Arial, Sans-serif; - padding: 4px 16px 4px 0px; + padding: 8px 20px 6px 10px; } table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td { border-top: 1px solid #ddd; diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html index 6dc52c4d..5a30c98c 100644 --- a/wqflask/wqflask/templates/collections/list.html +++ b/wqflask/wqflask/templates/collections/list.html @@ -25,11 +25,21 @@

Your Collections

{% endif %}
- +
+ + + + + + + +
+
-
{{header}}{{header}}Max  
LRS ?
Max LRS ?{{header}}{{header}}{{header}}{{header}}{{header}}{{header}}Add  
Effect ?
Additive Effect ?{{header}}{{header}}{{header}}{{header}}{{header}}{{header}}Sample r  NSample p(r)Lit rTissue rSample r  NSample p(r)Lit rTissue rSample rhoNSample p(rho)Lit rTissue rhoSample rhoNSample p(rho)Lit rTissue rhoSample r  NSample p(r)Sample r  NSample p(r)Sample rho  NSample p(rho)Sample rho  NSample p(rho)Sample rNSample p(r)Sample rNSample p(r)Sample rhoNSample p(rho)Sample rhoNSample p(rho)
   {{ loop.index }} {{ trait.location_repr }} {{ '%0.3f' % trait.mean|float }}{% if trait.LRS_score_repr != "N/A" %}{{ '%0.1f' % trait.LRS_score_repr|float }}{% else %}N/A{% endif %}{{ trait.LRS_location_repr }}{% if trait.additive != "" %}{{ '%0.3f' % trait.additive|float }}{% else %}N/A{% endif %}{{'%0.3f'|format(trait.sample_r)}}{{ trait.num_overlap }}{{'%0.3e'|format(trait.sample_p)}}{% if trait.LRS_score_repr != "N/A" %}{{ '%0.1f' % trait.LRS_score_repr|float }}{% else %}N/A{% endif %}{{ trait.LRS_location_repr }}{% if trait.additive != "" %}{{ '%0.3f' % trait.additive|float }}{% else %}N/A{% endif %}{{'%0.3f'|format(trait.sample_r)}}{{ trait.num_overlap }}{{'%0.3e'|format(trait.sample_p)}}----{{'%0.3f'|format(trait.lit_corr)}}{{'%0.3f'|format(trait.lit_corr)}}----{{'%0.3f'|format(trait.tissue_corr)}}{{'%0.3f'|format(trait.tissue_corr)}}{{ trait.description_display }} {{ trait.LRS_score_repr }}{{ trait.LRS_location_repr }}{% if trait.additive != "" %}{{ '%0.3f' % trait.additive|float }}{% else %}N/A{% endif %}{{'%0.3f'|format(trait.sample_r)}}{{ trait.num_overlap }}{{'%0.3e'|format(trait.sample_p)}}{{ trait.LRS_score_repr }}{{ trait.LRS_location_repr }}{% if trait.additive != "" %}{{ '%0.3f' % trait.additive|float }}{% else %}N/A{% endif %}{{'%0.3f'|format(trait.sample_r)}}{{ trait.num_overlap }}{{'%0.3e'|format(trait.sample_p)}}{{ trait.location_repr }}{{'%0.3f'|format(trait.sample_r)}}{{ trait.num_overlap }}{{'%0.3e'|format(trait.sample_p)}}{{ trait.location_repr }}{{'%0.3f'|format(trait.sample_r)}}{{ trait.num_overlap }}{{'%0.3e'|format(trait.sample_p)}}
+
+ @@ -41,7 +51,8 @@ {% for uc in collections %} - + {% else %} @@ -64,6 +75,7 @@ {% block js %} + @@ -72,24 +84,24 @@ - - {% if "color_by_trait" in params %} {% endif %} {% endblock %} diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html index 9d03e6d7..094bc273 100644 --- a/wqflask/wqflask/templates/collections/view.html +++ b/wqflask/wqflask/templates/collections/view.html @@ -2,8 +2,7 @@ {% block title %}View Collection{% endblock %} {% block css %} - - + {% endblock %} {% block content %} @@ -29,42 +28,40 @@ {% for this_trait in trait_obs %} {{ this_trait.name }}:{{ this_trait.dataset.name }}, {% endfor %}" > -
+ -
-
+ + -
-
+ + -
-
+ + -
-
+ + -
-
+ + -
+
-
-

@@ -80,7 +77,7 @@
-
Index Name Created
{{ loop.index }} + {{ loop.index }} {% if g.user_session.user_ob %} {{ uc.name }}
+
@@ -90,9 +87,9 @@ - + - + @@ -141,8 +138,8 @@ - - + + - - + + - + @@ -172,6 +172,7 @@ console.time("Creating table"); {% if dataset.type == 'ProbeSet' %} //ZS: Need to make sort by symbol, also need to make sure blank symbol fields at the bottom and symbols starting with numbers below letters + $('#trait_table').DataTable( { "drawCallback": function( settings ) { $('#trait_table tr').click(function(event) { @@ -182,8 +183,7 @@ $('.trait_checkbox:checkbox').on("change", change_buttons); }, "createdRow": function ( row, data, index ) { - $('td', row).eq(0).attr('style', 'padding-right: 0px;'); - $('td', row).eq(0).attr('align', 'center'); + $('td', row).eq(0).attr('style', 'padding-left: 8px; padding-right: 0px; padding-top: 4px; align: center;'); $('td', row).eq(1).attr('align', 'right'); $('td', row).eq(1).attr('data-export', index+1); $('td', row).eq(2).attr('data-export', $('td', row).eq(2).text()); @@ -207,15 +207,15 @@ "data": json_trait_list, "columns": [ { "type": "natural", "width": "2%" }, - { "type": "natural", "width": "4%" }, + { "type": "natural", "width": "5%" }, { "type": "natural", "width": "12%" }, { "type": "natural", "width": "12%" }, - { "type": "natural", "width": "25%" }, + { "type": "natural" }, { "type": "natural", "width": "11%" }, + { "type": "natural", "width": "4%" }, { "type": "natural", "width": "5%" }, - { "type": "natural", "width": "6%" }, { "type": "natural", "width": "11%" }, - { "type": "natural", "width": "6%" } + { "type": "natural", "width": "5%" } ], "columnDefs": [ { "targets": 0, @@ -224,8 +224,7 @@ "order": [[1, "asc" ]], buttons: [ { - extend: 'colvis', - text: 'Show or Hide Columns', + extend: 'columnsToggle', columns: ':not(:first-child)', postfixButtons: [ 'colvisRestore' ] } @@ -238,7 +237,8 @@ "scrollY": "600px", "scrollCollapse": false, "scroller": true, - "paging": false + "paging": false, + "orderClasses": true } ); {% elif dataset.type == 'Publish' %} @@ -358,6 +358,7 @@ "paging": false } ); {% endif %} + console.timeEnd("Creating table"); var table = $('#trait_table').DataTable(); -- cgit v1.2.3 From 3c46a58f50f339ec56027db6d2108de5b21d63ac Mon Sep 17 00:00:00 2001 From: zsloan Date: Tue, 25 Apr 2017 16:52:47 +0000 Subject: Fixed issue with correlation result trait links if target dataset is different from base dataset Improved collection list and view table appearances Added question mark image for glossary entries in table headers Fixed issue where extra decimal place sometimes appeared in bar chart Y axis tick values --- wqflask/runserver.py | 3 ++ .../wqflask/static/new/images/question_mark.jpg | Bin 0 -> 47158 bytes wqflask/wqflask/static/new/javascript/bar_chart.js | 11 ++++++ wqflask/wqflask/templates/collections/list.html | 9 ++++- wqflask/wqflask/templates/collections/view.html | 8 ----- wqflask/wqflask/templates/correlation_page.html | 2 +- wqflask/wqflask/templates/search_result_page.html | 39 +++++++++++---------- 7 files changed, 43 insertions(+), 29 deletions(-) create mode 100644 wqflask/wqflask/static/new/images/question_mark.jpg diff --git a/wqflask/runserver.py b/wqflask/runserver.py index a6ae28af..50805643 100644 --- a/wqflask/runserver.py +++ b/wqflask/runserver.py @@ -11,6 +11,9 @@ import logging import utility.logger logger = utility.logger.getLogger(__name__ ) +import signal +signal.signal(signal.SIGPIPE, signal.SIG_DFL) + BLUE = '\033[94m' GREEN = '\033[92m' BOLD = '\033[1m' diff --git a/wqflask/wqflask/static/new/images/question_mark.jpg b/wqflask/wqflask/static/new/images/question_mark.jpg new file mode 100644 index 00000000..82df7e81 Binary files /dev/null and b/wqflask/wqflask/static/new/images/question_mark.jpg differ diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.js b/wqflask/wqflask/static/new/javascript/bar_chart.js index 7ec35148..d8540580 100644 --- a/wqflask/wqflask/static/new/javascript/bar_chart.js +++ b/wqflask/wqflask/static/new/javascript/bar_chart.js @@ -253,6 +253,17 @@ })()) ]); console.log("values: ", values); + + decimal_exists = "False"; + for(i=0; i < values.length; i++){ + if (values[i]['y'] % 1 != 0){ + decimal_exists = "True"; + break; + } + } + if (decimal_exists == "False"){ + _this.chart.yAxis.tickFormat(d3.format('d')) + } d3.select("#bar_chart_container svg").datum([ { values: values diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html index 5a30c98c..b1284895 100644 --- a/wqflask/wqflask/templates/collections/list.html +++ b/wqflask/wqflask/templates/collections/list.html @@ -51,7 +51,7 @@ {% for uc in collections %} - + @@ -89,6 +89,13 @@ {% endif %} - + + - - -{% endblock %} \ No newline at end of file + +{% endblock %} -- cgit v1.2.3
Description Location MeanMax LRS ?Max LRS Max LRS LocationAdditive Effect ?Additive Effect
{{ loop.index }} {% if g.user_session.user_ob %} {{ uc.name }}