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
{{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)}}