gwaslab 3.4.49__py3-none-any.whl → 3.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of gwaslab might be problematic. Click here for more details.

gwaslab/g_Sumstats.py CHANGED
@@ -81,6 +81,7 @@ from gwaslab.bd_get_hapmap3 import gethapmap3
81
81
  from gwaslab.util_abf_finemapping import abf_finemapping
82
82
  from gwaslab.util_abf_finemapping import make_cs
83
83
  import gc
84
+ from gwaslab.viz_plot_phe_heatmap import _gwheatmap
84
85
 
85
86
  #20220309
86
87
  class Sumstats():
@@ -602,6 +603,11 @@ class Sumstats():
602
603
  def plot_daf(self, **kwargs):
603
604
  fig,outliers = plotdaf(self.data, **kwargs)
604
605
  return fig, outliers
606
+
607
+ def plot_gwheatmap(self, **kwargs):
608
+ fig = _gwheatmap(self.data, **kwargs)
609
+ return fig
610
+
605
611
  def plot_mqq(self, build=None, **kwargs):
606
612
 
607
613
  chrom="CHR"
@@ -705,7 +711,7 @@ class Sumstats():
705
711
  # return sumstats object
706
712
  return output
707
713
 
708
- def check_cis(self, **kwargs):
714
+ def check_cis(self, gls=False, **kwargs):
709
715
  if "SNPID" in self.data.columns:
710
716
  id_to_use = "SNPID"
711
717
  else:
@@ -717,7 +723,13 @@ class Sumstats():
717
723
  p="P",
718
724
  log=self.log,
719
725
  **kwargs)
720
- # return sumstats object
726
+
727
+ # return sumstats object
728
+ if gls == True:
729
+ new_Sumstats_object = copy.deepcopy(self)
730
+ new_Sumstats_object.data = output
731
+ gc.collect()
732
+ return new_Sumstats_object
721
733
  return output
722
734
 
723
735
  def check_novel_set(self, **kwargs):
gwaslab/g_version.py CHANGED
@@ -15,8 +15,8 @@ def _get_version():
15
15
  def gwaslab_info():
16
16
  # version meta information
17
17
  dic={
18
- "version":"3.4.49",
19
- "release_date":"20241019"
18
+ "version":"3.5.0",
19
+ "release_date":"20241029"
20
20
  }
21
21
  return dic
22
22
 
