a8694a3b22d43f0536c02101e9f3b56b5339b4dc max Wed Sep 9 05:47:17 2026 -0700 hubtools: add "import igv" and "splitHap", and the bTaeGut7 zebra finch hub import igv builds a hub from an IGV session XML. Every Track element becomes a track, in session order, with the IGV display attributes translated to trackDb settings. Files the browser can read over the network are linked where they are; bed, gff, gtf, wig and bedGraph are downloaded and converted, which needs chrom.sizes and gets them from --chromSizes, from the UCSC assembly, or from a bigWig of the session itself, the only source there is for a custom assembly. The BED cleaner exists because real files are not to spec: reversed start/end, scores over 1000, "#rrggbb" colours, names past 255 characters, and columns that are not the BED field they sit in, such as trf writing the repeat motif where thickStart belongs. splitHap turns a hub built on a diploid assembly into one hub with a genome per haplotype, reading both assemblies' chrom.sizes and chromAlias from GenArk and sending each record to whichever assembly has its sequence. It writes splitHap.report.txt with the records per track per haplotype, the sequences neither assembly has, and the records reaching past a sequence end, and checks every track as it goes: records read must equal records matched plus records with no sequence, and every match must produce an output record or a drop. A track that does not add up stops the run rather than being written up as a finding. Two conversion fixes that came out of the zebra finch data. GFF3 requires unique IDs, but an annotation of a phased assembly often gives both haplotypes the same ID; gff3ToGenePred then merges the two copies into one transcript spanning two chromosomes and discards it, which was losing 31 of 182 retrocopies. IDs that occur on more than one sequence are now made unique per sequence first. And a feature name is now taken from the first non-numeric attribute, so a RepeatMasker GFF gives Motif:Tgut716A rather than the running number in ID=. genark addContrib gains --tier alpha|beta|public. It edits only betaGenArk.txt and publicGenArk.txt; beta.hub.txt and public.hub.txt are generated from those lists and shipped by quickPush.pl, so writing them by hand would push content outside the normal flow and lose it at the next clade build. The default alpha tier leaves the lists untouched, so re-running an install cannot demote a collection that is already promoted. doc/contrib/bTaeGut7 and trackDb/contrib/bTaeGut7 are the zebra finch telomere-to-telomere hub built with the above, from the IGV session the authors ship with the annotations on GenomeArk (Formenti et al, Cell 2026, PMID 42561917). 21 tracks in 6 collections plus 3 standalone, 27 description pages, and a makeDoc recording where every record went. diff --git src/hg/makeDb/doc/contrib/bTaeGut7/mkContribLinks.sh src/hg/makeDb/doc/contrib/bTaeGut7/mkContribLinks.sh new file mode 100755 index 00000000000..efe1c79a7fe --- /dev/null +++ src/hg/makeDb/doc/contrib/bTaeGut7/mkContribLinks.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# Put the bTaeGut7 tracks into a GenArk assembly's contrib/ directory. +# +# A contributed track reaches an assembly hub in two pieces: a trackDb fragment that +# mkGenomes.pl concatenates into the generated hub.txt, and a directory of symlinks that +# the fragment's paths point at. Both live under the assembly's build directory: +# +# <buildDir>/contrib/bTaeGut7/bTaeGut7.trackDb.txt <- the name mkGenomes.pl globs for +# <buildDir>/contrib/bTaeGut7/<data and html> +# +# The fragment is not the same file as the hub's trackDb. A hub's trackDb sits next to its +# data, so its paths are bare file names; a contrib fragment is read from the hub root, so +# every bigDataUrl and html has to be prefixed with contrib/bTaeGut7/. This script derives +# the fragment from the master trackDb rather than keeping a second copy by hand. +# +# The data comes from the split hub, whose sequences are already named the way the assembly +# names them, so the browser needs no chromAlias indirection and no paternal features are +# carried on a maternal assembly. +# +# Once the links are in place, alpha.hub.txt picks the tracks up on the next +# mkGenomes.pl dynablat-01 4040 <one line asmId tsv> +# with no entry in any control list. betaGenArk.txt and publicGenArk.txt are what promote +# it beyond alpha, and those are Hiram's to edit. +# +# Usage: mkContribLinks.sh <accession> <buildDir> +set -e + +if [ $# -ne 2 ]; then + echo "usage: mkContribLinks.sh <accession> <buildDir>" >&2 + echo " e.g. mkContribLinks.sh GCF_048771995.1 \\" >&2 + echo " /hive/data/genomes/asmHubs/refseqBuild/GCF/048/771/995/GCF_048771995.1_bTaeGut7.mat" >&2 + exit 255 +fi +acc="$1" +buildDir="$2" +name=bTaeGut7 +scriptDir="$(cd "$(dirname "$0")" && pwd)" +master="$scriptDir/../../../trackDb/contrib/$name/$name.trackDb.txt" +src="/hive/data/outside/genark/$name/split/$acc" +staging="/hive/data/outside/genark/$name/contrib/$acc" + +[ -s "$master" ] || { echo "no master trackDb at $master" >&2; exit 1; } +[ -d "$src" ] || { echo "no split hub data at $src" >&2; exit 1; } +[ -d "$buildDir" ] || { echo "no build directory at $buildDir" >&2; exit 1; } +# contrib/ in a build directory is a real directory; refuse to follow a symlink into +# somewhere unintended, which is easy to do by accident here +if [ -L "$buildDir/contrib" ]; then + echo "$buildDir/contrib is a symlink, refusing to write through it" >&2 + exit 1 +fi + +# the fragment, kept in our own area so the build tree holds only symlinks +mkdir -p "$staging" +sed -E 's#^([[:space:]]*)(bigDataUrl|html) #\1\2 contrib/'"$name"'/#' \ + "$master" > "$staging/$name.trackDb.txt" +echo "wrote $staging/$name.trackDb.txt" + +dest="$buildDir/contrib/$name" +mkdir -p "$dest" +ln -sfn "$staging/$name.trackDb.txt" "$dest/$name.trackDb.txt" +n=0 +for f in "$src"/*.bb "$src"/*.bw "$src"/*.html; do + [ -e "$f" ] || continue + ln -sfn "$f" "$dest/$(basename "$f")" + n=$((n+1)) +done +echo "linked $n files into $dest"