diff options
author | Zachary Sloan | 2014-06-06 22:00:30 +0000 |
---|---|---|
committer | Zachary Sloan | 2014-06-06 22:00:30 +0000 |
commit | 0bdeca3490c1ddbb7fa29165893a97f90eeefba7 (patch) | |
tree | 3ea8786848218f459fd8101f6b49a1b7587e08fc /wqflask | |
parent | 515662ecabd5d3a90eef6987aa5f8d4dbe63611f (diff) | |
download | genenetwork2-0bdeca3490c1ddbb7fa29165893a97f90eeefba7.tar.gz |
Implimented Karl Broman's lodchart code for the interval mapping function.
Suggestive/significant bars and additive effect curve added
Diffstat (limited to 'wqflask')
32 files changed, 3156 insertions, 178 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py index f4ca3ae0..a2b13748 100755 --- a/wqflask/base/data_set.py +++ b/wqflask/base/data_set.py @@ -167,28 +167,56 @@ class Markers(object): marker['Mb'] = float(marker['Mb']) self.markers = markers - print("self.markers:", self.markers) + #print("self.markers:", self.markers) def add_pvalues(self, p_values): print("length of self.markers:", len(self.markers)) print("length of p_values:", len(p_values)) - # THIS IS only needed for the case when we are limiting the number of p-values calculated - if len(self.markers) < len(p_values): - self.markers = self.markers[:len(p_values)] - - for marker, p_value in itertools.izip(self.markers, p_values): - if not p_value: - continue - marker['p_value'] = float(p_value) - if math.isnan(marker['p_value']) or marker['p_value'] <= 0: - marker['lod_score'] = 0 - marker['lrs_value'] = 0 - else: - marker['lod_score'] = -math.log10(marker['p_value']) - #Using -log(p) for the LRS; need to ask Rob how he wants to get LRS from p-values - marker['lrs_value'] = -math.log10(marker['p_value']) * 4.61 + if type(p_values) is list: + # THIS IS only needed for the case when we are limiting the number of p-values calculated + #if len(self.markers) > len(p_values): + # self.markers = self.markers[:len(p_values)] + + for marker, p_value in itertools.izip(self.markers, p_values): + if not p_value: + continue + marker['p_value'] = float(p_value) + if math.isnan(marker['p_value']) or marker['p_value'] <= 0: + marker['lod_score'] = 0 + marker['lrs_value'] = 0 + else: + marker['lod_score'] = -math.log10(marker['p_value']) + #Using -log(p) for the LRS; need to ask Rob how he wants to get LRS from p-values + marker['lrs_value'] = -math.log10(marker['p_value']) * 4.61 + elif type(p_values) is dict: + filtered_markers = [] + for marker in self.markers: + #print("marker[name]", marker['name']) + #print("p_values:", p_values) + if marker['name'] in p_values: + #print("marker {} IS in p_values".format(i)) + marker['p_value'] = p_values[marker['name']] + if math.isnan(marker['p_value']) or (marker['p_value'] <= 0): + marker['lod_score'] = 0 + marker['lrs_value'] = 0 + else: + marker['lod_score'] = -math.log10(marker['p_value']) + #Using -log(p) for the LRS; need to ask Rob how he wants to get LRS from p-values + marker['lrs_value'] = -math.log10(marker['p_value']) * 4.61 + filtered_markers.append(marker) + #else: + #print("marker {} NOT in p_values".format(i)) + #self.markers.remove(marker) + #del self.markers[i] + self.markers = filtered_markers + + #for i, marker in enumerate(self.markers): + # if not 'p_value' in marker: + # #print("self.markers[i]", self.markers[i]) + # del self.markers[i] + # #self.markers.remove(self.markers[i]) class HumanMarkers(Markers): @@ -226,15 +254,15 @@ class HumanMarkers(Markers): # #Using -log(p) for the LRS; need to ask Rob how he wants to get LRS from p-values # marker['lrs_value'] = -math.log10(marker['p_value']) * 4.61 - print("p_values2:", p_values) + #print("p_values2:", pf(p_values)) super(HumanMarkers, self).add_pvalues(p_values) - with Bench("deleting markers"): - markers = [] - for marker in self.markers: - if not marker['Mb'] <= 0 and not marker['chr'] == 0: - markers.append(marker) - self.markers = markers + #with Bench("deleting markers"): + # markers = [] + # for marker in self.markers: + # if not marker['Mb'] <= 0 and not marker['chr'] == 0: + # markers.append(marker) + # self.markers = markers @@ -254,7 +282,7 @@ class DatasetGroup(object): self.name = "BXD" self.f1list = None - self.parlist = None + self.parlist = None self.get_f1_parent_strains() #print("parents/f1s: {}:{}".format(self.parlist, self.f1list)) @@ -476,8 +504,9 @@ class DataSet(object): else: self.samplelist = self.group.samplelist - if (self.group.parlist + self.group.f1list) in self.samplelist: - self.samplelist += self.group.parlist + self.group.f1list + if self.group.parlist != None and self.group.f1list != None: + if (self.group.parlist + self.group.f1list) in self.samplelist: + self.samplelist += self.group.parlist + self.group.f1list query = """ SELECT Strain.Name, Strain.Id FROM Strain, Species @@ -547,7 +576,11 @@ class DataSet(object): order by {}.Id """.format(*mescape(self.type, self.type, self.type, self.type, self.name, dataset_type, self.type, self.type, dataset_type)) + + #print("trait data query: ", query) + results = g.db.execute(query).fetchall() + #print("query results:", results) trait_sample_data.append(results) trait_count = len(trait_sample_data[0]) diff --git a/wqflask/base/mrna_assay_tissue_data.py b/wqflask/base/mrna_assay_tissue_data.py index be5df657..1a05fce7 100755 --- a/wqflask/base/mrna_assay_tissue_data.py +++ b/wqflask/base/mrna_assay_tissue_data.py @@ -19,6 +19,8 @@ class MrnaAssayTissueData(object): if self.gene_symbols == None: self.gene_symbols = [] + print("self.gene_symbols:", self.gene_symbols) + self.data = collections.defaultdict(Bunch) #self.gene_id_dict ={} @@ -28,7 +30,7 @@ class MrnaAssayTissueData(object): #self.desc_dict = {} #self.probe_target_desc_dict = {} - query = '''select t.Symbol, t.GeneId, t.DataId,t.Chr, t.Mb, t.description, t.Probe_Target_Description + query = '''select t.Symbol, t.GeneId, t.DataId, t.Chr, t.Mb, t.description, t.Probe_Target_Description from ( select Symbol, max(Mean) as maxmean from TissueProbeSetXRef @@ -53,6 +55,7 @@ class MrnaAssayTissueData(object): '''.format(in_clause) results = g.db.execute(query).fetchall() + for result in results: symbol = result[0] if symbol in gene_symbols: @@ -66,7 +69,7 @@ class MrnaAssayTissueData(object): self.data[symbol].description = result.description self.data[symbol].probe_target_description = result.Probe_Target_Description - #print("self.data: ", pf(self.data)) + print("self.data: ", pf(self.data)) ########################################################################### #Input: cursor, symbolList (list), dataIdDict(Dict) @@ -79,6 +82,8 @@ class MrnaAssayTissueData(object): def get_symbol_values_pairs(self): id_list = [self.data[symbol].data_id for symbol in self.data] + print("id_list:", id_list) + symbol_values_dict = {} query = """SELECT TissueProbeSetXRef.Symbol, TissueProbeSetData.value @@ -86,6 +91,8 @@ class MrnaAssayTissueData(object): WHERE TissueProbeSetData.Id IN {} and TissueProbeSetXRef.DataId = TissueProbeSetData.Id""".format(db_tools.create_in_clause(id_list)) + print("TISSUE QUERY:", query) + results = g.db.execute(query).fetchall() for result in results: if result.Symbol.lower() not in symbol_values_dict: diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py index 712d9af5..3f80d4a4 100755 --- a/wqflask/base/trait.py +++ b/wqflask/base/trait.py @@ -40,6 +40,7 @@ class GeneralTrait(object): else: self.dataset = kw.get('dataset') self.name = kw.get('name') # Trait ID, ProbeSet ID, Published ID, etc. + print("THE NAME IS:", self.name) self.cellid = kw.get('cellid') self.identification = kw.get('identification', 'un-named trait') self.haveinfo = kw.get('haveinfo', False) @@ -295,6 +296,9 @@ class GeneralTrait(object): PublishXRef.InbredSetId = PublishFreeze.InbredSetId AND PublishFreeze.Id = %s """ % (self.name, self.dataset.id) + + print("query is:", query) + trait_info = g.db.execute(query).fetchone() #XZ, 05/08/2009: Xiaodong add this block to use ProbeSet.Id to find the probeset instead of just using ProbeSet.Name #XZ, 05/08/2009: to avoid the problem of same probeset name from different platforms. diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py index 0b66bc61..1cc932a0 100755 --- a/wqflask/wqflask/correlation/show_corr_results.py +++ b/wqflask/wqflask/correlation/show_corr_results.py @@ -93,8 +93,13 @@ class CorrelationResults(object): # get trait list from db (database name) # calculate correlation with Base vector and targets + print("TESTING...") + with Bench("Doing correlations"): helper_functions.get_species_dataset_trait(self, start_vars) + + print("TRAIT SYMBOL:", self.this_trait.symbol) + self.dataset.group.read_genotype_file() corr_samples_group = start_vars['corr_samples_group'] @@ -108,9 +113,11 @@ class CorrelationResults(object): #The two if statements below append samples to the sample list based upon whether the user #rselected Primary Samples Only, Other Samples Only, or All Samples - primary_samples = (self.dataset.group.parlist + - self.dataset.group.f1list + - self.dataset.group.samplelist) + primary_samples = self.dataset.group.samplelist + if self.dataset.group.parlist != None: + primary_samples += self.dataset.group.parlist + if self.dataset.group.f1list != None: + primary_samples += self.dataset.group.f1list #If either BXD/whatever Only or All Samples, append all of that group's samplelist if corr_samples_group != 'samples_other': @@ -156,6 +163,7 @@ class CorrelationResults(object): for _trait_counter, trait in enumerate(self.correlation_data.keys()[:self.return_number]): + print("trait name:", trait) trait_object = GeneralTrait(dataset=self.dataset, name=trait, get_qtl_info=True) (trait_object.sample_r, @@ -329,8 +337,8 @@ class CorrelationResults(object): key=lambda t: -abs(t[1][1]))) return tissue_corr_data - - + + def do_lit_correlation_for_trait_list(self): input_trait_mouse_gene_id = self.convert_to_mouse_gene_id(self.dataset.group.species.lower(), self.this_trait.geneid) @@ -348,14 +356,14 @@ class CorrelationResults(object): FROM LCorrRamin3 WHERE GeneId1='%s' and GeneId2='%s' - """ % (escape(trait.mouse_gene_id), escape(input_trait_mouse_gene_id)) + """ % (escape(str(trait.mouse_gene_id)), escape(str(input_trait_mouse_gene_id))) ).fetchone() if not result: result = g.db.execute("""SELECT value FROM LCorrRamin3 WHERE GeneId2='%s' and GeneId1='%s' - """ % (escape(trait.mouse_gene_id), escape(input_trait_mouse_gene_id)) + """ % (escape(str(trait.mouse_gene_id)), escape(str(input_trait_mouse_gene_id))) ).fetchone() if result: @@ -419,20 +427,30 @@ class CorrelationResults(object): mouse_gene_id = gene_id elif species == 'rat': - mouse_gene_id = g.db.execute( - """SELECT mouse + + query = """SELECT mouse FROM GeneIDXRef - WHERE rat='%d' - """, escape(int(gene_id))).fetchone().mouse + WHERE rat='%s'""" % escape(gene_id) + + print("GENE_ID QUERY: ", query) + + result = g.db.execute(query).fetchone() + if result != None: + mouse_gene_id = result.mouse elif species == 'human': - mouse_gene_id = g.db.execute( - """SELECT mouse + + query = """SELECT mouse FROM GeneIDXRef - WHERE human='%d' - """, escape(int(gene_id))).fetchone().mouse + WHERE human='%s'""" % escape(gene_id) + + print("GENE_ID QUERY: ", query) + + result = g.db.execute(query).fetchone() + if result != None: + mouse_gene_id = result.mouse - #print("mouse_geneid:", mouse_geneid) + print("mouse_geneid:", mouse_gene_id) return mouse_gene_id @@ -456,6 +474,8 @@ class CorrelationResults(object): this_trait_vals.append(sample_value) target_vals.append(target_sample_value) + print("trait:", trait) + this_trait_vals, target_vals, num_overlap = corr_result_helpers.normalize_values( this_trait_vals, target_vals) @@ -1010,6 +1030,7 @@ class CorrelationResults(object): values_2.append(target_value) correlation = calCorrelation(values_1, values_2) self.correlation_data[trait] = correlation + """ correlations = [] diff --git a/wqflask/wqflask/interval_mapping/interval_mapping.py b/wqflask/wqflask/interval_mapping/interval_mapping.py index f0985cc2..d28cb24b 100755 --- a/wqflask/wqflask/interval_mapping/interval_mapping.py +++ b/wqflask/wqflask/interval_mapping/interval_mapping.py @@ -23,6 +23,7 @@ from base.trait import GeneralTrait from base import data_set from base import species from base import webqtlConfig +from utility import webqtlUtil from wqflask.my_pylmm.data import prep_data from wqflask.my_pylmm.pyLMM import lmm from wqflask.my_pylmm.pyLMM import input @@ -55,7 +56,10 @@ class IntervalMapping(object): self.set_options(start_vars) + self.json_data = {} + if self.method == "qtl_reaper": + self.json_data['lodnames'] = ['lod.hk'] self.gen_reaper_results(tempdata) else: self.gen_pylmm_results(tempdata) @@ -63,14 +67,24 @@ class IntervalMapping(object): #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) + chromosome_mb_lengths[key] = self.species.chromosomes.chromosomes[key].mb_length #print("self.qtl_results:", self.qtl_results) + print("JSON DATA:", self.json_data) + + #os.chdir(webqtlConfig.TMPDIR) + json_filename = webqtlUtil.genRandStr(prefix="intmap_") + json.dumps(self.json_data, webqtlConfig.TMPDIR + json_filename) + self.js_data = dict( chromosomes = chromosome_mb_lengths, qtl_results = self.qtl_results, + json_data = self.json_data #lrs_lod = self.lrs_lod, ) @@ -144,8 +158,18 @@ class IntervalMapping(object): #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary self.qtl_results = [] + self.json_data['chr'] = [] + self.json_data['pos'] = [] + self.json_data['lod.hk'] = [] + self.json_data['additive'] = [] + self.json_data['markernames'] = [] for qtl in reaper_results: reaper_locus = qtl.locus + self.json_data['chr'].append(reaper_locus.chr) + self.json_data['pos'].append(reaper_locus.Mb) + self.json_data['lod.hk'].append(qtl.lrs) + self.json_data['markernames'].append(reaper_locus.name) + self.json_data['additive'].append(qtl.additive) locus = {"name":reaper_locus.name, "chr":reaper_locus.chr, "cM":reaper_locus.cM, "Mb":reaper_locus.Mb} qtl = {"lrs": qtl.lrs, "locus": locus, "additive": qtl.additive} self.qtl_results.append(qtl) @@ -166,8 +190,11 @@ class IntervalMapping(object): self.lrs_array = genotype.permutation(strains = trimmed_samples, trait = trimmed_values, nperm= self.num_permutations) + self.suggestive = self.lrs_array[int(self.num_permutations*0.37-1)] self.significant = self.lrs_array[int(self.num_permutations*0.95-1)] + self.json_data['suggestive'] = self.suggestive + self.json_data['significant'] = self.significant print("samples:", trimmed_samples) @@ -179,10 +206,21 @@ class IntervalMapping(object): reaper_results = genotype.regression(strains = trimmed_samples, trait = trimmed_values) + self.json_data['chr'] = [] + self.json_data['pos'] = [] + self.json_data['lod.hk'] = [] + self.json_data['additive'] = [] + self.json_data['markernames'] = [] + #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary self.qtl_results = [] for qtl in reaper_results: reaper_locus = qtl.locus + self.json_data['chr'].append(reaper_locus.chr) + self.json_data['pos'].append(reaper_locus.Mb) + self.json_data['lod.hk'].append(qtl.lrs) + self.json_data['markernames'].append(reaper_locus.name) + self.json_data['additive'].append(qtl.additive) locus = {"name":reaper_locus.name, "chr":reaper_locus.chr, "cM":reaper_locus.cM, "Mb":reaper_locus.Mb} qtl = {"lrs_value": qtl.lrs, "chr":reaper_locus.chr, "Mb":reaper_locus.Mb, "cM":reaper_locus.cM, "name":reaper_locus.name, "additive":qtl.additive} diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py index c220d2c9..525a2253 100755 --- a/wqflask/wqflask/marker_regression/marker_regression.py +++ b/wqflask/wqflask/marker_regression/marker_regression.py @@ -22,6 +22,8 @@ import simplejson as json from redis import Redis Redis = Redis() +from flask import Flask, g + from base.trait import GeneralTrait from base import data_set from base import species @@ -60,18 +62,20 @@ class MarkerRegression(object): qtl_results = self.run_gemma() elif self.mapping_method == "plink": qtl_results = self.run_plink() + #print("qtl_results:", pf(qtl_results)) elif self.mapping_method == "pylmm": #self.qtl_results = self.gen_data(tempdata) qtl_results = self.gen_data(str(temp_uuid)) - self.lod_cutoff = self.get_lod_score_cutoff() + self.lod_cutoff = 2 self.filtered_markers = [] for marker in qtl_results: - #if marker['lod_score'] > self.lod_cutoff: - if marker['lod_score'] > 1: + if marker['chr'] > 0: self.filtered_markers.append(marker) + #if marker['lod_score'] > self.lod_cutoff: + - print("filtered_markers:", self.filtered_markers) + #print("filtered_markers:", self.filtered_markers) #Get chromosome lengths for drawing the manhattan plot chromosome_mb_lengths = {} @@ -86,6 +90,8 @@ class MarkerRegression(object): def run_gemma(self): """Generates p-values for each marker using GEMMA""" + self.dataset.group.get_markers() + #filename = webqtlUtil.genRandStr("{}_{}_".format(self.dataset.group.name, self.this_trait.name)) self.gen_pheno_txt_file() @@ -156,6 +162,205 @@ class MarkerRegression(object): def run_plink(self): os.chdir("/home/zas1024/plink") + + self.dataset.group.get_markers() + + plink_output_filename = webqtlUtil.genRandStr("%s_%s_"%(self.dataset.group.name, self.this_trait.name)) + + self.gen_pheno_txt_file_plink(pheno_filename = plink_output_filename) + + plink_command = './plink --noweb --ped %s.ped --no-fid --no-parents --no-sex --no-pheno --map %s.map --pheno %s/%s.txt --pheno-name %s --missing-phenotype -9999 --out %s%s --assoc ' % (self.dataset.group.name, self.dataset.group.name, webqtlConfig.TMPDIR, plink_output_filename, self.this_trait.name, webqtlConfig.TMPDIR, plink_output_filename) + + os.system(plink_command) + + count, p_values = self.parse_plink_output(plink_output_filename) + #gemma_command = './gemma -bfile %s -k output_%s.cXX.txt -lmm 1 -o %s_output' % ( + # self.dataset.group.name, + # self.dataset.group.name, + # self.dataset.group.name) + #print("gemma_command:" + gemma_command) + # + #os.system(gemma_command) + # + #included_markers, p_values = self.parse_gemma_output() + # + #self.dataset.group.get_specified_markers(markers = included_markers) + + #for marker in self.dataset.group.markers.markers: + # if marker['name'] not in included_markers: + # print("marker:", marker) + # self.dataset.group.markers.markers.remove(marker) + # #del self.dataset.group.markers.markers[marker] + + print("p_values:", pf(p_values)) + + self.dataset.group.markers.add_pvalues(p_values) + + return self.dataset.group.markers.markers + + + def gen_pheno_txt_file_plink(self, pheno_filename = ''): + ped_sample_list = self.get_samples_from_ped_file() + output_file = open("%s%s.txt" % (webqtlConfig.TMPDIR, pheno_filename), "wb") + header = 'FID\tIID\t%s\n' % self.this_trait.name + output_file.write(header) + + new_value_list = [] + + #if valueDict does not include some strain, value will be set to -9999 as missing value + for i, sample in enumerate(ped_sample_list): + try: + value = self.vals[i] + value = str(value).replace('value=','') + value = value.strip() + except: + value = -9999 + + new_value_list.append(value) + + + new_line = '' + for i, sample in enumerate(ped_sample_list): + j = i+1 + value = new_value_list[i] + new_line += '%s\t%s\t%s\n'%(sample, sample, value) + + if j%1000 == 0: + output_file.write(newLine) + new_line = '' + + if new_line: + output_file.write(new_line) + + output_file.close() + + # get strain name from ped file in order + def get_samples_from_ped_file(self): + + os.chdir("/home/zas1024/plink") + + ped_file= open("{}.ped".format(self.dataset.group.name),"r") + line = ped_file.readline() + sample_list=[] + + while line: + lineList = string.split(string.strip(line), '\t') + lineList = map(string.strip, lineList) + + sample_name = lineList[0] + sample_list.append(sample_name) + + line = ped_file.readline() + + return sample_list + + ################################################################ + # Generate Chr list, Chr OrderId and Retrieve Length Information + ################################################################ + #def getChrNameOrderIdLength(self,RISet=''): + # try: + # query = """ + # Select + # Chr_Length.Name,Chr_Length.OrderId,Length from Chr_Length, InbredSet + # where + # Chr_Length.SpeciesId = InbredSet.SpeciesId AND + # InbredSet.Name = '%s' + # Order by OrderId + # """ % (self.dataset.group.name) + # results =g.db.execute(query).fetchall() + # ChrList=[] + # ChrLengthMbList=[] + # ChrNameOrderIdDict={} + # ChrOrderIdNameDict={} + # + # for item in results: + # ChrList.append(item[0]) + # ChrNameOrderIdDict[item[0]]=item[1] # key is chr name, value is orderId + # ChrOrderIdNameDict[item[1]]=item[0] # key is orderId, value is chr name + # ChrLengthMbList.append(item[2]) + # + # except: + # ChrList=[] + # ChrNameOrderIdDict={} + # ChrLengthMbList=[] + # + # return ChrList,ChrNameOrderIdDict,ChrOrderIdNameDict,ChrLengthMbList + + + def parse_plink_output(self, output_filename): + plink_results={} + + threshold_p_value = 0.01 + + result_fp = open("%s%s.qassoc"% (webqtlConfig.TMPDIR, output_filename), "rb") + + header_line = result_fp.readline()# read header line + line = result_fp.readline() + + value_list = [] # initialize value list, this list will include snp, bp and pvalue info + p_value_dict = {} + count = 0 + + while line: + #convert line from str to list + line_list = self.build_line_list(line=line) + + # only keep the records whose chromosome name is in db + if self.species.chromosomes.chromosomes.has_key(int(line_list[0])) and line_list[-1] and line_list[-1].strip()!='NA': + + chr_name = self.species.chromosomes.chromosomes[int(line_list[0])] + snp = line_list[1] + BP = line_list[2] + p_value = float(line_list[-1]) + if threshold_p_value >= 0 and threshold_p_value <= 1: + if p_value < threshold_p_value: + p_value_dict[snp] = p_value + + if plink_results.has_key(chr_name): + value_list = plink_results[chr_name] + + # pvalue range is [0,1] + if threshold_p_value >=0 and threshold_p_value <= 1: + if p_value < threshold_p_value: + value_list.append((snp, BP, p_value)) + count += 1 + + plink_results[chr_name] = value_list + value_list = [] + else: + if threshold_p_value >= 0 and threshold_p_value <= 1: + if p_value < threshold_p_value: + value_list.append((snp, BP, p_value)) + count += 1 + + if value_list: + plink_results[chr_name] = value_list + + value_list=[] + + line = result_fp.readline() + else: + line = result_fp.readline() + + #if p_value_list: + # min_p_value = min(p_value_list) + #else: + # min_p_value = 0 + + return count, p_value_dict + + ###################################################### + # input: line: str,one line read from file + # function: convert line from str to list; + # output: lineList list + ####################################################### + def build_line_list(self, line=None): + + line_list = string.split(string.strip(line),' ')# irregular number of whitespaces between columns + line_list = [item for item in line_list if item <>''] + line_list = map(string.strip, line_list) + + return line_list #def gen_data(self, tempdata): def gen_data(self, temp_uuid): @@ -238,7 +443,7 @@ class MarkerRegression(object): self.dataset.group.markers.add_pvalues(p_values) - self.get_lod_score_cutoff() + #self.get_lod_score_cutoff() return self.dataset.group.markers.markers @@ -309,6 +514,7 @@ class MarkerRegression(object): return p_values, t_stats def get_lod_score_cutoff(self): + print("INSIDE GET LOD CUTOFF") high_qtl_count = 0 for marker in self.dataset.group.markers.markers: if marker['lod_score'] > 1: diff --git a/wqflask/wqflask/static/new/css/panelutil.css b/wqflask/wqflask/static/new/css/panelutil.css new file mode 100644 index 00000000..d02c47d5 --- /dev/null +++ b/wqflask/wqflask/static/new/css/panelutil.css @@ -0,0 +1,87 @@ +body {
+ font-family: sans-serif;
+}
+
+text {
+ font-family: sans-serif;
+ font-size: 11pt;
+}
+
+.title text {
+ dominant-baseline: middle;
+ fill: blue;
+ text-anchor: middle;
+}
+
+.y.axis text {
+ dominant-baseline: middle;
+ text-anchor: end;
+}
+
+.y.axis text.title {
+ text-anchor: middle;
+ fill: slateblue;
+}
+
+.x.axis text {
+ dominant-baseline: hanging;
+ text-anchor: middle;
+}
+
+.x.axis text.title {
+ fill: slateblue;
+}
+
+line.axis.grid {
+ fill: none;
+ stroke-width: 1;
+ pointer-events: none;
+}
+
+line.x.axis.grid {
+ stroke: rgb(200, 200, 200);
+ stroke-width: 3;
+}
+
+line.y.axis.grid {
+ stroke: white;
+}
+
+.extent {
+ fill: #cac;
+ opacity: 0.3;
+}
+
+circle.selected {
+ fill: hotpink;
+ opacity: 1;
+}
+
+.caption {
+ margin-left: 60px;
+ width: 600px;
+}
+
+.d3-tip {
+ background: darkslateblue;
+ color: #fff;
+ stroke: none;
+ font-weight: bold;
+ font-size: 16px;
+ font-family: sans-serif;
+ padding: 5px;
+}
+
+.d3-tip.e:after {
+ color: darkslateblue;
+}
+
+a {
+ color: #08c;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #333;
+ text-decoration: underline;
+}
diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.coffee b/wqflask/wqflask/static/new/javascript/bar_chart.coffee index beaeb0a7..a48718de 100755 --- a/wqflask/wqflask/static/new/javascript/bar_chart.coffee +++ b/wqflask/wqflask/static/new/javascript/bar_chart.coffee @@ -13,7 +13,8 @@ class Bar_Chart longest_sample_name = d3.max(sample.length for sample in @sample_names) @margin = {top: 20, right: 20, bottom: longest_sample_name * 7, left: 40} - @plot_width = @sample_vals.length * 16 - @margin.left - @margin.right + @plot_width = @sample_vals.length * 20 - @margin.left - @margin.right + @range = @sample_vals.length * 20 @plot_height = 500 - @margin.top - @margin.bottom @x_buffer = @plot_width/20 @@ -172,7 +173,7 @@ class Bar_Chart console.log("sample_names2:", sample_names) x_scale = d3.scale.ordinal() .domain(sample_names) - .rangeBands([0, @plot_width], .1) + .rangeRoundBands([0, @range], 0.1, 0) $('.bar_chart').find('.x.axis').remove() @add_x_axis(x_scale) @@ -283,7 +284,7 @@ class Bar_Chart create_scales: () -> @x_scale = d3.scale.ordinal() .domain(@sample_names) - .rangeBands([0, @plot_width], 0.3) + .rangeRoundBands([0, @range], 0.1, 0) @y_scale = d3.scale.linear() .domain([@y_min * 0.75, @y_max]) diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.js b/wqflask/wqflask/static/new/javascript/bar_chart.js index c5802a6d..6f9b27e0 100755 --- a/wqflask/wqflask/static/new/javascript/bar_chart.js +++ b/wqflask/wqflask/static/new/javascript/bar_chart.js @@ -35,7 +35,8 @@ bottom: longest_sample_name * 7, left: 40 }; - this.plot_width = this.sample_vals.length * 16 - this.margin.left - this.margin.right; + this.plot_width = this.sample_vals.length * 20 - this.margin.left - this.margin.right; + this.range = this.sample_vals.length * 20; this.plot_height = 500 - this.margin.top - this.margin.bottom; this.x_buffer = this.plot_width / 20; this.y_buffer = this.plot_height / 20; @@ -124,7 +125,7 @@ return _results; })(); console.log("sample_names2:", sample_names); - x_scale = d3.scale.ordinal().domain(sample_names).rangeBands([0, this.plot_width], .1); + x_scale = d3.scale.ordinal().domain(sample_names).rangeRoundBands([0, this.range], 0.1, 0); $('.bar_chart').find('.x.axis').remove(); return this.add_x_axis(x_scale); }; @@ -306,7 +307,7 @@ }; Bar_Chart.prototype.create_scales = function() { - this.x_scale = d3.scale.ordinal().domain(this.sample_names).rangeBands([0, this.plot_width], 0.3); + this.x_scale = d3.scale.ordinal().domain(this.sample_names).rangeRoundBands([0, this.range], 0.1, 0); return this.y_scale = d3.scale.linear().domain([this.y_min * 0.75, this.y_max]).range([this.plot_height, this.y_buffer]); }; diff --git a/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.coffee b/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.coffee index 74eb2e88..8b27caa1 100755 --- a/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.coffee +++ b/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.coffee @@ -73,12 +73,12 @@ class Chr_Manhattan_Plot high_qtl_count += 1
console.log("high_qtl_count:", high_qtl_count)
- if high_qtl_count > 10000
- @y_axis_filter = 2
- else if high_qtl_count > 1000
- @y_axis_filter = 1
- else
- @y_axis_filter = 0
+ #if high_qtl_count > 10000
+ @y_axis_filter = 2
+ #else if high_qtl_count > 1000
+ # @y_axis_filter = 1
+ #else
+ # @y_axis_filter = 0
create_coordinates: () ->
for result in @these_results
@@ -108,7 +108,6 @@ class Chr_Manhattan_Plot return @y_max/2
else
return 2
-
create_graph: () ->
@add_border()
@@ -216,16 +215,16 @@ class Chr_Manhattan_Plot return @y_scale(d[1])
)
.attr("r", (d) =>
- if d[1] > 2
- return 3
- else
- return 2
+ #if d[1] > 2
+ # return 3
+ #else
+ return 2
)
.attr("fill", (d) =>
- if d[1] > 2
- return "white"
- else
- return "black"
+ #if d[1] > 2
+ # return "white"
+ #else
+ return "black"
)
.attr("stroke", "black")
.attr("stroke-width", "1")
@@ -247,16 +246,16 @@ class Chr_Manhattan_Plot this_id = "point_" + String(d[2])
d3.select("#" + this_id).classed("d3_highlight", false)
.attr("r", (d) =>
- if d[1] > 2
- return 3
- else
- return 2
+ #if d[1] > 2
+ # return 3
+ #else
+ return 2
)
.attr("fill", (d) =>
- if d[1] > 2
- return "white"
- else
- return "black"
+ #if d[1] > 2
+ # return "white"
+ #else
+ return "black"
)
.attr("stroke", "black")
.attr("stroke-width", "1")
diff --git a/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.js b/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.js index a38cfe5d..b7f64094 100755 --- a/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.js +++ b/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.js @@ -93,13 +93,7 @@ } } console.log("high_qtl_count:", high_qtl_count); - if (high_qtl_count > 10000) { - return this.y_axis_filter = 2; - } else if (high_qtl_count > 1000) { - return this.y_axis_filter = 1; - } else { - return this.y_axis_filter = 0; - } + return this.y_axis_filter = 2; }; Chr_Manhattan_Plot.prototype.create_coordinates = function() { @@ -193,17 +187,9 @@ }).attr("cy", function(d) { return _this.y_scale(d[1]); }).attr("r", function(d) { - if (d[1] > 2) { - return 3; - } else { - return 2; - } + return 2; }).attr("fill", function(d) { - if (d[1] > 2) { - return "white"; - } else { - return "black"; - } + return "black"; }).attr("stroke", "black").attr("stroke-width", "1").attr("id", function(d) { return "point_" + String(d[2]); }).classed("circle", true).on("mouseover", function(d) { @@ -216,17 +202,9 @@ var this_id; this_id = "point_" + String(d[2]); return d3.select("#" + this_id).classed("d3_highlight", false).attr("r", function(d) { - if (d[1] > 2) { - return 3; - } else { - return 2; - } + return 2; }).attr("fill", function(d) { - if (d[1] > 2) { - return "white"; - } else { - return "black"; - } + return "black"; }).attr("stroke", "black").attr("stroke-width", "1"); }).append("svg:title").text(function(d) { return d[2]; diff --git a/wqflask/wqflask/static/new/javascript/interval_map_new.coffee b/wqflask/wqflask/static/new/javascript/interval_map_new.coffee new file mode 100644 index 00000000..898df6d1 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/interval_map_new.coffee @@ -0,0 +1,71 @@ +h = 500
+w = 1200
+margin = {left:60, top:40, right:40, bottom: 40, inner:5}
+halfh = (h+margin.top+margin.bottom)
+totalh = halfh*2
+totalw = (w+margin.left+margin.right)
+
+# simplest use
+#d3.json "data.json", (data) ->
+mychart = lodchart().lodvarname("lod.hk")
+ .height(h)
+ .width(w)
+ .margin(margin)
+
+data = js_data.json_data
+
+d3.select("div#topchart")
+ .datum(data)
+ .call(mychart)
+
+# grab chromosome rectangles; color pink on hover
+chrrect = mychart.chrSelect()
+chrrect.on "mouseover", ->
+ d3.select(this).attr("fill", "#E9CFEC")
+ .on "mouseout", (d,i) ->
+ d3.select(this).attr("fill", ->
+ return "#F1F1F9" if i % 2
+ "#FBFBFF")
+
+# animate points at markers on click
+mychart.markerSelect()
+ .on "click", (d) ->
+ r = d3.select(this).attr("r")
+ d3.select(this)
+ .transition().duration(500).attr("r", r*3)
+ .transition().duration(500).attr("r", r)
+
+# two LOD charts within one SVG
+#d3.json "data.json", (data) ->
+# mychart_em = lodchart().lodvarname("lod.em")
+# .height(h)
+# .width(w)
+# .margin(margin)
+# .ylab("LOD score (by EM)")
+# .pointsize(1)
+# .nyticks(9)
+# .title("Standard interval mapping")
+# mychart_hk = lodchart().lodvarname("lod.hk")
+# .height(h)
+# .width(w)
+# .margin(margin)
+# .ylab("LOD score (by H-K)")
+# .linecolor("Crimson")
+# .yticks([0, 1, 2, 4, 6, 8])
+# .title("Haley-Knott regression")
+#
+# svg = d3.select("div#bottomchart")
+# .append("svg")
+# .attr("height", totalh)
+# .attr("width", totalw)
+#
+# chart1 = svg.append("g").attr("id", "chart1")
+#
+# chart2 = svg.append("g").attr("id", "chart2")
+# .attr("transform", "translate(0, #{halfh})")
+#
+# chart1.datum(data)
+# .call(mychart_em)
+#
+# chart2.datum(data)
+# .call(mychart_hk)
\ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/interval_map_new.js b/wqflask/wqflask/static/new/javascript/interval_map_new.js new file mode 100644 index 00000000..8861419c --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/interval_map_new.js @@ -0,0 +1,48 @@ +// Generated by CoffeeScript 1.6.1 +(function() { + var chrrect, data, h, halfh, margin, mychart, totalh, totalw, w; + + h = 500; + + w = 1200; + + margin = { + left: 60, + top: 40, + right: 40, + bottom: 40, + inner: 5 + }; + + halfh = h + margin.top + margin.bottom; + + totalh = halfh * 2; + + totalw = w + margin.left + margin.right; + + mychart = lodchart().lodvarname("lod.hk").height(h).width(w).margin(margin); + + data = js_data.json_data; + + d3.select("div#topchart").datum(data).call(mychart); + + chrrect = mychart.chrSelect(); + + chrrect.on("mouseover", function() { + return d3.select(this).attr("fill", "#E9CFEC"); + }).on("mouseout", function(d, i) { + return d3.select(this).attr("fill", function() { + if (i % 2) { + return "#F1F1F9"; + } + return "#FBFBFF"; + }); + }); + + mychart.markerSelect().on("click", function(d) { + var r; + r = d3.select(this).attr("r"); + return d3.select(this).transition().duration(500).attr("r", r * 3).transition().duration(500).attr("r", r); + }); + +}).call(this); diff --git a/wqflask/wqflask/static/new/javascript/lod_chart.coffee b/wqflask/wqflask/static/new/javascript/lod_chart.coffee new file mode 100644 index 00000000..fb11eeae --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/lod_chart.coffee @@ -0,0 +1,550 @@ +root = exports ? this
+
+lodchart = () ->
+ width = 800
+ height = 500
+ margin = {left:60, top:40, right:40, bottom: 40, inner:5}
+ axispos = {xtitle:25, ytitle:30, xlabel:5, ylabel:5}
+ titlepos = 20
+ ylim = null
+ additive_ylim = null
+ nyticks = 5
+ yticks = null
+ additive_yticks = null
+ chrGap = 8
+ darkrect = "#F1F1F9"
+ lightrect = "#FBFBFF"
+ lodlinecolor = "darkslateblue"
+ additivelinecolor = "red"
+ linewidth = 2
+ suggestivecolor = "gainsboro"
+ significantcolor = "#EBC7C7"
+ pointcolor = "#E9CFEC" # pink
+ pointsize = 0 # default = no visible points at markers
+ pointstroke = "black"
+ title = ""
+ xlab = "Chromosome"
+ ylab = "LRS score"
+ additive_ylab = "Additive Effect"
+ rotate_ylab = null
+ yscale = d3.scale.linear()
+ additive_yscale = d3.scale.linear()
+ xscale = null
+ pad4heatmap = false
+ lodcurve = null
+ lodvarname = null
+ markerSelect = null
+ chrSelect = null
+ pointsAtMarkers = true
+
+ ## the main function
+ chart = (selection) ->
+ selection.each (data) ->
+ lodvarname = lodvarname ? data.lodnames[0]
+ data[lodvarname] = (Math.abs(x) for x in data[lodvarname]) # take absolute values
+ data['additive'] = (Math.abs(x) for x in data['additive'])
+ ylim = ylim ? [0, d3.max(data[lodvarname])]
+ additive_ylim = additive_ylim ? [0, d3.max(data['additive'])]
+ lodvarnum = data.lodnames.indexOf(lodvarname)
+
+ # Select the svg element, if it exists.
+ svg = d3.select(this).selectAll("svg").data([data])
+
+ # Otherwise, create the skeletal chart.
+ gEnter = svg.enter().append("svg").append("g")
+
+ # Update the outer dimensions.
+ svg.attr("width", width+margin.left+margin.right)
+ .attr("height", height+margin.top+margin.bottom)
+
+ # Update the inner dimensions.
+ g = svg.select("g")
+
+ # box
+ g.append("rect")
+ .attr("x", margin.left)
+ .attr("y", margin.top)
+ .attr("height", height)
+ .attr("width", width)
+ .attr("fill", darkrect)
+ .attr("stroke", "none")
+
+ yscale.domain(ylim)
+ .range([height+margin.top, margin.top+margin.inner])
+
+ additive_yscale.domain(additive_ylim)
+ .range([height+margin.top, margin.top+margin.inner + height/2])
+
+ # if yticks not provided, use nyticks to choose pretty ones
+ yticks = yticks ? yscale.ticks(nyticks)
+ additive_yticks = additive_yticks ? additive_yscale.ticks(nyticks)
+
+ # reorganize lod,pos by chromosomes
+ data = reorgLodData(data, lodvarname)
+
+ # add chromosome scales (for x-axis)
+ data = chrscales(data, width, chrGap, margin.left, pad4heatmap)
+ xscale = data.xscale
+
+ # chr rectangles
+ chrSelect =
+ g.append("g").attr("class", "chrRect")
+ .selectAll("empty")
+ .data(data.chrnames)
+ .enter()
+ .append("rect")
+ .attr("id", (d) -> "chrrect#{d}")
+ .attr("x", (d,i) ->
+ return data.chrStart[i] if i==0 and pad4heatmap
+ data.chrStart[i]-chrGap/2)
+ .attr("width", (d,i) ->
+ return data.chrEnd[i] - data.chrStart[i]+chrGap/2 if (i==0 or i+1 == data.chrnames.length) and pad4heatmap
+ data.chrEnd[i] - data.chrStart[i]+chrGap)
+ .attr("y", margin.top)
+ .attr("height", height)
+ .attr("fill", (d,i) ->
+ return darkrect if i % 2
+ lightrect)
+ .attr("stroke", "none")
+
+ # x-axis labels
+ xaxis = g.append("g").attr("class", "x axis")
+ xaxis.selectAll("empty")
+ .data(data.chrnames)
+ .enter()
+ .append("text")
+ .text((d) -> d)
+ .attr("x", (d,i) -> (data.chrStart[i]+data.chrEnd[i])/2)
+ .attr("y", margin.top+height+axispos.xlabel)
+ xaxis.append("text").attr("class", "title")
+ .attr("y", margin.top+height+axispos.xtitle)
+ .attr("x", margin.left+width/2)
+ .text(xlab)
+
+ # y-axis
+ rotate_ylab = rotate_ylab ? (ylab.length > 1)
+ yaxis = g.append("g").attr("class", "y axis")
+ yaxis.selectAll("empty")
+ .data(yticks)
+ .enter()
+ .append("line")
+ .attr("y1", (d) -> yscale(d))
+ .attr("y2", (d) -> yscale(d))
+ .attr("x1", margin.left)
+ .attr("x2", margin.left+7)
+ .attr("fill", "none")
+ .attr("stroke", "white")
+ .attr("stroke-width", 1)
+ .style("pointer-events", "none")
+
+ yaxis.selectAll("empty")
+ .data(yticks)
+ .enter()
+ .append("text")
+ .attr("y", (d) -> yscale(d))
+ .attr("x", margin.left-axispos.ylabel)
+ .attr("fill", "blue")
+ .text((d) -> formatAxis(yticks)(d))
+
+ yaxis.append("text").attr("class", "title")
+ .attr("y", margin.top+height/2)
+ .attr("x", margin.left-axispos.ytitle)
+ .text(ylab)
+ .attr("transform", if rotate_ylab then "rotate(270,#{margin.left-axispos.ytitle},#{margin.top+height/2})" else "")
+
+ rotate_additive_ylab = rotate_additive_ylab ? (additive_ylab.length > 1)
+ additive_yaxis = g.append("g").attr("class", "y axis")
+ additive_yaxis.selectAll("empty")
+ .data(additive_yticks)
+ .enter()
+ .append("line")
+ .attr("y1", (d) -> additive_yscale(d))
+ .attr("y2", (d) -> additive_yscale(d))
+ .attr("x1", margin.left + width)
+ .attr("x2", margin.left + width - 7)
+ .attr("fill", "none")
+ .attr("stroke", "white")
+ .attr("stroke-width", 1)
+ .style("pointer-events", "none")
+
+ additive_yaxis.selectAll("empty")
+ .data(additive_yticks)
+ .enter()
+ .append("text")
+ .attr("y", (d) -> additive_yscale(d))
+ .attr("x", (d) -> margin.left + width + axispos.ylabel + 20)
+ .attr("fill", "green")
+ .text((d) -> formatAxis(additive_yticks)(d))
+
+ additive_yaxis.append("text").attr("class", "title")
+ .attr("y", margin.top+1.5*height)
+ .attr("x", margin.left + width + axispos.ytitle)
+ .text(additive_ylab)
+ .attr("transform", if rotate_additive_ylab then "rotate(270,#{margin.left + width + axispos.ytitle}, #{margin.top+height*1.5})" else "")
+
+
+ suggestive_bar = g.append("g").attr("class", "suggestive")
+ suggestive_bar.selectAll("empty")
+ .data([data.suggestive])
+ .enter()
+ .append("line")
+ .attr("y1", (d) -> yscale(d))
+ .attr("y2", (d) -> yscale(d))
+ .attr("x1", margin.left)
+ .attr("x2", margin.left+width)
+ .attr("fill", "none")
+ .attr("stroke", suggestivecolor)
+ .attr("stroke-width", 5)
+ .style("pointer-events", "none")
+
+ suggestive_bar = g.append("g").attr("class", "significant")
+ suggestive_bar.selectAll("empty")
+ .data([data.significant])
+ .enter()
+ .append("line")
+ .attr("y1", (d) -> yscale(d))
+ .attr("y2", (d) -> yscale(d))
+ .attr("x1", margin.left)
+ .attr("x2", margin.left+width)
+ .attr("fill", "none")
+ .attr("stroke", significantcolor)
+ .attr("stroke-width", 5)
+ .style("pointer-events", "none")
+
+ # lod curves by chr
+ lodcurve = (chr, lodcolumn) ->
+ d3.svg.line()
+ .x((d) -> xscale[chr](d))
+ .y((d,i) -> yscale(data.lodByChr[chr][i][lodcolumn]))
+
+ additivecurve = (chr, lodcolumn) ->
+ d3.svg.line()
+ .x((d) -> xscale[chr](d))
+ .y((d,i) -> additive_yscale(data.additiveByChr[chr][i][lodcolumn]))
+
+ curves = g.append("g").attr("id", "curves")
+
+ for chr in data.chrnames
+ curves.append("path")
+ .datum(data.posByChr[chr])
+ .attr("d", lodcurve(chr, lodvarnum))
+ .attr("stroke", lodlinecolor)
+ .attr("fill", "none")
+ .attr("stroke-width", linewidth)
+ .style("pointer-events", "none")
+
+ for chr in data.chrnames
+ curves.append("path")
+ .datum(data.posByChr[chr])
+ .attr("d", additivecurve(chr, lodvarnum))
+ .attr("stroke", additivelinecolor)
+ .attr("fill", "none")
+ .attr("stroke-width", 1)
+ .style("pointer-events", "none")
+
+ # points at markers
+ if pointsize > 0
+ markerpoints = g.append("g").attr("id", "markerpoints_visible")
+ markerpoints.selectAll("empty")
+ .data(data.markers)
+ .enter()
+ .append("circle")
+ .attr("cx", (d) -> xscale[d.chr](d.pos))
+ .attr("cy", (d) -> yscale(d.lod))
+ .attr("r", pointsize)
+ .attr("fill", pointcolor)
+ .attr("stroke", pointstroke)
+ .attr("pointer-events", "hidden")
+
+ if pointsAtMarkers
+ # these hidden points are what gets selected...a bit larger
+ hiddenpoints = g.append("g").attr("id", "markerpoints_hidden")
+
+ markertip = d3.tip()
+ .attr('class', 'd3-tip')
+ .html((d) ->
+ [d.name, " LRS = #{d3.format('.2f')(d.lod)}"])
+ .direction("e")
+ .offset([0,10])
+ svg.call(markertip)
+
+ markerSelect =
+ hiddenpoints.selectAll("empty")
+ .data(data.markers)
+ .enter()
+ .append("circle")
+ .attr("cx", (d) -> xscale[d.chr](d.pos))
+ .attr("cy", (d) -> yscale(d.lod))
+ .attr("id", (d) -> d.name)
+ .attr("r", d3.max([pointsize*2, 3]))
+ .attr("opacity", 0)
+ .attr("fill", pointcolor)
+ .attr("stroke", pointstroke)
+ .attr("stroke-width", "1")
+ .on "mouseover.paneltip", (d) ->
+ d3.select(this).attr("opacity", 1)
+ markertip.show(d)
+ .on "mouseout.paneltip", ->
+ d3.select(this).attr("opacity", 0)
+ .call(markertip.hide)
+
+ # title
+ titlegrp = g.append("g").attr("class", "title")
+ .append("text")
+ .attr("x", margin.left+width/2)
+ .attr("y", margin.top-titlepos)
+ .text(title)
+
+ # another box around edge
+ g.append("rect")
+ .attr("x", margin.left)
+ .attr("y", margin.top)
+ .attr("height", height)
+ .attr("width", () ->
+ return(data.chrEnd[-1..][0]-margin.left) if pad4heatmap
+ data.chrEnd[-1..][0]-margin.left+chrGap/2)
+ .attr("fill", "none")
+ .attr("stroke", "black")
+ .attr("stroke-width", "none")
+
+ ## configuration parameters
+ chart.width = (value) ->
+ return width unless arguments.length
+ width = value
+ chart
+
+ chart.height = (value) ->
+ return height unless arguments.length
+ height = value
+ chart
+
+ chart.margin = (value) ->
+ return margin unless arguments.length
+ margin = value
+ chart
+
+ chart.titlepos = (value) ->
+ return titlepos unless arguments.length
+ titlepos
+ chart
+
+ chart.axispos = (value) ->
+ return axispos unless arguments.length
+ axispos = value
+ chart
+
+ chart.ylim = (value) ->
+ return ylim unless arguments.length
+ ylim = value
+ chart
+
+ chart.additive_ylim = (value) ->
+ return additive_ylim unless arguments.length
+ additive_ylim = value
+ chart
+
+ chart.nyticks = (value) ->
+ return nyticks unless arguments.length
+ nyticks = value
+ chart
+
+ chart.yticks = (value) ->
+ return yticks unless arguments.length
+ yticks = value
+ chart
+
+ chart.chrGap = (value) ->
+ return chrGap unless arguments.length
+ chrGap = value
+ chart
+
+ chart.darkrect = (value) ->
+ return darkrect unless arguments.length
+ darkrect = value
+ chart
+
+ chart.lightrect = (value) ->
+ return lightrect unless arguments.length
+ lightrect = value
+ chart
+
+ chart.linecolor = (value) ->
+ return linecolor unless arguments.length
+ linecolor = value
+ chart
+
+ chart.linewidth = (value) ->
+ return linewidth unless arguments.length
+ linewidth = value
+ chart
+
+ chart.pointcolor = (value) ->
+ return pointcolor unless arguments.length
+ pointcolor = value
+ chart
+
+ chart.pointsize = (value) ->
+ return pointsize unless arguments.length
+ pointsize = value
+ chart
+
+ chart.pointstroke = (value) ->
+ return pointstroke unless arguments.length
+ pointstroke = value
+ chart
+
+ chart.title = (value) ->
+ return title unless arguments.length
+ title = value
+ chart
+
+ chart.xlab = (value) ->
+ return xlab unless arguments.length
+ xlab = value
+ chart
+
+ chart.ylab = (value) ->
+ return ylab unless arguments.length
+ ylab = value
+ chart
+
+ chart.rotate_ylab = (value) ->
+ return rotate_ylab if !arguments.length
+ rotate_ylab = value
+ chart
+
+ chart.lodvarname = (value) ->
+ return lodvarname unless arguments.length
+ lodvarname = value
+ chart
+
+ chart.pad4heatmap = (value) ->
+ return pad4heatmap unless arguments.length
+ pad4heatmap = value
+ chart
+
+ chart.pointsAtMarkers = (value) ->
+ return pointsAtMarkers unless arguments.length
+ pointsAtMarkers = value
+ chart
+
+ chart.yscale = () ->
+ return yscale
+
+ chart.additive_yscale = () ->
+ return additive_yscale
+
+ chart.xscale = () ->
+ return xscale
+
+ chart.lodcurve = () ->
+ return lodcurve
+
+ chart.additivecurve = () ->
+ return additivecurve
+
+ chart.markerSelect = () ->
+ return markerSelect
+
+ chart.chrSelect = () ->
+ return chrSelect
+
+ # return the chart function
+ chart
+
+root.lodchart = lodchart
+
+# reorganize lod/pos by chromosome
+# lodvarname==null -> case for multiple LOD columns (lodheatmap)
+# lodvarname provided -> case for one LOD column (lodchart)
+reorgLodData = (data, lodvarname=null) ->
+ data.posByChr = {}
+ data.lodByChr = {}
+ data.additiveByChr = {}
+
+ for chr,i in data.chrnames
+ data.posByChr[chr] = []
+ data.lodByChr[chr] = []
+ data.additiveByChr[chr] = []
+ for pos, j in data.pos
+ if data.chr[j] == chr
+ data.posByChr[chr].push(pos)
+ data.lodnames = [data.lodnames] unless Array.isArray(data.lodnames)
+ additiveval = (data['additive'][j] for lodcolumn in data.lodnames)
+ lodval = (data[lodcolumn][j] for lodcolumn in data.lodnames)
+ data.additiveByChr[chr].push(additiveval)
+ data.lodByChr[chr].push(lodval)
+
+
+ if lodvarname?
+ data.markers = []
+ for marker,i in data.markernames
+ if marker != ""
+ data.markers.push({name:marker, chr:data.chr[i], pos:data.pos[i], lod:data[lodvarname][i]})
+
+ data
+
+
+# calculate chromosome start/end + scales, for heat map
+chrscales = (data, width, chrGap, leftMargin, pad4heatmap) ->
+ # start and end of chromosome positions
+ chrStart = []
+ chrEnd = []
+ chrLength = []
+ totalChrLength = 0
+ maxd = 0
+ for chr in data.chrnames
+ d = maxdiff(data.posByChr[chr])
+ maxd = d if d > maxd
+
+ rng = d3.extent(data.posByChr[chr])
+ chrStart.push(rng[0])
+ chrEnd.push(rng[1])
+ L = rng[1] - rng[0]
+ chrLength.push(L)
+ totalChrLength += L
+
+ # adjust lengths for heatmap
+ if pad4heatmap
+ data.recwidth = maxd
+ chrStart = chrStart.map (x) -> x-maxd/2
+ chrEnd = chrEnd.map (x) -> x+maxd/2
+ chrLength = chrLength.map (x) -> x+maxd
+ totalChrLength += (chrLength.length*maxd)
+
+ # break up x axis into chromosomes by length, with gaps
+ data.chrStart = []
+ data.chrEnd = []
+ cur = leftMargin
+ cur += chrGap/2 unless pad4heatmap
+ data.xscale = {}
+ for chr,i in data.chrnames
+ data.chrStart.push(cur)
+ w = Math.round((width-chrGap*(data.chrnames.length-pad4heatmap))/totalChrLength*chrLength[i])
+ data.chrEnd.push(cur + w)
+ cur = data.chrEnd[i] + chrGap
+ # x-axis scales, by chromosome
+ data.xscale[chr] = d3.scale.linear()
+ .domain([chrStart[i], chrEnd[i]])
+ .range([data.chrStart[i], data.chrEnd[i]])
+
+ # return data with new stuff added
+ data
+
+# maximum difference between adjacent values in a vector
+maxdiff = (x) ->
+ return null if x.length < 2
+ result = x[1] - x[0]
+ return result if x.length < 3
+ for i in [2...x.length]
+ d = x[i] - x[i-1]
+ result = d if d > result
+ result
+
+# determine rounding of axis labels
+formatAxis = (d) ->
+ d = d[1] - d[0]
+ ndig = Math.floor( Math.log(d % 10) / Math.log(10) )
+ ndig = 0 if ndig > 0
+ ndig = Math.abs(ndig)
+ d3.format(".#{ndig}f")
diff --git a/wqflask/wqflask/static/new/javascript/lod_chart.js b/wqflask/wqflask/static/new/javascript/lod_chart.js new file mode 100644 index 00000000..14aff1a7 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/lod_chart.js @@ -0,0 +1,562 @@ +// Generated by CoffeeScript 1.6.1 +(function() { + var chrscales, formatAxis, lodchart, maxdiff, reorgLodData, root; + + root = typeof exports !== "undefined" && exports !== null ? exports : this; + + lodchart = function() { + var additive_ylab, additive_ylim, additive_yscale, additive_yticks, additivelinecolor, axispos, chart, chrGap, chrSelect, darkrect, height, lightrect, linewidth, lodcurve, lodlinecolor, lodvarname, margin, markerSelect, nyticks, pad4heatmap, pointcolor, pointsAtMarkers, pointsize, pointstroke, rotate_ylab, significantcolor, suggestivecolor, title, titlepos, width, xlab, xscale, ylab, ylim, yscale, yticks; + width = 800; + height = 500; + margin = { + left: 60, + top: 40, + right: 40, + bottom: 40, + inner: 5 + }; + axispos = { + xtitle: 25, + ytitle: 30, + xlabel: 5, + ylabel: 5 + }; + titlepos = 20; + ylim = null; + additive_ylim = null; + nyticks = 5; + yticks = null; + additive_yticks = null; + chrGap = 8; + darkrect = "#F1F1F9"; + lightrect = "#FBFBFF"; + lodlinecolor = "darkslateblue"; + additivelinecolor = "red"; + linewidth = 2; + suggestivecolor = "gainsboro"; + significantcolor = "#EBC7C7"; + pointcolor = "#E9CFEC"; + pointsize = 0; + pointstroke = "black"; + title = ""; + xlab = "Chromosome"; + ylab = "LRS score"; + additive_ylab = "Additive Effect"; + rotate_ylab = null; + yscale = d3.scale.linear(); + additive_yscale = d3.scale.linear(); + xscale = null; + pad4heatmap = false; + lodcurve = null; + lodvarname = null; + markerSelect = null; + chrSelect = null; + pointsAtMarkers = true; + chart = function(selection) { + return selection.each(function(data) { + var additive_yaxis, additivecurve, chr, curves, g, gEnter, hiddenpoints, lodvarnum, markerpoints, markertip, rotate_additive_ylab, suggestive_bar, svg, titlegrp, x, xaxis, yaxis, _i, _j, _len, _len1, _ref, _ref1; + lodvarname = lodvarname != null ? lodvarname : data.lodnames[0]; + data[lodvarname] = (function() { + var _i, _len, _ref, _results; + _ref = data[lodvarname]; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + x = _ref[_i]; + _results.push(Math.abs(x)); + } + return _results; + })(); + data['additive'] = (function() { + var _i, _len, _ref, _results; + _ref = data['additive']; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + x = _ref[_i]; + _results.push(Math.abs(x)); + } + return _results; + })(); + ylim = ylim != null ? ylim : [0, d3.max(data[lodvarname])]; + additive_ylim = additive_ylim != null ? additive_ylim : [0, d3.max(data['additive'])]; + lodvarnum = data.lodnames.indexOf(lodvarname); + svg = d3.select(this).selectAll("svg").data([data]); + gEnter = svg.enter().append("svg").append("g"); + svg.attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom); + g = svg.select("g"); + g.append("rect").attr("x", margin.left).attr("y", margin.top).attr("height", height).attr("width", width).attr("fill", darkrect).attr("stroke", "none"); + yscale.domain(ylim).range([height + margin.top, margin.top + margin.inner]); + additive_yscale.domain(additive_ylim).range([height + margin.top, margin.top + margin.inner + height / 2]); + yticks = yticks != null ? yticks : yscale.ticks(nyticks); + additive_yticks = additive_yticks != null ? additive_yticks : additive_yscale.ticks(nyticks); + data = reorgLodData(data, lodvarname); + data = chrscales(data, width, chrGap, margin.left, pad4heatmap); + xscale = data.xscale; + chrSelect = g.append("g").attr("class", "chrRect").selectAll("empty").data(data.chrnames).enter().append("rect").attr("id", function(d) { + return "chrrect" + d; + }).attr("x", function(d, i) { + if (i === 0 && pad4heatmap) { + return data.chrStart[i]; + } + return data.chrStart[i] - chrGap / 2; + }).attr("width", function(d, i) { + if ((i === 0 || i + 1 === data.chrnames.length) && pad4heatmap) { + return data.chrEnd[i] - data.chrStart[i] + chrGap / 2; + } + return data.chrEnd[i] - data.chrStart[i] + chrGap; + }).attr("y", margin.top).attr("height", height).attr("fill", function(d, i) { + if (i % 2) { + return darkrect; + } + return lightrect; + }).attr("stroke", "none"); + xaxis = g.append("g").attr("class", "x axis"); + xaxis.selectAll("empty").data(data.chrnames).enter().append("text").text(function(d) { + return d; + }).attr("x", function(d, i) { + return (data.chrStart[i] + data.chrEnd[i]) / 2; + }).attr("y", margin.top + height + axispos.xlabel); + xaxis.append("text").attr("class", "title").attr("y", margin.top + height + axispos.xtitle).attr("x", margin.left + width / 2).text(xlab); + rotate_ylab = rotate_ylab != null ? rotate_ylab : ylab.length > 1; + yaxis = g.append("g").attr("class", "y axis"); + yaxis.selectAll("empty").data(yticks).enter().append("line").attr("y1", function(d) { + return yscale(d); + }).attr("y2", function(d) { + return yscale(d); + }).attr("x1", margin.left).attr("x2", margin.left + 7).attr("fill", "none").attr("stroke", "white").attr("stroke-width", 1).style("pointer-events", "none"); + yaxis.selectAll("empty").data(yticks).enter().append("text").attr("y", function(d) { + return yscale(d); + }).attr("x", margin.left - axispos.ylabel).attr("fill", "blue").text(function(d) { + return formatAxis(yticks)(d); + }); + yaxis.append("text").attr("class", "title").attr("y", margin.top + height / 2).attr("x", margin.left - axispos.ytitle).text(ylab).attr("transform", rotate_ylab ? "rotate(270," + (margin.left - axispos.ytitle) + "," + (margin.top + height / 2) + ")" : ""); + rotate_additive_ylab = rotate_additive_ylab != null ? rotate_additive_ylab : additive_ylab.length > 1; + additive_yaxis = g.append("g").attr("class", "y axis"); + additive_yaxis.selectAll("empty").data(additive_yticks).enter().append("line").attr("y1", function(d) { + return additive_yscale(d); + }).attr("y2", function(d) { + return additive_yscale(d); + }).attr("x1", margin.left + width).attr("x2", margin.left + width - 7).attr("fill", "none").attr("stroke", "white").attr("stroke-width", 1).style("pointer-events", "none"); + additive_yaxis.selectAll("empty").data(additive_yticks).enter().append("text").attr("y", function(d) { + return additive_yscale(d); + }).attr("x", function(d) { + return margin.left + width + axispos.ylabel + 20; + }).attr("fill", "green").text(function(d) { + return formatAxis(additive_yticks)(d); + }); + additive_yaxis.append("text").attr("class", "title").attr("y", margin.top + 1.5 * height).attr("x", margin.left + width + axispos.ytitle).text(additive_ylab).attr("transform", rotate_additive_ylab ? "rotate(270," + (margin.left + width + axispos.ytitle) + ", " + (margin.top + height * 1.5) + ")" : ""); + suggestive_bar = g.append("g").attr("class", "suggestive"); + suggestive_bar.selectAll("empty").data([data.suggestive]).enter().append("line").attr("y1", function(d) { + return yscale(d); + }).attr("y2", function(d) { + return yscale(d); + }).attr("x1", margin.left).attr("x2", margin.left + width).attr("fill", "none").attr("stroke", suggestivecolor).attr("stroke-width", 5).style("pointer-events", "none"); + suggestive_bar = g.append("g").attr("class", "significant"); + suggestive_bar.selectAll("empty").data([data.significant]).enter().append("line").attr("y1", function(d) { + return yscale(d); + }).attr("y2", function(d) { + return yscale(d); + }).attr("x1", margin.left).attr("x2", margin.left + width).attr("fill", "none").attr("stroke", significantcolor).attr("stroke-width", 5).style("pointer-events", "none"); + lodcurve = function(chr, lodcolumn) { + return d3.svg.line().x(function(d) { + return xscale[chr](d); + }).y(function(d, i) { + return yscale(data.lodByChr[chr][i][lodcolumn]); + }); + }; + additivecurve = function(chr, lodcolumn) { + return d3.svg.line().x(function(d) { + return xscale[chr](d); + }).y(function(d, i) { + return additive_yscale(data.additiveByChr[chr][i][lodcolumn]); + }); + }; + curves = g.append("g").attr("id", "curves"); + _ref = data.chrnames; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + chr = _ref[_i]; + curves.append("path").datum(data.posByChr[chr]).attr("d", lodcurve(chr, lodvarnum)).attr("stroke", lodlinecolor).attr("fill", "none").attr("stroke-width", linewidth).style("pointer-events", "none"); + } + _ref1 = data.chrnames; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + chr = _ref1[_j]; + curves.append("path").datum(data.posByChr[chr]).attr("d", additivecurve(chr, lodvarnum)).attr("stroke", additivelinecolor).attr("fill", "none").attr("stroke-width", 1).style("pointer-events", "none"); + } + if (pointsize > 0) { + markerpoints = g.append("g").attr("id", "markerpoints_visible"); + markerpoints.selectAll("empty").data(data.markers).enter().append("circle").attr("cx", function(d) { + return xscale[d.chr](d.pos); + }).attr("cy", function(d) { + return yscale(d.lod); + }).attr("r", pointsize).attr("fill", pointcolor).attr("stroke", pointstroke).attr("pointer-events", "hidden"); + } + if (pointsAtMarkers) { + hiddenpoints = g.append("g").attr("id", "markerpoints_hidden"); + markertip = d3.tip().attr('class', 'd3-tip').html(function(d) { + return [d.name, " LRS = " + (d3.format('.2f')(d.lod))]; + }).direction("e").offset([0, 10]); + svg.call(markertip); + markerSelect = hiddenpoints.selectAll("empty").data(data.markers).enter().append("circle").attr("cx", function(d) { + return xscale[d.chr](d.pos); + }).attr("cy", function(d) { + return yscale(d.lod); + }).attr("id", function(d) { + return d.name; + }).attr("r", d3.max([pointsize * 2, 3])).attr("opacity", 0).attr("fill", pointcolor).attr("stroke", pointstroke).attr("stroke-width", "1").on("mouseover.paneltip", function(d) { + d3.select(this).attr("opacity", 1); + return markertip.show(d); + }).on("mouseout.paneltip", function() { + return d3.select(this).attr("opacity", 0).call(markertip.hide); + }); + } + titlegrp = g.append("g").attr("class", "title").append("text").attr("x", margin.left + width / 2).attr("y", margin.top - titlepos).text(title); + return g.append("rect").attr("x", margin.left).attr("y", margin.top).attr("height", height).attr("width", function() { + if (pad4heatmap) { + return data.chrEnd.slice(-1)[0] - margin.left; + } + return data.chrEnd.slice(-1)[0] - margin.left + chrGap / 2; + }).attr("fill", "none").attr("stroke", "black").attr("stroke-width", "none"); + }); + }; + chart.width = function(value) { + if (!arguments.length) { + return width; + } + width = value; + return chart; + }; + chart.height = function(value) { + if (!arguments.length) { + return height; + } + height = value; + return chart; + }; + chart.margin = function(value) { + if (!arguments.length) { + return margin; + } + margin = value; + return chart; + }; + chart.titlepos = function(value) { + if (!arguments.length) { + return titlepos; + } + titlepos; + return chart; + }; + chart.axispos = function(value) { + if (!arguments.length) { + return axispos; + } + axispos = value; + return chart; + }; + chart.ylim = function(value) { + if (!arguments.length) { + return ylim; + } + ylim = value; + return chart; + }; + chart.additive_ylim = function(value) { + if (!arguments.length) { + return additive_ylim; + } + additive_ylim = value; + return chart; + }; + chart.nyticks = function(value) { + if (!arguments.length) { + return nyticks; + } + nyticks = value; + return chart; + }; + chart.yticks = function(value) { + if (!arguments.length) { + return yticks; + } + yticks = value; + return chart; + }; + chart.chrGap = function(value) { + if (!arguments.length) { + return chrGap; + } + chrGap = value; + return chart; + }; + chart.darkrect = function(value) { + if (!arguments.length) { + return darkrect; + } + darkrect = value; + return chart; + }; + chart.lightrect = function(value) { + if (!arguments.length) { + return lightrect; + } + lightrect = value; + return chart; + }; + chart.linecolor = function(value) { + var linecolor; + if (!arguments.length) { + return linecolor; + } + linecolor = value; + return chart; + }; + chart.linewidth = function(value) { + if (!arguments.length) { + return linewidth; + } + linewidth = value; + return chart; + }; + chart.pointcolor = function(value) { + if (!arguments.length) { + return pointcolor; + } + pointcolor = value; + return chart; + }; + chart.pointsize = function(value) { + if (!arguments.length) { + return pointsize; + } + pointsize = value; + return chart; + }; + chart.pointstroke = function(value) { + if (!arguments.length) { + return pointstroke; + } + pointstroke = value; + return chart; + }; + chart.title = function(value) { + if (!arguments.length) { + return title; + } + title = value; + return chart; + }; + chart.xlab = function(value) { + if (!arguments.length) { + return xlab; + } + xlab = value; + return chart; + }; + chart.ylab = function(value) { + if (!arguments.length) { + return ylab; + } + ylab = value; + return chart; + }; + chart.rotate_ylab = function(value) { + if (!arguments.length) { + return rotate_ylab; + } + rotate_ylab = value; + return chart; + }; + chart.lodvarname = function(value) { + if (!arguments.length) { + return lodvarname; + } + lodvarname = value; + return chart; + }; + chart.pad4heatmap = function(value) { + if (!arguments.length) { + return pad4heatmap; + } + pad4heatmap = value; + return chart; + }; + chart.pointsAtMarkers = function(value) { + if (!arguments.length) { + return pointsAtMarkers; + } + pointsAtMarkers = value; + return chart; + }; + chart.yscale = function() { + return yscale; + }; + chart.additive_yscale = function() { + return additive_yscale; + }; + chart.xscale = function() { + return xscale; + }; + chart.lodcurve = function() { + return lodcurve; + }; + chart.additivecurve = function() { + return additivecurve; + }; + chart.markerSelect = function() { + return markerSelect; + }; + chart.chrSelect = function() { + return chrSelect; + }; + return chart; + }; + + root.lodchart = lodchart; + + reorgLodData = function(data, lodvarname) { + var additiveval, chr, i, j, lodcolumn, lodval, marker, pos, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2; + if (lodvarname == null) { + lodvarname = null; + } + data.posByChr = {}; + data.lodByChr = {}; + data.additiveByChr = {}; + _ref = data.chrnames; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + chr = _ref[i]; + data.posByChr[chr] = []; + data.lodByChr[chr] = []; + data.additiveByChr[chr] = []; + _ref1 = data.pos; + for (j = _j = 0, _len1 = _ref1.length; _j < _len1; j = ++_j) { + pos = _ref1[j]; + if (data.chr[j] === chr) { + data.posByChr[chr].push(pos); + if (!Array.isArray(data.lodnames)) { + data.lodnames = [data.lodnames]; + } + additiveval = (function() { + var _k, _len2, _ref2, _results; + _ref2 = data.lodnames; + _results = []; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + lodcolumn = _ref2[_k]; + _results.push(data['additive'][j]); + } + return _results; + })(); + lodval = (function() { + var _k, _len2, _ref2, _results; + _ref2 = data.lodnames; + _results = []; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + lodcolumn = _ref2[_k]; + _results.push(data[lodcolumn][j]); + } + return _results; + })(); + data.additiveByChr[chr].push(additiveval); + data.lodByChr[chr].push(lodval); + } + } + } + if (lodvarname != null) { + data.markers = []; + _ref2 = data.markernames; + for (i = _k = 0, _len2 = _ref2.length; _k < _len2; i = ++_k) { + marker = _ref2[i]; + if (marker !== "") { + data.markers.push({ + name: marker, + chr: data.chr[i], + pos: data.pos[i], + lod: data[lodvarname][i] + }); + } + } + } + return data; + }; + + chrscales = function(data, width, chrGap, leftMargin, pad4heatmap) { + var L, chr, chrEnd, chrLength, chrStart, cur, d, i, maxd, rng, totalChrLength, w, _i, _j, _len, _len1, _ref, _ref1; + chrStart = []; + chrEnd = []; + chrLength = []; + totalChrLength = 0; + maxd = 0; + _ref = data.chrnames; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + chr = _ref[_i]; + d = maxdiff(data.posByChr[chr]); + if (d > maxd) { + maxd = d; + } + rng = d3.extent(data.posByChr[chr]); + chrStart.push(rng[0]); + chrEnd.push(rng[1]); + L = rng[1] - rng[0]; + chrLength.push(L); + totalChrLength += L; + } + if (pad4heatmap) { + data.recwidth = maxd; + chrStart = chrStart.map(function(x) { + return x - maxd / 2; + }); + chrEnd = chrEnd.map(function(x) { + return x + maxd / 2; + }); + chrLength = chrLength.map(function(x) { + return x + maxd; + }); + totalChrLength += chrLength.length * maxd; + } + data.chrStart = []; + data.chrEnd = []; + cur = leftMargin; + if (!pad4heatmap) { + cur += chrGap / 2; + } + data.xscale = {}; + _ref1 = data.chrnames; + for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) { + chr = _ref1[i]; + data.chrStart.push(cur); + w = Math.round((width - chrGap * (data.chrnames.length - pad4heatmap)) / totalChrLength * chrLength[i]); + data.chrEnd.push(cur + w); + cur = data.chrEnd[i] + chrGap; + data.xscale[chr] = d3.scale.linear().domain([chrStart[i], chrEnd[i]]).range([data.chrStart[i], data.chrEnd[i]]); + } + return data; + }; + + maxdiff = function(x) { + var d, i, result, _i, _ref; + if (x.length < 2) { + return null; + } + result = x[1] - x[0]; + if (x.length < 3) { + return result; + } + for (i = _i = 2, _ref = x.length; 2 <= _ref ? _i < _ref : _i > _ref; i = 2 <= _ref ? ++_i : --_i) { + d = x[i] - x[i - 1]; + if (d > result) { + result = d; + } + } + return result; + }; + + formatAxis = function(d) { + var ndig; + d = d[1] - d[0]; + ndig = Math.floor(Math.log(d % 10) / Math.log(10)); + if (ndig > 0) { + ndig = 0; + } + ndig = Math.abs(ndig); + return d3.format("." + ndig + "f"); + }; + +}).call(this); diff --git a/wqflask/wqflask/static/new/javascript/marker_regression.coffee b/wqflask/wqflask/static/new/javascript/marker_regression.coffee index a0d492c1..8038ad9a 100755 --- a/wqflask/wqflask/static/new/javascript/marker_regression.coffee +++ b/wqflask/wqflask/static/new/javascript/marker_regression.coffee @@ -87,12 +87,12 @@ class Manhattan_Plot high_qtl_count += 1 console.log("high_qtl_count:", high_qtl_count) - if high_qtl_count > 10000 - @y_axis_filter = 2 - else if high_qtl_count > 1000 - @y_axis_filter = 1 - else - @y_axis_filter = 0 + #if high_qtl_count > 10000 + @y_axis_filter = 2 + #else if high_qtl_count > 1000 + # @y_axis_filter = 1 + #else + # @y_axis_filter = 0 create_coordinates: () -> @@ -364,8 +364,8 @@ class Manhattan_Plot .append("text") .attr("class", "chr_label") .text((d) =>
- if @max_chr == "24" - if d[0] == 23 + if @max_chr == 23 + if d[0] == "23" return "X" else if d[0] == "24" return "X/Y"
@@ -404,16 +404,16 @@ class Manhattan_Plot return @y_scale(d[1]) ) .attr("r", (d) => - if d[1] > 3 - return 3 - else - return 2 + #if d[1] > 3 + # return 3 + #else + return 2 ) .attr("fill", (d) => - if d[1] > 3 - return "white" - else - return "black" + #if d[1] > 3 + # return "white" + #else + return "black" ) .attr("stroke", "black") .attr("stroke-width", "1") @@ -435,16 +435,16 @@ class Manhattan_Plot this_id = "point_" + String(d[2]) d3.select("#" + this_id).classed("d3_highlight", false) .attr("r", (d) => - if d[1] > 2 - return 3 - else - return 2 + #if d[1] > 2 + # return 3 + #else + return 2 ) .attr("fill", (d) => - if d[1] > 2 - return "white" - else - return "black" + #if d[1] > 2 + # return "white" + #else + return "black" ) .attr("stroke", "black") .attr("stroke-width", "1") diff --git a/wqflask/wqflask/static/new/javascript/marker_regression.js b/wqflask/wqflask/static/new/javascript/marker_regression.js index 59b801d5..e3c316dd 100755 --- a/wqflask/wqflask/static/new/javascript/marker_regression.js +++ b/wqflask/wqflask/static/new/javascript/marker_regression.js @@ -94,13 +94,7 @@ } } console.log("high_qtl_count:", high_qtl_count); - if (high_qtl_count > 10000) { - return this.y_axis_filter = 2; - } else if (high_qtl_count > 1000) { - return this.y_axis_filter = 1; - } else { - return this.y_axis_filter = 0; - } + return this.y_axis_filter = 2; }; Manhattan_Plot.prototype.create_coordinates = function() { @@ -299,8 +293,8 @@ return this.svg.selectAll("text").data(chr_info, function(d) { return d; }).enter().append("text").attr("class", "chr_label").text(function(d) { - if (_this.max_chr === "24") { - if (d[0] === 23) { + if (_this.max_chr === 23) { + if (d[0] === "23") { return "X"; } else if (d[0] === "24") { return "X/Y"; @@ -330,17 +324,9 @@ }).attr("cy", function(d) { return _this.y_scale(d[1]); }).attr("r", function(d) { - if (d[1] > 3) { - return 3; - } else { - return 2; - } + return 2; }).attr("fill", function(d) { - if (d[1] > 3) { - return "white"; - } else { - return "black"; - } + return "black"; }).attr("stroke", "black").attr("stroke-width", "1").attr("id", function(d) { return "point_" + String(d[2]); }).classed("circle", true).on("mouseover", function(d) { @@ -353,17 +339,9 @@ var this_id; this_id = "point_" + String(d[2]); return d3.select("#" + this_id).classed("d3_highlight", false).attr("r", function(d) { - if (d[1] > 2) { - return 3; - } else { - return 2; - } + return 2; }).attr("fill", function(d) { - if (d[1] > 2) { - return "white"; - } else { - return "black"; - } + return "black"; }).attr("stroke", "black").attr("stroke-width", "1"); }).append("svg:title").text(function(d) { return d[2]; diff --git a/wqflask/wqflask/static/new/javascript/panelutil.coffee b/wqflask/wqflask/static/new/javascript/panelutil.coffee new file mode 100644 index 00000000..42636369 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/panelutil.coffee @@ -0,0 +1,205 @@ +# A variety of utility functions used by the different panel functions
+
+root = exports ? this
+
+# determine rounding of axis labels
+formatAxis = (d) ->
+ d = d[1] - d[0]
+ ndig = Math.floor( Math.log(d % 10) / Math.log(10) )
+ ndig = 0 if ndig > 0
+ ndig = Math.abs(ndig)
+ d3.format(".#{ndig}f")
+
+# unique values of array (ignore nulls)
+unique = (x) ->
+ output = {}
+ output[v] = v for v in x when v
+ output[v] for v of output
+
+# Pull out a variable (column) from a two-dimensional array
+pullVarAsArray = (data, variable) ->
+ v = []
+ for i of data
+ v = v.concat data[i][variable]
+ v
+
+# reorganize lod/pos by chromosome
+# lodvarname==null -> case for multiple LOD columns (lodheatmap)
+# lodvarname provided -> case for one LOD column (lodchart)
+reorgLodData = (data, lodvarname=null) ->
+ data.posByChr = {}
+ data.lodByChr = {}
+
+ for chr,i in data.chrnames
+ data.posByChr[chr] = []
+ data.lodByChr[chr] = []
+ for pos,j in data.pos
+ if data.chr[j] == chr
+ data.posByChr[chr].push(pos)
+ data.lodnames = [data.lodnames] unless Array.isArray(data.lodnames)
+ lodval = (data[lodcolumn][j] for lodcolumn in data.lodnames)
+ data.lodByChr[chr].push(lodval)
+
+ if lodvarname?
+ data.markers = []
+ for marker,i in data.markernames
+ if marker != ""
+ data.markers.push({name:marker, chr:data.chr[i], pos:data.pos[i], lod:data[lodvarname][i]})
+
+ data
+
+# calculate chromosome start/end + scales, for heat map
+chrscales = (data, width, chrGap, leftMargin, pad4heatmap) ->
+ # start and end of chromosome positions
+ chrStart = []
+ chrEnd = []
+ chrLength = []
+ totalChrLength = 0
+ maxd = 0
+ for chr in data.chrnames
+ d = maxdiff(data.posByChr[chr])
+ maxd = d if d > maxd
+
+ rng = d3.extent(data.posByChr[chr])
+ chrStart.push(rng[0])
+ chrEnd.push(rng[1])
+ L = rng[1] - rng[0]
+ chrLength.push(L)
+ totalChrLength += L
+
+ # adjust lengths for heatmap
+ if pad4heatmap
+ data.recwidth = maxd
+ chrStart = chrStart.map (x) -> x-maxd/2
+ chrEnd = chrEnd.map (x) -> x+maxd/2
+ chrLength = chrLength.map (x) -> x+maxd
+ totalChrLength += (chrLength.length*maxd)
+
+ # break up x axis into chromosomes by length, with gaps
+ data.chrStart = []
+ data.chrEnd = []
+ cur = leftMargin
+ cur += chrGap/2 unless pad4heatmap
+ data.xscale = {}
+ for chr,i in data.chrnames
+ data.chrStart.push(cur)
+ w = Math.round((width-chrGap*(data.chrnames.length-pad4heatmap))/totalChrLength*chrLength[i])
+ data.chrEnd.push(cur + w)
+ cur = data.chrEnd[i] + chrGap
+ # x-axis scales, by chromosome
+ data.xscale[chr] = d3.scale.linear()
+ .domain([chrStart[i], chrEnd[i]])
+ .range([data.chrStart[i], data.chrEnd[i]])
+
+ # return data with new stuff added
+ data
+
+# Select a set of categorical colors
+# ngroup is positive integer
+# palette = "dark" or "pastel"
+selectGroupColors = (ngroup, palette) ->
+ return [] if ngroup == 0
+
+ if palette == "dark"
+ return ["slateblue"] if ngroup == 1
+ return ["MediumVioletRed", "slateblue"] if ngroup == 2
+ return colorbrewer.Set1[ngroup] if ngroup <= 9
+ return d3.scale.category20().range()[0...ngroup]
+ else
+ return [d3.rgb(190, 190, 190)] if ngroup == 1
+ return ["lightpink", "lightblue"] if ngroup == 2
+ return colorbrewer.Pastel1[ngroup] if ngroup <= 9
+ # below is rough attempt to make _big_ pastel palette
+ return ["#8fc7f4", "#fed7f8", "#ffbf8e", "#fffbb8",
+ "#8ce08c", "#d8ffca", "#f68788", "#ffd8d6",
+ "#d4a7fd", "#f5f0f5", "#cc968b", "#f4dcd4",
+ "#f3b7f2", "#f7f6f2", "#bfbfbf", "#f7f7f7",
+ "#fcfd82", "#fbfbcd", "#87feff", "#defaf5"][0...ngroup]
+
+# expand element/array (e.g., of colors) to a given length
+# single elment -> array, then repeated to length n
+expand2vector = (input, n) ->
+ return input if Array.isArray(input) and input.length >= n
+ input = [input] unless Array.isArray(input)
+ input = (input[0] for i of d3.range(n)) if input.length == 1 and n > 1
+ input
+
+# median of a vector
+median = (x) ->
+ return null if !x?
+ n = x.length
+ x.sort((a,b) -> a-b)
+ if n % 2 == 1
+ return x[(n-1)/2]
+ (x[n/2] + x[(n/2)-1])/2
+
+# given a vector of x's, return hash with values to left and right, and the differences
+getLeftRight = (x) ->
+ n = x.length
+ x.sort( (a,b) -> a-b )
+
+ xdif = []
+ result = {}
+ for v in x
+ result[v] = {}
+
+ for i in [1...n]
+ xdif.push(x[i]-x[i-1])
+ result[x[i]].left = x[i-1]
+ for i in [0...(n-1)]
+ result[x[i]].right = x[i+1]
+
+ xdif = median(xdif)
+ result.mediandiff = xdif
+
+ result[x[0]].left = x[0]-xdif
+ result[x[n-1]].right = x[n-1]+xdif
+ result.extent = [x[0]-xdif/2, x[n-1]+xdif/2]
+
+ result
+
+# maximum difference between adjacent values in a vector
+maxdiff = (x) ->
+ return null if x.length < 2
+ result = x[1] - x[0]
+ return result if x.length < 3
+ for i in [2...x.length]
+ d = x[i] - x[i-1]
+ result = d if d > result
+ result
+
+# matrix extent, min max
+matrixMin = (mat) ->
+ result = mat[0][0]
+ for i of mat
+ for j of mat[i]
+ result = mat[i][j] if result > mat[i][j]
+ result
+
+matrixMax = (mat) ->
+ result = mat[0][0]
+ for i of mat
+ for j of mat[i]
+ result = mat[i][j] if result < mat[i][j]
+ result
+
+matrixMaxAbs = (mat) ->
+ result = Math.abs(mat[0][0])
+ for i of mat
+ for j of mat[i]
+ result = Math.abs(mat[i][j]) if result < mat[i][j]
+ result
+
+matrixExtent = (mat) -> [matrixMin(mat), matrixMax(mat)]
+
+d3.selection.prototype.moveToFront = () ->
+ this.each () -> this.parentNode.appendChild(this)
+
+d3.selection.prototype.moveToBack = () ->
+ this.each () ->
+ firstChild = this.parentNode.firstchild
+ this.parentNode.insertBefore(this, firstChild) if firstChild
+
+forceAsArray = (x) ->
+ return x if Array.isArray(x)
+ [x]
\ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/panelutil.js b/wqflask/wqflask/static/new/javascript/panelutil.js new file mode 100644 index 00000000..d5e7fd27 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/panelutil.js @@ -0,0 +1,324 @@ +// Generated by CoffeeScript 1.6.1 +(function() { + var chrscales, expand2vector, forceAsArray, formatAxis, getLeftRight, matrixExtent, matrixMax, matrixMaxAbs, matrixMin, maxdiff, median, pullVarAsArray, reorgLodData, root, selectGroupColors, unique; + + root = typeof exports !== "undefined" && exports !== null ? exports : this; + + formatAxis = function(d) { + var ndig; + d = d[1] - d[0]; + ndig = Math.floor(Math.log(d % 10) / Math.log(10)); + if (ndig > 0) { + ndig = 0; + } + ndig = Math.abs(ndig); + return d3.format("." + ndig + "f"); + }; + + unique = function(x) { + var output, v, _i, _len, _results; + output = {}; + for (_i = 0, _len = x.length; _i < _len; _i++) { + v = x[_i]; + if (v) { + output[v] = v; + } + } + _results = []; + for (v in output) { + _results.push(output[v]); + } + return _results; + }; + + pullVarAsArray = function(data, variable) { + var i, v; + v = []; + for (i in data) { + v = v.concat(data[i][variable]); + } + return v; + }; + + reorgLodData = function(data, lodvarname) { + var chr, i, j, lodcolumn, lodval, marker, pos, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2; + if (lodvarname == null) { + lodvarname = null; + } + data.posByChr = {}; + data.lodByChr = {}; + _ref = data.chrnames; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + chr = _ref[i]; + data.posByChr[chr] = []; + data.lodByChr[chr] = []; + _ref1 = data.pos; + for (j = _j = 0, _len1 = _ref1.length; _j < _len1; j = ++_j) { + pos = _ref1[j]; + if (data.chr[j] === chr) { + data.posByChr[chr].push(pos); + if (!Array.isArray(data.lodnames)) { + data.lodnames = [data.lodnames]; + } + lodval = (function() { + var _k, _len2, _ref2, _results; + _ref2 = data.lodnames; + _results = []; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + lodcolumn = _ref2[_k]; + _results.push(data[lodcolumn][j]); + } + return _results; + })(); + data.lodByChr[chr].push(lodval); + } + } + } + if (lodvarname != null) { + data.markers = []; + _ref2 = data.markernames; + for (i = _k = 0, _len2 = _ref2.length; _k < _len2; i = ++_k) { + marker = _ref2[i]; + if (marker !== "") { + data.markers.push({ + name: marker, + chr: data.chr[i], + pos: data.pos[i], + lod: data[lodvarname][i] + }); + } + } + } + return data; + }; + + chrscales = function(data, width, chrGap, leftMargin, pad4heatmap) { + var L, chr, chrEnd, chrLength, chrStart, cur, d, i, maxd, rng, totalChrLength, w, _i, _j, _len, _len1, _ref, _ref1; + chrStart = []; + chrEnd = []; + chrLength = []; + totalChrLength = 0; + maxd = 0; + _ref = data.chrnames; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + chr = _ref[_i]; + d = maxdiff(data.posByChr[chr]); + if (d > maxd) { + maxd = d; + } + rng = d3.extent(data.posByChr[chr]); + chrStart.push(rng[0]); + chrEnd.push(rng[1]); + L = rng[1] - rng[0]; + chrLength.push(L); + totalChrLength += L; + } + if (pad4heatmap) { + data.recwidth = maxd; + chrStart = chrStart.map(function(x) { + return x - maxd / 2; + }); + chrEnd = chrEnd.map(function(x) { + return x + maxd / 2; + }); + chrLength = chrLength.map(function(x) { + return x + maxd; + }); + totalChrLength += chrLength.length * maxd; + } + data.chrStart = []; + data.chrEnd = []; + cur = leftMargin; + if (!pad4heatmap) { + cur += chrGap / 2; + } + data.xscale = {}; + _ref1 = data.chrnames; + for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) { + chr = _ref1[i]; + data.chrStart.push(cur); + w = Math.round((width - chrGap * (data.chrnames.length - pad4heatmap)) / totalChrLength * chrLength[i]); + data.chrEnd.push(cur + w); + cur = data.chrEnd[i] + chrGap; + data.xscale[chr] = d3.scale.linear().domain([chrStart[i], chrEnd[i]]).range([data.chrStart[i], data.chrEnd[i]]); + } + return data; + }; + + selectGroupColors = function(ngroup, palette) { + if (ngroup === 0) { + return []; + } + if (palette === "dark") { + if (ngroup === 1) { + return ["slateblue"]; + } + if (ngroup === 2) { + return ["MediumVioletRed", "slateblue"]; + } + if (ngroup <= 9) { + return colorbrewer.Set1[ngroup]; + } + return d3.scale.category20().range().slice(0, ngroup); + } else { + if (ngroup === 1) { + return [d3.rgb(190, 190, 190)]; + } + if (ngroup === 2) { + return ["lightpink", "lightblue"]; + } + if (ngroup <= 9) { + return colorbrewer.Pastel1[ngroup]; + } + return ["#8fc7f4", "#fed7f8", "#ffbf8e", "#fffbb8", "#8ce08c", "#d8ffca", "#f68788", "#ffd8d6", "#d4a7fd", "#f5f0f5", "#cc968b", "#f4dcd4", "#f3b7f2", "#f7f6f2", "#bfbfbf", "#f7f7f7", "#fcfd82", "#fbfbcd", "#87feff", "#defaf5"].slice(0, ngroup); + } + }; + + expand2vector = function(input, n) { + var i; + if (Array.isArray(input) && input.length >= n) { + return input; + } + if (!Array.isArray(input)) { + input = [input]; + } + if (input.length === 1 && n > 1) { + input = (function() { + var _results; + _results = []; + for (i in d3.range(n)) { + _results.push(input[0]); + } + return _results; + })(); + } + return input; + }; + + median = function(x) { + var n; + if (x == null) { + return null; + } + n = x.length; + x.sort(function(a, b) { + return a - b; + }); + if (n % 2 === 1) { + return x[(n - 1) / 2]; + } + return (x[n / 2] + x[(n / 2) - 1]) / 2; + }; + + getLeftRight = function(x) { + var i, n, result, v, xdif, _i, _j, _k, _len, _ref; + n = x.length; + x.sort(function(a, b) { + return a - b; + }); + xdif = []; + result = {}; + for (_i = 0, _len = x.length; _i < _len; _i++) { + v = x[_i]; + result[v] = {}; + } + for (i = _j = 1; 1 <= n ? _j < n : _j > n; i = 1 <= n ? ++_j : --_j) { + xdif.push(x[i] - x[i - 1]); + result[x[i]].left = x[i - 1]; + } + for (i = _k = 0, _ref = n - 1; 0 <= _ref ? _k < _ref : _k > _ref; i = 0 <= _ref ? ++_k : --_k) { + result[x[i]].right = x[i + 1]; + } + xdif = median(xdif); + result.mediandiff = xdif; + result[x[0]].left = x[0] - xdif; + result[x[n - 1]].right = x[n - 1] + xdif; + result.extent = [x[0] - xdif / 2, x[n - 1] + xdif / 2]; + return result; + }; + + maxdiff = function(x) { + var d, i, result, _i, _ref; + if (x.length < 2) { + return null; + } + result = x[1] - x[0]; + if (x.length < 3) { + return result; + } + for (i = _i = 2, _ref = x.length; 2 <= _ref ? _i < _ref : _i > _ref; i = 2 <= _ref ? ++_i : --_i) { + d = x[i] - x[i - 1]; + if (d > result) { + result = d; + } + } + return result; + }; + + matrixMin = function(mat) { + var i, j, result; + result = mat[0][0]; + for (i in mat) { + for (j in mat[i]) { + if (result > mat[i][j]) { + result = mat[i][j]; + } + } + } + return result; + }; + + matrixMax = function(mat) { + var i, j, result; + result = mat[0][0]; + for (i in mat) { + for (j in mat[i]) { + if (result < mat[i][j]) { + result = mat[i][j]; + } + } + } + return result; + }; + + matrixMaxAbs = function(mat) { + var i, j, result; + result = Math.abs(mat[0][0]); + for (i in mat) { + for (j in mat[i]) { + if (result < mat[i][j]) { + result = Math.abs(mat[i][j]); + } + } + } + return result; + }; + + matrixExtent = function(mat) { + return [matrixMin(mat), matrixMax(mat)]; + }; + + d3.selection.prototype.moveToFront = function() { + return this.each(function() { + return this.parentNode.appendChild(this); + }); + }; + + d3.selection.prototype.moveToBack = function() { + return this.each(function() { + var firstChild; + firstChild = this.parentNode.firstchild; + if (firstChild) { + return this.parentNode.insertBefore(this, firstChild); + } + }); + }; + + forceAsArray = function(x) { + if (Array.isArray(x)) { + return x; + } + return [x]; + }; + +}).call(this); diff --git a/wqflask/wqflask/static/new/javascript/scatterplot.coffee b/wqflask/wqflask/static/new/javascript/scatterplot.coffee new file mode 100644 index 00000000..546205ce --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/scatterplot.coffee @@ -0,0 +1,407 @@ +scatterplot = () ->
+ width = 800
+ height = 500
+ margin = {left:60, top:40, right:40, bottom: 40, inner:5}
+ axispos = {xtitle:25, ytitle:30, xlabel:5, ylabel:5}
+ titlepos = 20
+ xNA = {handle:true, force:false, width:15, gap:10}
+ yNA = {handle:true, force:false, width:15, gap:10}
+ xlim = null
+ ylim = null
+ nxticks = 5
+ xticks = null
+ nyticks = 5
+ yticks = null
+ rectcolor = d3.rgb(230, 230, 230)
+ pointcolor = null
+ pointstroke = "black"
+ pointsize = 3 # default = no visible points at markers
+ title = ""
+ xlab = "X"
+ ylab = "Y"
+ rotate_ylab = null
+ yscale = d3.scale.linear()
+ xscale = d3.scale.linear()
+ xvar = 0
+ yvar = 1
+ pointsSelect = null
+ dataByInd = true
+
+ ## the main function
+ chart = (selection) ->
+ selection.each (data) ->
+
+ if dataByInd
+ x = data.data.map (d) -> d[xvar]
+ y = data.data.map (d) -> d[yvar]
+ else # reorganize data
+ x = data.data[xvar]
+ y = data.data[yvar]
+
+ # grab indID if it's there
+ # if no indID, create a vector of them
+ indID = data?.indID ? null
+ indID = indID ? [1..x.length]
+
+ # groups of colors
+ group = data?.group ? (1 for i in x)
+ ngroup = d3.max(group)
+ group = (g-1 for g in group) # changed from (1,2,3,...) to (0,1,2,...)
+
+ # colors of the points in the different groups
+ pointcolor = pointcolor ? selectGroupColors(ngroup, "dark")
+ pointcolor = expand2vector(pointcolor, ngroup)
+
+ # if all (x,y) not null
+ xNA.handle = false if x.every (v) -> (v?) and !xNA.force
+ yNA.handle = false if y.every (v) -> (v?) and !yNA.force
+ if xNA.handle
+ paneloffset = xNA.width + xNA.gap
+ panelwidth = width - paneloffset
+ else
+ paneloffset = 0
+ panelwidth = width
+ if yNA.handle
+ panelheight = height - (yNA.width + yNA.gap)
+ else
+ panelheight = height
+
+ xlim = xlim ? d3.extent(x)
+ ylim = ylim ? d3.extent(y)
+
+ # I'll replace missing values something smaller than what's observed
+ na_value = d3.min(x.concat y) - 100
+
+ # Select the svg element, if it exists.
+ svg = d3.select(this).selectAll("svg").data([data])
+
+ # Otherwise, create the skeletal chart.
+ gEnter = svg.enter().append("svg").append("g")
+
+ # Update the outer dimensions.
+ svg.attr("width", width+margin.left+margin.right)
+ .attr("height", height+margin.top+margin.bottom)
+
+ g = svg.select("g")
+
+ # box
+ g.append("rect")
+ .attr("x", paneloffset+margin.left)
+ .attr("y", margin.top)
+ .attr("height", panelheight)
+ .attr("width", panelwidth)
+ .attr("fill", rectcolor)
+ .attr("stroke", "none")
+ if xNA.handle
+ g.append("rect")
+ .attr("x", margin.left)
+ .attr("y", margin.top)
+ .attr("height", panelheight)
+ .attr("width", xNA.width)
+ .attr("fill", rectcolor)
+ .attr("stroke", "none")
+ if xNA.handle and yNA.handle
+ g.append("rect")
+ .attr("x", margin.left)
+ .attr("y", margin.top+height - yNA.width)
+ .attr("height", yNA.width)
+ .attr("width", xNA.width)
+ .attr("fill", rectcolor)
+ .attr("stroke", "none")
+ if yNA.handle
+ g.append("rect")
+ .attr("x", margin.left+paneloffset)
+ .attr("y", margin.top+height-yNA.width)
+ .attr("height", yNA.width)
+ .attr("width", panelwidth)
+ .attr("fill", rectcolor)
+ .attr("stroke", "none")
+
+ # simple scales (ignore NA business)
+ xrange = [margin.left+paneloffset+margin.inner, margin.left+paneloffset+panelwidth-margin.inner]
+ yrange = [margin.top+panelheight-margin.inner, margin.top+margin.inner]
+ xscale.domain(xlim).range(xrange)
+ yscale.domain(ylim).range(yrange)
+ xs = d3.scale.linear().domain(xlim).range(xrange)
+ ys = d3.scale.linear().domain(ylim).range(yrange)
+
+ # "polylinear" scales to handle missing values
+ if xNA.handle
+ xscale.domain([na_value].concat xlim)
+ .range([margin.left + xNA.width/2].concat xrange)
+ x = x.map (e) -> if e? then e else na_value
+ if yNA.handle
+ yscale.domain([na_value].concat ylim)
+ .range([height+margin.top-yNA.width/2].concat yrange)
+ y = y.map (e) -> if e? then e else na_value
+
+ # if yticks not provided, use nyticks to choose pretty ones
+ yticks = yticks ? ys.ticks(nyticks)
+ xticks = xticks ? xs.ticks(nxticks)
+
+ # title
+ titlegrp = g.append("g").attr("class", "title")
+ .append("text")
+ .attr("x", margin.left + width/2)
+ .attr("y", margin.top - titlepos)
+ .text(title)
+
+ # x-axis
+ xaxis = g.append("g").attr("class", "x axis")
+ xaxis.selectAll("empty")
+ .data(xticks)
+ .enter()
+ .append("line")
+ .attr("x1", (d) -> xscale(d))
+ .attr("x2", (d) -> xscale(d))
+ .attr("y1", margin.top)
+ .attr("y2", margin.top+height)
+ .attr("fill", "none")
+ .attr("stroke", "white")
+ .attr("stroke-width", 1)
+ .style("pointer-events", "none")
+ xaxis.selectAll("empty")
+ .data(xticks)
+ .enter()
+ .append("text")
+ .attr("x", (d) -> xscale(d))
+ .attr("y", margin.top+height+axispos.xlabel)
+ .text((d) -> formatAxis(xticks)(d))
+ xaxis.append("text").attr("class", "title")
+ .attr("x", margin.left+width/2)
+ .attr("y", margin.top+height+axispos.xtitle)
+ .text(xlab)
+ if xNA.handle
+ xaxis.append("text")
+ .attr("x", margin.left+xNA.width/2)
+ .attr("y", margin.top+height+axispos.xlabel)
+ .text("N/A")
+
+ # y-axis
+ rotate_ylab = rotate_ylab ? (ylab.length > 1)
+ yaxis = g.append("g").attr("class", "y axis")
+ yaxis.selectAll("empty")
+ .data(yticks)
+ .enter()
+ .append("line")
+ .attr("y1", (d) -> yscale(d))
+ .attr("y2", (d) -> yscale(d))
+ .attr("x1", margin.left)
+ .attr("x2", margin.left+width)
+ .attr("fill", "none")
+ .attr("stroke", "white")
+ .attr("stroke-width", 1)
+ .style("pointer-events", "none")
+ yaxis.selectAll("empty")
+ .data(yticks)
+ .enter()
+ .append("text")
+ .attr("y", (d) -> yscale(d))
+ .attr("x", margin.left-axispos.ylabel)
+ .text((d) -> formatAxis(yticks)(d))
+ yaxis.append("text").attr("class", "title")
+ .attr("y", margin.top+height/2)
+ .attr("x", margin.left-axispos.ytitle)
+ .text(ylab)
+ .attr("transform", if rotate_ylab then "rotate(270,#{margin.left-axispos.ytitle},#{margin.top+height/2})" else "")
+ if yNA.handle
+ yaxis.append("text")
+ .attr("x", margin.left-axispos.ylabel)
+ .attr("y", margin.top+height-yNA.width/2)
+ .text("N/A")
+
+ indtip = d3.tip()
+ .attr('class', 'd3-tip')
+ .html((d,i) -> indID[i])
+ .direction('e')
+ .offset([0,10])
+ svg.call(indtip)
+
+ points = g.append("g").attr("id", "points")
+ pointsSelect =
+ points.selectAll("empty")
+ .data(d3.range(x.length))
+ .enter()
+ .append("circle")
+ .attr("cx", (d,i) -> xscale(x[i]))
+ .attr("cy", (d,i) -> yscale(y[i]))
+ .attr("class", (d,i) -> "pt#{i}")
+ .attr("r", pointsize)
+ .attr("fill", (d,i) -> pointcolor[group[i]])
+ .attr("stroke", pointstroke)
+ .attr("stroke-width", "1")
+ .attr("opacity", (d,i) ->
+ return 1 if (x[i]? or xNA.handle) and (y[i]? or yNA.handle)
+ return 0)
+ .on("mouseover.paneltip", indtip.show)
+ .on("mouseout.paneltip", indtip.hide)
+
+ # box
+ g.append("rect")
+ .attr("x", margin.left+paneloffset)
+ .attr("y", margin.top)
+ .attr("height", panelheight)
+ .attr("width", panelwidth)
+ .attr("fill", "none")
+ .attr("stroke", "black")
+ .attr("stroke-width", "none")
+ if xNA.handle
+ g.append("rect")
+ .attr("x", margin.left)
+ .attr("y", margin.top)
+ .attr("height", panelheight)
+ .attr("width", xNA.width)
+ .attr("fill", "none")
+ .attr("stroke", "black")
+ .attr("stroke-width", "none")
+ if xNA.handle and yNA.handle
+ g.append("rect")
+ .attr("x", margin.left)
+ .attr("y", margin.top+height - yNA.width)
+ .attr("height", yNA.width)
+ .attr("width", xNA.width)
+ .attr("fill", "none")
+ .attr("stroke", "black")
+ .attr("stroke-width", "none")
+ if yNA.handle
+ g.append("rect")
+ .attr("x", margin.left+paneloffset)
+ .attr("y", margin.top+height-yNA.width)
+ .attr("height", yNA.width)
+ .attr("width", panelwidth)
+ .attr("fill", "none")
+ .attr("stroke", "black")
+ .attr("stroke-width", "none")
+
+ ## configuration parameters
+ chart.width = (value) ->
+ return width if !arguments.length
+ width = value
+ chart
+
+ chart.height = (value) ->
+ return height if !arguments.length
+ height = value
+ chart
+
+ chart.margin = (value) ->
+ return margin if !arguments.length
+ margin = value
+ chart
+
+ chart.axispos = (value) ->
+ return axispos if !arguments.length
+ axispos = value
+ chart
+
+ chart.titlepos = (value) ->
+ return titlepos if !arguments.length
+ titlepos
+ chart
+
+ chart.xlim = (value) ->
+ return xlim if !arguments.length
+ xlim = value
+ chart
+
+ chart.nxticks = (value) ->
+ return nxticks if !arguments.length
+ nxticks = value
+ chart
+
+ chart.xticks = (value) ->
+ return xticks if !arguments.length
+ xticks = value
+ chart
+
+ chart.ylim = (value) ->
+ return ylim if !arguments.length
+ ylim = value
+ chart
+
+ chart.nyticks = (value) ->
+ return nyticks if !arguments.length
+ nyticks = value
+ chart
+
+ chart.yticks = (value) ->
+ return yticks if !arguments.length
+ yticks = value
+ chart
+
+ chart.rectcolor = (value) ->
+ return rectcolor if !arguments.length
+ rectcolor = value
+ chart
+
+ chart.pointcolor = (value) ->
+ return pointcolor if !arguments.length
+ pointcolor = value
+ chart
+
+ chart.pointsize = (value) ->
+ return pointsize if !arguments.length
+ pointsize = value
+ chart
+
+ chart.pointstroke = (value) ->
+ return pointstroke if !arguments.length
+ pointstroke = value
+ chart
+
+ chart.dataByInd = (value) ->
+ return dataByInd if !arguments.length
+ dataByInd = value
+ chart
+
+ chart.title = (value) ->
+ return title if !arguments.length
+ title = value
+ chart
+
+ chart.xlab = (value) ->
+ return xlab if !arguments.length
+ xlab = value
+ chart
+
+ chart.ylab = (value) ->
+ return ylab if !arguments.length
+ ylab = value
+ chart
+
+ chart.rotate_ylab = (value) ->
+ return rotate_ylab if !arguments.length
+ rotate_ylab = value
+ chart
+
+ chart.xvar = (value) ->
+ return xvar if !arguments.length
+ xvar = value
+ chart
+
+ chart.yvar = (value) ->
+ return yvar if !arguments.length
+ yvar = value
+ chart
+
+ chart.xNA = (value) ->
+ return xNA if !arguments.length
+ xNA = value
+ chart
+
+ chart.yNA = (value) ->
+ return yNA if !arguments.length
+ yNA = value
+ chart
+
+ chart.yscale = () ->
+ return yscale
+
+ chart.xscale = () ->
+ return xscale
+
+ chart.pointsSelect = () ->
+ return pointsSelect
+
+ # return the chart function
+ chart
\ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/scatterplot.js b/wqflask/wqflask/static/new/javascript/scatterplot.js new file mode 100644 index 00000000..23a66e6b --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/scatterplot.js @@ -0,0 +1,406 @@ +// Generated by CoffeeScript 1.6.1 +(function() { + var scatterplot; + + scatterplot = function() { + var axispos, chart, dataByInd, height, margin, nxticks, nyticks, pointcolor, pointsSelect, pointsize, pointstroke, rectcolor, rotate_ylab, title, titlepos, width, xNA, xlab, xlim, xscale, xticks, xvar, yNA, ylab, ylim, yscale, yticks, yvar; + width = 800; + height = 500; + margin = { + left: 60, + top: 40, + right: 40, + bottom: 40, + inner: 5 + }; + axispos = { + xtitle: 25, + ytitle: 30, + xlabel: 5, + ylabel: 5 + }; + titlepos = 20; + xNA = { + handle: true, + force: false, + width: 15, + gap: 10 + }; + yNA = { + handle: true, + force: false, + width: 15, + gap: 10 + }; + xlim = null; + ylim = null; + nxticks = 5; + xticks = null; + nyticks = 5; + yticks = null; + rectcolor = d3.rgb(230, 230, 230); + pointcolor = null; + pointstroke = "black"; + pointsize = 3; + title = ""; + xlab = "X"; + ylab = "Y"; + rotate_ylab = null; + yscale = d3.scale.linear(); + xscale = d3.scale.linear(); + xvar = 0; + yvar = 1; + pointsSelect = null; + dataByInd = true; + chart = function(selection) { + return selection.each(function(data) { + var g, gEnter, group, i, indID, indtip, na_value, ngroup, panelheight, paneloffset, panelwidth, points, svg, titlegrp, x, xaxis, xrange, xs, y, yaxis, yrange, ys, _i, _ref, _ref1, _ref2, _results; + if (dataByInd) { + x = data.data.map(function(d) { + return d[xvar]; + }); + y = data.data.map(function(d) { + return d[yvar]; + }); + } else { + x = data.data[xvar]; + y = data.data[yvar]; + } + indID = (_ref = data != null ? data.indID : void 0) != null ? _ref : null; + indID = indID != null ? indID : (function() { + _results = []; + for (var _i = 1, _ref1 = x.length; 1 <= _ref1 ? _i <= _ref1 : _i >= _ref1; 1 <= _ref1 ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + group = (_ref2 = data != null ? data.group : void 0) != null ? _ref2 : (function() { + var _j, _len, _results1; + _results1 = []; + for (_j = 0, _len = x.length; _j < _len; _j++) { + i = x[_j]; + _results1.push(1); + } + return _results1; + })(); + ngroup = d3.max(group); + group = (function() { + var _j, _len, _results1; + _results1 = []; + for (_j = 0, _len = group.length; _j < _len; _j++) { + g = group[_j]; + _results1.push(g - 1); + } + return _results1; + })(); + pointcolor = pointcolor != null ? pointcolor : selectGroupColors(ngroup, "dark"); + pointcolor = expand2vector(pointcolor, ngroup); + if (x.every(function(v) { + return (v != null) && !xNA.force; + })) { + xNA.handle = false; + } + if (y.every(function(v) { + return (v != null) && !yNA.force; + })) { + yNA.handle = false; + } + if (xNA.handle) { + paneloffset = xNA.width + xNA.gap; + panelwidth = width - paneloffset; + } else { + paneloffset = 0; + panelwidth = width; + } + if (yNA.handle) { + panelheight = height - (yNA.width + yNA.gap); + } else { + panelheight = height; + } + xlim = xlim != null ? xlim : d3.extent(x); + ylim = ylim != null ? ylim : d3.extent(y); + na_value = d3.min(x.concat(y)) - 100; + svg = d3.select(this).selectAll("svg").data([data]); + gEnter = svg.enter().append("svg").append("g"); + svg.attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom); + g = svg.select("g"); + g.append("rect").attr("x", paneloffset + margin.left).attr("y", margin.top).attr("height", panelheight).attr("width", panelwidth).attr("fill", rectcolor).attr("stroke", "none"); + if (xNA.handle) { + g.append("rect").attr("x", margin.left).attr("y", margin.top).attr("height", panelheight).attr("width", xNA.width).attr("fill", rectcolor).attr("stroke", "none"); + } + if (xNA.handle && yNA.handle) { + g.append("rect").attr("x", margin.left).attr("y", margin.top + height - yNA.width).attr("height", yNA.width).attr("width", xNA.width).attr("fill", rectcolor).attr("stroke", "none"); + } + if (yNA.handle) { + g.append("rect").attr("x", margin.left + paneloffset).attr("y", margin.top + height - yNA.width).attr("height", yNA.width).attr("width", panelwidth).attr("fill", rectcolor).attr("stroke", "none"); + } + xrange = [margin.left + paneloffset + margin.inner, margin.left + paneloffset + panelwidth - margin.inner]; + yrange = [margin.top + panelheight - margin.inner, margin.top + margin.inner]; + xscale.domain(xlim).range(xrange); + yscale.domain(ylim).range(yrange); + xs = d3.scale.linear().domain(xlim).range(xrange); + ys = d3.scale.linear().domain(ylim).range(yrange); + if (xNA.handle) { + xscale.domain([na_value].concat(xlim)).range([margin.left + xNA.width / 2].concat(xrange)); + x = x.map(function(e) { + if (e != null) { + return e; + } else { + return na_value; + } + }); + } + if (yNA.handle) { + yscale.domain([na_value].concat(ylim)).range([height + margin.top - yNA.width / 2].concat(yrange)); + y = y.map(function(e) { + if (e != null) { + return e; + } else { + return na_value; + } + }); + } + 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).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); + }).attr("x2", function(d) { + return xscale(d); + }).attr("y1", margin.top).attr("y2", margin.top + height).attr("fill", "none").attr("stroke", "white").attr("stroke-width", 1).style("pointer-events", "none"); + xaxis.selectAll("empty").data(xticks).enter().append("text").attr("x", function(d) { + return xscale(d); + }).attr("y", margin.top + height + axispos.xlabel).text(function(d) { + return formatAxis(xticks)(d); + }); + xaxis.append("text").attr("class", "title").attr("x", margin.left + width / 2).attr("y", margin.top + height + axispos.xtitle).text(xlab); + if (xNA.handle) { + xaxis.append("text").attr("x", margin.left + xNA.width / 2).attr("y", margin.top + height + axispos.xlabel).text("N/A"); + } + rotate_ylab = rotate_ylab != null ? rotate_ylab : ylab.length > 1; + yaxis = g.append("g").attr("class", "y axis"); + yaxis.selectAll("empty").data(yticks).enter().append("line").attr("y1", function(d) { + return yscale(d); + }).attr("y2", function(d) { + return yscale(d); + }).attr("x1", margin.left).attr("x2", margin.left + width).attr("fill", "none").attr("stroke", "white").attr("stroke-width", 1).style("pointer-events", "none"); + yaxis.selectAll("empty").data(yticks).enter().append("text").attr("y", function(d) { + return yscale(d); + }).attr("x", margin.left - axispos.ylabel).text(function(d) { + return formatAxis(yticks)(d); + }); + yaxis.append("text").attr("class", "title").attr("y", margin.top + height / 2).attr("x", margin.left - axispos.ytitle).text(ylab).attr("transform", rotate_ylab ? "rotate(270," + (margin.left - axispos.ytitle) + "," + (margin.top + height / 2) + ")" : ""); + if (yNA.handle) { + yaxis.append("text").attr("x", margin.left - axispos.ylabel).attr("y", margin.top + height - yNA.width / 2).text("N/A"); + } + indtip = d3.tip().attr('class', 'd3-tip').html(function(d, i) { + return indID[i]; + }).direction('e').offset([0, 10]); + svg.call(indtip); + points = g.append("g").attr("id", "points"); + pointsSelect = points.selectAll("empty").data(d3.range(x.length)).enter().append("circle").attr("cx", function(d, i) { + return xscale(x[i]); + }).attr("cy", function(d, i) { + return yscale(y[i]); + }).attr("class", function(d, i) { + return "pt" + i; + }).attr("r", pointsize).attr("fill", function(d, i) { + return pointcolor[group[i]]; + }).attr("stroke", pointstroke).attr("stroke-width", "1").attr("opacity", function(d, i) { + if (((x[i] != null) || xNA.handle) && ((y[i] != null) || yNA.handle)) { + return 1; + } + return 0; + }).on("mouseover.paneltip", indtip.show).on("mouseout.paneltip", indtip.hide); + g.append("rect").attr("x", margin.left + paneloffset).attr("y", margin.top).attr("height", panelheight).attr("width", panelwidth).attr("fill", "none").attr("stroke", "black").attr("stroke-width", "none"); + if (xNA.handle) { + g.append("rect").attr("x", margin.left).attr("y", margin.top).attr("height", panelheight).attr("width", xNA.width).attr("fill", "none").attr("stroke", "black").attr("stroke-width", "none"); + } + if (xNA.handle && yNA.handle) { + g.append("rect").attr("x", margin.left).attr("y", margin.top + height - yNA.width).attr("height", yNA.width).attr("width", xNA.width).attr("fill", "none").attr("stroke", "black").attr("stroke-width", "none"); + } + if (yNA.handle) { + return g.append("rect").attr("x", margin.left + paneloffset).attr("y", margin.top + height - yNA.width).attr("height", yNA.width).attr("width", panelwidth).attr("fill", "none").attr("stroke", "black").attr("stroke-width", "none"); + } + }); + }; + chart.width = function(value) { + if (!arguments.length) { + return width; + } + width = value; + return chart; + }; + chart.height = function(value) { + if (!arguments.length) { + return height; + } + height = value; + return chart; + }; + chart.margin = function(value) { + if (!arguments.length) { + return margin; + } + margin = value; + return chart; + }; + chart.axispos = function(value) { + if (!arguments.length) { + return axispos; + } + axispos = value; + return chart; + }; + chart.titlepos = function(value) { + if (!arguments.length) { + return titlepos; + } + titlepos; + return chart; + }; + chart.xlim = function(value) { + if (!arguments.length) { + return xlim; + } + xlim = value; + return chart; + }; + chart.nxticks = function(value) { + if (!arguments.length) { + return nxticks; + } + nxticks = value; + return chart; + }; + chart.xticks = function(value) { + if (!arguments.length) { + return xticks; + } + xticks = value; + return chart; + }; + chart.ylim = function(value) { + if (!arguments.length) { + return ylim; + } + ylim = value; + return chart; + }; + chart.nyticks = function(value) { + if (!arguments.length) { + return nyticks; + } + nyticks = value; + return chart; + }; + chart.yticks = function(value) { + if (!arguments.length) { + return yticks; + } + yticks = value; + return chart; + }; + chart.rectcolor = function(value) { + if (!arguments.length) { + return rectcolor; + } + rectcolor = value; + return chart; + }; + chart.pointcolor = function(value) { + if (!arguments.length) { + return pointcolor; + } + pointcolor = value; + return chart; + }; + chart.pointsize = function(value) { + if (!arguments.length) { + return pointsize; + } + pointsize = value; + return chart; + }; + chart.pointstroke = function(value) { + if (!arguments.length) { + return pointstroke; + } + pointstroke = value; + return chart; + }; + chart.dataByInd = function(value) { + if (!arguments.length) { + return dataByInd; + } + dataByInd = value; + return chart; + }; + chart.title = function(value) { + if (!arguments.length) { + return title; + } + title = value; + return chart; + }; + chart.xlab = function(value) { + if (!arguments.length) { + return xlab; + } + xlab = value; + return chart; + }; + chart.ylab = function(value) { + if (!arguments.length) { + return ylab; + } + ylab = value; + return chart; + }; + chart.rotate_ylab = function(value) { + if (!arguments.length) { + return rotate_ylab; + } + rotate_ylab = value; + return chart; + }; + chart.xvar = function(value) { + if (!arguments.length) { + return xvar; + } + xvar = value; + return chart; + }; + chart.yvar = function(value) { + if (!arguments.length) { + return yvar; + } + yvar = value; + return chart; + }; + chart.xNA = function(value) { + if (!arguments.length) { + return xNA; + } + xNA = value; + return chart; + }; + chart.yNA = function(value) { + if (!arguments.length) { + return yNA; + } + yNA = value; + return chart; + }; + chart.yscale = function() { + return yscale; + }; + chart.xscale = function() { + return xscale; + }; + chart.pointsSelect = function() { + return pointsSelect; + }; + return chart; + }; + +}).call(this); diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee index 1d375686..6118eae8 100755 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee @@ -120,6 +120,7 @@ $ -> ) $("#plink_compute").click(() => + $("#static_progress_bar_container").modal() url = "/marker_regression" $('input[name=method]').val("plink") $('input[name=mapping_display_all]').val($('input[name=display_all_plink]')) @@ -135,11 +136,11 @@ $ -> alert("Sorry, an error occurred") console.log(xhr) clearInterval(this.my_timer) - $('#progress_bar_container').modal('hide') + $('#static_progress_bar_container').modal('hide') $("body").html("We got an error.") success: (data) => clearInterval(this.my_timer) - $('#progress_bar_container').modal('hide') + $('#static_progress_bar_container').modal('hide') $("body").html(data) ) console.log("settingInterval") @@ -149,6 +150,7 @@ $ -> ) $("#gemma_compute").click(() => + $("#static_progress_bar_container").modal() url = "/marker_regression" $('input[name=method]').val("gemma") $('input[name=mapping_display_all]').val($('input[name=display_all_gemma]')) @@ -164,11 +166,11 @@ $ -> alert("Sorry, an error occurred") console.log(xhr) clearInterval(this.my_timer) - $('#progress_bar_container').modal('hide') + $('#static_progress_bar_container').modal('hide') $("body").html("We got an error.") success: (data) => clearInterval(this.my_timer) - $('#progress_bar_container').modal('hide') + $('#static_progress_bar_container').modal('hide') $("body").html(data) ) console.log("settingInterval") diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js index dbc26e3b..ee930c80 100755 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js @@ -132,6 +132,7 @@ }); $("#plink_compute").click(function() { var form_data, url; + $("#static_progress_bar_container").modal(); url = "/marker_regression"; $('input[name=method]').val("plink"); $('input[name=mapping_display_all]').val($('input[name=display_all_plink]')); @@ -147,12 +148,12 @@ alert("Sorry, an error occurred"); console.log(xhr); clearInterval(_this.my_timer); - $('#progress_bar_container').modal('hide'); + $('#static_progress_bar_container').modal('hide'); return $("body").html("We got an error."); }, success: function(data) { clearInterval(_this.my_timer); - $('#progress_bar_container').modal('hide'); + $('#static_progress_bar_container').modal('hide'); return $("body").html(data); } }); @@ -162,6 +163,7 @@ }); $("#gemma_compute").click(function() { var form_data, url; + $("#static_progress_bar_container").modal(); url = "/marker_regression"; $('input[name=method]').val("gemma"); $('input[name=mapping_display_all]').val($('input[name=display_all_gemma]')); @@ -177,12 +179,12 @@ alert("Sorry, an error occurred"); console.log(xhr); clearInterval(_this.my_timer); - $('#progress_bar_container').modal('hide'); + $('#static_progress_bar_container').modal('hide'); return $("body").html("We got an error."); }, success: function(data) { clearInterval(_this.my_timer); - $('#progress_bar_container').modal('hide'); + $('#static_progress_bar_container').modal('hide'); return $("body").html(data); } }); diff --git a/wqflask/wqflask/static/new/js_external/d3-tip.min.js b/wqflask/wqflask/static/new/js_external/d3-tip.min.js new file mode 100644 index 00000000..d881b1dc --- /dev/null +++ b/wqflask/wqflask/static/new/js_external/d3-tip.min.js @@ -0,0 +1 @@ +!function(t,e){"function"==typeof define&&define.amd?define(["d3"],e):t.d3.tip=e(t.d3)}(this,function(t){return function(){function e(t){w=m(t),T=w.createSVGPoint(),document.body.appendChild(v)}function n(){return"n"}function r(){return[0,0]}function o(){return" "}function l(){var t=d();return{top:t.n.y-v.offsetHeight,left:t.n.x-v.offsetWidth/2}}function s(){var t=d();return{top:t.s.y,left:t.s.x-v.offsetWidth/2}}function f(){var t=d();return{top:t.e.y-v.offsetHeight/2,left:t.e.x}}function i(){var t=d();return{top:t.w.y-v.offsetHeight/2,left:t.w.x-v.offsetWidth}}function u(){var t=d();return{top:t.nw.y-v.offsetHeight,left:t.nw.x-v.offsetWidth}}function a(){var t=d();return{top:t.ne.y-v.offsetHeight,left:t.ne.x}}function c(){var t=d();return{top:t.sw.y,left:t.sw.x-v.offsetWidth}}function p(){var t=d();return{top:t.se.y,left:t.e.x}}function y(){var e=t.select(document.createElement("div"));return e.style({position:"absolute",top:0,opacity:0,"pointer-events":"none","box-sizing":"border-box"}),e.node()}function m(t){return t=t.node(),"svg"==t.tagName.toLowerCase()?t:t.ownerSVGElement}function d(){var e=b||t.event.target,n={},r=e.getScreenCTM(),o=e.getBBox(),l=o.width,s=o.height,f=o.x,i=o.y;return T.x=f,T.y=i,n.nw=T.matrixTransform(r),T.x+=l,n.ne=T.matrixTransform(r),T.y+=s,n.se=T.matrixTransform(r),T.x-=l,n.sw=T.matrixTransform(r),T.y-=s/2,n.w=T.matrixTransform(r),T.x+=l,n.e=T.matrixTransform(r),T.x-=l/2,T.y-=s/2,n.n=T.matrixTransform(r),T.y+=s,n.s=T.matrixTransform(r),n}var g=n,h=r,x=o,v=y(),w=null,T=null,b=null;e.show=function(){var n=Array.prototype.slice.call(arguments);n[n.length-1]instanceof SVGElement&&(b=n.pop());var r,o=x.apply(this,n),l=h.apply(this,n),s=g.apply(this,n),f=t.select(v),i=H.length,u=document.documentElement.scrollTop||document.body.scrollTop,a=document.documentElement.scrollLeft||document.body.scrollLeft;for(f.html(o).style({opacity:1,"pointer-events":"all"});i--;)f.classed(H[i],!1);return r=E.get(s).apply(this),f.classed(s,!0).style({top:r.top+l[0]+u+"px",left:r.left+l[1]+a+"px"}),e},e.hide=function(){return nodel=t.select(v),nodel.style({opacity:0,"pointer-events":"none"}),e},e.attr=function(n){if(arguments.length<2&&"string"==typeof n)return t.select(v).attr(n);var r=Array.prototype.slice.call(arguments);return t.selection.prototype.attr.apply(t.select(v),r),e},e.style=function(n){if(arguments.length<2&&"string"==typeof n)return t.select(v).style(n);var r=Array.prototype.slice.call(arguments);return t.selection.prototype.style.apply(t.select(v),r),e},e.direction=function(n){return arguments.length?(g=null==n?n:t.functor(n),e):g},e.offset=function(n){return arguments.length?(h=null==n?n:t.functor(n),e):h},e.html=function(n){return arguments.length?(x=null==n?n:t.functor(n),e):x};var E=t.map({n:l,s:s,e:f,w:i,nw:u,ne:a,sw:c,se:p}),H=E.keys();return e}});
\ No newline at end of file diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html index e4819d61..61d17a22 100755 --- a/wqflask/wqflask/templates/correlation_page.html +++ b/wqflask/wqflask/templates/correlation_page.html @@ -25,6 +25,7 @@ <table id="corr_results" class="table table-hover table-striped table-bordered"> <thead> <tr> + {% if dataset.type == 'ProbeSet' %} <th>Trait</th> <th>Symbol</th> <th>Description</th> @@ -47,11 +48,27 @@ <th>Tissue rho</th> <th>Tissue p(rho)</th> {% endif %} + {% elif dataset.type == "Publish" %} + <th>Record ID</th> + <th>Phenotype</th> + <th>Authors</th> + <th>Year</th> + {% if corr_method == 'pearson' %} + <th>Sample r</th> + <th>N Cases</th> + <th>Sample p(r)</th> + {% else %} + <th>Sample rho</th> + <th>N Cases</th> + <th>Sample p(rho)</th> + {% endif %} + {% endif %} </tr> </thead> <tbody> {% for trait in correlation_results %} <tr> + {% if dataset.type == 'ProbeSet' %} <td><a href="/show_trait?trait_id={{trait.name}}&dataset={{trait.dataset.name}}">{{ trait.name }}</a></td> <td>{{ trait.symbol }}</td> <td>{{ trait.description }} <br><br> <b>Aliases</b>: {{ trait.alias }}</td> @@ -65,6 +82,15 @@ <td>{{'%0.3f'|format(trait.lit_corr)}}</td> <td>{{'%0.3f'|format(trait.tissue_corr)}}</td> <td>{{'%0.3e'|format(trait.tissue_pvalue)}}</td> + {% elif dataset.type == "Publish" %} + <td><a href="/show_trait?trait_id={{trait.name}}&dataset={{trait.dataset.name}}">{{ trait.name }}</a></td> + <td>{{ trait.post_publication_description }}</td> + <td>{{ trait.authors }}</td> + <td>{{ trait.year }}</td> + <td><a target="_blank" href="corr_scatter_plot?dataset_1={{dataset.name}}&dataset_2={{trait.dataset.name}}&trait_1={{this_trait.name}}&trait_2={{trait.name}}">{{'%0.3f'|format(trait.sample_r)}}</a></td> + <td>{{ trait.num_overlap }}</td> + <td>{{'%0.3e'|format(trait.sample_p)}}</td> + {% endif %} </tr> {% endfor %} </tbody> diff --git a/wqflask/wqflask/templates/interval_mapping.html b/wqflask/wqflask/templates/interval_mapping.html index e4b93bf4..e3c164ea 100755 --- a/wqflask/wqflask/templates/interval_mapping.html +++ b/wqflask/wqflask/templates/interval_mapping.html @@ -5,6 +5,8 @@ <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/css/jquery.dataTables.css" />
<link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" />
<link rel="stylesheet" type="text/css" href="/static/packages/TableTools/media/css/TableTools.css" />
+ <link rel="stylesheet" type="text/css" href="/static/new/css/panelutil.css" />
+ <link rel="stylesheet" type="text/css" href="/static/new/css/d3-tip.min.css" />
{% endblock %}
{% block content %} <!-- Start of body -->
@@ -17,7 +19,7 @@ Whole Genome Mapping
</h2>
</div>
- <div id="interval_map" class="interval_map">
+ <div id="topchart">
</div>
<div>
@@ -69,7 +71,10 @@ <!-- <script language="javascript" type="text/javascript" src="/static/packages/jqplot/excanvas.js"></script>-->
<![endif]-->
<script language="javascript" type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/interval_mapping.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/new/js_external/d3-tip.min.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/new/javascript/panelutil.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/new/javascript/lod_chart.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/new/javascript/interval_map_new.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.dataTables.min.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/dataTables.scientific.js"></script>
diff --git a/wqflask/wqflask/templates/show_trait_details.html b/wqflask/wqflask/templates/show_trait_details.html index b57c3c21..88fd74d9 100755 --- a/wqflask/wqflask/templates/show_trait_details.html +++ b/wqflask/wqflask/templates/show_trait_details.html @@ -29,7 +29,7 @@ -<div class="btn-toolbar"> +<!--<div class="btn-toolbar"> <div class="btn-group"> <button class="btn btn-primary" title="Add to collection"> <i class="icon-plus-sign icon-white"></i> Add @@ -63,4 +63,4 @@ </button> </div> -</div> +</div>--> diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html index f380988e..a2c7564f 100755 --- a/wqflask/wqflask/templates/show_trait_mapping_tools.html +++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html @@ -7,7 +7,7 @@ <a href="#interval_mapping" data-toggle="tab">Interval Mapping</a> </li> <li> - <a href="#marker_regression" data-toggle="tab">Marker Regression</a> + <a href="#pylmm" data-toggle="tab">pyLMM</a> </li> <li> <a href="#plink" data-toggle="tab">PLINK</a> @@ -112,7 +112,7 @@ </div> </div> - <div class="tab-pane" id="marker_regression"> + <div class="tab-pane" id="pylmm"> <div class="control-group" id="display_all_div"> <label class="control-label">Display all</label> <div class="controls"> diff --git a/wqflask/wqflask/templates/show_trait_progress_bar.html b/wqflask/wqflask/templates/show_trait_progress_bar.html index 0c3f0e6e..aebf64a4 100755 --- a/wqflask/wqflask/templates/show_trait_progress_bar.html +++ b/wqflask/wqflask/templates/show_trait_progress_bar.html @@ -9,4 +9,17 @@ <div id="time_remaining"> </div> </div> +</div> + +<div id="static_progress_bar_container" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="progress_bar" aria-hidden="true"> + <div class="modal-header"> + <h3 id="progress_bar">Loading... (Estimated time ~10-15m)</h3> + </div> + <div class="modal-body"> + <div class="progress progress-striped active"> + <div id="marker_regression_progress" class="bar" style="width: 100%"></div> + </div> + <div id="time_remaining"> + </div> + </div> </div>
\ No newline at end of file diff --git a/wqflask/wqflask/templates/show_trait_statistics_new.html b/wqflask/wqflask/templates/show_trait_statistics_new.html index 3a68d8c5..8f6f07ce 100755 --- a/wqflask/wqflask/templates/show_trait_statistics_new.html +++ b/wqflask/wqflask/templates/show_trait_statistics_new.html @@ -10,9 +10,9 @@ <li> <a href="#bar_chart_tab" data-toggle="tab">Bar Chart</a> </li> - <li> +<!-- <li> <a href="#box_plot_tab" data-toggle="tab">Box Plot</a> - </li> + </li>--> </ul> <div class="tab-content"> <div class="tab-pane active" id="histogram_tab"> @@ -67,7 +67,7 @@ <div id="bar_chart"></div> </div> </div> - <div class="tab-pane" id="box_plot_tab"> +<!-- <div class="tab-pane" id="box_plot_tab"> {% if sample_groups|length > 1 %} <select class="box_plot_samples_group"> {% for group, pretty_group in sample_group_types.items() %} @@ -79,7 +79,7 @@ <div id="box_plot_container"> <div id="box_plot"></div> </div> - </div> + </div>--> </div> </div> </div> diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py index e4fb60e4..2ee5bbca 100755 --- a/wqflask/wqflask/user_manager.py +++ b/wqflask/wqflask/user_manager.py @@ -131,7 +131,10 @@ class UserSession(object): @property def user_id(self): """Shortcut to the user_id""" - return self.record['user_id'] + if 'user_id' in self.record: + return self.record['user_id'] + else: + return '' @property def user_ob(self): diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py index 20516205..7bde1006 100755 --- a/wqflask/wqflask/views.py +++ b/wqflask/wqflask/views.py @@ -279,7 +279,7 @@ def interval_mapping_page(): if key in wanted or key.startswith(('value:')): start_vars[key] = value - version = "v7" + version = "v11" key = "interval_mapping:{}:".format(version) + json.dumps(start_vars, sort_keys=True) print("key is:", pf(key)) with Bench("Loading cache"): |