147740e133aa59c5aa7938ef68f1b66f3696c701 braney Fri Mar 13 15:29:49 2026 -0700 Revert noDots mafClick/mafFrag work from master, refs #21477 Remove the mafClickMafFrag/noDots code path from mafClick.c, hgMaf.c, hgMaf.h, and mafFrag.c. Also remove mafFrag unit tests added as part of this work. The code is preserved on the mafFragNoDots and mafClickMafFrag branches. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> diff --git src/hg/hgc/mafClick.c src/hg/hgc/mafClick.c index 183dc44fc03..dba605cdb72 100644 --- src/hg/hgc/mafClick.c +++ src/hg/hgc/mafClick.c @@ -6,51 +6,48 @@ #include "common.h" #include "hash.h" #include "linefile.h" #include "hgc.h" #include "maf.h" #include "obscure.h" #include "cheapcgi.h" #include "genePred.h" #include "botDelay.h" #include "hgMaf.h" #include "hui.h" #include "hCommon.h" #include "hubConnect.h" #include "trackHub.h" #include "chromAlias.h" -#include "hgConfig.h" extern boolean issueBotWarning; #define ADDEXONCAPITAL /* Javascript to help make a selection from a drop-down * go back to the server. */ static char *autoSubmit = "document.gpForm.submit();"; static void blueCapWrite(FILE *f, char *s, int size, char *r) /* Write capital letters in blue. */ { boolean isBlue = FALSE; int i; for (i=0; i<size; ++i) { if (r!=NULL && s[i]==r[i]) - { fprintf(f, "."); - } else { char c = s[i]; if (isupper(c)) { if (!isBlue) { fprintf(f, "<span style='color:#0000FF;'>"); isBlue = TRUE; } } else if (islower(c)) { if (isBlue) { @@ -104,35 +101,33 @@ startChars = sizeChars = srcSizeChars = 0; for (mc = maf->components; mc != NULL; mc = mc->next) { /* Figure out length of source (species) field. */ /*if (mc->size != 0)*/ { char dbOnly[128]; int len; char *org; memset(dbOnly, 0, sizeof(dbOnly)); safef(dbOnly, sizeof(dbOnly), "%s", mc->src); chopPrefix(dbOnly); - if ((labelHash == NULL) || ((org = hashFindVal(labelHash, dbOnly)) == NULL)) - { if ((org = hOrganism(dbOnly)) == NULL) - org = dbOnly; - } + len = strlen(dbOnly); + else len = strlen(org); if (srcChars < len) srcChars = len; len = digitsBaseTen(mc->start); if (startChars < len) startChars = len; len = digitsBaseTen(mc->size); if (sizeChars < len) sizeChars = len; len = digitsBaseTen(mc->srcSize); if (srcSizeChars < len) srcSizeChars = len; if (mc->text && (mc->rightStatus == MAF_INSERT_STATUS) && (masterMc->start + masterMc->size < winEnd)) @@ -447,88 +442,30 @@ } static void capMafOnTrack(struct mafAli *maf, char *track, boolean onlyCds) /* Capitalize parts of maf that correspond to exons according * to given gene prediction track. */ { char dbOnly[64]; char *chrom; struct mafComp *mc = maf->components; strncpy(dbOnly, mc->src, sizeof(dbOnly)); chrom = chopPrefix(dbOnly); capAliTextOnTrack(maf, dbOnly, chrom, track, onlyCds); } #endif -static void mafStripEmptyRefGaps(struct mafAli *maf) -/* Remove columns where the reference (first component) has a gap character - * AND no other component has actual sequence in that column. Columns where - * at least one non-reference species has a base are kept. */ -{ -struct mafComp *mc; -struct mafComp *ref = maf->components; -if (ref == NULL || ref->text == NULL) - return; -int textSize = maf->textSize; - -/* Build boolean array of columns to keep */ -bool *keep = needMem(textSize); -int newSize = 0; -int ii; -for (ii = 0; ii < textSize; ii++) - { - if (ref->text[ii] != '-') - { - keep[ii] = TRUE; - newSize++; - } - else - { - /* Reference has gap — check if any other species has sequence */ - for (mc = ref->next; mc != NULL; mc = mc->next) - { - if (mc->text != NULL && isalpha(mc->text[ii])) - { - keep[ii] = TRUE; - newSize++; - break; - } - } - } - } - -if (newSize == textSize) - { - freeMem(keep); - return; - } - -/* Compact all component texts in place */ -for (mc = maf->components; mc != NULL; mc = mc->next) - { - if (mc->text == NULL) - continue; - int jj = 0; - for (ii = 0; ii < textSize; ii++) - if (keep[ii]) - mc->text[jj++] = mc->text[ii]; - mc->text[jj] = '\0'; - } -maf->textSize = newSize; -freeMem(keep); -} - static struct mafAli *mafOrAxtLoadInRegion2(struct sqlConnection *conn,struct sqlConnection *conn2, struct trackDb *tdb, char *chrom, int start, int end, char *axtOtherDb, char *file) { if (axtOtherDb != NULL) { struct hash *qSizeHash = hChromSizeHash(axtOtherDb); struct mafAli *mafList = axtLoadAsMafInRegion(conn, tdb->table, chrom, start, end, database, axtOtherDb, hChromSize(database, chrom), qSizeHash); hashFree(&qSizeHash); return mafList; } else return mafLoadInRegion2(conn, conn2, tdb->table, chrom, start, end, file); @@ -549,231 +486,121 @@ static void conservationStatsLink(struct trackDb *tdb, char *label, char *table) /* write link that to display statistics of phastCons table */ { char *chrom = cartCgiUsualString(cart, "c", "chr7"); printf("<A HREF=\"%s&g=%s&i=%s&c=%s&l=%d&r=%d&o=%d&db=%s" "&parentWigMaf=%s\" TARGET=\"_blank\">%s</A>", hgcPathAndSettings(), table, table, chrom, winStart, winEnd, winStart, database, tdb->track, label); } static void mafOrAxtClick2(struct sqlConnection *conn, struct sqlConnection *conn2, struct trackDb *tdb, char *axtOtherDb, char *fileName) /* Display details for MAF or AXT tracks. */ { -boolean useMafFrag = cfgOptionBooleanDefault("mafClickMafFrag", FALSE); if (issueBotWarning) { char *ip = getenv("REMOTE_ADDR"); botDelayMessage(ip, botDelayMillis); } if (winEnd - winStart > 30000) { printf("Zoom so that window is 30,000 bases or less to see alignments and conservation statistics\n"); } else { struct mafAli *mafList = NULL, *maf, *subList = NULL; int aliIx = 0, realCount = 0; char dbChrom[64]; char option[128]; char *capTrack; struct consWiggle *consWig, *consWiggles; struct hash *speciesOffHash = NULL; char *speciesOrder = NULL; char *speciesTarget = trackDbSetting(tdb, SPECIES_TARGET_VAR); char buffer[1024]; int useTarg = FALSE; int useIrowChains = FALSE; struct hash *labelHash = mafGetLabelHash(tdb); - struct slName *orderList = NULL; safef(option, sizeof(option), "%s.%s", tdb->track, MAF_CHAIN_VAR); if (cartCgiUsualBoolean(cart, option, FALSE) && trackDbSetting(tdb, "irows") != NULL) useIrowChains = TRUE; safef(buffer, sizeof(buffer), "%s.vis",tdb->track); if (useIrowChains) { if (!cartVarExists(cart, buffer) && (speciesTarget != NULL)) useTarg = TRUE; else { char *val; val = cartUsualString(cart, buffer, "useCheck"); useTarg = sameString("useTarg",val); } } - if (useMafFrag) - { - /* New mafFrag code path: determine species order from trackDb settings, - * matching hgTracks logic, then use hgMafFrag to stitch into a single - * continuous alignment in reference coordinates */ - char *speciesGroup = trackDbSetting(tdb, SPECIES_GROUP_VAR); - char *speciesUseFile = trackDbSetting(tdb, SPECIES_USE_FILE); - speciesOrder = trackDbSetting(tdb, SPECIES_ORDER_VAR); - - /* Check cart override for speciesOrder */ - safef(option, sizeof(option), "%s.speciesOrder", tdb->track); - char *cartOrder = cartUsualString(cart, option, NULL); - if (cartOrder != NULL) - speciesOrder = cartOrder; - - if (speciesUseFile) - speciesOrder = cartGetOrderFromFile(database, cart, speciesUseFile); - - /* Build hash of species that default to off */ - char *speciesOff = trackDbSetting(tdb, SPECIES_DEFAULT_OFF_VAR); - struct hash *defaultOffHash = NULL; - if (speciesOff) - { - char *offSpecies[2048]; - int offCt = chopLine(cloneString(speciesOff), offSpecies); - defaultOffHash = newHash(5); - int ii; - for (ii = 0; ii < offCt; ii++) - hashAdd(defaultOffHash, offSpecies[ii], NULL); - } - - /* Build orderList of selected species for mafFrag, matching - * newSpeciesItems() logic in wigMafTrack.c */ - if (speciesOrder || speciesGroup) - { - char *groups[1000]; - char sGroup[2048]; - int groupCt = 1; - int group; - - if (speciesGroup) - groupCt = chopLine(cloneString(speciesGroup), groups); - - /* Add reference database as first in list */ - slNameAddHead(&orderList, database); - - for (group = 0; group < groupCt; group++) - { - char *species[2048]; - int speciesCt; - if (groupCt != 1 || !speciesOrder) - { - safef(sGroup, sizeof sGroup, "%s%s", - SPECIES_GROUP_PREFIX, groups[group]); - speciesOrder = trackDbRequiredSetting(tdb, sGroup); - } - speciesCt = chopLine(cloneString(speciesOrder), species); - - int ii; - for (ii = 0; ii < speciesCt; ii++) - { - boolean defaultOn = (defaultOffHash == NULL - || hashLookup(defaultOffHash, species[ii]) == NULL); - if (useTarg || cartUsualBooleanClosestToHome(cart, tdb, - FALSE, species[ii], defaultOn)) - { - slNameAddTail(&orderList, species[ii]); - } - else - { - if (speciesOffHash == NULL) - speciesOffHash = newHash(4); - char *organism = hOrganism(species[ii]); - if (!organism) - organism = species[ii]; - hashStoreName(speciesOffHash, organism); - } - } - } - } - - /* Load alignment using mafFragNoDots approach — returns a list of - * maf blocks, each containing only assemblies with actual sequence. */ - if (sameString(tdb->type, "bigMaf")) - { - char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl"); - struct bbiFile *bbi = bigBedFileOpenAlias(bigDataUrl, chromAliasFindAliases); - subList = hgBigMafFragNoDots(database, bbi, seqName, winStart, winEnd, '+', NULL, orderList); - bbiFileClose(&bbi); - } - else if (axtOtherDb == NULL && fileName == NULL) - { - /* Regular MAF from database */ - subList = hgMafFragNoDots(database, tdb->table, seqName, winStart, winEnd, '+', NULL, orderList); - } - else - { - /* AXT or MAF with external file - load blocks, then stitch */ - mafList = mafOrAxtLoadInRegion2(conn, conn2, tdb, seqName, - winStart, winEnd, axtOtherDb, fileName); - subList = hgMafFragFromMafListNoDots(database, seqName, winStart, winEnd, '+', - mafList, NULL, orderList); - mafList = NULL; /* consumed by hgMafFragFromMafListNoDots */ - } - - /* Strip ref gap columns where no other species has sequence */ - for (maf = subList; maf != NULL; maf = maf->next) - mafStripEmptyRefGaps(maf); - - realCount = slCount(subList); - } - else - { - /* Original block-by-block code path */ if (sameString(tdb->type, "bigMaf")) { - char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl"); - struct bbiFile *bbi = bigBedFileOpenAlias(bigDataUrl, chromAliasFindAliases); + char *fileName = trackDbSetting(tdb, "bigDataUrl"); + struct bbiFile *bbi = bigBedFileOpenAlias(fileName, chromAliasFindAliases); mafList = bigMafLoadInRegion(bbi, seqName, winStart, winEnd); } else mafList = mafOrAxtLoadInRegion2(conn,conn2, tdb, seqName, winStart, winEnd, axtOtherDb, fileName); safef(dbChrom, sizeof(dbChrom), "%s.%s", hubConnectSkipHubPrefix(database), seqName); safef(option, sizeof(option), "%s.speciesOrder", tdb->track); speciesOrder = cartUsualString(cart, option, NULL); if (speciesOrder == NULL) speciesOrder = trackDbSetting(tdb, "speciesOrder"); int speciesCt = 0; char *species[2048]; struct mafComp **newOrder; if (speciesOrder) { + // chop up speciesOrder string and store it away, checking for errors along the way speciesCt = chopLine(cloneString(speciesOrder), species); newOrder = needMem((speciesCt + 1) * sizeof (struct mafComp *)); int ii; struct hash *nameHash = newHash(5); for(ii=0; ii < speciesCt; ii++) { if (hashLookup(nameHash, species[ii])) errAbort("speciesOrder contains %s more than once.", species[ii]); hashStore(nameHash, species[ii]); } } for (maf = mafList; maf != NULL; maf = maf->next) { int mcCount = 0; struct mafComp *mc; struct mafAli *subset; struct mafComp *nextMc; + /* remove empty components and configured off components + * from MAF, and ignore + * the entire MAF if all components are empty + * (solely for gap annotation) */ + if (!useTarg) { for (mc = maf->components->next; mc != NULL; mc = nextMc) { char buf[64]; char *organism; mafSrcDb(mc->src, buf, sizeof buf); organism = hOrganism(buf); if (!organism) organism = buf; nextMc = mc->next; safef(option, sizeof(option), "%s.%s", tdb->track, buf); if (!cartUsualBoolean(cart, option, TRUE)) { if (speciesOffHash == NULL) @@ -808,42 +635,43 @@ newOrder[mcCount++] = mcThis; } maf->components = NULL; for (i = 0; i < mcCount; i++) { newOrder[i]->next = 0; slAddHead(&maf->components, newOrder[i]); } slReverse(&maf->components); } subset = mafSubsetE(maf, dbChrom, winStart, winEnd, TRUE); if (subset != NULL) { + /* Reformat MAF if needed so that sequence from current + * database is the first component and on the + * plus strand. */ mafMoveComponentToTop(subset, dbChrom); if (subset->components->strand == '-') mafFlipStrand(subset); subset->score = mafScoreMultiz(subset); slAddHead(&subList, subset); ++realCount; } } slReverse(&subList); mafAliFreeList(&mafList); - } - if (subList != NULL) { char *showVarName = "hgc.showMultiBase"; char *showVarVal = cartUsualString(cart, showVarName, "all"); boolean onlyDiff = sameWord(showVarVal, "diff"); #ifdef ADDEXONCAPITAL char *codeVarName = "hgc.multiCapCoding"; char *codeVarVal = cartUsualString(cart, codeVarName, "coding"); boolean onlyCds = sameWord(codeVarVal, "coding"); #endif /* add links for conservation score statistics */ consWiggles = wigMafWiggles(database, tdb); int wigCount = slCount(consWiggles); if (wigCount == 1) { @@ -946,57 +774,50 @@ puts("for aligned species, click on 'D' to get DNA for aligned species.<BR>"); printf("<TT><PRE>"); /* notify if species removed from alignment */ if (speciesOffHash) { char *species; struct hashCookie hc = hashFirst(speciesOffHash); puts("<B>Components not displayed:</B> "); while ((species = hashNextName(&hc)) != NULL) printf("%s ", species); puts("<BR>"); } + for (maf = subList; maf != NULL; maf = maf->next) { mafLowerCase(maf); #ifdef ADDEXONCAPITAL if (capTrack != NULL) capMafOnTrack(maf, capTrack, onlyCds); #endif - ++aliIx; - if (useMafFrag) - printf("<B>Alignment %d - %d, %d bps </B>\n", - maf->components->start + 1, - maf->components->start + maf->components->size, - maf->components->size); - else printf("<B>Alignment block %d of %d in window, %d - %d, %d bps </B>\n", - aliIx,realCount,maf->components->start + 1, + ++aliIx,realCount,maf->components->start + 1, maf->components->start + maf->components->size, maf->components->size); - mafPrettyOut(stdout, maf, useMafFrag ? maf->textSize : 70, onlyDiff, aliIx, labelHash); + mafPrettyOut(stdout, maf, 70,onlyDiff, aliIx, labelHash); } mafAliFreeList(&subList); } else { printf("No multiple alignment in browser window"); } printf("</PRE></TT>"); - slNameFreeList(&orderList); } } static void mafOrAxtClick(struct sqlConnection *conn, struct trackDb *tdb, char *axtOtherDb) { struct sqlConnection *conn2 = NULL; if (!(isHubTrack(tdb->track) || trackHubDatabase(database))) conn2 = hAllocConn(database); // MAF file location is optionally in trackDb char *mafFile = hashFindVal(tdb->settingsHash, "mafFile"); mafOrAxtClick2(conn, conn2, tdb, axtOtherDb, mafFile); hFreeConn(&conn2); }