4fb78c6bbad5852d825f348e8ec13faaa6b46f5c
markd
  Tue Jul 18 12:37:09 2023 -0700
allow UTR as a discontinouis feature

diff --git src/lib/gff3.c src/lib/gff3.c
index 18e05cc..494e823 100644
--- src/lib/gff3.c
+++ src/lib/gff3.c
@@ -47,30 +47,31 @@
 char *gff3FeatGene = "gene";
 char *gff3FeatPseudogene = "pseudogene";
 char *gff3FeatNCRnaGene ="ncRNA_gene";
 char *gff3FeatNCRna ="ncRNA";
 char *gff3FeatRRna = "rRNA";
 char *gff3FeatTRna = "tRNA";
 char *gff3FeatMRna = "mRNA";
 char *gff3FeatLncRna = "lnc_RNA";
 char *gff3FeatPseudogenicTranscript = "pseudogenic_transcript";
 char *gff3FeatScRna = "scRNA";
 char *gff3FeatSnRna = "snRNA";
 char *gff3FeatSnoRna = "snoRNA";
 char *gff3FeatUnconfirmedTranscript = "unconfirmed_transcript";
 char *gff3FeatExon = "exon";
 char *gff3FeatCDS = "CDS";
+char *gff3FeatUTR = "UTR";
 char *gff3FeatThreePrimeUTR = "three_prime_UTR";
 char *gff3FeatFivePrimeUTR = "five_prime_UTR";
 char *gff3FeatStartCodon = "start_codon";
 char *gff3FeatStopCodon = "stop_codon";
 char *gff3FeatTranscript = "transcript";
 char *gff3FeatPrimaryTranscript = "primary_transcript";
 char *gff3FeatCGeneSegment = "C_gene_segment";
 char *gff3FeatDGeneSegment = "D_gene_segment";
 char *gff3FeatJGeneSegment = "J_gene_segment";
 char *gff3FeatVGeneSegment = "V_gene_segment";
 
 static bool gff3FileStopDueToErrors(struct gff3File *g3f)
 /* determine if we should stop due to the number of errors */
 {
 return g3f->errCnt > g3f->maxErr;
@@ -944,30 +945,31 @@
     gff3AnnErr(g3a, FALSE, "Annotation records for discontinuous features with ID=\"%s\" must have one and only one parent", g3a->id);
 for (struct gff3Ann *g3a2 = g3a->nextPart; (g3a2 != NULL) && !gff3FileStopDueToErrors(g3a->file); g3a2 = g3a2->nextPart)
     {
     if (slCount(g3a2->parentIds) != 1)
         gff3AnnErr(g3a2, FALSE, "Annotation records for discontinuous features with ID=\"%s\" must have one and only one parent", g3a2->id);
     else if (!sameString(g3a->type, g3a2->type))
         gff3AnnErr(g3a2, FALSE, "Annotation records for discontinuous features with ID=\"%s\" do not have the same type, found \"%s\" and \"%s\"", g3a->id, g3a->type, g3a2->type);
     else if (!sameString(g3a2->parentIds->name, g3a->parentIds->name))
         gff3AnnErr(g3a2, FALSE, "Annotation records for discontinuous features with ID=\"%s\" must have same parent, found: \"%s\" and \"%s\"", g3a->id,
                    g3a2->parentIds->name, g3a->parentIds->name);
     }
 
 // The discontinuous features abomination means we can't check for duplicate
 // ids in features were it makes no sense. Add non-spec restriction.
 if (!(sameString(g3a->type, gff3FeatCDS) ||
+      sameString(g3a->type, gff3FeatUTR) ||
       sameString(g3a->type, gff3FeatThreePrimeUTR) ||
       sameString(g3a->type, gff3FeatFivePrimeUTR) ||
       sameString(g3a->type, gff3FeatStartCodon) ||
       sameString(g3a->type, gff3FeatStopCodon)))
     gff3AnnErr(g3a, FALSE, "Incorrect duplicated ID=\"%s\" or attempt to create discontinuous features for type \"%s\"",
                g3a->id, g3a->type);
 }
 
 static void discontinFeatureFillArray(struct gff3Ann *g3a, int numAnns, struct gff3Ann *featAnns[])
 /* convert list to array for sorting */
 {
 int i = 0;
 for (; g3a != NULL; g3a = g3a->nextPart)
     featAnns[i++] = g3a;
 }