@@ -15,7 +15,7 @@ def volcano(
1515 y : str ,
1616 net : pd .DataFrame | None = None ,
1717 name : str | None = None ,
18- top : int = 5 ,
18+ top : int | str | list [ str ] = 5 ,
1919 thr_stat : float = 0.5 ,
2020 thr_sign : float = 0.05 ,
2121 max_stat : float | None = None ,
@@ -40,7 +40,8 @@ def volcano(
4040 name
4141 Name of the source to subset ``net``.
4242 top
43- Number of top differentially abundant features to show.
43+ Number of top differentially abundant features to show. Can also be a gene name
44+ (``str``) or a list of gene names (``list[str]``) to annotate specific features.
4445 thr_stat
4546 Significance threshold for change statitsics.
4647 thr_sign
@@ -76,7 +77,14 @@ def volcano(
7677 assert isinstance (data , pd .DataFrame ), m
7778 assert {x , y }.issubset (data .columns ), m
7879 assert (net is None ) == (name is None ), "net and name must be both defined or both None"
79- assert isinstance (top , int ) and top > 0 , "top must be int and > 0"
80+ if isinstance (top , str ):
81+ top = [top ]
82+ if isinstance (top , list ):
83+ assert all (isinstance (g , str ) for g in top ), "top must contain only str gene names"
84+ missing = [g for g in top if g not in data .index ]
85+ assert not missing , f"gene names not found in data.index: { missing } "
86+ else :
87+ assert isinstance (top , int ) and top > 0 , "top must be int, str, list[str], and int must be > 0"
8088 assert isinstance (thr_stat , int | float ) and thr_stat > 0 , "thr_stat must be numeric and > 0"
8189 assert isinstance (thr_sign , int | float ) and thr_sign > 0 , "thr_sign must be numeric and > 0"
8290 if max_stat is None :
@@ -127,8 +135,11 @@ def volcano(
127135 bp .ax .set_xlabel (x )
128136 bp .ax .set_ylabel (rf"$-\log_{{10}}({ y } )$" )
129137 # Show top sign features
130- signs = df [up_msk | dw_msk ].sort_values ("pval" , ascending = False )
131- signs = signs .iloc [:top ]
138+ if isinstance (top , list ):
139+ signs = df [df .index .isin (top )]
140+ else :
141+ signs = df [up_msk | dw_msk ].sort_values ("pval" , ascending = False )
142+ signs = signs .iloc [:top ]
132143 texts = []
133144 for x , y , s in zip (signs ["stat" ], signs ["pval" ], signs .index , strict = False ):
134145 texts .append (bp .ax .text (x , y , s ))
0 commit comments