dc5b5de8b09d0cd08c953805e29601860bbbd2ad
chmalee
  Mon Jul 27 11:44:51 2026 -0700
allow '>' one-way and '~' bidirectional relatedTracks entries, refs #37390

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

diff --git src/hg/makeDb/trackDb/buildRelatedTracks src/hg/makeDb/trackDb/buildRelatedTracks
index 6609b400e1c..3aa0eac29a2 100755
--- src/hg/makeDb/trackDb/buildRelatedTracks
+++ src/hg/makeDb/trackDb/buildRelatedTracks
@@ -1,38 +1,45 @@
 #!/bin/bash
 # Build the relatedTracks table for each assembly
 set -beEu -o pipefail
 
 function usage() {
     printf "Usage: %s relatedTrack_name db1 db2 ...\n" "`basename $0`"
     printf "Build the relatedTrack tables for each assembly listed in relatedTracks.ra\n"
     printf "The first argument must be the name of the table to build, followed by all\nthe"
     printf "assemblies to update (similar to trackDb update process)\n"
 }
 
 if [ $# -lt 2 ] ; then
     echo "wrong # args" >&2
     usage >&2
     exit 1
 fi
 
 tbl="$1"; shift;
 
 for db in $*; do
     set +e
     grep -wq "^$db" relatedTracks.ra &> /dev/null
     if [ $? -eq 0 ]
     then
         set -e
-        # enfore two lines per relationship:
-        uniqTables=$(comm -3 <(grep -w "^$db" relatedTracks.ra | cut -d' ' -f2 | sort) <(grep -w "^$db" relatedTracks.ra | cut -d' ' -f3 | sort) | wc -l)
+        # enfore two lines per relationship, skipping the '>' and '~' entries
+        # that state their own direction:
+        recip=$(grep -w "^$db" relatedTracks.ra | grep -v "^[^ ]* [>~]" || true)
+        uniqTables=$(comm -3 <(echo "$recip" | cut -d' ' -f2 | sort) <(echo "$recip" | cut -d' ' -f3 | sort) | wc -l)
         if [ $uniqTables -gt 0 ]; then
             printf "ERROR: mismatched primary and secondary related tracks for '%s'\n" "$db"
-            echo "Tracks:" $(comm -3 <(grep -w "^$db" relatedTracks.ra | cut -d' ' -f2 | sort) <(grep -w "^$db" relatedTracks.ra | cut -d' ' -f3 | sort))
+            echo "Tracks:" $(comm -3 <(echo "$recip" | cut -d' ' -f2 | sort) <(echo "$recip" | cut -d' ' -f3 | sort))
             exit 255
         fi
+        # '>track1' is one way, so just drop the marker.  '~track1' is bidirectional,
+        # so emit the line as written and again with the two tracks swapped.  In that
+        # second expression \1 is track1, \2 is track2 and \3 is the reason text.
         grep -w "^$db" relatedTracks.ra | cut -d' ' -f2- \
+            | sed -e 's/^>//' \
+                  -e 's/^~\([^ ]*\) \([^ ]*\) \(.*\)/\1 \2 \3\n\2 \1 \3/' \
             | sed -e 's/ /\t/' -e 's/ /\t/' | sort -k1 -k2 \
             | /cluster/bin/x86_64/hgLoadSqlTab "$db" "$tbl" ~/kent/src/hg/lib/relatedTrack.sql stdin
         printf "done building relatedTrack table for %s\n" "$db"
     fi
 done