@@ -619,8 +619,10 @@ def _check_cis(insumstats,
619
619
  except:
620
620
  pass
621
621
 
622
- allsig["CIS/TRANS"] = allsig.apply(lambda x: determine_if_cis(x, group_key,windowsizekb, reference_dict), axis=1)
623
-
622
+ #allsig["CIS/TRANS"] = allsig.apply(lambda x: determine_if_cis(x, group_key,windowsizekb, reference_dict), axis=1)
623
+ cis_tuples = allsig.apply(lambda x: determine_if_cis2(x, group_key,windowsizekb, reference_dict), axis=1)
624
+ allsig[["CIS/TRANS","REF_CHR","REF_START","REF_END"]] = pd.DataFrame(cis_tuples.tolist(), index=allsig.index)
625
+
624
626
  try:
625
627
  allsig = allsig.where(~pd.isna(allsig), pd.NA)
626
628
  except:
@@ -689,6 +691,20 @@ def determine_if_cis(x, group_key,windowsizekb, reference_dict):
689
691
  else:
690
692
  return "NoReference"
691
693
 
694
+ def determine_if_cis2(x, group_key,windowsizekb, reference_dict):
695
+ if x[group_key] in reference_dict.keys():
696
+ is_same_chr = str(reference_dict[x[group_key]][0]) == str(x["CHR"])
697
+ is_large_than_start = int(reference_dict[x[group_key]][1]) - windowsizekb*1000 <= x["POS"]
698
+ is_smaller_than_end = int(reference_dict[x[group_key]][2]) + windowsizekb*1000 >= x["POS"]
699
+
700
+ if is_same_chr and is_large_than_start and is_smaller_than_end:
701
+ return "Cis", int(reference_dict[x[group_key]][0]), int(reference_dict[x[group_key]][1]), int(reference_dict[x[group_key]][2])
702
+ else:
703
+ return "Trans", int(reference_dict[x[group_key]][0]), int(reference_dict[x[group_key]][1]), int(reference_dict[x[group_key]][2])
704
+ else:
705
+ return "NoReference", pd.NA, pd.NA, pd.NA
706
+
707
+
692
708
  def determine_distance(allsig, knownsig):
693
709
  if len(allsig)==0:
694
710
  return allsig
@@ -60,21 +60,21 @@ def annotate_single(
60
60
  elif anno:
61
61
  annotation_col=anno
62
62
  log.write(" -Annotating using column "+annotation_col+"...", verbose=verbose)
63
-
63
+ ################################################################################################################################
64
64
  ## calculate y span
65
65
  if region is not None:
66
66
  y_span = region[2] - region[1]
67
67
  else:
68
68
  y_span = sumstats["i"].max()-sumstats["i"].min()
69
-
70
69
  log.write(" -Adjusting text positions with repel_force={}...".format(repel_force), verbose=verbose)
71
70
  if anno_style == "expand" :
72
71
  to_annotate.loc[:, "ADJUSTED_i"] = adjust_text_position(to_annotate["i"].values.copy(), y_span, repel_force,max_iter=anno_max_iter,log=log,amode=amode,verbose=verbose)
73
72
  ## iterate through variants to be annotated
73
+ ################################################################################################################################
74
+
74
75
  anno_to_adjust_list = list()
75
76
 
76
77
  for rowi,row in to_annotate.iterrows():
77
-
78
78
  # avoid text overlapping
79
79
  ## adjust x to avoid overlapping################################################################
80
80
  if anno_style == "right" :
@@ -93,7 +93,7 @@ def annotate_single(
93
93
  else:
94
94
  pass
95
95
  ################################################################
96
- #shrink or increase the arm
96
+ # shrink or increase the arm by a factor (arm_scale)
97
97
  if arm_scale_d is not None:
98
98
  if anno_count not in arm_scale_d.keys():
99
99
  arm_scale =1
@@ -102,20 +102,32 @@ def annotate_single(
102
102
  ################################################################
103
103
 
104
104
  # vertical arm length in pixels
105
- #to_annotate["scaled_P"] = to_annotate5["scaled_P_2"].copy()
106
- # arm length in pixels
107
- #armB_length_in_point = ax1.transData.transform((skip,1.15*maxy))[1]-ax1.transData.transform((skip, row["scaled_P"]+1))[1]-arm_offset/2
108
- armB_length_in_point = ax1.transData.transform((skip,1.15*maxy))[1]-ax1.transData.transform((skip, row["scaled_P"]+0.01*maxy))[1]-arm_offset/2
109
- # scale if needed
110
- armB_length_in_point = armB_length_in_point*arm_scale
105
+ # Annotation y : 1.15 * maxy_anno
106
+ # Top dot: 1 * maxy_anno
107
+ # armB_length_in_point_raw = 0.15 * maxy_anno -> gap_pixel
108
+ # Fixed Offset: 0.5 * 0.15 * gap_pixel
109
+
110
+ #Calculate armB length in pixels
111
+ # arm_scale: raise up the ceiling
112
+
113
+ # gap : 0.5* space between top variant and annotation text
114
+ gap_pixel = (ax1.transData.transform((0,1.15*maxy*arm_scale))[1]-ax1.transData.transform((0, maxy*arm_scale))[1])*0.5
115
+
116
+ # armB_length_in_pixel_raw : distance between variant to annotate and annotation text
117
+ armB_length_in_pixel_raw = ax1.transData.transform((0,1.15*maxy*arm_scale))[1]-ax1.transData.transform((0, row["scaled_P"]+1))[1]
118
+
119
+ armB_length_in_pixel = armB_length_in_pixel_raw - gap_pixel
120
+
111
121
  ################################################################
122
+ # armB_length_in_pixel should not be negative
112
123
  if arm_scale>=1:
113
- #armB_length_in_point= armB_length_in_point if armB_length_in_point>0 else ax1.transData.transform((skip, maxy+2))[1]-ax1.transData.transform((skip, row["scaled_P"]+1))[1]
114
- armB_length_in_point= armB_length_in_point if armB_length_in_point>0 else ax1.transData.transform((skip, maxy+0.02*maxy))[1]-ax1.transData.transform((skip, row["scaled_P"]+0.01*maxy))[1]
115
- ###if anno_fixed_arm_length #############################################################
124
+ armB_length_in_pixel = max(0, armB_length_in_pixel)
125
+
126
+ ################################################################
127
+ #if setting anno_fixed_arm_length
116
128
  if anno_fixed_arm_length is not None:
117
- anno_fixed_arm_length_factor = ax1.transData.transform((skip,anno_fixed_arm_length))[1]-ax1.transData.transform((skip,0))[1]
118
- armB_length_in_point = anno_fixed_arm_length_factor
129
+ armB_length_in_pixel = ax1.transData.transform((skip,anno_fixed_arm_length))[1]-ax1.transData.transform((skip,0))[1]
130
+
119
131
  ################################################################################################################################
120
132
  # annotation alias
121
133
  if anno==True:
@@ -129,26 +141,31 @@ def annotate_single(
129
141
  else:
130
142
  annotation_text=row["Annotation"]
131
143
 
132
-
133
- #xy=(row["i"],row["scaled_P"]+0.2)
144
+ ################################################################################################################################
145
+ # setting arrow xy and text xy
146
+ # add a small space between variant and arrow head
134
147
  xy=(row["i"],row["scaled_P"]+0.01*maxy)
135
- xytext=(last_pos,1.15*maxy*arm_scale*anno_height)
148
+
149
+ # text xy is of the same height
150
+ # anno_height can be used to adjust the height of annotation text
151
+ xytext=(last_pos,1.15*maxy*(arm_scale + anno_height -1))
136
152
 
153
+ # for anno_fixed_arm_length
137
154
  if anno_fixed_arm_length is not None:
138
- armB_length_in_point = anno_fixed_arm_length
139
- xytext=(row["i"],row["scaled_P"]+0.2+anno_fixed_arm_length)
140
-
155
+ xytext=(row["i"],row["scaled_P"] + 0.2 + anno_fixed_arm_length)
156
+
157
+ ################################################################################################################################
158
+ # if not changing the directions of some annotation arror arms
141
159
  if anno_count not in anno_d.keys():
142
- #arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
143
- # connectionstyle="arc,angleA=0,armA=0,angleB=90,armB="+str(armB_length_in_point)+",rad=0")
144
160
  if _invert==False:
145
161
  arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
146
- connectionstyle="arc,angleA=0,armA=0,angleB=90,armB="+str(armB_length_in_point)+",rad=0")
162
+ connectionstyle="arc,angleA=0,armA=0,angleB=90,armB="+str(armB_length_in_pixel)+",rad=0")
147
163
  else:
148
164
  arrowargs = dict(arrowstyle="-|>",relpos=(0,1),color="#ebebeb",
149
- connectionstyle="arc,angleA=0,armA=0,angleB=-90,armB="+str(armB_length_in_point)+",rad=0")
165
+ connectionstyle="arc,angleA=0,armA=0,angleB=-90,armB="+str(armB_length_in_pixel)+",rad=0")
150
166
  else:
151
- # adjuest horizontal direction
167
+ # if not changing the directions of some annotation arror arms
168
+ # adjust horizontal direction
152
169
  xy=(row["i"],row["scaled_P"])
153
170
  if anno_d[anno_count] in ["right","left","l","r"]:
154
171
  if anno_d[anno_count]=="right" or anno_d[anno_count]=="r":
@@ -170,7 +187,7 @@ def annotate_single(
170
187
  elif anno_d[anno_count]=="left" or anno_d[anno_count]=="l":
171
188
  arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
172
189
  connectionstyle="arc,angleA=-135,armA="+str( anno_d[anno_count][1])+",angleB=135,armB="+str( anno_d[anno_count][1])+",rad=0")
173
-
190
+ ################################################################################################################################
174
191
 
175
192
  if "r" in mode:
176
193
  arrowargs["color"] = "black"
@@ -179,16 +196,19 @@ def annotate_single(
179
196
  bbox_para[key]=value
180
197
  else:
181
198
  bbox_para=None
182
-
199
+
200
+ ################################################################################################################################
183
201
  if _invert==False:
184
- anno_default = {"rotation":40,"fontstyle":"italic","ha":"left","va":"bottom","fontsize":anno_fontsize,"fontweight":"normal","fontfamily":font_family}
202
+ anno_default = {"rotation":40, "fontstyle":"italic","ha":"left","va":"bottom","fontsize":anno_fontsize,"fontweight":"normal","fontfamily":font_family}
185
203
  else:
186
- anno_default = {"rotation":-40,"fontstyle":"italic","ha":"left","va":"top","fontsize":anno_fontsize,"fontweight":"normal","fontfamily":font_family}
204
+ anno_default = {"rotation":-40,"fontstyle":"italic","ha":"left","va":"top", "fontsize":anno_fontsize,"fontweight":"normal","fontfamily":font_family}
187
205
 
206
+ ################################################################################################################################
188
207
  if anno_style == "expand" :
189
208
  anno_default["rotation"] = 90
190
209
  if anno_style == "tight" :
191
210
  anno_default["rotation"] = 90
211
+ ################################################################################################################################
192
212
 
193
213
  for key,value in anno_args.items():
194
214
  anno_default[key]=value
@@ -196,12 +216,13 @@ def annotate_single(
196
216
  if row["i"] in highlight_i:
197
217
  for key,value in highlight_anno_args.items():
198
218
  anno_default[key]=value
199
-
219
+ ################################################################################################################################
200
220
  if anno_adjust==True:
201
221
  if _invert==False:
202
222
  arrowargs=dict(arrowstyle='-|>', color='grey', shrinkA=10, linewidth=0.1, relpos=(0,0.5))
203
223
  else:
204
224
  arrowargs=dict(arrowstyle='-|>', color='grey', shrinkA=10, linewidth=0.1, relpos=(1,0.5))
225
+ ################################################################################################################################
205
226
 
206
227
  anno_to_adjust = ax1.annotate(annotation_text,
207
228
  xy=xy,
@@ -213,6 +234,8 @@ def annotate_single(
213
234
  )
214
235
  anno_to_adjust_list.append(anno_to_adjust)
215
236
  anno_count +=1
237
+ ################################################################################################################################
238
+
216
239
  #anno_adjust_keyargs = {"arrowprops":dict(arrowstyle='->', color='grey', linewidth=0.1,relpos=(0.5,0.5))}
217
240
  if anno_adjust==True:
218
241
  log.write(" -Auto-adjusting text positions...", verbose=verbose)
@@ -354,15 +377,25 @@ def annotate_pair(
354
377
  arm_scale = arm_scale_d[anno_count]
355
378
 
356
379
  # vertical arm length in pixels
357
- armB_length_in_point = ax.transData.transform((skip,1.15*maxy_anno))[1]-ax.transData.transform((skip, row["scaled_P"]+1))[1]-arm_offset/2
358
- # times arm_scale to increase or reduce the length
359
- armB_length_in_point = armB_length_in_point*arm_scale
380
+ # Annotation y : 1.15 * maxy_anno
381
+ # Top dot: 1 * maxy_anno
382
+ # armB_length_in_point_raw = 0.15 * maxy_anno -> gap_pixel
383
+ # Fixed Offset: 0.5 * 0.15 * gap_pixel
384
+
385
+ #Calculate armB length in pixels
386
+ # arm_scale: raise up the ceiling
387
+ gap_pixel = (ax1.transData.transform((0,1.15*maxy_anno*arm_scale))[1]-ax1.transData.transform((0, maxy_anno*arm_scale))[1])*0.5
388
+
389
+ armB_length_in_pixel_raw = ax1.transData.transform((0,1.15*maxy_anno*arm_scale))[1]-ax1.transData.transform((0, row["scaled_P"]+1))[1]
390
+
391
+ armB_length_in_pixel = armB_length_in_pixel_raw - gap_pixel
360
392
 
361
393
  if arm_scale>=1:
362
- armB_length_in_point= armB_length_in_point if armB_length_in_point>0 else 0 #ax.transData.transform((skip, maxy_anno+2))[1]-ax.transData.transform((skip, row["scaled_P"]+1))[1]
394
+ armB_length_in_pixel= armB_length_in_pixel if armB_length_in_pixel>0 else 0
395
+
363
396
  if anno_fixed_arm_length is not None:
364
397
  anno_fixed_arm_length_factor = ax.transData.transform((skip,anno_fixed_arm_length))[1]-ax.transData.transform((skip,0))[1]
365
- armB_length_in_point = anno_fixed_arm_length_factor
398
+ armB_length_in_pixel = anno_fixed_arm_length_factor
366
399
 
367
400
  if anno==True:
368
401
  if row[snpid] in anno_alias.keys():
@@ -383,24 +416,24 @@ def annotate_pair(
383
416
  xytext=(last_pos,1.15*maxy_anno*arm_scale)
384
417
 
385
418
  if anno_fixed_arm_length is not None:
386
- armB_length_in_point = anno_fixed_arm_length
419
+ armB_length_in_pixel = anno_fixed_arm_length
387
420
  xytext=(row["i"],row["scaled_P"]+0.2+anno_fixed_arm_length)
388
421
 
389
422
  if anno_count not in anno_d.keys():
390
423
  if index==0:
391
424
  #upper panel
392
- if armB_length_in_point <5:
425
+ if armB_length_in_pixel <5:
393
426
  arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",connectionstyle="arc,armA=0,armB=0,rad=0.")
394
427
  else:
395
428
  arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
396
- connectionstyle="arc,angleA=0,armA=0,angleB=90,armB="+str(armB_length_in_point)+",rad=0")
429
+ connectionstyle="arc,angleA=0,armA=0,angleB=90,armB="+str(armB_length_in_pixel)+",rad=0")
397
430
  else:
398
431
  #lower panel
399
- if armB_length_in_point <5:
432
+ if armB_length_in_pixel <5:
400
433
  arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",connectionstyle="arc,armA=0,armB=0,rad=0.")
401
434
  else:
402
435
  arrowargs = dict(arrowstyle="-|>",relpos=(0,1),color="#ebebeb",
403
- connectionstyle="arc,angleA=0,armA=0,angleB=-90,armB="+str(armB_length_in_point)+",rad=0")
436
+ connectionstyle="arc,angleA=0,armA=0,angleB=-90,armB="+str(armB_length_in_pixel)+",rad=0")
404
437
 
405
438
  else:
406
439
  xy=(row["i"],row["scaled_P"])
@@ -478,204 +511,4 @@ def annotate_pair(
478
511
  )
479
512
  else:
480
513
  log.write(" -Skip annotating", verbose=verbose)
481
- return ax1,ax5
482
-
483
-
484
- # subtype plot
485
- def annotate_subtype(
486
- sumstats,
487
- anno,
488
- mode,
489
- ax1,
490
- highlight_i,
491
- to_annotate,
492
- anno_d,
493
- anno_alias,
494
- anno_style,
495
- anno_args,
496
- arm_scale,
497
- anno_max_iter,
498
- arm_scale_d,
499
- arm_offset,
500
- anno_adjust,
501
- anno_fixed_arm_length,
502
- maxy,
503
- anno_fontsize,
504
- region,
505
- region_anno_bbox_args,
506
- skip,
507
- snpid="SNPID",
508
- chrom="CHR",
509
- pos="POS",
510
- repel_force=0.02,
511
- verbose=True,
512
- log=Log()
513
- ):
514
- if anno and (to_annotate.empty is not True):
515
- #initiate a list for text and a starting position
516
- text = []
517
- last_pos=0
518
- anno_count=0
519
- to_annotate = to_annotate.sort_values(by=[chrom,pos])
520
- ## log : annotation column
521
- if anno==True:
522
- annotation_col="CHR:POS"
523
- elif anno:
524
- annotation_col=anno
525
- log.write(" -Annotating using column "+annotation_col+"...", verbose=verbose)
526
-
527
- ## calculate y span
528
- if region is not None:
529
- y_span = region[2] - region[1]
530
- else:
531
- y_span = sumstats["i"].max()-sumstats["i"].min()
532
-
533
- log.write(" -Adjusting text positions with repel_force={}...".format(repel_force), verbose=verbose)
534
- if anno_style == "expand" :
535
- to_annotate.loc[:, "ADJUSTED_i"] = adjust_text_position(to_annotate["i"].values.copy(), y_span, repel_force,max_iter=anno_max_iter,log=log,verbose=verbose)
536
- ## iterate through variants to be annotated
537
- anno_to_adjust_list = list()
538
-
539
- for rowi,row in to_annotate.iterrows():
540
-
541
- # avoid text overlapping
542
- ## adjust x to avoid overlapping################################################################
543
- if anno_style == "right" :
544
- #right style
545
- if row["i"]>last_pos+repel_force*y_span:
546
- last_pos=row["i"]
547
- else:
548
- last_pos+=repel_force*y_span
549
- elif anno_style == "expand" :
550
- #expand style
551
- last_pos = row["ADJUSTED_i"]
552
- anno_args["rotation"] = 90
553
- elif anno_style == "tight" :
554
- #tight style
555
- anno_fixed_arm_length = 1
556
- anno_adjust = True
557
- anno_args["rotation"] = 90
558
- else:
559
- pass
560
- ################################################################
561
- #shrink or increase the arm
562
- if arm_scale_d is not None:
563
- if anno_count not in arm_scale_d.keys():
564
- arm_scale =1
565
- else:
566
- arm_scale = arm_scale_d[anno_count]
567
- ################################################################
568
-
569
- # vertical arm length in pixels
570
- armB_length_in_point = ax1.transData.transform((skip,1.15*maxy))[1]-ax1.transData.transform((skip, row["scaled_P"]+1))[1]-arm_offset/2
571
- # scale if needed
572
- armB_length_in_point = armB_length_in_point*arm_scale
573
- ################################################################
574
- if arm_scale>=1:
575
- armB_length_in_point= armB_length_in_point if armB_length_in_point>0 else ax1.transData.transform((skip, maxy+2))[1]-ax1.transData.transform((skip, row["scaled_P"]+1))[1]
576
- ###if anno_fixed_arm_length #############################################################
577
- if anno_fixed_arm_length is not None:
578
- anno_fixed_arm_length_factor = ax1.transData.transform((skip,anno_fixed_arm_length))[1]-ax1.transData.transform((skip,0))[1]
579
- armB_length_in_point = anno_fixed_arm_length_factor
580
- ################################################################################################################################
581
- # annotation alias
582
- if anno==True:
583
- if row[snpid] in anno_alias.keys():
584
- annotation_text = anno_alias[row[snpid]]
585
- else:
586
- annotation_text="Chr"+ str(row[chrom]) +":"+ str(int(row[pos]))
587
- elif anno:
588
- annotation_text=row["Annotation"]
589
-
590
- #
591
- fontweight = "normal"
592
- if len(highlight_i) >0:
593
- if row["i"] in highlight_i:
594
- fontweight = "bold"
595
-
596
-
597
- xy=(row["i"],row["scaled_P"]+0.2)
598
- xytext=(last_pos, 1.15*maxy*arm_scale)
599
-
600
- if anno_fixed_arm_length is not None:
601
- armB_length_in_point = anno_fixed_arm_length
602
- xytext=(row["i"],row["scaled_P"]+0.2+anno_fixed_arm_length)
603
-
604
- if anno_count not in anno_d.keys():
605
- #arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
606
- # connectionstyle="arc,angleA=0,armA=0,angleB=90,armB="+str(armB_length_in_point)+",rad=0")
607
- arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
608
- connectionstyle="arc,angleA=0,armA=0,angleB=90,armB="+str(armB_length_in_point)+",rad=0")
609
- else:
610
- # adjuest direction
611
- xy=(row["i"],row["scaled_P"])
612
- if anno_d[anno_count] in ["right","left","l","r"]:
613
- if anno_d[anno_count]=="right" or anno_d[anno_count]=="r":
614
- armoffsetall = (ax1.transData.transform(xytext)[0]-ax1.transData.transform(xy)[0])*np.sqrt(2)
615
- armoffsetb = arm_offset
616
- armoffseta = armoffsetall - armoffsetb
617
- arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
618
- connectionstyle="arc,angleA=-135,armA="+str(armoffseta)+",angleB=45,armB="+str(armoffsetb)+",rad=0")
619
- elif anno_d[anno_count]=="left" or anno_d[anno_count]=="l":
620
- arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
621
- connectionstyle="arc,angleA=-135,armA="+str(arm_offset)+",angleB=135,armB="+str(arm_offset)+",rad=0")
622
- else:
623
- if anno_d[anno_count][0]=="right" or anno_d[anno_count][0]=="r":
624
- armoffsetall = (ax1.transData.transform(xytext)[0]-ax1.transData.transform(xy)[0])*np.sqrt(2)
625
- armoffsetb = anno_d[anno_count][1]
626
- armoffseta = armoffsetall - armoffsetb
627
- arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
628
- connectionstyle="arc,angleA=-135,armA="+str(armoffseta)+",angleB=45,armB="+str(armoffsetb)+",rad=0")
629
- elif anno_d[anno_count]=="left" or anno_d[anno_count]=="l":
630
- arrowargs = dict(arrowstyle="-|>",relpos=(0,0),color="#ebebeb",
631
- connectionstyle="arc,angleA=-135,armA="+str( anno_d[anno_count][1])+",angleB=135,armB="+str( anno_d[anno_count][1])+",rad=0")
632
-
633
-
634
- if "r" in mode:
635
- arrowargs["color"] = "black"
636
- bbox_para=dict(boxstyle="round", fc="white",zorder=3)
637
- for key,value in region_anno_bbox_args.items():
638
- bbox_para[key]=value
639
- else:
640
- bbox_para=None
641
-
642
- anno_default = {"rotation":40,"style":"italic","ha":"left","va":"bottom","fontsize":anno_fontsize,"fontweight":fontweight}
643
- for key,value in anno_args.items():
644
- anno_default[key]=value
645
-
646
- if anno_adjust==True:
647
- arrowargs=dict(arrowstyle='-|>', color='grey', shrinkA=10, linewidth=0.1, relpos=(0,0.5))
648
- anno_to_adjust = ax1.annotate(annotation_text,
649
- xy=xy,
650
- xytext=xytext,
651
- bbox=bbox_para,
652
- arrowprops=arrowargs,
653
- zorder=100,
654
- **anno_default
655
- )
656
- anno_to_adjust_list.append(anno_to_adjust)
657
- anno_count +=1
658
- #anno_adjust_keyargs = {"arrowprops":dict(arrowstyle='->', color='grey', linewidth=0.1,relpos=(0.5,0.5))}
659
- if anno_adjust==True:
660
- log.write(" -Auto-adjusting text positions...", verbose=verbose)
661
- adjust_text(texts = anno_to_adjust_list,
662
- autoalign=False,
663
- only_move={'points':'x', 'text':'x', 'objects':'x'},
664
- ax=ax1,
665
- precision=0.02,
666
- force_text=(repel_force,repel_force),
667
- expand_text=(1,1),
668
- expand_objects=(0,0),
669
- expand_points=(0,0),
670
- va="bottom",
671
- ha='left',
672
- avoid_points=False,
673
- lim =100
674
- #kwargs = anno_adjust_keyargs
675
- )
676
-
677
- else:
678
- log.write(" -Skip annotating", verbose=verbose)
679
-
680
- return ax1
681
-
514
+ return ax1,ax5
@@ -80,6 +80,7 @@ def _quick_fix_chr(seires, chr_dict,log=Log(), verbose=True):
80
80
  '''
81
81
  if pd.api.types.is_string_dtype(seires) == True:
82
82
  # if chr is string dtype: convert using chr_dict
83
+ seires = seires.astype("string")
83
84
  seires = seires.map(chr_dict, na_action="ignore")
84
85
  seires = np.floor(pd.to_numeric(seires, errors='coerce')).astype('Int64')
85
86
  return seires
@@ -93,6 +94,12 @@ def _quick_fix_pos(seires,log=Log(), verbose=True):
93
94
  return seires
94
95
 
95
96
 
97
+ def _dropna_in_cols(sumstats, cols, log=Log(), verbose=True):
98
+ to_drop = sumstats[cols].isna().any(axis=1)
99
+ log.write(" -Dropping {} variants due to missing values in {}.".format(sum(to_drop),cols))
100
+ return sumstats.loc[~to_drop,:]
101
+
102
+
96
103
  def _get_largenumber(*args,log=Log(), verbose=True):
97
104
  '''
