ca9aa98fe525e6a571de9edb55def7cad009c920
markd
  Fri Jun 30 00:20:40 2023 -0700
add pslMap -check option to check for valid PSLs to aid in debugging

diff --git src/utils/pslMap/pslMap.c src/utils/pslMap/pslMap.c
index 2f552bb..026a0f9 100644
--- src/utils/pslMap/pslMap.c
+++ src/utils/pslMap/pslMap.c
@@ -8,48 +8,50 @@
 #include "options.h"
 #include "linefile.h"
 #include "genomeRangeTree.h"
 #include "dystring.h"
 #include "psl.h"
 #include "dnautil.h"
 #include "chain.h"
 #include "verbose.h"
 
 
 /* command line option specifications */
 static struct optionSpec optionSpecs[] = {
     {"suffix", OPTION_STRING},
     {"keepTranslated", OPTION_BOOLEAN},
     {"mapFileWithInQName", OPTION_BOOLEAN},
+    {"check", OPTION_BOOLEAN},
     {"chainMapFile", OPTION_BOOLEAN},
     {"swapMap", OPTION_BOOLEAN},
     {"swapIn", OPTION_BOOLEAN},
     {"mapInfo", OPTION_STRING},
     {"mappingPsls", OPTION_STRING},
     {"inType", OPTION_STRING},
     {"mapType", OPTION_STRING},
     {"simplifyMappingIds", OPTION_BOOLEAN},
     {NULL, 0}
 };
 
 /* Values parsed from command line */
 static char* suffix = NULL;
 static unsigned mapOpts = pslTransMapNoOpts;
 static boolean mapFileWithInQName = FALSE;
 static boolean chainMapFile = FALSE;
 static boolean swapMap = FALSE;
 static boolean swapIn = FALSE;
+static boolean check = FALSE;
 static boolean simplifyMappingIds = FALSE;
 static char* mapInfoFile = NULL;
 static char* mappingPslFile = NULL;
 static enum pslType inPslType = pslTypeUnspecified;
 static enum pslType mapPslType = pslTypeUnspecified;
 
 static char *mapInfoHdr =
     "#srcQName\t" "srcQStart\t" "srcQEnd\t" "srcQSize\t"
     "srcTName\t" "srcTStart\t" "srcTEnd\t"
     "srcStrand\t" "srcAligned\t"
     "mappingQName\t" "mappingQStart\t" "mappingQEnd\t"
     "mappingTName\t" "mappingTStart\t" "mappingTEnd\t"
     "mappingStrand\t" "mappingId\t"
     "mappedQName\t" "mappedQStart\t" "mappedQEnd\t"
     "mappedTName\t" "mappedTStart\t" "mappedTEnd\t"
@@ -309,39 +311,44 @@
     addQNameSuffix(mappedPsl);
 pslTabOut(mappedPsl, outPslFh);
 if (mapInfoFh != NULL)
     writeMapInfo(mapInfoFh, inPsl, mapAln, mappedPsl, outPslLine);
 if (mappingPslFh != NULL)
     pslTabOut(mapAln->psl, mappingPslFh);
 }
 
 static boolean mapPslPair(struct psl *inPsl, struct mapAln *mapAln,
                           FILE* outPslFh, FILE *mapInfoFh, FILE *mappingPslFh,
                           unsigned* outPslLineRef)
 /* map one pair of query and target PSL */
 {
 verbosePslNl(2, "inAln", inPsl);
 verbosePslNl(2, "mapAln", mapAln->psl);
+if (check && (pslCheck("input PSL", stderr, inPsl) > 0))
+    errAbort("BUG: invalid input PSL, run with -verbose=2 for more details");
+if (check && (pslCheck("mapping PSL", stderr, mapAln->psl) > 0))
+    errAbort("BUG: invalid mapping PSL, run with -verbose=2 for more details");
 
 struct psl* mappedPsl = pslTransMap(mapOpts, inPsl, inPslType, mapAln->psl, mapPslType);
-
-verbosePslNl(2, "mappedAln", mappedPsl);
+verbosePslNl(2, "mappedPsl", mappedPsl);
 
 /* only output if blocks were actually mapped */
 boolean wasMapped = mappedPsl != NULL;
 if (wasMapped)
     {
+    if (check && (pslCheck("mapped psl", stderr, mappedPsl) > 0))
+        errAbort("BUG: invalid mapped PSL created, run with -verbose=2 for more details");
     mappedPslOutput(inPsl, mapAln, mappedPsl, outPslFh, mapInfoFh, mappingPslFh, *outPslLineRef);
     (*outPslLineRef)++;
     }
 pslFree(&mappedPsl);
 return wasMapped;
 }
 
 static void mapQueryPsl(struct psl* inPsl, struct genomeRangeTree *mapAlns,
                         FILE* outPslFh, FILE *mapInfoFh, FILE *mappingPslFh,
                         unsigned* outPslLineRef)
 /* map a query psl to all targets  */
 {
 static struct dyString *idBuf = NULL;
 struct range *overMapAlnNodes = genomeRangeTreeAllOverlapping(mapAlns, getMappingId(inPsl->tName, &idBuf), inPsl->tStart, inPsl->tEnd);
 struct range *overMapAlnNode;
@@ -400,30 +407,31 @@
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 optionInit(&argc, argv, optionSpecs);
 if (argc != 4)
     usage();
 suffix = optionVal("suffix", NULL);
 if (optionExists("keepTranslated"))
     mapOpts |= pslTransMapKeepTrans;
 mapFileWithInQName = optionExists("mapFileWithInQName");
 chainMapFile = optionExists("chainMapFile");
 if (mapFileWithInQName && chainMapFile)
     errAbort("can't specify -mapFileWithInQName with -chainMapFile");
 swapMap = optionExists("swapMap");
 swapIn = optionExists("swapIn");
+check = optionExists("check");
 simplifyMappingIds = optionExists("simplifyMappingIds");
 char *typeStr;
 if ((typeStr = optionVal("inType", NULL)) != NULL)
     inPslType = parsePslType(typeStr);
 if ((typeStr = optionVal("mapType", NULL)) != NULL)
     mapPslType = parsePslType(typeStr);
 
 mapInfoFile = optionVal("mapInfo", NULL);
 mappingPslFile = optionVal("mappingPsls", NULL);
 pslMap(argv[1], argv[2], argv[3]);
 
 return 0;
 }
 /*
  * Local Variables: