0750648bee41e57d7f1cbc3de8e3d9177bfd4c70 angie Fri May 1 10:02:25 2026 -0700 Initial support for ripples seach in usher-sampled-server. Enabled by config param ripplesEnabled. If enabled, there is a new checkbox for the user to click if they want the extra search. Currently hardcoded to max of 10 sequences, otherwise extra search is not done (too slow). Ripples results, if any, are displayed in a table before the usual summary table. diff --git src/hg/hgPhyloPlace/phyloPlace.h src/hg/hgPhyloPlace/phyloPlace.h index ac8cc21014e..192f2a79336 100644 --- src/hg/hgPhyloPlace/phyloPlace.h +++ src/hg/hgPhyloPlace/phyloPlace.h @@ -13,30 +13,34 @@ #include "phyloTree.h" #include "seqWindow.h" #include "trackLayout.h" #include "trashDir.h" #define PHYLOPLACE_DATA_DIR "hgPhyloPlaceData" // Allow users to upload a lot of sequences, but put limits on how much detail we'll show and // how many custom tracks we'll create. #define MAX_SUBTREE_SIZE 5000 #define MAX_MICROBETRACE_SUBTREE_SIZE 500 #define MAX_SUBTREE_BUTTONS 5 #define MAX_SEQ_DETAILS 1000 #define MAX_SUBTREE_CTS 10 +// When in server mode with only a few uploaded seqs, we can run ripples too. +#define MAX_RIPPLES_SEARCH 10 +#define RIPPLES_ANCESTOR_RADIUS "5" + // For usher's -K option (single subtree): #define SINGLE_SUBTREE_SIZE "2000" #define USHER_NUM_THREADS "16" #define USHER_SERVER_CHILD_TIMEOUT "600" #define USHER_DEDUP_PREFIX "uploaded_" #define NEXTSTRAIN_DRAG_DROP_DOC "https://docs.nextstrain.org/projects/auspice/en/latest/advanced-functionality/drag-drop-csv-tsv.html" #define NEXTSTRAIN_URL_PARAMS "?f_userOrOld=uploaded%20sample" #define MICROBETRACE_URL_PARAMS "" #define OUTBREAK_INFO_URLBASE "https://outbreak.info/situation-reports?pango=" #define PANGO_DESIGNATION_ISSUE_URLBASE "https://github.com/cov-lineages/pango-designation/issues/" // usher now preprends "node_" to node numbers when parsing protobuf, although they're still stored // numeric in the protobuf. #define USHER_NODE_PREFIX "node_" @@ -108,37 +112,64 @@ char *nearestNeighbor; // Nearest neighbor in phylogenetic tree/NULL if not found char *neighborLineage; // Lineage of nearest neighbor/NULL if not found }; struct subtreeInfo /* Parsed subtree from usher and derivative products. */ { struct subtreeInfo *next; struct tempName *subtreeTn; // Newick file from usher (may have condensed nodes) struct phyloTree *subtree; // Parsed subtree (#*** with annotated muts? shoudl we?_ struct hash *subtreeIdToIx; // Map of subtree nodes to VCF output sample order struct slName *subtreeUserSampleIds; // List of user-uploaded samples in this subtree struct slName *subtreeNameList; // List of leaf names with nicer names for cond. nodes }; +struct recombinantInfo +/* Properties of a potential recombinant and its parents. */ +{ + struct recombinantInfo *next; + char *recombNodeId; // Node ID of the potential recombinant node + char *donorNodeId; // Node ID of the potential parent at start of genome + char *acceptorNodeId; // Node ID of the potential parent at middle/end of genome + uint recombNumDesc; // Number of descendants of recombinant ndoe + uint donorNumDesc; // Number of descendants of donor node + uint acceptorNumDesc; // Number of descendants of acceptor node + uint bp1Min; // First breakpoint minimum coordinate + uint bp1Max; // First breakpoint maximum coordinate + uint bp2Min; // Second breakpoint minimum coordinate + uint bp2Max; // Second breakpoint maximum coordinate + char *recombClade; // First clade annotation assigned to recombinant node + char *recombLineage; // Second clade annotation assigned to recombinant node + char *donorClade; // First clade annotation assigned to donor node + char *donorLineage; // Second clade annotation assigned to donor node + char *acceptorClade; // First clade annotation assigned to acceptor node + char *acceptorLineage; // Second clade annotation assigned to acceptor node + char *representative; // Representative descendant of recombinant node + uint originalParsimony; // Parsimony score of recombinant node in tree + uint parsimonyImprovement; // Reduction in parsimony score given parents/breakpoints +}; + struct usherResults /* Tree+samples download file, sample placements, and subtrees parsed from usher output. */ { struct tempName *bigTreePlusTn; // Newick file: original tree plus user's samples struct hash *samplePlacements; // Info about each sample's placement in the tree struct subtreeInfo *singleSubtreeInfo; // Comprehensive subtree with all uploaded samples struct subtreeInfo *subtreeInfoList; // For each subtree: tree, file, node info etc. + struct recombinantInfo *recombinants;// Potential recombinants found by ripples search + struct hash *recombinantDescendants; // Leaf descendants of each potential recombinant node }; struct sampleMetadataStore /* Storage for sample metadata: hash of array of strings for named columns. */ { struct mmHash *mmh; // Either NULL (if hash is non-NULL) or a memory-mapped hash. struct hash *hash; // Either NULL (if mmh is non-NULL) or a regular hash. size_t columnCount; // Number of metadata columns char **columnNames; // Metadata column names (e.g. date, genbank_accession, pangolin_lineage) }; struct geneInfo /* Information sufficient to determine whether a genome change causes a coding change. */ { struct geneInfo *next; @@ -156,40 +187,41 @@ struct mmHash *mmh; // Either NULL (if hash is non-NULL) or a memory-mapped hash. struct hash *hash; // Either NULL (if mmh is non-NULL) or a regular hash. }; struct tempName *vcfFromFasta(struct lineFile *lf, char *org, char *db, struct dnaSeq *refGenome, struct slName **maskSites, struct hashOrMmHash *treeNames, struct slName **retSampleIds, struct seqInfo **retSeqInfo, struct slPair **retFailedSeqs, struct slPair **retFailedPsls, int *pStartTime); /* Read in FASTA from lf and make sure each item has a reasonable size and not too high * percentage of N's. Align to reference, extract SNVs from alignment, and save as VCF * with sample genotype columns. */ struct usherResults *runUsher(char *org, char *usherPath, char *usherAssignmentsPath, char *vcfFile, int subtreeSize, struct slName **pUserSampleIds, - struct treeChoices *treeChoices, char *anchorFile, int *pStartTime); + struct treeChoices *treeChoices, char *anchorFile, + boolean ripplesEnabled, uint genomeSize, int *pStartTime); /* Open a pipe from Yatish Turakhia's usher program, save resulting big trees and * subtrees to trash files, return list of slRef to struct tempName for the trash files * and parse other results out of stderr output. The usher-sampled version of usher might * modify userSampleIds, adding a prefix if a sample with the same name is already in the tree. */ struct usherResults *runMatUtilsExtractSubtrees(char *org, char *matUtilsPath, char *protobufPath, int subtreeSize, struct slName *sampleIds, struct treeChoices *treeChoices, char *anchorFile, - int *pStartTime); + uint genomeSize, int *pStartTime); /* Open a pipe from Yatish Turakhia and Jakob McBroome's matUtils extract to extract subtrees * containing sampleIds, save resulting subtrees to trash files, return subtree results. * Caller must ensure that sampleIds are names of leaves in the protobuf tree. */ boolean serverIsConfigured(char *org); /* Return TRUE if all necessary configuration settings are in place to run usher-sampled-server. */ boolean serverIsRunning(char *org, FILE *errFile); /* Return TRUE if we can find a PID for server and that PID looks alive according to /proc. */ boolean startServer(char *org, struct treeChoices *treeChoices, FILE *errFile); /* Start up an usher-sampled-server process to run in the background. */ void serverReloadProtobufs(char *org, struct treeChoices *treeChoices); /* Send a reload command and list of protobufs for org to usher server. */