98
105
  get a helper large number, >> max(pos)
@@ -330,7 +337,7 @@ def _cut(series, mode,cutfactor,cut,skip, ylabels, cut_log, verbose, lines_to_pl
330
337
  if "b" not in mode:
331
338
  log.write(" -Minus log10(P) values above " + str(cut)+" will be shrunk with a shrinkage factor of " + str(cutfactor)+"...", verbose=verbose)
332
339
  else:
333
- log.write(" -Minus DENSITY values above " + str(cut)+" will be shrunk with a shrinkage factor of " + str(cutfactor)+"...", verbose=verbose)
340
+ log.write(" -DENSITY values above " + str(cut)+" will be shrunk with a shrinkage factor of " + str(cutfactor)+"...", verbose=verbose)
334
341
 
335
342
  maxticker=int(np.round(series.max(skipna=True)))
336
343
 
@@ -448,4 +455,4 @@ def _jagged_y(cut,skip,ax1,mode,mqqratio,jagged_len,jagged_wid, log=Log(), verbo
448
455
  ax1.plot((x0,-dx), (tycut,tycut+dy), zorder=1001, **kwargs)
449
456
  ax1.plot((-dx,+dx), (tycut+dy,tycut+3*dy), zorder=1001, **kwargs)
450
457
  ax1.plot((+dx,x0), (tycut+3*dy,tycut+4*dy), zorder=1001, **kwargs)
451
- return ax1
458
+ return ax1
@@ -50,7 +50,8 @@ def get_default_path(keyword,fmt="png"):
50
50
  "ldscrg":"ldscrg_heatmap",
51
51
  "miami":"miami",
52
52
  "esc":"effect_size_comparision",
53
- "afc":"allele_frequency_comparision"
53
+ "afc":"allele_frequency_comparision",
54
+ "gwheatmap":"genome_wide_heatmap"
54
55
  }
55
56
  prefix = path_dictionary[keyword]
56
57
  count = 1
@@ -9,6 +9,7 @@ from matplotlib.patches import Rectangle
9
9
  from adjustText import adjust_text
10
10
  from gwaslab.viz_aux_save_figure import save_figure
11
11
  from gwaslab.util_in_get_sig import getsig
12
+ from gwaslab.util_in_get_sig import annogene
12
13
  from gwaslab.g_Log import Log
13
14
  from gwaslab.util_in_correct_winnerscurse import wc_correct
14
15
  from gwaslab.util_in_correct_winnerscurse import wc_correct_test
@@ -59,6 +60,7 @@ def compare_effect(path1,
59
60
  xylabel_prefix="Per-allele effect size in ",
60
61
  helper_line_args=None,
61
62
  fontargs=None,
63
+ build="19",
62
64
  r_or_r2="r",
63
65
  #
64
66
  errargs=None,
@@ -77,10 +79,9 @@ def compare_effect(path1,
77
79
  scaled2 = True
78
80
  if is_q_mc=="fdr" or is_q_mc=="bon":
79
81
  is_q = True
80
-
81
82
  if is_q == True:
82
83
  if is_q_mc not in [False,"fdr","bon","non"]:
83
- raise ValueError("Please select either fdr or bon or non for is_q_mc.")
84
+ raise ValueError('Please select either "fdr" or "bon" or "non"/False for is_q_mc.')
84
85
  if save_args is None:
85
86
  save_args = {"dpi":300,"facecolor":"white"}
86
87
  if reg_box is None:
@@ -89,6 +90,8 @@ def compare_effect(path1,
89
90
  sep = ["\t","\t"]
90
91
  if get_lead_args is None:
91
92
  get_lead_args = {}
93
+ if anno=="GENENAME":
94
+ get_lead_args["anno"]=True
92
95
  if errargs is None:
93
96
  errargs={"ecolor":"#cccccc","elinewidth":1}
94
97
  if fontargs is None:
@@ -191,10 +194,12 @@ def compare_effect(path1,
191
194
  ######### 8.1 if a snplist is provided, use the snp list
192
195
  log.write(" -Extract variants in the given list from "+label[0]+"...")
193
196
  sig_list_1 = sumstats.loc[sumstats["SNPID"].isin(snplist),:].copy()
197
+ if anno=="GENENAME":
198
+ sig_list_1 = annogene(sumstats,"SNPID","CHR","POS", build=build, verbose=verbose,**get_lead_args)
194
199
  else:
195
- ######### 8,2 otherwise use the sutomatically detected lead SNPs
200
+ ######### 8,2 otherwise use the automatically detected lead SNPs
196
201
  log.write(" -Extract lead variants from "+label[0]+"...")
197
- sig_list_1 = getsig(sumstats,"SNPID","CHR","POS","P", verbose=verbose,sig_level=sig_level,**get_lead_args)
202
+ sig_list_1 = getsig(sumstats,"SNPID","CHR","POS","P", build=build, verbose=verbose,sig_level=sig_level,**get_lead_args)
198
203
 
199
204
  if drop==True:
200
205
  sig_list_1 = drop_duplicate_and_na(sig_list_1, sort_by="P", log=log ,verbose=verbose)
@@ -235,10 +240,12 @@ def compare_effect(path1,
235
240
  ######### 12.1 if a snplist is provided, use the snp list
236
241
  log.write(" -Extract snps in the given list from "+label[1]+"...")
237
242
  sig_list_2 = sumstats.loc[sumstats["SNPID"].isin(snplist),:].copy()
243
+ if anno=="GENENAME":
244
+ sig_list_2 = annogene(sumstats,"SNPID","CHR","POS", build=build, verbose=verbose,**get_lead_args)
238
245
  else:
239
246
  log.write(" -Extract lead snps from "+label[1]+"...")
240
247
  ######### 12.2 otherwise use the sutomatically detected lead SNPs
241
- sig_list_2 = getsig(sumstats,"SNPID","CHR","POS","P",
248
+ sig_list_2 = getsig(sumstats,"SNPID","CHR","POS","P",build=build,
242
249
  verbose=verbose,sig_level=sig_level,**get_lead_args)
243
250
  if drop==True:
244
251
  sig_list_2 = drop_duplicate_and_na(sig_list_2, sort_by="P", log=log ,verbose=verbose)
@@ -248,6 +255,10 @@ def compare_effect(path1,
248
255
  log.write("Merging snps from "+label[0]+" and "+label[1]+"...")
249
256
 
250
257
  sig_list_merged = pd.merge(sig_list_1,sig_list_2,left_on="SNPID",right_on="SNPID",how="outer",suffixes=('_1', '_2'))
258
+ if anno == "GENENAME":
259
+ sig_list_merged.loc[sig_list_merged["SNPID"].isin((sig_list_1["SNPID"])),"GENENAME"] = sig_list_merged.loc[sig_list_merged["SNPID"].isin((sig_list_1["SNPID"])),"GENE_1"]
260
+ sig_list_merged.loc[~sig_list_merged["SNPID"].isin((sig_list_1["SNPID"])),"GENENAME"] = sig_list_merged.loc[~sig_list_merged["SNPID"].isin((sig_list_1["SNPID"])),"GENE_2"]
261
+ sig_list_merged = sig_list_merged.drop(columns=["GENE_1","GENE_2","LOCATION_1","LOCATION_2"])
251
262
  # SNPID P_1 P_2
252
263
  #0 rs117986209 0.142569 0.394455
253
264
  #1 rs6704312 0.652104 0.143750
@@ -533,7 +544,7 @@ def compare_effect(path1,
533
544
 
534
545
  ########################## Het test############################################################
535
546
  ## heterogeneity test
536
- if (is_q is True):
547
+ if (is_q == True):
537
548
  log.write(" -Calculating Cochran's Q statistics and peform chisq test...", verbose=verbose)
538
549
  if mode=="beta" or mode=="BETA" or mode=="Beta":
539
550
  sig_list_merged = test_q(sig_list_merged,"EFFECT_1","SE_1","EFFECT_2_aligned","SE_2",q_level=q_level,is_q_mc=is_q_mc, log=log, verbose=verbose)
@@ -552,7 +563,7 @@ def compare_effect(path1,
552
563
  log.write(" -Exclude "+str(len(sig_list_merged) -sum(both_eaf_clear))+ " variants with maf <",maf_level, verbose=verbose)
553
564
  sig_list_merged = sig_list_merged.loc[both_eaf_clear,:]
554
565
  # heterogeneity summary
555
- if (is_q is True):
566
+ if (is_q == True):
556
567
  log.write(" -Significant het:" ,len(sig_list_merged.loc[sig_list_merged["HetP"]<0.05,:]), verbose=verbose)
557
568
  log.write(" -All sig:" ,len(sig_list_merged), verbose=verbose)
558
569
  log.write(" -Het rate:" ,len(sig_list_merged.loc[sig_list_merged["HetP"]<0.05,:])/len(sig_list_merged), verbose=verbose)
@@ -633,11 +644,11 @@ def compare_effect(path1,
633
644
  ax.scatter(both["OR_1"],both["OR_2_aligned"],label=label[2],zorder=2,color="#205be6",edgecolors=both["Edge_color"],marker="s",**scatterargs)
634
645
  legend_elements.append(label[2])
635
646
  ## annotation #################################################################################################################
636
- if anno==True:
647
+ if anno==True or anno=="GENENAME":
637
648
  sig_list_toanno = sig_list_merged.dropna(axis=0)
638
649
  if is_q==True and anno_het == True:
639
650
  sig_list_toanno = sig_list_toanno.loc[sig_list_toanno["Edge_color"]=="black",:]
640
-
651
+
641
652
  if mode=="beta":
642
653
  sig_list_toanno = sig_list_toanno.loc[sig_list_toanno["EFFECT_1"].abs() >=anno_min1 ,:]
643
654
  sig_list_toanno = sig_list_toanno.loc[sig_list_toanno["EFFECT_2_aligned"].abs() >=anno_min2 ,:]
@@ -651,22 +662,38 @@ def compare_effect(path1,
651
662
 
652
663
  texts_l=[]
653
664
  texts_r=[]
665
+
666
+ if anno==True:
667
+ log.write("Annotating variants using {}".format("SNPID"), verbose=verbose)
668
+ elif anno=="GENENAME":
669
+ log.write("Annotating variants using {}".format("GENENAME"), verbose=verbose)
670
+
654
671
  for index, row in sig_list_toanno.iterrows():
672
+ log.write("Annotating {}...".format(row), verbose=verbose)
673
+ if anno==True:
674
+ to_anno_text = index
675
+ elif type(anno) is str:
676
+ if not pd.isna(row[anno]):
677
+ to_anno_text = row[anno]
678
+ else:
679
+ to_anno_text = index
680
+
655
681
  if mode=="beta" or mode=="BETA" or mode=="Beta":
656
682
  if row["EFFECT_1"] < row["EFFECT_2_aligned"]:
657
- texts_l.append(plt.text(row["EFFECT_1"], row["EFFECT_2_aligned"],index,ha="right",va="bottom"))
683
+ texts_l.append(plt.text(row["EFFECT_1"], row["EFFECT_2_aligned"],to_anno_text,ha="right",va="bottom"))
658
684
  else:
659
- texts_r.append(plt.text(row["EFFECT_1"], row["EFFECT_2_aligned"],index,ha="left",va="top"))
685
+ texts_r.append(plt.text(row["EFFECT_1"], row["EFFECT_2_aligned"],to_anno_text,ha="left",va="top"))
660
686
  else:
661
687
  if row["OR_1"] < row["OR_2_aligned"]:
662
- texts_l.append(plt.text(row["OR_1"], row["OR_2_aligned"],index, ha='right', va='bottom'))
688
+ texts_l.append(plt.text(row["OR_1"], row["OR_2_aligned"],to_anno_text, ha='right', va='bottom'))
663
689
  else:
664
- texts_r.append(plt.text(row["OR_1"], row["OR_2_aligned"],index, ha='left', va='top'))
665
-
666
- adjust_text(texts_l,autoalign =False,precision =0.001,lim=1000, ha="right",va="bottom", expand_text=(1,1.8) , expand_objects=(0.1,0.1), expand_points=(1.8,1.8) ,force_objects=(0.8,0.8) ,arrowprops=dict(arrowstyle='-|>', color='grey'),ax=ax)
667
- adjust_text(texts_r,autoalign =False,precision =0.001,lim=1000, ha="left",va="top", expand_text=(1,1.8) , expand_objects=(0.1,0.1), expand_points=(1.8,1.8) ,force_objects =(0.8,0.8),arrowprops=dict(arrowstyle='-|>', color='grey'),ax=ax)
668
-
690
+ texts_r.append(plt.text(row["OR_1"], row["OR_2_aligned"],to_anno_text, ha='left', va='top'))
691
+ if len(texts_l)>0:
692
+ adjust_text(texts_l,autoalign =False,precision =0.001,lim=1000, ha="right",va="bottom", expand_text=(1,1.8) , expand_objects=(0.1,0.1), expand_points=(1.8,1.8) ,force_objects=(0.8,0.8) ,arrowprops=dict(arrowstyle='-|>', color='grey'),ax=ax)
693
+ if len(texts_r)>0:
694
+ adjust_text(texts_r,autoalign =False,precision =0.001,lim=1000, ha="left",va="top", expand_text=(1,1.8) , expand_objects=(0.1,0.1), expand_points=(1.8,1.8) ,force_objects =(0.8,0.8),arrowprops=dict(arrowstyle='-|>', color='grey'),ax=ax)
669
695
  elif type(anno) is dict:
696
+ sig_list_toanno = sig_list_merged.dropna(axis=0)
670
697
  # if input is a dict
671
698
  sig_list_toanno = sig_list_toanno.loc[sig_list_toanno.index.isin(list(anno.keys())),:]
672
699
  if is_q==True and anno_het == True:
@@ -696,9 +723,10 @@ def compare_effect(path1,
696
723
  texts_l.append(plt.text(row["OR_1"], row["OR_2_aligned"],anno[index], ha='right', va='bottom'))
697
724
  else:
698
725
  texts_r.append(plt.text(row["OR_1"], row["OR_2_aligned"],anno[index], ha='left', va='top'))
699
-
700
- adjust_text(texts_l,autoalign =False,precision =0.001,lim=1000, ha="right",va="bottom", expand_text=(1,1.8) , expand_objects=(0.1,0.1), expand_points=(1.8,1.8) ,force_objects=(0.8,0.8) ,arrowprops=dict(arrowstyle='-|>', color='grey'),ax=ax)
701
- adjust_text(texts_r,autoalign =False,precision =0.001,lim=1000, ha="left",va="top", expand_text=(1,1.8) , expand_objects=(0.1,0.1), expand_points=(1.8,1.8) ,force_objects =(0.8,0.8),arrowprops=dict(arrowstyle='-|>', color='grey'),ax=ax)
726
+ if len(texts_l)>0:
727
+ adjust_text(texts_l,autoalign =False,precision =0.001,lim=1000, ha="right",va="bottom", expand_text=(1,1.8) , expand_objects=(0.1,0.1), expand_points=(1.8,1.8) ,force_objects=(0.8,0.8) ,arrowprops=dict(arrowstyle='-|>', color='grey'),ax=ax)
728
+ if len(texts_r)>0:
729
+ adjust_text(texts_r,autoalign =False,precision =0.001,lim=1000, ha="left",va="top", expand_text=(1,1.8) , expand_objects=(0.1,0.1), expand_points=(1.8,1.8) ,force_objects =(0.8,0.8),arrowprops=dict(arrowstyle='-|>', color='grey'),ax=ax)
702
730
  #################################################################################################################################
703
731
 
704
732
  # plot x=0,y=0, and a 45 degree line
@@ -139,7 +139,7 @@ def mqqplot(insumstats,
139
139
  anno_gtf_path=None,
140
140
  anno_adjust=False,
141
141
  anno_max_iter=100,
142
- arm_offset=50,
142
+ arm_offset=None,
143
143
  arm_scale=1,
144
144
  anno_height=1,
145
145
  arm_scale_d=None,
@@ -291,7 +291,7 @@ def mqqplot(insumstats,
291
291
  if maf_bin_colors is None:
292
292
  maf_bin_colors = ["#f0ad4e","#5cb85c", "#5bc0de","#000042"]
293
293
  if save_args is None:
294
- save_args = {"dpi":300,"facecolor":"white"}
294
+ save_args = {"dpi":400,"facecolor":"white"}
295
295
  if highlight is None:
296
296
  highlight = list()
297
297
  if highlight_anno_args is None:
@@ -329,6 +329,20 @@ def mqqplot(insumstats,
329
329
  fig_args["dpi"]=72
330
330
  scatter_args["rasterized"]=True
331
331
  qq_scatter_args["rasterized"]=True
332
+ else:
333
+ fig_args["dpi"] = save_args["dpi"]
334
+
335
+ # configure dpi if saving the plot
336
+ fig_args, scatter_args, qq_scatter_args, save_args = _configure_fig_save_kwargs(save = save,
337
+ fig_args = fig_args,
338
+ scatter_args = scatter_args,
339
+ qq_scatter_args = qq_scatter_args,
340
+ save_args = save_args)
341
+
342
+
343
+ if len(anno_d) > 0 and arm_offset is None:
344
+ # in pixels
345
+ arm_offset = fig_args["dpi"] * repel_force * fig_args["figsize"][0]*0.5
332
346
 
333
347
  log.write("Start to create MQQ plot...{}:".format(_get_version()),verbose=verbose)
334
348
  log.write(" -Genomic coordinates version: {}...".format(build),verbose=verbose)
@@ -401,7 +415,7 @@ def mqqplot(insumstats,
401
415
  if mode=="b":
402
416
  sig_level=1,
403
417
  sig_line=False,
404
- windowsizekb = 100000000
418
+ #windowsizekb = 100000000
405
419
  mode="mb"
406
420
  scatter_args={"marker":"s"}
407
421
  marker_size= (marker_size[1],marker_size[1])
@@ -522,8 +536,12 @@ def mqqplot(insumstats,
522
536
  pos=pos,
523
537
  verbose=verbose,
524
538
  log=log)
539
+
540
+ lines_to_plot = pd.Series(lines_to_plot.to_list() + [bmean, bmedian])
541
+
525
542
  else:
526
543
  bmean, bmedian=0,0
544
+
527
545
  # P value conversion #####################################################################################################
528
546
 
529
547
  # add raw_P and scaled_P
@@ -956,7 +974,7 @@ def mqqplot(insumstats,
956
974
  ax1.set_title(mtitle,fontsize=title_fontsize,family=font_family)
957
975
  log.write("Finished processing figure arts.",verbose=verbose)
958
976
 
959
- # Add annotation arrows and texts
977
+ ## Add annotation arrows and texts
960
978
  log.write("Start to annotate variants...",verbose=verbose)
961
979
  ax1 = annotate_single(
962
980
  sumstats=sumstats,
@@ -1055,7 +1073,8 @@ def mqqplot(insumstats,
1055
1073
  fig.suptitle(title , fontsize = title_fontsize ,x=0.5, y=1.05)
1056
1074
  else:
1057
1075
  fig.suptitle(title , fontsize = title_fontsize, x=0.5,y=1)
1058
-
1076
+ ## Add annotation arrows and texts
1077
+
1059
1078
  # Saving figure
1060
1079
  save_figure(fig = fig, save = save, keyword=mode, save_args=save_args, log = log, verbose=verbose)
1061
1080
 
@@ -1069,7 +1088,31 @@ def mqqplot(insumstats,
1069
1088
 
1070
1089
  ##############################################################################################################################################################################
1071
1090
 
1091
+ def _configure_fig_save_kwargs(save=None,
1092
+ fig_args=None,
1093
+ scatter_args=None,
1094
+ qq_scatter_args=None,
1095
+ save_args=None):
1096
+ if fig_args is None:
1097
+ fig_args = dict()
1098
+ if scatter_args is None:
1099
+ scatter_args = dict()
1100
+ if qq_scatter_args is None:
1101
+ qq_scatter_args = dict()
1102
+ if save_args is None:
1103
+ save_args = dict()
1072
1104
 
1105
+ if save is not None:
1106
+ if type(save) is not bool:
1107
+ if len(save)>3:
1108
+ if save[-3:]=="pdf" or save[-3:]=="svg":
1109
+ # to save as vectorized plot
1110
+ fig_args["dpi"]=72
1111
+ scatter_args["rasterized"]=True
1112
+ qq_scatter_args["rasterized"]=True
1113
+ else:
1114
+ fig_args["dpi"] = save_args["dpi"]
1115
+ return fig_args, scatter_args, qq_scatter_args, save_args
1073
1116
 
1074
1117
 
1075
1118
  def _add_pad_to_x_axis(ax1, xpad, xpadl, xpadr, sumstats, pos, chrpad, xtight, log, verbose):
@@ -1104,12 +1147,6 @@ def _add_pad_to_x_axis(ax1, xpad, xpadl, xpadr, sumstats, pos, chrpad, xtight, l
1104
1147
  return ax1
1105
1148
 
1106
1149
 
1107
-
1108
-
1109
-
1110
-
1111
-
1112
-
1113
1150
  ##############################################################################################################################################################################
1114
1151
  def _configure_cols_to_use(insumstats, snpid, chrom, pos, ea, nea, eaf, p, mlog10p,scaled, mode,stratified,anno, anno_set, anno_alias,_chrom_df_for_i,highlight ,pinpoint,density_color):
1115
1152
  usecols=[]
@@ -1287,9 +1324,10 @@ def _process_density(sumstats, mode, bwindowsizekb, chrom, pos, verbose, log):
1287
1324
  else:
1288
1325
  break
1289
1326
  df = pd.DataFrame(stack,columns=["SNPID","TCHR+POS","DENSITY"])
1290
- sumstats["DENSITY"] = df["DENSITY"].values
1291
- bmean=sumstats["DENSITY"].mean()
1292
- bmedian=sumstats["DENSITY"].median()
1327
+ sumstats["DENSITY"] = df["DENSITY"].astype("Float64").values
1328
+
1329
+ bmean=sumstats.drop_duplicates(subset="SNPID")["DENSITY"].mean()
1330
+ bmedian=sumstats.drop_duplicates(subset="SNPID")["DENSITY"].median()
1293
1331
  elif "b" in mode and "DENSITY" in sumstats.columns:
1294
1332
  bmean=sumstats["DENSITY"].mean()
1295
1333
  bmedian=sumstats["DENSITY"].median()
@@ -1305,6 +1343,7 @@ def _process_line(ax1, sig_line, suggestive_sig_line, additional_line, lines_to_
1305
1343
  linestyle="--",
1306
1344
  color=sig_line_color,
1307
1345
  zorder=1)
1346
+
1308
1347
  if suggestive_sig_line is True:
1309
1348
  suggestive_sig_line = ax1.axhline(y=lines_to_plot[1],
1310
1349
  linewidth = sc_linewidth,
@@ -1312,15 +1351,20 @@ def _process_line(ax1, sig_line, suggestive_sig_line, additional_line, lines_to_
1312
1351
  color=suggestive_sig_line_color,
1313
1352
  zorder=1)
1314
1353
  if additional_line is not None:
1315
- for index, level in enumerate(lines_to_plot[2:].values):
1354
+ for index, level in enumerate(lines_to_plot[2:2+len(additional_line)].values):
1316
1355
  ax1.axhline(y=level,
1317
1356
  linewidth = sc_linewidth,
1318
1357
  linestyle="--",
1319
1358
  color=additional_line_color[index%len(additional_line_color)],
1320
1359
  zorder=1)
1321
- if "b" in mode:
1360
+ if "b" in mode:
1361
+ bmean = lines_to_plot.iat[-2]
1362
+ bmedian = lines_to_plot.iat[-1]
1322
1363
  # for brisbane plot, add median and mean line
1364
+ log.write(" -Plotting horizontal line ( mean DENISTY): y = {}".format(bmean),verbose=verbose)
1323
1365
  meanline = ax1.axhline(y=bmean, linewidth = sc_linewidth,linestyle="-",color=sig_line_color,zorder=1000)
1366
+
1367
+ log.write(" -Plotting horizontal line ( median DENISTY): y = {}".format(bmedian),verbose=verbose)
1324
1368
  medianline = ax1.axhline(y=bmedian, linewidth = sc_linewidth,linestyle="--",color=sig_line_color,zorder=1000)
1325
1369
  return ax1
1326
1370
 
@@ -1441,10 +1485,16 @@ def _process_layout(mode, figax, fig_args, mqqratio, region_hspace):
1441
1485
  ax2 = None
1442
1486
  plt.subplots_adjust(hspace=region_hspace)
1443
1487
  elif mode =="b" :
1444
- fig_args["figsize"] = (15,5)
1445
- fig, ax1 = plt.subplots(1, 1,**fig_args)
1446
- ax2 = None
1447
- ax3 = None
1488
+ if figax is not None:
1489
+ fig = figax[0]
1490
+ ax1 = figax[1]
1491
+ ax3 = None
1492
+ ax2 = None
1493
+ else:
1494
+ fig_args["figsize"] = (15,5)
1495
+ fig, ax1 = plt.subplots(1, 1,**fig_args)
1496
+ ax2 = None
1497
+ ax3 = None
1448
1498
  else:
1449
1499
  raise ValueError("Please select one from the 5 modes: mqq/qqm/m/qq/r/b")
1450
1500
  ax4=None
@@ -0,0 +1,260 @@
1
+ import pandas as pd
2
+ import matplotlib.pyplot as plt
3
+ import seaborn as sns
4
+ import numpy as np
5
+ import scipy as sp
6
+ from gwaslab.viz_aux_quickfix import _quick_assign_i_with_rank
7
+ from gwaslab.viz_aux_quickfix import _get_largenumber
8
+ from gwaslab.viz_aux_quickfix import _quick_fix_p_value
9
+ from gwaslab.viz_aux_quickfix import _quick_fix_pos
10
+ from gwaslab.viz_aux_quickfix import _quick_fix_chr
11
+ from gwaslab.viz_aux_quickfix import _quick_fix_eaf
12
+ from gwaslab.viz_aux_quickfix import _quick_fix_mlog10p
13
+ from gwaslab.viz_aux_quickfix import _dropna_in_cols
14
+ from gwaslab.viz_plot_mqqplot import _process_p_value
15
+ from gwaslab.viz_plot_mqqplot import _configure_fig_save_kwargs
16
+ from gwaslab.viz_plot_mqqplot import mqqplot
17
+ from gwaslab.viz_aux_save_figure import save_figure
18
+ from gwaslab.g_Log import Log
19
+ import copy
20
+ from gwaslab.bd_common_data import get_chr_to_number
21
+ from gwaslab.bd_common_data import get_number_to_chr
22
+ from gwaslab.g_version import _get_version
23
+
24
+ def _gwheatmap(
25
+ insumstats,
26
+ chrom="CHR",
27
+ pos="POS",
28
+ ref_chrom="REF_CHR",
29
+ ref_pos="REF_START",
30
+ p="P",
31
+ scaled=False,
32
+ sizes = (10,50),
33
+ alpha=0.5,
34
+ mlog10p="MLOG10P",
35
+ snpid="SNPID",
36
+ eaf=None,
37
+ group="CIS/TRANS",
38
+ ea="EA",
39
+ nea="NEA",
40
+ colors=None,
41
+ check = True,
42
+ chr_dict = None,
43
+ xchrpad = 0,
44
+ ychrpad=0,
45
+ use_rank = False,
46
+ xtick_chr_dict=None,
47
+ ytick_chr_dict=None,
48
+ fontsize=10,
49
+ add_b =False,
50
+ log=Log(),
51
+ fig_kwargs=None,
52
+ scatter_kwargs=None,
53
+ height_ratios=None,
54
+ hspace = 0.1,
55
+ font_family="Arial",
56
+ cis_windowsizekb=100,
57
+ verbose=True,
58
+ save=True,
59
+ save_kwargs=None,
60
+ grid_linewidth=1,
61
+ grid_linecolor="grey",
62
+ **mqq_kwargs
63
+ ):
64
+ log.write("Start to create genome-wide scatter plot...{}:".format(_get_version()),verbose=verbose)
65
+ if height_ratios is None:
66
+ height_ratios = [1, 2]
67
+ if xtick_chr_dict is None:
68
+ xtick_chr_dict = get_number_to_chr()
69
+ if ytick_chr_dict is None:
70
+ ytick_chr_dict = get_number_to_chr()
71
+ if chr_dict is None:
72
+ chr_dict = get_chr_to_number()
73
+ if colors is None:
74
+ colors=["#CB132D","#597FBD"]
75
+ if fig_kwargs is None:
76
+ fig_kwargs= dict(figsize=(15,15))
77
+ if save_kwargs is None:
78
+ save_kwargs = {"dpi":300,"facecolor":"white"}
79
+ if scatter_kwargs is None:
80
+ scatter_kwargs = {}
81
+
82
+ fig_kwargs, scatter_kwargs, qq_scatter_args, save_kwargs = _configure_fig_save_kwargs(save=save,
83
+ fig_args = fig_kwargs,
84
+ scatter_args = scatter_kwargs,
85
+ qq_scatter_args = dict(),
86
+ save_args = save_kwargs)
87
+
88
+ sumstats = insumstats.copy()
89
+
90
+ # Data QC and format
91
+ if check ==True:
92
+ sumstats[pos] = _quick_fix_pos(sumstats[pos])
93
+ sumstats[chrom] = _quick_fix_chr(sumstats[chrom], chr_dict=chr_dict)
94
+ sumstats[ref_pos] = _quick_fix_pos(sumstats[ref_pos])
95
+ sumstats[ref_chrom] = _quick_fix_chr(sumstats[ref_chrom], chr_dict=chr_dict)
96
+ sumstats = _dropna_in_cols(sumstats, [pos, chrom, ref_pos, ref_chrom], log=log, verbose=verbose)
97
+
98
+ # dropna
99
+ sumstats = sumstats.sort_values(by=group)
100
+
101
+ if scaled is True:
102
+ sumstats["raw_P"] = pd.to_numeric(sumstats[mlog10p], errors='coerce')
103
+ else:
104
+ sumstats["raw_P"] = sumstats[p].astype("float64")
105
+
106
+ sumstats = _process_p_value(sumstats=sumstats,
107
+ mode="m",
108
+ p=p,
109
+ mlog10p=mlog10p,
110
+ scaled=scaled,
111
+ log=log,
112
+ verbose=verbose )
113
+
114
+
115
+
116
+ if add_b ==False:
117
+ fig, ax1 = plt.subplots(**fig_kwargs)
118
+ else:
119
+ fig, (ax2, ax1) = plt.subplots( nrows=2 ,sharex=True, gridspec_kw={'height_ratios': height_ratios }, **fig_kwargs)
120
+ plt.subplots_adjust(hspace=hspace)
121
+
122
+ ## assign i for variants
123
+ sumstats, chrom_df_x = _quick_assign_i_with_rank(sumstats,
124
+ chrpad=xchrpad,
125
+ use_rank=use_rank,
126
+ chrom=chrom,
127
+ pos=pos,
128
+ verbose=verbose)
129
+ chrom_df_b = chrom_df_x
130
+ sumstats = sumstats.rename(columns={"i":"i_x"})
131
+ add_x_unique = list(sumstats["_ADD"].unique())
132
+
133
+ ## determine grouping methods for Y
134
+ ## assign i for Y group
135
+ sumstats, chrom_df_y = _quick_assign_i_with_rank(sumstats,
136
+ chrpad=ychrpad,
137
+ use_rank=use_rank,
138
+ chrom=ref_chrom,
139
+ pos=ref_pos,
140
+ verbose=verbose)
141
+
142
+ sumstats = sumstats.rename(columns={"i":"i_y"})
143
+ add_y_unique = list(sumstats["_ADD"].unique())
144
+
145
+ if add_b == True:
146
+ sumstats["i"] = sumstats["i_x"]
147
+ fig,log = mqqplot(sumstats,
148
+ chrom=chrom,
149
+ pos=pos,
150
+ p=p,
151
+ mlog10p=mlog10p,
152
+ snpid=snpid,
153
+ scaled=scaled,
154
+ log=log,
155
+ mode="b",
156
+ figax=(fig,ax2),
157
+ _chrom_df_for_i = chrom_df_b,
158
+ _invert=False,
159
+ _if_quick_qc=False,
160
+ **mqq_kwargs
161
+ )
162
+ ##
163
+ #min_xy = min(min(sumstats["i_x"]),min(sumstats["i_y"]))
164
+ #max_xy = max(max(sumstats["i_x"]),max(sumstats["i_y"]))
165
+
166
+ ## determine color
167
+
168
+ ## determine dot size
169
+
170
+ ## plot
171
+ legend = True
172
+ style=None
173
+ linewidth=0
174
+ edgecolor="black"
175
+
176
+ palette = sns.color_palette(colors,n_colors=sumstats[group].nunique())
177
+
178
+ #for index,g in enumerate(sumstats[group].unique()):
179
+ #
180
+ # palette = sns.color_palette("dark:{}".format(colors[index]), as_cmap=True)
181
+ #
182
+ # plot = sns.scatterplot(data=sumstats.loc[sumstats[group]==g,:], x='i_x', y='i_y',
183
+ # hue="scaled_P",
184
+ # palette=palette,
185
+ # size="scaled_P",
186
+ # alpha=alpha,
187
+ # sizes=sizes,
188
+ # legend=legend,
189
+ # style=style,
190
+ # linewidth=linewidth,
191
+ # edgecolor = edgecolor,
192
+ # zorder=2,
193
+ # ax=ax1)
194
+
195
+ plot = sns.scatterplot(data=sumstats, x='i_x', y='i_y',
196
+ hue=group,
197
+ palette=palette,
198
+ size="scaled_P",
199
+ alpha=alpha,
200
+ sizes=sizes,
201
+ legend=legend,
202
+ style=style,
203
+ linewidth=linewidth,
204
+ edgecolor = edgecolor,
205
+ zorder=2,
206
+ ax=ax1)
207
+
208
+ handles, labels = ax1.get_legend_handles_labels()
209
+ new_labels = []
210
+ ncol = len(labels)
211
+ for i in labels:
212
+ if i==group:
213
+ new_labels.append("Group")
214
+ elif i=="scaled_P":
215
+ new_labels.append("$-log_{10}(P)$")
216
+ else:
217
+ new_labels.append(i)
218
+
219
+ ax1.legend(labels = new_labels, handles=handles, loc="lower center", bbox_to_anchor=(.45, -0.17),
220
+ ncol=ncol, scatterpoints=2, title=None, frameon=False)
221
+
222
+ ## add vertical line
223
+ for i in add_x_unique:
224
+ ax1.axvline(x = i+0.5, linewidth = grid_linewidth,color=grid_linecolor,zorder=1000 )
225
+ for i in add_y_unique:
226
+ ax1.axhline(y = i+0.5, linewidth = grid_linewidth,color=grid_linecolor,zorder=1000 )
227
+
228
+
229
+ ## add X tick label
230
+ ax1 = _process_xtick(ax1, chrom_df_x, xtick_chr_dict, fontsize, font_family, log=log,verbose=True)
231
+ ## add Y tick label
232
+ ax1 = _process_ytick(ax1, chrom_df_y, ytick_chr_dict, fontsize, font_family, log=log,verbose=True)
233
+
234
+ ## set x y lim
235
+ ax1.set_ylim([0.5,sumstats["i_y"].max()+1])
236
+ ax1.set_xlim([0.5,sumstats["i_x"].max()+1])
237
+
238
+ ## set x y label
239
+
240
+ xlabel = "pQTL position"
241
+ ax1.set_xlabel(xlabel,fontsize=fontsize,family=font_family)
242
+ ylabel = "location of the gene encoding the target protein"
243
+ ax1.set_ylabel(ylabel,fontsize=fontsize,family=font_family)
244
+
245
+ save_figure(fig = fig, save = save, keyword="gwheatmap", save_args=save_kwargs, log = log, verbose=verbose)
246
+
247
+ return fig, log
248
+
249
+ ################################################################################################################
250
+ def _process_xtick(ax1, chrom_df, xtick_chr_dict, fontsize, font_family, log=Log(),verbose=True):
251
+ log.write(" -Processing X ticks...",verbose=verbose)
252
+ ax1.set_xticks(chrom_df.astype("float64"))
253
+ ax1.set_xticklabels(chrom_df.index.astype("Int64").map(xtick_chr_dict),fontsize=fontsize,family=font_family)
254
+ return ax1
255
+
256
+ def _process_ytick(ax1, chrom_df, ytick_chr_dict, fontsize, font_family, log=Log(),verbose=True):
257
+ log.write(" -Processing Y ticks...",verbose=verbose)
258
+ ax1.set_yticks(chrom_df.astype("float64"))
259
+ ax1.set_yticklabels(chrom_df.index.astype("Int64").map(ytick_chr_dict),fontsize=fontsize,family=font_family)
260
+ return ax1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gwaslab
3
- Version: 3.4.49
3
+ Version: 3.5.0
4
4
  Summary: A collection of handy tools for GWAS SumStats
5
5
  Author-email: Yunye <yunye@gwaslab.com>
6
6
  Project-URL: Homepage, https://cloufield.github.io/gwaslab/
@@ -6,13 +6,13 @@ gwaslab/bd_get_hapmap3.py,sha256=asNjQYeGfQi8u3jnfenRvDdKMs5ptql5wpcUzqMlwUI,393
6
6
  gwaslab/cache_manager.py,sha256=HOTnSkCOyGEPLRl90WT8D_6pAdI8d8AzenMIDGuCeWc,28113
7
7
  gwaslab/g_Log.py,sha256=C3Zv-_6c3C9ms8bgQ-ytplz22sjk7euqXYkWr9zNeAs,1573
8
8
  gwaslab/g_Phenotypes.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- gwaslab/g_Sumstats.py,sha256=qWBh14-XheS88KLm2vr0OKRAhU9VmbUvy90T4L52zAo,36265
9
+ gwaslab/g_Sumstats.py,sha256=6bzc7Sf23fIZRP85h-hQJC8DsBl3YLZNBUKJaOboHJQ,36639
10
10
  gwaslab/g_SumstatsPair.py,sha256=20snPb4SlI6ftMGVjgxAuyxsxYRQF-GzzlBSnoB-3Lo,8851
11
11
  gwaslab/g_SumstatsT.py,sha256=u_DighLMnMxwTLnqm-B58pA0G6WXRj6pudPyKMVKjSU,2133
12
12
  gwaslab/g_Sumstats_summary.py,sha256=FECvvFXJVKaCX5dggBvvk9YvJ6AbdbcLfjltysX7wEE,6380
13
13
  gwaslab/g_meta.py,sha256=htWlgURWclm9R6UqFcX1a93WN27xny7lGUeyJZOtszQ,2583
14
14
  gwaslab/g_vchange_status.py,sha256=w3zsYYOcCaI3PTeboonvkQjudzUAfVIgATzRdiPViZs,1939
15
- gwaslab/g_version.py,sha256=dhN-3rbJKALlFhTZACsxBZL_U8j4PQmcVuCuWx9dapo,1886
15
+ gwaslab/g_version.py,sha256=ll9kIVGycz_99ofwzsFd_semBDePvcEjIqqCgWdVa_8,1885
16
16
  gwaslab/hm_casting.py,sha256=FqP4EQl83Q2OKLw004OgLIvUH795TVCGwziLk5jsHqY,11368
17
17
  gwaslab/hm_harmonize_sumstats.py,sha256=_sZ8soikAxDokw-dcr_CLguBB8OmTmPPS04MfmsJc_Q,79509
18
18
  gwaslab/hm_rsid_to_chrpos.py,sha256=ODWREO0jPN0RAfNzL5fRzSRANfhiksOvUVPuEsFZQqA,6552
@@ -50,20 +50,21 @@ gwaslab/util_in_correct_winnerscurse.py,sha256=Gp--yAQ8MMzdkWIvXP9C1BHVjZc-YzqHf
50
50
  gwaslab/util_in_fill_data.py,sha256=iVq5WLWwFI03v9HyvBanu5si3j2p-oyPFTl8jsX69xM,14693
51
51
  gwaslab/util_in_filter_value.py,sha256=dY4X66N9A4MHCRHjPqLYFufMM91ggLRwUBf_nJYh8Lg,23605
52
52
  gwaslab/util_in_get_density.py,sha256=kpKXH69acMkeYVG5vs-VbJC3COhmuLBfYco-wuOxgjc,3934
53
- gwaslab/util_in_get_sig.py,sha256=9kq1GXacknO2YnVmsTli1GlPA728ASweTZ3UKm3Wszo,38783
53
+ gwaslab/util_in_get_sig.py,sha256=53NOh7KueLY3vJPTNhhb37KPAIgLEfcP3k2zIV61lc4,39845
54
54
  gwaslab/util_in_meta.py,sha256=5K9lIZcIgUy0AERqHy1GvMN2X6dp45JUUgopuDLgt4o,11284
55
55
  gwaslab/util_in_snphwe.py,sha256=-KpIDx6vn_nah6H55IkV2OyjXQVXV13XyBL069WE1wM,1751
56
- gwaslab/viz_aux_annotate_plot.py,sha256=UTOx-OpFsM_UVphBHxqQZwCFI8bjwwB6CMsgFbAfheQ,32215
56
+ gwaslab/viz_aux_annotate_plot.py,sha256=i-Fvg_4H6LZvENM6F_yH9-sVSxjD_9LwVhlvgHusW6w,25006
57
57
  gwaslab/viz_aux_chromatin.py,sha256=7cGmej5EkKO7fxR1b5w8r1oRRl9ofVzFRG52SCYWtz0,4109
58
- gwaslab/viz_aux_quickfix.py,sha256=5XM-J9D2yp5FVbK6YQKEhSCqAYBLNWSQms9WjpXxVn8,18313
58
+ gwaslab/viz_aux_quickfix.py,sha256=HnhVvY0GP0EN0gLJ-B11OYiE5PWDcdKGUpQ3QZeu0lE,18592
59
59
  gwaslab/viz_aux_reposition_text.py,sha256=iRIP-Rkltlei068HekJcVubiqPrunBqvAoSQ1eHk04M,4304
60
- gwaslab/viz_aux_save_figure.py,sha256=nL-aoE8Kg06h7FgleGRBIZjhI-6w5gpn3E1HWMwBig8,2664
60
+ gwaslab/viz_aux_save_figure.py,sha256=GdUXNBOelsWqtTXm8pEZzeGGwDxHYnBkyrGwLOK16ew,2723
61
61
  gwaslab/viz_plot_compare_af.py,sha256=qtXW45-Sq_ugK8ZfqBYMpmf58SKi3lB3YyHnzn_akcE,5344
62
- gwaslab/viz_plot_compare_effect.py,sha256=lV-4KSQatTSsYqzEGGTkBu17I2VlVyVh1uJr-kCq630,49585
62
+ gwaslab/viz_plot_compare_effect.py,sha256=60KlfRGj1TSc0-NCaInZ7GMiAUveXe4qDCjIW-RHJNE,51304
63
63
  gwaslab/viz_plot_forestplot.py,sha256=xgOnefh737CgdQxu5naVyRNBX1NQXPFKzf51fbh6afs,6771
64
64
  gwaslab/viz_plot_miamiplot.py,sha256=rCFEp7VNuVqeBBG3WRkmFAtFklbF79BvIQQYiSY70VY,31238
65
65
  gwaslab/viz_plot_miamiplot2.py,sha256=xiFCgFX8hEySmCJORpEurMVER9eEXQyy_Ik7mLkbi9g,16015
66
- gwaslab/viz_plot_mqqplot.py,sha256=q_c_ZDRdirEcdHHnb030h7dTUWAFy9OVuzwbdCzZ3gU,64580
66
+ gwaslab/viz_plot_mqqplot.py,sha256=nIwS3fMAXv_LVn7l9koSFZiZbcKCyuVq6Qg5fMzrEps,67049
67
+ gwaslab/viz_plot_phe_heatmap.py,sha256=vCCPAiTyBBVklZahXG_zmyxXPgm0d7ArVha7A6gJaok,9514
67
68
  gwaslab/viz_plot_qqplot.py,sha256=psQgVpP29686CEZkzQz0iRbApzqy7aE3GGiBcazVvNw,7247
68
69
  gwaslab/viz_plot_regional2.py,sha256=tBoGox-4ngL5o_twdIjk_VW6Iam3JDyrPKuttm6_4Sg,36862
69
70
  gwaslab/viz_plot_regionalplot.py,sha256=8u-5-yfy-UaXhaxVVz3Y5k2kBAoqzczUw1hyyD450iI,37983
@@ -78,9 +79,9 @@ gwaslab/data/hapmap3_SNPs/hapmap3_db150_hg19.snplist.gz,sha256=qD9RsC5S2h6l-OdpW
78
79
  gwaslab/data/hapmap3_SNPs/hapmap3_db151_hg38.snplist.gz,sha256=Y8ZT2FIAhbhlgCJdE9qQVAiwnV_fcsPt72usBa7RSBM,10225828
79
80
  gwaslab/data/high_ld/high_ld_hla_hg19.bed.gz,sha256=R7IkssKu0L4WwkU9SrS84xCMdrkkKL0gnTNO_OKbG0Y,219
80
81
  gwaslab/data/high_ld/high_ld_hla_hg38.bed.gz,sha256=76CIU0pibDJ72Y6UY-TbIKE9gEPwTELAaIbCXyjm80Q,470
81
- gwaslab-3.4.49.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
82
- gwaslab-3.4.49.dist-info/LICENSE_before_v3.4.39,sha256=GhLOU_1UDEKeOacYhsRN_m9u-eIuVTazSndZPeNcTZA,1066
83
- gwaslab-3.4.49.dist-info/METADATA,sha256=bA0qeWgxt5mOkt_aL4aW_v4csyNSJCsbY6wrKMLyqY8,7752
84
- gwaslab-3.4.49.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
85
- gwaslab-3.4.49.dist-info/top_level.txt,sha256=PyY6hWtrALpv2MAN3kjkIAzJNmmBTH5a2risz9KwH08,8
86
- gwaslab-3.4.49.dist-info/RECORD,,
82
+ gwaslab-3.5.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
83
+ gwaslab-3.5.0.dist-info/LICENSE_before_v3.4.39,sha256=GhLOU_1UDEKeOacYhsRN_m9u-eIuVTazSndZPeNcTZA,1066
84
+ gwaslab-3.5.0.dist-info/METADATA,sha256=SocHVFBOrjeEchxsvVLUgI4CZPwSypppxfSE7o7yp1I,7751
85
+ gwaslab-3.5.0.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
86
+ gwaslab-3.5.0.dist-info/top_level.txt,sha256=PyY6hWtrALpv2MAN3kjkIAzJNmmBTH5a2risz9KwH08,8
87
+ gwaslab-3.5.0.dist-info/RECORD,,