6175649026c35358cc0871c3f2cdf39328736885 markd Sun Oct 30 20:44:31 2022 -0700 initial implementation of all gencode transcript rank filters, not GUI yet diff --git src/hg/hgc/gencodeClick.c src/hg/hgc/gencodeClick.c index 948f754..1360248 100644 --- src/hg/hgc/gencodeClick.c +++ src/hg/hgc/gencodeClick.c @@ -1,123 +1,131 @@ /* gencodeClick - click handling for GENCODE tracks */ /* Copyright (C) 2014 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #include "common.h" #include "hgc.h" #include "gencodeClick.h" +#include "gencodeTracksCommon.h" #include "ccdsClick.h" #include "genePred.h" #include "genePredReader.h" #include "ensFace.h" #include "htmshell.h" #include "jksql.h" #include "regexHelper.h" #include "encode/wgEncodeGencodeAttrs.h" #include "encode/wgEncodeGencodeGeneSource.h" #include "encode/wgEncodeGencodePdb.h" #include "encode/wgEncodeGencodePubMed.h" #include "encode/wgEncodeGencodeRefSeq.h" #include "encode/wgEncodeGencodeTag.h" #include "encode/wgEncodeGencodeTranscriptSource.h" #include "encode/wgEncodeGencodeTranscriptSupport.h" #include "encode/wgEncodeGencodeExonSupport.h" #include "encode/wgEncodeGencodeUniProt.h" #include "encode/wgEncodeGencodeEntrezGene.h" #include "encode/wgEncodeGencodeAnnotationRemark.h" #include "encode/wgEncodeGencodeTranscriptionSupportLevel.h" +#include "encode/wgEncodeGencodeGeneSymbol.h" /* * General notes: * - this will be integrated into hgGene at some point, however this was * done as part of hgc for timing reasons and to allow more time to design * the hgGene part. * - Tables below will output at least one row even if no data is available. * */ /* Various URLs and URL templates. At one time, these were in the ra file, * but that didn't prove that helpful and end up requiring updated the ra * files for every GENCODE version if a URL was added or changed. */ //FIXME: clean up RA files when CGIs no longer need them static char *ensemblTranscriptIdUrl = "http://www.ensembl.org/%s/Transcript/Summary?db=core;t=%s"; static char *ensemblGeneIdUrl = "http://www.ensembl.org/%s/Gene/Summary?db=core;t=%s"; static char *ensemblProteinIdUrl = "http://www.ensembl.org/%s/Transcript/ProteinSummary?db=core;t=%s"; static char *ensemblSupportingEvidUrl = "http://www.ensembl.org/%s/Transcript/SupportingEvidence?db=core;t=%s"; static char *ensemblH37TranscriptIdUrl = "http://grch37.ensembl.org/%s/Transcript/Summary?db=core;t=%s"; static char *ensemblH37GeneIdUrl = "http://grch37.ensembl.org/%s/Gene/Summary?db=core;t=%s"; static char *ensemblH37ProteinIdUrl = "http://grch37.ensembl.org/%s/Transcript/ProteinSummary?db=core;t=%s"; static char *ensemblH37SupportingEvidUrl = "http://grch37.ensembl.org/%s/Transcript/SupportingEvidence?db=core;t=%s"; static char *gencodeBiotypesUrl = "http://www.gencodegenes.org/pages/biotypes.html"; static char *gencodeTagsUrl = "http://www.gencodegenes.org/pages/tags.html"; static char *yalePseudoUrl = "http://tables.pseudogene.org/%s"; -static char *hgncUrl = " https://www.genenames.org/data/gene-symbol-report/#!/symbol/%s"; -static char *geneCardsUrl = "http://www.genecards.org/cgi-bin/carddisp.pl?gene=%s"; static char *apprisHomeUrl = "https://appris.bioinfo.cnio.es/#/"; static char *apprisGeneUrl = "https://appris.bioinfo.cnio.es/#/database/id/%s/%s?sc=ensembl"; -static char* UNKNOWN = "unknown"; - -static char *getBaseAcc(char *acc, char *accBuf, int accBufSize) -/* get the accession with version number dropped. */ -{ -safecpy(accBuf, accBufSize, acc); -char *dot = strchr(accBuf, '.'); -if (dot != NULL) - *dot = '\0'; -return accBuf; -} +// species-specific +static char *hgncByIdUrl = "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/%s"; +static char *hgncBySymUrl = " https://www.genenames.org/data/gene-symbol-report/#!/symbol/%s"; +static char *geneCardsUrl = "http://www.genecards.org/cgi-bin/carddisp.pl?gene=%s"; +static char *mgiBySymUrl = "http://www.informatics.jax.org/quicksearch/summary?queryType=exactPhrase&query=%s"; +static char *mgiByIdUrl = "http://www.informatics.jax.org/accession/%s"; -static char* getGencodeVersion(struct trackDb *tdb) -/* get the GENCODE version */ -{ -return trackDbRequiredSetting(tdb, "wgEncodeGencodeVersion"); -} +static char* UNKNOWN = "unknown"; -static char *getGencodeTable(struct trackDb *tdb, char *tableBase) -/* Return the table name with the version attached. This just leaks the memory - * and lets exit() clean up. It is tiny */ +static boolean isGrcHuman() +/* is this a GRC human assembly? */ { -char table[64]; -safef(table, sizeof(table), "%sV%s", tableBase, getGencodeVersion(tdb)); -return cloneString(table); +if (startsWith("hg", database)) + return TRUE; +else if (startsWith("mm", database)) + return FALSE; +else + errAbort("BUG: gencodeClick on wrong database: %s", database); + return FALSE; } static bool haveGencodeTable(struct sqlConnection *conn, struct trackDb *tdb, char *tableBase) /* determine if a gencode table exists; it might be option or not in older releases */ { -return sqlTableExists(conn, getGencodeTable(tdb, tableBase)); +return sqlTableExists(conn, gencodeGetTableName(tdb, tableBase)); } static boolean isGrcH37Native(struct trackDb *tdb) /* Is this GENCODE GRCh37 native build, which requires a different Ensembl site. */ { // check for non-lifted GENCODE on GRCh37/hg19 if (sameString(database, "hg19")) - return stringIn("lift37", getGencodeVersion(tdb)) == NULL; + return stringIn("lift37", gencodeGetVersion(tdb)) == NULL; else return FALSE; } -static boolean isFakeGeneSymbol(char* sym) -/* is this a static gene symbol? */ +static boolean isRealGeneSymbol(char* geneName, boolean haveGeneSymbolSource, + struct wgEncodeGencodeGeneSymbol *geneSymbolSource) +/* Attempt to determine if this is a gene symbol assigned by HGNC/MGI or a + * generate one. newer versions of GENCODE have wgEncodeGencodeGeneSymbol, + * which has the definitions. With older version of GENCODE guess a guess + * is make by trying to match older clone-based names ones. + */ { -static const char *regexp = "^AC[0-9]+\\.[0-9]+$"; -return regexMatch(sym, regexp); +if (haveGeneSymbolSource) + { + return geneSymbolSource != NULL; + } +else + { + // 'A' followed by one or more letters, then followed by numbers and a '.', + // followed by an incrementing gene number. + static const char *regexp = "^A[A-Z]+[0-9]+\\.[0-9]+$1)"; + return regexMatch(geneName, regexp); + } } static int transAnnoCmp(const void *va, const void *vb) /* Compare genePreds, sorting to keep select gene first. The only cases * that annotations will be duplicated is if they are in the PAR and thus * on different chroms. */ { const struct genePred *a = *((struct genePred **)va); const struct genePred *b = *((struct genePred **)vb); if (sameString(a->name, seqName)) return -1; else if (sameString(b->name, seqName)) return 1; else return strcmp(a->name, b->name); @@ -134,66 +142,66 @@ * first. Should only have one or two. */ { // must check chrom due to PAR char where[256]; sqlSafef(where, sizeof(where), "(chrom = \"%s\") and (name = \"%s\")", seqName, gencodeId); struct genePred *transAnno = genePredReaderLoadQuery(conn, tdb->track, where); slSort(&transAnno, transAnnoCmp); return transAnno; } static struct wgEncodeGencodeAttrs *transAttrsLoad(struct trackDb *tdb, struct sqlConnection *conn, char *gencodeId) /* load the gencode attributes */ { char query[1024]; sqlSafef(query, sizeof(query), "select * from %s where transcriptId = \"%s\"", - getGencodeTable(tdb, "wgEncodeGencodeAttrs"), gencodeId); + gencodeGetTableName(tdb, "wgEncodeGencodeAttrs"), gencodeId); struct sqlResult *sr = sqlGetResult(conn, query); char **row = sqlNextRow(sr); if (row == NULL) errAbort("gencode transcript %s not found in %s", gencodeId, - getGencodeTable(tdb, "wgEncodeGencodeAttrs")); + gencodeGetTableName(tdb, "wgEncodeGencodeAttrs")); // older version don't have proteinId column. struct wgEncodeGencodeAttrs *transAttrs = wgEncodeGencodeAttrsLoad(row, sqlCountColumns(sr)); sqlFreeResult(&sr); return transAttrs; } static void getGeneBounds(struct trackDb *tdb, struct sqlConnection *conn, struct genePred *transAnno, int *geneChromStart, int *geneChromEnd) /* find bounds for the gene */ { // must check chrom due to PAR char where[256]; sqlSafef(where, sizeof(where), "(chrom = \"%s\") and (name2 = \"%s\")", seqName, transAnno->name2); struct genePred *geneAnnos = genePredReaderLoadQuery(conn, tdb->track, where); struct genePred *geneAnno; *geneChromStart = transAnno->txStart; *geneChromEnd = transAnno->txEnd; for (geneAnno = geneAnnos; geneAnno != NULL; geneAnno = geneAnno->next) { *geneChromStart = min(*geneChromStart, geneAnno->txStart); *geneChromEnd = max(*geneChromEnd, transAnno->txEnd); } genePredFreeList(&geneAnnos); } static void *metaDataLoad(struct trackDb *tdb, struct sqlConnection *conn, char *gencodeId, char *tableBase, char *keyCol, unsigned queryOpts, sqlLoadFunc loadFunc) /* load autoSql objects for gencode meta data. */ { return sqlQueryObjs(conn, loadFunc, queryOpts, "select * from %s where %s = \"%s\"", - getGencodeTable(tdb, tableBase), keyCol, gencodeId); + gencodeGetTableName(tdb, tableBase), keyCol, gencodeId); } static int uniProtDatasetCmp(const void *va, const void *vb) /* Compare wgEncodeGencodeUniProt by dateset */ { const struct wgEncodeGencodeUniProt *a = *((struct wgEncodeGencodeUniProt **)va); const struct wgEncodeGencodeUniProt *b = *((struct wgEncodeGencodeUniProt **)vb); return a->dataset - b->dataset; } static char *getMethodDesc(char *source) /* return the annotation method name based gene or transcript source */ { // sometimes backmap doesn't get every entry method entry mapped. Until that // is fixed, allow it to be missing @@ -291,53 +299,53 @@ { printf(""); prEnsIdAnchor(id, urlTemplate); } static void prApprisTdAnchor(char *id, char *label, char *urlTemplate) /* print a gene or transcript link to APPRIS */ { // under bar separated, lower case species name. char *speciesArg = hScientificName(database); toLowerN(speciesArg, strlen(speciesArg)); subChar(speciesArg, ' ', '_'); char accBuf[64]; printf("%s", label); freeMem(speciesArg); } static void writePosLink(char *chrom, int chromStart, int chromEnd) /* write link to a genomic position */ { printf("%s:%d-%d", hgTracksPathAndSettings(), database, chrom, chromStart, chromEnd, chrom, chromStart+1, chromEnd); } static bool geneHasApprisTranscripts(struct trackDb *tdb, struct sqlConnection *conn, struct wgEncodeGencodeAttrs *transAttrs) /* check if any transcript in a gene has an APPRIS tags */ { char query[1024]; sqlSafef(query, sizeof(query), "%s tag where tag.tag like 'appris%%' and transcriptId in " "(select transcriptId from %s where geneId='%s')", - getGencodeTable(tdb, "wgEncodeGencodeTag"), - getGencodeTable(tdb, "wgEncodeGencodeAttrs"), + gencodeGetTableName(tdb, "wgEncodeGencodeTag"), + gencodeGetTableName(tdb, "wgEncodeGencodeAttrs"), transAttrs->geneId); return sqlRowCount(conn, query) > 0; } static char* findApprisTag(struct wgEncodeGencodeTag *tags) /* search list for APPRIS tag or NULL */ { struct wgEncodeGencodeTag *tag; for (tag = tags; tag != NULL; tag = tag->next) { if (startsWith("appris_", tag->tag)) return tag->tag; } return NULL; } @@ -366,35 +374,82 @@ char *geneLabel = ((apprisTag != NULL) || geneHasApprisTranscripts(tdb, conn, transAttrs)) ? transAttrs->geneName : NULL; // APPRIS gene and transcript now go to the same location printf("APPRIS\n", apprisHomeUrl); if (transLabel != NULL) prApprisTdAnchor(transAttrs->geneId, transLabel, apprisGeneUrl); else printf(" "); if (geneLabel != NULL) prApprisTdAnchor(transAttrs->geneId, geneLabel, apprisGeneUrl); else printf(" "); printf("\n"); } + +static void writeHumanGeneLinkout(struct wgEncodeGencodeAttrs *transAttrs, + boolean haveGeneSymbolSource, struct wgEncodeGencodeGeneSymbol *geneSymbolSource) +/* Write external gene database links for human if they appear to be a real + * gene symbol Getting it wrong is not a disaster, as the target database will + * just report not found. + */ +{ +boolean isReal = isRealGeneSymbol(transAttrs->geneName, haveGeneSymbolSource, geneSymbolSource); +printf("HGNC gene information"); +if (isReal) + { + if (haveGeneSymbolSource) + prExtIdAnchor(geneSymbolSource->geneId, hgncByIdUrl); + else + prExtIdAnchor(transAttrs->geneName, hgncBySymUrl); + + } +printf("\n"); + +printf("GeneCards"); +if (isReal) + prExtIdAnchor(transAttrs->geneName, geneCardsUrl); +printf("\n"); +} + +static void writeMouseGeneLinkout(struct wgEncodeGencodeAttrs *transAttrs, + boolean haveGeneSymbolSource, struct wgEncodeGencodeGeneSymbol *geneSymbolSource) +/* Write external gene database links for mouse if they appear to be a real + * gene symbol Getting it wrong is not a disaster, as the target database will + * just report not found. + */ +{ +boolean isReal = isRealGeneSymbol(transAttrs->geneName, haveGeneSymbolSource, geneSymbolSource); +printf("MGI gene information"); +if (isReal) + { + if (haveGeneSymbolSource) + prExtIdAnchor(geneSymbolSource->geneId, mgiByIdUrl); + else + prExtIdAnchor(transAttrs->geneName, mgiBySymUrl); + } +printf("\n"); + +} + static void writeBasicInfoHtml(struct sqlConnection *conn, struct trackDb *tdb, char *gencodeId, struct genePred *transAnno, struct wgEncodeGencodeAttrs *transAttrs, int geneChromStart, int geneChromEnd, struct wgEncodeGencodeGeneSource *geneSource, struct wgEncodeGencodeTranscriptSource *transcriptSource, - struct wgEncodeGencodeTag *tags, bool haveTsl, struct wgEncodeGencodeTranscriptionSupportLevel *tsl) + struct wgEncodeGencodeTag *tags, bool haveTsl, struct wgEncodeGencodeTranscriptionSupportLevel *tsl, + boolean haveGeneSymbolSource, struct wgEncodeGencodeGeneSymbol *geneSymbolSource) /* write basic HTML info for all genes */ { // basic gene and transcript information printf("\n"); printf("\n"); printf("\n"); printf("\n"); if (transAttrs->proteinId != NULL) @@ -425,49 +480,46 @@ printf("\n", transAnno->strand); printf("\n", gencodeBiotypesUrl, transAttrs->transcriptType, transAttrs->geneType); printf("\n", getLevelDesc(transAttrs->level), transAttrs->level); char *transSrcDesc = (transcriptSource != NULL) ? getMethodDesc(transcriptSource->source) : UNKNOWN; char *geneSrcDesc = (geneSource != NULL) ? getMethodDesc(geneSource->source) : UNKNOWN; printf("\n", transSrcDesc, geneSrcDesc); if (haveTsl) { char *tslDesc = getSupportLevelDesc(tsl); printf("\n", tslDesc, tslDesc); } -printf("\n"); + +if (isGrcHuman()) + writeHumanGeneLinkout(transAttrs, haveGeneSymbolSource, geneSymbolSource); +else + writeMouseGeneLinkout(transAttrs, haveGeneSymbolSource, geneSymbolSource); + printf("\n"); -printf("\n"); - if (isProteinCodingTrans(transAttrs)) writeAprrisRow(conn, tdb, transAttrs, tags); // FIXME: add sequence here?? printf("
TranscriptGene
GENCODE id"); prTdEnsIdAnchor(transAttrs->transcriptId, (isGrcH37Native(tdb) ? ensemblH37TranscriptIdUrl: ensemblTranscriptIdUrl)); prTdEnsIdAnchor(transAttrs->geneId, (isGrcH37Native(tdb) ? ensemblH37GeneIdUrl : ensemblGeneIdUrl)); printf("
Strand%s
Biotype%s%s
Annotation Level%s (%d)
Annotation Method%s%s
Transcription Support Level%s
HGNC gene symbol"); -if (!isFakeGeneSymbol(transAttrs->geneName)) - prExtIdAnchor(transAttrs->geneName, hgncUrl); -printf("
CCDS"); if (!isEmpty(transAttrs->ccdsId)) { printf("ccdsId); printf("\" target=_blank>%s", transAttrs->ccdsId); } printf("
GeneCards"); -if (!isFakeGeneSymbol(transAttrs->geneName)) - prExtIdAnchor(transAttrs->geneName, geneCardsUrl); -printf("
\n"); } static void writeSequenceHtml(struct trackDb *tdb, char *gencodeId, struct genePred *transAnno) /* write links to get sequences */ { printf("\n"); printf("\n"); printf("\n"); if (transAnno->cdsStart < transAnno->cdsEnd) { @@ -849,71 +901,75 @@ struct wgEncodeGencodePdb *pdbs = metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodePdb", "transcriptId", sqlQueryMulti, (sqlLoadFunc)wgEncodeGencodePdbLoad); struct wgEncodeGencodePubMed *pubMeds = metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodePubMed", "transcriptId", sqlQueryMulti, (sqlLoadFunc)wgEncodeGencodePubMedLoad); bool haveEntrezGene = haveGencodeTable(conn, tdb, "wgEncodeGencodeEntrezGene"); struct wgEncodeGencodeEntrezGene *entrezGenes = haveEntrezGene ? metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodeEntrezGene", "transcriptId", sqlQueryMulti, (sqlLoadFunc)wgEncodeGencodeEntrezGeneLoad) : NULL; struct wgEncodeGencodeRefSeq *refSeqs = metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodeRefSeq", "transcriptId", sqlQueryMulti, (sqlLoadFunc)wgEncodeGencodeRefSeqLoad); struct wgEncodeGencodeTag *tags = metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodeTag", "transcriptId", sqlQueryMulti, (sqlLoadFunc)wgEncodeGencodeTagLoad); struct wgEncodeGencodeTranscriptSupport *transcriptSupports = metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodeTranscriptSupport", "transcriptId", sqlQueryMulti, (sqlLoadFunc)wgEncodeGencodeTranscriptSupportLoad); struct wgEncodeGencodeExonSupport *exonSupports = NULL; // exonSupports not available in back mapped GENCODE releases if (haveGencodeTable(conn, tdb, "wgEncodeGencodeExonSupport")) exonSupports = metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodeExonSupport", "transcriptId", sqlQueryMulti, (sqlLoadFunc)wgEncodeGencodeExonSupportLoad); struct wgEncodeGencodeUniProt *uniProts = metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodeUniProt", "transcriptId", sqlQueryMulti, (sqlLoadFunc)wgEncodeGencodeUniProtLoad); slSort(&uniProts, uniProtDatasetCmp); bool haveTsl = haveGencodeTable(conn, tdb, "wgEncodeGencodeTranscriptionSupportLevel"); struct wgEncodeGencodeTranscriptionSupportLevel *tsl = haveTsl ? metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodeTranscriptionSupportLevel", "transcriptId", 0, (sqlLoadFunc)wgEncodeGencodeTranscriptionSupportLevelLoad) : NULL; +boolean haveGeneSymbolSource = haveGencodeTable(conn, tdb, "wgEncodeGencodeGeneSymbol"); +struct wgEncodeGencodeGeneSymbol *geneSymbolSource = haveGeneSymbolSource ? metaDataLoad(tdb, conn, gencodeId, "wgEncodeGencodeGeneSymbol", "transcriptId", 0, (sqlLoadFunc)wgEncodeGencodeGeneSymbolLoad) : NULL; int geneChromStart, geneChromEnd; getGeneBounds(tdb, conn, transAnno, &geneChromStart, &geneChromEnd); char title[256]; -safef(title, sizeof(title), "GENCODE V%s Transcript Annotation", getGencodeVersion(tdb)); +safef(title, sizeof(title), "GENCODE V%s Transcript Annotation", gencodeGetVersion(tdb)); char header[256]; safef(header, sizeof(header), "%s %s", title, gencodeId); if (!isEmpty(transAttrs->geneName)) safef(header, sizeof(header), "%s %s (%s)", title, gencodeId, transAttrs->geneName); else safef(header, sizeof(header), "%s %s", title, gencodeId); cartWebStart(cart, database, "%s", header); printf("

%s

\n", header); -writeBasicInfoHtml(conn, tdb, gencodeId, transAnno, transAttrs, geneChromStart, geneChromEnd, geneSource, transcriptSource, tags, haveTsl, tsl); +writeBasicInfoHtml(conn, tdb, gencodeId, transAnno, transAttrs, geneChromStart, geneChromEnd, geneSource, transcriptSource, tags, + haveTsl, tsl, haveGeneSymbolSource, geneSymbolSource); writeTagLinkHtml(tags); writeSequenceHtml(tdb, gencodeId, transAnno); if (haveRemarks) writeAnnotationRemarkHtml(remarks); if (isProteinCodingTrans(transAttrs)) writePdbLinkHtml(pdbs); writePubMedLinkHtml(pubMeds); if (haveEntrezGene) writeEntrezGeneLinkHtml(entrezGenes); writeRefSeqLinkHtml(refSeqs); if (isProteinCodingTrans(transAttrs)) writeUniProtLinkHtml(uniProts); writeSupportingEvidenceLinkHtml(tdb, gencodeId, transcriptSupports, exonSupports); wgEncodeGencodeAttrsFree(&transAttrs); wgEncodeGencodeAnnotationRemarkFreeList(&remarks); wgEncodeGencodeGeneSourceFreeList(&geneSource); wgEncodeGencodeTranscriptSourceFreeList(&transcriptSource); wgEncodeGencodePdbFreeList(&pdbs); wgEncodeGencodePubMedFreeList(&pubMeds); wgEncodeGencodeEntrezGeneFreeList(&entrezGenes); wgEncodeGencodeRefSeqFreeList(&refSeqs); wgEncodeGencodeTranscriptSupportFreeList(&transcriptSupports); wgEncodeGencodeExonSupportFreeList(&exonSupports); wgEncodeGencodeUniProtFreeList(&uniProts); +wgEncodeGencodeGeneSymbolFreeList(&geneSymbolSource); wgEncodeGencodeTranscriptionSupportLevelFreeList(&tsl); } static void doGencodeGene2WayPseudo(struct trackDb *tdb, char *gencodeId, struct sqlConnection *conn, struct genePred *pseudoAnno) /* Process click on a GENCODE two-way pseudogene annotation track. */ { char header[256]; safef(header, sizeof(header), "GENCODE 2-way consensus pseudogene %s", gencodeId); cartWebStart(cart, database, "%s", header); printf("

%s

\n", header); printf("Yale id: "); prExtIdAnchor(gencodeId, yalePseudoUrl); printf("
"); printPos(pseudoAnno->chrom, pseudoAnno->txStart, pseudoAnno->txEnd, pseudoAnno->strand, FALSE, NULL); }
Sequences