@@ -664,15 +664,13 @@ async def _create_gene_info_file(
664664 The gene information file will be created by reading each matrix filepath in the provided list
665665 """
666666
667- async def read_counts (file : Path ) -> list [str ]:
667+ async def read_ensembl_gene_ids (file : Path ) -> list [str ]:
668668 data = await _read_file (file , h5ad_as_df = False )
669-
669+ if isinstance (data , pd .DataFrame ):
670+ data : pd .DataFrame
671+ return data ["ensembl_gene_id" ].tolist ()
670672 try :
671- conversion = await (
672- ensembl_to_gene_id_and_symbol (ids = data ["ensembl_gene_id" ].tolist (), taxon = taxon )
673- if isinstance (data , pd .DataFrame )
674- else gene_symbol_to_ensembl_and_gene_id (symbols = data .var_names .tolist (), taxon = taxon )
675- )
673+ conversion = await gene_symbol_to_ensembl_and_gene_id (symbols = data .var_names .tolist (), taxon = taxon )
676674 except json .JSONDecodeError :
677675 _log_and_raise_error (
678676 f"Got a JSON decode error for file '{ counts_matrix_filepaths } '" ,
@@ -681,32 +679,48 @@ async def read_counts(file: Path) -> list[str]:
681679 )
682680
683681 # Remove NA values from entrez_gene_id dataframe column
684- return conversion ["entrez_gene_id " ].tolist ()
682+ return conversion ["ensembl_gene_id " ].tolist ()
685683
686684 logger .info ("Fetching gene info - this can take up to 5 minutes depending on the number of genes and your internet connection" )
687- genes = set (chain .from_iterable (await asyncio .gather (* [read_counts (f ) for f in counts_matrix_filepaths ])))
688- gene_data = await MyGene (cache = cache ).query (items = list (genes ), taxon = taxon , scopes = "entrezgene" )
685+
686+ ensembl_ids : set [str ] = set (chain .from_iterable (await asyncio .gather (* [read_ensembl_gene_ids (f ) for f in counts_matrix_filepaths ])))
687+ gene_data : list [dict [str , str | int | list [str ] | list [int ] | None ]] = await MyGene (cache = cache ).query (
688+ items = list (ensembl_ids ),
689+ taxon = taxon ,
690+ scopes = "ensemblgene" ,
691+ )
689692 gene_info : pd .DataFrame = pd .DataFrame (
690693 data = None ,
691- columns = ["ensembl_gene_id" , "gene_symbol" , "entrez_gene_id" , "size" ],
692- index = list (range (len (gene_data ))),
694+ columns = pd . Index ( data = ["ensembl_gene_id" , "gene_symbol" , "entrez_gene_id" , "size" ]) ,
695+ index = pd . Index ( data = list (range (len (ensembl_ids ) ))),
693696 )
694- for i , data in enumerate (gene_data ):
695- ensembl_ids = data .get ("genomic_pos.ensemblgene" , pd .NA )
696- if isinstance (ensembl_ids , list ):
697- ensembl_ids = ensembl_ids [0 ]
698-
699- start_pos = data .get ("genomic_pos.start" , 0 )
700- start_pos : int = int (sum (start_pos ) / len (start_pos )) if isinstance (start_pos , list ) else int (start_pos )
701- end_pos = data .get ("genomic_pos.end" , 0 )
702- end_pos : int = int (sum (end_pos ) / len (end_pos )) if isinstance (end_pos , list ) else int (end_pos )
703-
704- gene_info .at [i , "gene_symbol" ] = data .get ("symbol" , pd .NA )
705- gene_info .at [i , "entrez_gene_id" ] = data .get ("entrezgene" , pd .NA )
706- gene_info .at [i , "ensembl_gene_id" ] = ensembl_ids
707- gene_info .at [i , "size" ] = end_pos - start_pos
708- gene_info .sort_values (by = "ensembl_gene_id" , inplace = True )
709697
698+ for i , data in enumerate (gene_data ):
699+ data : dict [str , str | int | list [str ] | list [int ] | None ]
700+ ensembl_genes : str | list [str ] = cast (str | list [str ], data .get ("ensembl.gene" , "-" ))
701+ start_pos : int | list [int ] = cast (int | list [int ], data .get ("genomic_pos.start" , 0 ))
702+ end_pos : int | list [int ] = cast (int | list [int ], data .get ("genomic_pos.end" , 0 ))
703+
704+ avg_start : int | float = sum (start_pos ) / len (start_pos ) if isinstance (start_pos , list ) else start_pos
705+ avg_end : int | float = sum (end_pos ) / len (end_pos ) if isinstance (end_pos , list ) else end_pos
706+ size : int = int (avg_end - avg_start )
707+
708+ gene_info .at [i , "gene_symbol" ] = data .get ("symbol" , "-" )
709+ gene_info .at [i , "entrez_gene_id" ] = data .get ("entrezgene" , "-" )
710+ gene_info .at [i , "ensembl_gene_id" ] = "," .join (ensembl_genes ) if isinstance (ensembl_genes , list ) else ensembl_genes
711+ gene_info .at [i , "size" ] = size if size > 0 else - 1
712+
713+ gene_info ["size" ] = gene_info ["size" ].astype (str ) # replace no-length values with "-" to match rows where every value is "-"
714+ gene_info ["size" ] = gene_info ["size" ].replace ("-1" , "-" )
715+ gene_info = cast (pd .DataFrame , gene_info [~ (gene_info == "-" ).all (axis = 1 )]) # remove rows where every value is "-"
716+
717+ gene_info ["ensembl_gene_id" ] = gene_info ["ensembl_gene_id" ].str .split ("," ) # extend lists into multiple rows
718+ gene_info = gene_info .explode (column = ["ensembl_gene_id" ])
719+ gene_info ["size" ] = gene_info ["size" ].astype (int )
720+ # we would set `entrez_gene_id` to int here as well, but not all ensembl ids are mapped to entrez ids,
721+ # and as a result, there are still "-" values in the entrez id column that cannot be converted to an integer
722+
723+ gene_info : pd .DataFrame = cast (pd .DataFrame , gene_info .sort_values (by = "ensembl_gene_id" ))
710724 output_filepath .parent .mkdir (parents = True , exist_ok = True )
711725 gene_info .to_csv (output_filepath , index = False )
712726 logger .success (f"Gene Info file written at '{ output_filepath } '" )
@@ -728,7 +742,7 @@ async def _process_como_input(
728742 rna = rna ,
729743 )
730744 with pd .ExcelWriter (output_config_filepath ) as writer :
731- subset_config = config_df [config_df ["library_prep" ] == rna .value ]
745+ subset_config = config_df [config_df ["library_prep" ]. str . lower () == rna .value . lower () ]
732746 subset_config .to_excel (writer , sheet_name = context_name , header = True , index = False )
733747
734748
0 commit comments