da33d70c10ddaae6c3290cb900d7d0cc2b6ee01b hiram Tue Mar 17 13:57:24 2026 -0700 allow calculation of GC percent on the fly with code help from claude refs #35958 diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c index 1fdbec2d209..fafdfa1af60 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -24163,30 +24163,65 @@ static void doOligoMatch(char *item) /* Print info about oligo match. */ { char *oligo = cartUsualString(cart, oligoMatchVar, cloneString(oligoMatchDefault)); touppers(oligo); cartWebStart(cart, database, "Perfect Matches to Short Sequence"); printf("Sequence: %s
\n", oligo); printf("Chromosome: %s
\n", seqName); printf("Start: %s
\n", item+1); printf("Strand: %c
\n", item[0]); webIncludeHelpFile(OLIGO_MATCH_TRACK_NAME, TRUE); } +static void doGcOnFly(void) +/* Display GC percent info for visible window, computed on the fly from sequence. + * No tdb or bigWig file needed - this is a synthetic track with no database table. */ +{ +char *winSizeStr = cartUsualString(cart, gcOnFlyWindowSize, gcOnFlyDefaultSize); +int span = atoi(winSizeStr); +char num1Buf[64], num2Buf[64]; + +cartWebStart(cart, database, "GC Percent On the Fly"); +sprintLongWithCommas(num1Buf, BASE_1(winStart)); +sprintLongWithCommas(num2Buf, winEnd); +printf("Position: %s:%s-%s
\n", seqName, num1Buf, num2Buf); +sprintLongWithCommas(num1Buf, winEnd - winStart); +printf("Total bases in view: %s
\n", num1Buf); +printf("Window size for GC calculation: %d bases
\n", span); + +struct dnaSeq *seq = hChromSeq(database, seqName, winStart, winEnd); +if (seq != NULL) + { + int gcCount = 0, validBases = 0; + int i; + for (i = 0; i < seq->size; i++) + { + char b = seq->dna[i]; + if (b == 'g' || b == 'c') { gcCount++; validBases++; } + else if (b != 'n') validBases++; + } + if (validBases > 0) + printf("GC percent in view: %.3f%%
\n", + 100.0 * gcCount / validBases); + dnaSeqFree(&seq); + } +webIncludeHelpFile(GC_ON_FLY_TRACK_NAME, TRUE); +} + struct slName *cutterIsoligamers(struct cutter *myEnzyme) /* Find enzymes with same cut site. */ { struct sqlConnection *conn; struct cutter *cutters = NULL; struct slName *ret = NULL; conn = hAllocConn("hgFixed"); char query[1024]; sqlSafef(query, sizeof query, "select * from cutters"); cutters = cutterLoadByQuery(conn, query); ret = findIsoligamers(myEnzyme, cutters); hFreeConn(&conn); cutterFreeList(&cutters); return ret; @@ -27149,30 +27184,32 @@ else if (sameWord(table, "affyU95") || sameWord(table, "affyU133") || sameWord(table, "affyU74") || sameWord(table, "affyRAE230") || sameWord(table, "affyZebrafish") || sameWord(table, "affyGnf1h") || sameWord(table, "affyMOE430v2") || sameWord(table, "affyGnf1m") ) { doAffy(tdb, item, NULL); } else if (sameWord(table, WIKI_TRACK_TABLE)) doWikiTrack(item, seqName, winStart, winEnd); else if (sameWord(table, OLIGO_MATCH_TRACK_NAME)) doOligoMatch(item); +else if (sameWord(table, GC_ON_FLY_TRACK_NAME)) + doGcOnFly(); else if (sameWord(table, "refFullAli")) { doTSS(tdb, item); } else if (sameWord(table, "rikenMrna")) { doRikenRna(tdb, item); } else if (sameWord(table, "cgapSage")) { doCgapSage(tdb, item); } else if (sameWord(table, "ctgPos") || sameWord(table, "ctgPos2")) { doHgContig(tdb, item);