58e020e2059bc60516a8c7282781a4201be42e70 chmalee Fri May 24 14:57:10 2019 -0700 hubCheck reports errors in sortOrder setting of composite subtracks, refs #13428 diff --git src/hg/utils/hubCheck/hubCheck.c src/hg/utils/hubCheck/hubCheck.c index 59a9304..774dd6d 100644 --- src/hg/utils/hubCheck/hubCheck.c +++ src/hg/utils/hubCheck/hubCheck.c @@ -443,30 +443,61 @@ { /* check level */ struct trackHubSettingSpec *checkLevel = NULL; AllocVar(checkLevel); checkLevel->level = options->level; if (trackHubSettingLevel(hubSetting) < trackHubSettingLevel(checkLevel)) { dyStringPrintf(errors, "Setting '%s' is level '%s'\n", setting, hubSetting->level); retVal = 1; } freez(&checkLevel); } return retVal; } +void hubCheckCompositeSettings(struct trackHub *hub, struct trackHubGenome *genome, struct trackDb *tdb, struct dyString *errors) +/* Check composite level settings like subgroups, dimensions, sortOrder, etc */ +{ +if (!tdbIsComposite(tdb)) + return; + +sortOrder_t *sortOrder = NULL; +membership_t *membership = NULL; +struct slRef *subtrackRef, *subtrackRefList = NULL; + +// check that if a sortOrder is defined, then subtracks exist in the subgroup +sortOrder = sortOrderGet(NULL, tdb); +if (sortOrder) + { + subtrackRefList = trackDbListGetRefsToDescendantLeaves(tdb->subtracks); + for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next) + { + struct trackDb *subtrack = subtrackRef->val; + membership = subgroupMembershipGet(subtrack); + int i; + for (i = 0; i < sortOrder->count; i++) + { + char *col = sortOrder->column[i]; + if (membership == NULL || stringArrayIx(col, membership->subgroups, membership->count) == -1) + dyStringPrintf(errors, + "sortOrder %s defined for all subtracks of the composite track \"%s\", but the track \"%s\" is not a member of this subGroup\n", col, tdb->shortLabel, subtrack->shortLabel); + } + } + } +} + void hubCheckParentsAndChildren(struct trackDb *tdb) /* Check that a single trackDb stanza has the correct parent and subtrack pointers */ { if (tdbIsSuper(tdb) || tdbIsComposite(tdb) || tdbIsCompositeView(tdb) || tdbIsContainer(tdb)) { if (tdb->subtracks == NULL) { errAbort("Track \"%s\" is declared superTrack, compositeTrack, view or " "container, but has no subtracks", tdb->track); } // Containers should not have a bigDataUrl setting if (trackDbLocalSetting(tdb, "bigDataUrl")) { errAbort("Track \"%s\" is declared superTrack, compositeTrack, view or " @@ -510,30 +541,32 @@ { printf("\t%s : %s\n", pair->name, (char *)pair->val); } printf("\n"); } slPairFreeValsAndList(&metaPairs); } if (!options->checkFiles) return retVal; struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { hubCheckParentsAndChildren(tdb); + if (tdbIsComposite(tdb)) + hubCheckCompositeSettings(hub, genome, tdb, errors); hubCheckBigDataUrl(hub, genome, tdb); } errCatchEnd(errCatch); if (errCatch->gotError) { retVal = 1; dyStringPrintf(errors, "%s", errCatch->message->string); } errCatchFree(&errCatch); if (tdb->subtracks != NULL) { retVal |= hubCheckTrack(hub, genome, tdb->subtracks, options, errors); }