c2c65344c6ae672dbc05e7920049803c3fe29874 tdreszer Thu Sep 16 12:29:34 2010 -0700 Fixed tdbVisLimitedByAncestry which caused supertrack contained and visibble tracks to appear hidden in findTracks. Added composite/view vis reshaping based upon subtrack specific vis. diff --git src/hg/lib/cart.c src/hg/lib/cart.c index acbbb5a..6644ce4 100644 --- src/hg/lib/cart.c +++ src/hg/lib/cart.c @@ -831,32 +831,58 @@ hashElFreeList(&list); } -void cartRemoveLike(struct cart *cart, char *wildCard) -/* Remove all variable from cart that match wildCard. */ +struct slPair *cartVarsLike(struct cart *cart, char *wildCard) +/* Return a slPair list of cart vars that match the wildcard */ { +struct slPair *cartVars = NULL; struct hashEl *el, *elList = hashElListHash(cart->hash); - slSort(&elList, hashElCmp); for (el = elList; el != NULL; el = el->next) { if (wildMatch(wildCard, el->name)) - cartRemove(cart, el->name); + slAddHead(&cartVars,slPairNew(el->name,el->val)); } -hashElFreeList(&el); +hashElFreeList(&elList); +return cartVars; } -void cartRemovePrefix(struct cart *cart, char *prefix) -/* Remove variables with given prefix from cart. */ +struct slPair *cartVarsWithPrefix(struct cart *cart, char *prefix) +/* Return a slPair list of cart vars that begin with prefix */ { +struct slPair *cartVars = NULL; struct hashEl *el, *elList = hashElListHash(cart->hash); - slSort(&elList, hashElCmp); for (el = elList; el != NULL; el = el->next) { if (startsWith(prefix, el->name)) - cartRemove(cart, el->name); + slAddHead(&cartVars,slPairNew(el->name,el->val)); + } +hashElFreeList(&elList); +return cartVars; +} + +void cartRemoveLike(struct cart *cart, char *wildCard) +/* Remove all variable from cart that match wildCard. */ +{ +struct slPair *cartVars = cartVarsLike(cart,wildCard); +while(cartVars != NULL) + { + struct slPair *cartVar = slPopHead(&cartVars); + cartRemove(cart, cartVar->name); + freeMem(cartVar); + } +} + +void cartRemovePrefix(struct cart *cart, char *prefix) +/* Remove variables with given prefix from cart. */ +{ +struct slPair *cartVars = cartVarsWithPrefix(cart,prefix); +while(cartVars != NULL) + { + struct slPair *cartVar = slPopHead(&cartVars); + cartRemove(cart, cartVar->name); + freeMem(cartVar); } -hashElFreeList(&el); } boolean cartVarExists(struct cart *cart, char *var) @@ -1983,45 +2009,15 @@ return (differentString(newValue,oldValue)); } -struct slRef *cartNamesLike(struct cart *cart, char *wildCard) -/* Returns reference list of all variable names that match wildCard. */ -{ -struct hashEl *el, *elList = hashElListHash(cart->hash); -struct slRef *matches = NULL; - -for (el = elList; el != NULL; el = el->next) - { - if (wildMatch(wildCard, el->name)) - slAddHead(&matches,slRefNew(el->name)); - } -hashElFreeList(&elList); -return matches; -} - -struct slRef *cartNamesPrefixedBy(struct cart *cart, char *prefix) -/* Returns reference list of all variable names with given prefix. */ -{ -struct hashEl *el, *elList = hashElListHash(cart->hash); -struct slRef *matches = NULL; - -for (el = elList; el != NULL; el = el->next) - { - if (startsWith(prefix, el->name)) - slAddHead(&matches,slRefNew(el->name)); - } -hashElFreeList(&elList); -return matches; -} - int cartNamesPruneChanged(struct cart *newCart,struct hash *oldVars, - struct slRef **cartNames,boolean ignoreRemoved,boolean unChanged) + struct slPair **cartNames,boolean ignoreRemoved,boolean unChanged) /* Prunes a list of cartNames if the settings have changed between new and old cart. Returns pruned count */ { int pruned = 0; -struct slRef *oldList = *cartNames; -struct slRef *newList = NULL; -struct slRef *oneName = NULL; +struct slPair *oldList = *cartNames; +struct slPair *newList = NULL; +struct slPair *oneName = NULL; while ((oneName = slPopHead(&oldList)) != NULL) { boolean thisOneChanged = cartValueHasChanged(newCart,oldVars,oneName->val,ignoreRemoved,TRUE); @@ -2058,6 +2054,215 @@ return removed; } +// Shaping composite vis by subtrack specific vis comes in 3 flavors: +// Simple) No shaping. Subtrack specific vis overrides composite/view level but does not alter it +// Plan A) When composite is in default settings only, then composite/vis is shaped to reflect current subtrack vis +// Plan B) Whenever there is subtrack level vis, the composite and view vis are shaped to show maximum subtrack vis, +// while subtracks with inherited vis may be given subtrack specific vis to return them to that state +#define COMPOSITE_VIS_SHAPING_PLAN_A +//#define COMPOSITE_VIS_SHAPING_PLAN_B + +#if defined(COMPOSITE_VIS_SHAPING_PLAN_A) || defined(COMPOSITE_VIS_SHAPING_PLAN_B) +static int cartTdbParentShapeVis(struct cart *cart,struct trackDb *parent,char *view,struct slRef *refSubtracks,struct slPair *subVisVars,boolean compositeAtDefault) +// This shapes one level of vis (view or composite) based upon subtrack specific visibility. Returns count of subtracks affected +{ +int count=0; +struct slPair *subVisVar = NULL; +struct trackDb *subtrack = NULL; +char setting[512]; +if (view != NULL) + safef(setting,sizeof(setting),"%s.%s.vis",parent->parent->track,view); +else + safef(setting,sizeof(setting),"%s",parent->track); + +enum trackVisibility vis = tvHide; // Looking for max vis of subtrack specific +enum trackVisibility visOrig = hTvFromString(cartUsualString(cart,setting,hStringFromTv(parent->visibility))); +if (!compositeAtDefault) + vis = visOrig; // Default view vis to current vis +for(subVisVar=subVisVars;subVisVar!=NULL;subVisVar=subVisVar->next) + { + if (endsWith(subVisVar->name,"_sel")) + { + subtrack = subVisVar->val; + if (parent != subtrack->parent) // This should be true whether at view level or composite level, + continue; // since composite level call only happens composite has no views + + char *cartVis = cartOptionalString(cart,subtrack->track); + assert(cartVis != NULL); // Otherwise it wouldn't be in subVisVar + enum trackVisibility visSub = hTvFromString(cartVis); + if (tvCompare(vis, visSub) >= 0) + vis = visSub; // vis will wind up with setting of highest vis subtrack + } + } +if (vis != visOrig) + { + cartSetString(cart,setting,hStringFromTv(vis)); + //warn("Set %s to %s",(view?view:parent->track),hStringFromTv(vis)); + + // Now set all subtracks that inherit vis back to visOrig + struct slRef *refSub; + for(refSub = refSubtracks;refSub != NULL;refSub = refSub->next) + { + subtrack = refSub->val; + if (parent != subtrack->parent) // This should work whether at view level or composite level, + continue; // since composite level call only happens composite has no views + + if (!slPairFind(subVisVars, subtrack->track)) // if the subtrack doesn't have individual vis AND... + { + // FIXME problem is fourState gets cached + int fourState = subtrackFourStateChecked(subtrack,cart); + if (fourStateChecked(fourState)) // subtrack is checked + { + if (compositeAtDefault || visOrig == tvHide) + subtrackFourStateCheckedSet(subtrack, cart,FALSE,fourStateEnabled(fourState)); + else + cartSetString(cart,subtrack->track,hStringFromTv(visOrig)); + count++; + } + } + } + //warn("Altered %d subtrack(s) for %s",count,(view?view:parent->track)); + + if (tdbIsCompositeView(parent)) + { + cartSetString(cart,parent->parent->track,"full"); // Now set composite to full. + //warn("Set composite %s to full",tdbComposite->track); + } + } +return count; +} + +static boolean cartVarsAllFoundForTdb(struct cart *cart,struct slPair *subVisVars,struct trackDb *tdb) +{ +struct slPair *cartVar,*cartVars = cartVarsWithPrefix(cart,tdb->track); +if (cartVars != NULL) + { + for (cartVar = cartVars; cartVar != NULL; cartVar = cartVar->next) + { + if (tdbIsCompositeView(tdb) || !slPairFind(subVisVars, cartVar->name)) // subVisVars does not contain anything prefixed by view! + { + // NOTE: This is less than ideal! Composites (not memebers of superTracks) are getting their cart vis set on hgTracks:config page! + if (tdbIsComposite(tdb) + && sameString(cartVar->name,tdb->track) + && sameString((char *)cartVar->val,hStringFromTv(tdb->visibility)) ) + continue; + + slFreeList(&cartVars); + return FALSE; // Any view cart vars means non-default so do not "shape" composite + } + } + slFreeList(&cartVars); + } +return TRUE; +} +#endif/// defined(COMPOSITE_VIS_SHAPING_PLAN_A) || defined(COMPOSITE_VIS_SHAPING_PLAN_B) + +boolean cartTdbTreeMatchSubtrackVis(struct cart *cart,struct trackDb *tdbComposite) +/* When subtrack vis is set via findTracks, and composite has no cart settings, + then "shape" composite to match found */ +{ +#if !defined(COMPOSITE_VIS_SHAPING_PLAN_A) && !defined(COMPOSITE_VIS_SHAPING_PLAN_B) + return FALSE; // Don't do any shaping +#else/// if defined(COMPOSITE_VIS_SHAPING_PLAN_A) || defined(COMPOSITE_VIS_SHAPING_PLAN_B) + +// First look for subtrack vis +char setting[512]; +struct trackDb *subtrack = NULL; +struct slPair *subVisVar, *subVisVars = NULL; +struct slRef *tdbRef, *tdbRefList = trackDbListGetRefsToDescendantLeaves(tdbComposite->subtracks); +for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next) + { + subtrack = tdbRef->val; + char *val=cartOptionalString(cart,subtrack->track); + if (val && differentString(val,"hide")) // NOTE should we include hide? + { + subVisVar = slPairNew(subtrack->track,val); // subtrack has sub level vis + slAddHead(&subVisVars,subVisVar); + // Add the "_sel" setting which should also exist. Point it to subtrack + safef(setting,sizeof(setting),"%s_sel",subtrack->track); + subVisVar = slPairNew(setting,subtrack); + slAddHead(&subVisVars,subVisVar); + } + } +if (slCount(subVisVars) == 0) + { + //warn("No subtrack vis found."); + slFreeList(&tdbRefList); + return FALSE; + } + +// Next look for any cart settings other than subtrack vis/sel +boolean compositeAtDefault = TRUE; +compositeAtDefault = cartVarsAllFoundForTdb(cart,subVisVars,tdbComposite); +#ifndef COMPOSITE_VIS_SHAPING_PLAN_B +if (!compositeAtDefault) + { + slFreeList(&tdbRefList); + slFreeList(&subVisVars); + return FALSE; // Any view cart vars means non-default so do not "shape" composite + } +#endif///ndef COMPOSITE_VIS_SHAPING_PLAN_B + +// What about view level settings? +struct trackDb *tdbView = tdbComposite->subtracks; +boolean hasViews = FALSE; +if (tdbIsCompositeView(tdbView)) + { + if (compositeAtDefault) + { + for( ;tdbView != NULL; tdbView = tdbView->next ) + { + compositeAtDefault = cartVarsAllFoundForTdb(cart,subVisVars,tdbView); + #ifndef COMPOSITE_VIS_SHAPING_PLAN_B + if (!compositeAtDefault) + { + slFreeList(&tdbRefList); + slFreeList(&subVisVars); + return FALSE; // Any view cart vars means non-default so do not "shape" composite + } + #endif///ndef COMPOSITE_VIS_SHAPING_PLAN_B + } + } + hasViews = TRUE; + } + +// How about subtrack level settings? Assume that compositePrefix caught them? If views then YES +if (compositeAtDefault && !hasViews) + { + for(tdbRef = tdbRefList;tdbRef != NULL; tdbRef = tdbRef->next ) + { + compositeAtDefault = cartVarsAllFoundForTdb(cart,subVisVars,subtrack); + #ifndef COMPOSITE_VIS_SHAPING_PLAN_B + if (!compositeAtDefault) + { + slFreeList(&tdbRefList); + slFreeList(&subVisVars); + return FALSE; // Any view cart vars means non-default so do not "shape" composite + } + #endif///ndef COMPOSITE_VIS_SHAPING_PLAN_B + } + } + +// Now shape views and composite to match subtrack specific visibility + int count = 0; +if (hasViews) + { + for(tdbView = tdbComposite->subtracks;tdbView != NULL; tdbView = tdbView->next ) + { + char *view = trackDbSetting(tdbView,"view"); + assert(view != NULL); + count += cartTdbParentShapeVis(cart,tdbView,view,tdbRefList,subVisVars,compositeAtDefault); + } + } +else // If no views then composite is not set to fuul but to max of subtracks + count = cartTdbParentShapeVis(cart,tdbComposite,NULL,tdbRefList,subVisVars,compositeAtDefault); +//warn("Altered %d subtrack(s)",count); + +slFreeList(&tdbRefList); +slFreeList(&subVisVars); +return TRUE; +#endif/// defined(COMPOSITE_VIS_SHAPING_PLAN_A) || defined(COMPOSITE_VIS_SHAPING_PLAN_B) +} boolean cartTdbTreeCleanupOverrides(struct trackDb *tdb,struct cart *newCart,struct hash *oldVars) /* When composite/view settings changes, remove subtrack specific settings @@ -2069,7 +2274,7 @@ // vis is a special additive case! composite or view level changes then remove subtrack vis boolean compositeVisChanged = cartValueHasChanged(newCart,oldVars,tdb->track,TRUE,TRUE); struct trackDb *tdbView = NULL; -struct slRef *oneName = NULL; +struct slPair *oneName = NULL; char * var = NULL; int clensed = 0; @@ -2088,14 +2293,14 @@ safef(setting,sizeof(setting),"%s.",tdb->track); char * view = NULL; boolean hasViews = FALSE; -struct slRef *changedSettings = cartNamesPrefixedBy(newCart, setting); +struct slPair *changedSettings = cartVarsWithPrefix(newCart, setting); for (tdbView = tdb->subtracks;tdbView != NULL; tdbView = tdbView->next) { if (!tdbIsView(tdbView,&view)) break; hasViews = TRUE; safef(setting,sizeof(setting),"%s.",tdbView->track); - struct slRef *changeViewSettings = cartNamesPrefixedBy(newCart, setting); + struct slPair *changeViewSettings = cartVarsWithPrefix(newCart, setting); changedSettings = slCat(changedSettings, changeViewSettings); } if (changedSettings == NULL && !compositeVisChanged) @@ -2125,7 +2330,7 @@ safef(setting, sizeof(setting),"%s.%s.",tdb->track,view); // unfortunatly setting name could be wgEncodeBroadHistone.Sig.???r char settingAlt[512]; safef(settingAlt,sizeof(settingAlt),"%s.",tdbView->track); // or wgEncodeBroadHistoneViewSig.??? - struct slRef *leftOvers = NULL; + struct slPair *leftOvers = NULL; // Walk through settings that match this view while ((oneName = slPopHead(&changedSettings)) != NULL) {