cb2aa0e55497911448f0a42bff3b368057847eef hiram Tue Sep 29 11:58:39 2026 -0700 may have the primary query on target working OK refs #34360 diff --git src/hg/utils/automation/doMiniMap2.pl src/hg/utils/automation/doMiniMap2.pl index 48408288837..0ed60ca8612 100755 --- src/hg/utils/automation/doMiniMap2.pl +++ src/hg/utils/automation/doMiniMap2.pl @@ -10,35 +10,37 @@ # Intended use: two very similar same-species assemblies where blat's # -fastMap query-chunking dance isn't needed and minimap2's splice-free # asm5/asm10/asm20 presets do a better job with the larger indels and # structural differences you see between the two haplotypes of a # diploid (trio-binned or hifiasm/verkko dual-assembly) genome, or # between two closely related strain assemblies. # # Requires the kent command pafToPsl (PAF+cigar -> PSL) so the existing # axtChain/chainNet/netChainSubset toolchain can be reused unchanged. use Getopt::Long; use warnings; use strict; use FindBin qw($Bin); use lib "$Bin"; +use File::Basename qw(basename); use HgAutomate; use HgRemoteScript; use HgStepManager; use AssemblyDivergence qw(mashDistance choosePipeline $mashAsm5Max $mashAsm10Max $mashLastzMin $mashWarnMax); +use AsmHub qw(accessionFromPath asmBuildDir asmIdToPath); # Option variable names, both common and peculiar to this script: use vars @HgAutomate::commonOptionVars; use vars @HgStepManager::optionVars; use vars qw/ $opt_buildDir $opt_target2Bit $opt_targetSizes $opt_query2Bit $opt_querySizes $opt_minimapPreset $opt_minimapCpu $opt_minimapSecondaryN $opt_minimapSecondaryRatio $opt_chainRam @@ -140,61 +142,65 @@ 'fileServer' => '', 'ram' => $ramG, 'minimapCpu' => $minimapCpu, 'bigClusterHub' => ''); print STDERR " Automates a same-species/same-haplotype liftOver (minimap2/chain/net) pipeline, patterned after doSameSpeciesLiftOver.pl but using minimap2 in place of blat -fastMap: align: Aligns the assemblies using minimap2 -cx \$minimapPreset on a big cluster, one job per target sequence against the full query genome, then converts PAF+cigar to PSL with pafToPsl. chain: Chains the alignments on a big cluster. net: Nets the alignments, uses netChainSubset to extract liftOver chains. load: Installs liftOver chain files, calls hgAddLiftOverChain on $dbHost. cleanup: Removes or compresses intermediate files. -All operations are performed in the build directory which is -$HgAutomate::clusterData/\$fromDb/$HgAutomate::trackBuild/mm2.\$toDb.\$date unless -buildDir is given. +All operations are performed in the build directory, which defaults to +$HgAutomate::clusterData/\$fromDb/$HgAutomate::trackBuild/miniMap2\$ToDb.\$date +for a plain UCSC database \$fromDb, or to +.../asmHubs/{genbankBuild,refseqBuild}/GCx/ddd/ddd/ddd//trackData/miniMap2\$ToDb.\$date +when \$fromDb is a GenArk accession (matching how pairwise lastz builds are +organized under GenArk) -- unless -buildDir is given. "; # Detailed help (-help): print STDERR " Assumptions: 1. /scratch/data/\$db/\$db.2bit contains sequence for database/assembly \$db. 2. $HgAutomate::clusterData/\$db/chrom.sizes contains all sequence names and sizes from \$db.2bit. 3. The \$db.2bit files have already been distributed to cluster-scratch (/scratch/data//). 4. pafToPsl is on \$PATH on the machine that runs the align cluster jobs. 5. mash is on \$PATH on the machine that runs this script (used once, up front, to auto-select -minimapPreset unless it is given explicitly). 6. fromDb and toDb are two haplotypes/assemblies of the same species/ individual -- this is not a general any-vs-any pipeline. For that, use doBlastzChainNet.pl. " if ($detailed); print "\n"; exit $status; } # Globals: # Command line args: tDb=fromDb, qDb=toDb my ($tDb, $qDb); # Other: my ($buildDir); my ($tSeq, $tSizes, $qSeq, $qSizes, $QDb, $fileServer); -my ($liftOverChainDir, $liftOverChainFile, $liftOverChainPath, $dbExists); +my ($liftOverChainDir, $liftOverChainFile, $liftOverChainPath); sub checkOptions { # Make sure command line options are valid/supported. my $ok = GetOptions(@HgStepManager::optionSpec, 'buildDir=s', 'target2Bit=s', 'targetSizes=s', 'query2Bit=s', 'querySizes=s', 'minimapPreset=s', 'minimapCpu=i', 'minimapSecondaryN=i', 'minimapSecondaryRatio=f', 'chainRam=s', 'chainCpu=i', @@ -229,53 +235,62 @@ } else { my @okFilesystems = &HgAutomate::chooseFilesystemsForCluster($paraHub, 'in'); if ( -e "/scratch/data/$tDb/$tDb.2bit" ) { $tSeqScratch = "/scratch/data/$tDb/$tDb.2bit"; } else { foreach my $fs (@okFilesystems) { &HgAutomate::verbose(1, "checking $fs/$tDb/$tDb.2bit\n"); if (&HgAutomate::machineHasFile($paraHub, "$fs/$tDb/$tDb.2bit")) { $tSeqScratch = "$fs/$tDb/$tDb.2bit"; last; } } } if (! defined $tSeqScratch) { - die "align: can't find $tDb/$tDb.2bit in " . - join("/, ", @okFilesystems) . "/ -- please distribute.\n"; + # No pre-staged cluster-scratch copy -- fall back to $tSeq, already + # resolved by getSeqAndSizes() (GenArk build tree or clusterData), + # which every cluster node can also reach, just not as fast as true + # scratch storage: + &HgAutomate::verbose(1, + "align: no cluster-scratch copy of $tDb/$tDb.2bit found in " . + join("/, ", @okFilesystems) . "/ -- using $tSeq instead.\n"); + $tSeqScratch = $tSeq; } } if ($opt_query2Bit) { $qSeqScratch = $opt_query2Bit; } else { my @okFilesystems = &HgAutomate::chooseFilesystemsForCluster($paraHub, 'in'); if ( -e "/scratch/data/$qDb/$qDb.2bit" ) { $qSeqScratch = "/scratch/data/$qDb/$qDb.2bit"; } else { foreach my $fs (@okFilesystems) { if (&HgAutomate::machineHasFile($paraHub, "$fs/$qDb/$qDb.2bit")) { $qSeqScratch = "$fs/$qDb/$qDb.2bit"; last; } } } if (! defined $qSeqScratch) { - die "align: can't find $qDb/$qDb.2bit in " . - join("/, ", @okFilesystems) . "/ -- please distribute.\n"; + # Same fallback as the target side above: + &HgAutomate::verbose(1, + "align: no cluster-scratch copy of $qDb/$qDb.2bit found in " . + join("/, ", @okFilesystems) . "/ -- using $qSeq instead.\n"); + $qSeqScratch = $qSeq; } } &HgAutomate::verbose(1, "Using $paraHub, $tSeqScratch and $qSeqScratch\n"); return ($paraHub, $tSeqScratch, $qSeqScratch); } # getClusterSeqs ######################################################################### # * step: align [bigClusterHub] sub doAlign { my $runDir = "$buildDir/run.mm2"; &HgAutomate::mustMkdir($runDir); my $pafDir = "$runDir/paf"; @@ -558,108 +573,160 @@ rm -rf \$tmpDir/ _EOF_ ); $bossScript->execute(); } # doNet ######################################################################### # * step: load [dbHost] sub doLoad { my $runDir = "$buildDir/axtChain"; &HgAutomate::checkExistsUnlessDebug('net', 'load', "$runDir/$liftOverChainFile"); my $whatItDoes = -"It makes links from $HgAutomate::gbdb/ and goldenPath/ (download area) to the liftOver -chains file, calls hgAddLiftOverChain to register the $HgAutomate::gbdb location, and -builds the quickLift chain/link bigBed pair (for any target/query pair, regardless of -whether \$tDb is a real UCSC database)."; +"It builds the chain/chainLiftOver/quickLift bigBed pairs, links them into +$HgAutomate::gbdb/ (GenArk hub-build/accession chain, or native db layout -- +see installLinks() in ottoRequestWatch.sh, which this mirrors), and calls +hgAddLiftOverChain + addQuickLift.py to register both in hgcentral. None of +this needs \$tDb to be a real MySQL database -- hgAddLiftOverChain and +addQuickLift.py both work fine with obsolete/nonexistent ones by design +(see hgAddLiftOverChain.c's own comment to that effect)."; my $bossScript = newBash HgRemoteScript("$runDir/doLoad.bash", $dbHost, $runDir, $whatItDoes); $bossScript->add(<<_EOF_ wget --no-check-certificate -O bigChain.as 'https://raw.githubusercontent.com/ucscGenomeBrowser/kent/refs/heads/master/src/hg/lib/bigChain.as' wget --no-check-certificate -O bigLink.as 'https://raw.githubusercontent.com/ucscGenomeBrowser/kent/refs/heads/master/src/hg/lib/bigLink.as' -_EOF_ - ); - - if ($dbExists) { - $bossScript->add(<<_EOF_ -# Link to standardized location of liftOver files: -mkdir -p $liftOverChainDir -rm -f $liftOverChainPath -ln -s $runDir/$liftOverChainFile $liftOverChainPath -tmpFile=`mktemp -t -p /tmp tmpMd5.XXXXXX` -grep -v $liftOverChainFile $liftOverChainDir/md5sum.txt > \$tmpFile || true -md5sum $runDir/$liftOverChainFile | sed -e "s#$runDir/##;" >> \$tmpFile -sort \$tmpFile > $liftOverChainDir/md5sum.txt -rm -f \$tmpFile - -# Link from download area: -mkdir -p $HgAutomate::goldenPath/$tDb/liftOver -rm -f $HgAutomate::goldenPath/$tDb/liftOver/$liftOverChainFile -ln -s $liftOverChainPath $HgAutomate::goldenPath/$tDb/liftOver/ -# Link from genome browser fileserver: -mkdir -p $HgAutomate::gbdb/$tDb/liftOver -rm -f $HgAutomate::gbdb/$tDb/liftOver/$liftOverChainFile -ln -s $liftOverChainPath $HgAutomate::gbdb/$tDb/liftOver/ - -# Add an entry to liftOverChain table in central database (specified in -# ~/.hg.conf) so that hgLiftOver will know that this is available: -hgAddLiftOverChain $tDb $qDb -_EOF_ - ); - } else { - $bossScript->add(<<_EOF_ # Full-chain bigChain pair, from the complete alignment (all.chain.gz) -- -# the standard genome-browser Chain/Net-style track pair: +# the standard genome-browser Chain/Net-style track pair. Built for any +# target/query pair -- nothing about this needs \$tDb to be a real +# database, only \$tSizes and the chain files doNet already produced. hgLoadChain -test -noBin -tIndex $tDb chain$QDb $runDir/$tDb.$qDb.all.chain.gz sed 's/.000000//' chain.tab | awk 'BEGIN {OFS="\\t"} {print \$2, \$4, \$5, \$11, 1000, \$8, \$3, \$6, \$7, \$9, \$10, \$1}' > chain${QDb}.tab bedToBigBed -type=bed6+6 -as=bigChain.as -tab chain${QDb}.tab $tSizes chain${QDb}.bb awk 'BEGIN {OFS="\\t"} {print \$1, \$2, \$3, \$5, \$4}' link.tab | sort -k1,1 -k2,2n > chain${QDb}Link.tab bedToBigBed -type=bed4+1 -as=bigLink.as -tab chain${QDb}Link.tab $tSizes chain${QDb}Link.bb totalBases=`ave -col=2 $tSizes | grep "^total" | awk '{printf "%d", \$2}'` basesCovered=`bigBedInfo chain${QDb}Link.bb | grep "basesCovered" | cut -d' ' -f2 | tr -d ','` percentCovered=`echo \$basesCovered \$totalBases | awk '{printf "%.3f", 100.0*\$1/\$2}'` printf "%d bases of %d (%s%%) in intersection\\n" "\$basesCovered" "\$totalBases" "\$percentCovered" > $buildDir/fb.$tDb.chain${QDb}Link.txt rm -f link.tab chain.tab chain${QDb}.tab chain${QDb}Link.tab # LiftOver-subset bigChain pair, from the netChainSubset-extracted chain -# (over.chain.gz) -- the strict, single-best-path-per-region subset: +# (over.chain.gz) -- the strict, single-best-path-per-region subset. +# Also built unconditionally, same reasoning as above. hgLoadChain -test -noBin -tIndex $tDb chainLiftOver$QDb $runDir/$liftOverChainFile sed 's/.000000//' chain.tab | awk 'BEGIN {OFS="\\t"} {print \$2, \$4, \$5, \$11, 1000, \$8, \$3, \$6, \$7, \$9, \$10, \$1}' > chainLiftOver${QDb}.tab bedToBigBed -type=bed6+6 -as=bigChain.as -tab chainLiftOver${QDb}.tab $tSizes chainLiftOver${QDb}.bb awk 'BEGIN {OFS="\\t"} {print \$1, \$2, \$3, \$5, \$4}' link.tab | sort -k1,1 -k2,2n > chainLiftOver${QDb}Link.tab bedToBigBed -type=bed4+1 -as=bigLink.as -tab chainLiftOver${QDb}Link.tab $tSizes chainLiftOver${QDb}Link.bb liftOverBasesCovered=`bigBedInfo chainLiftOver${QDb}Link.bb | grep "basesCovered" | cut -d' ' -f2 | tr -d ','` liftOverPercentCovered=`echo \$liftOverBasesCovered \$totalBases | awk '{printf "%.3f", 100.0*\$1/\$2}'` printf "%d bases of %d (%s%%) in intersection\\n" "\$liftOverBasesCovered" "\$totalBases" "\$liftOverPercentCovered" > $buildDir/fb.$tDb.chainLiftOver${QDb}.txt rm -f link.tab chain.tab chainLiftOver${QDb}.tab chainLiftOver${QDb}Link.tab +_EOF_ + ); + + # Where the liftOver chain / quickLift bigBeds get linked, and what gets + # registered in hgcentral, depends only on whether $tDb LOOKS like a + # GenArk accession (a plain name-pattern check, same as everywhere else + # in this pipeline) -- never on whether it's a real MySQL database. + # This mirrors ottoRequestWatch.sh's installLinks() exactly, except + # resolving the GenArk build directory via genbankBuild/refseqBuild + # (AsmHub::asmBuildDir(), verified against the real on-disk layout) + # rather than the allBuild path installLinks() itself uses. + my $tAccession = &accessionFromPath($tDb); + if ($tAccession) { + my $tBuildDir = &asmBuildDir($tAccession); + die "doLoad: '$tDb' looks like a GenArk accession, but no build " . + "directory was found for it under $HgAutomate::clusterData/asmHubs/\n" + if (! $tBuildDir); + my $accessionPath = &asmIdToPath($tAccession) . "/$tAccession"; + my $accLevelDir = "$HgAutomate::clusterData/asmHubs/$accessionPath"; + my $gbdbGenarkDir = "/gbdb/genark/$accessionPath"; + $bossScript->add(<<_EOF_ +# GenArk assembly: link into the hub-build directory, then the +# accession-level convenience symlinks, then the public gbdb symlinks -- +# same three-tier chain installLinks() uses. +mkdir -p $tBuildDir/liftOver $tBuildDir/quickLift +rm -f $tBuildDir/liftOver/$liftOverChainFile +ln -s $runDir/$liftOverChainFile $tBuildDir/liftOver/$liftOverChainFile +rm -f $tBuildDir/quickLift/$qDb.bb $tBuildDir/quickLift/$qDb.link.bb +ln -s $runDir/$tDb.$qDb.quick.bb $tBuildDir/quickLift/$qDb.bb +ln -s $runDir/$tDb.$qDb.quickLink.bb $tBuildDir/quickLift/$qDb.link.bb + +mkdir -p $accLevelDir +rm -f $accLevelDir/liftOver $accLevelDir/quickLift +ln -s $tBuildDir/liftOver $accLevelDir/liftOver +ln -s $tBuildDir/quickLift $accLevelDir/quickLift + +mkdir -p $gbdbGenarkDir +rm -f $gbdbGenarkDir/liftOver $gbdbGenarkDir/quickLift +ln -s $accLevelDir/liftOver $gbdbGenarkDir/liftOver +ln -s $accLevelDir/quickLift $gbdbGenarkDir/quickLift + +# Register in hgcentral (works fine without a real MySQL database for +# \$tDb -- see hgAddLiftOverChain.c and addQuickLift.py): +hgAddLiftOverChain -minMatch=0.1 -multiple -path=$gbdbGenarkDir/liftOver/$liftOverChainFile $tDb $qDb +$Bin/addQuickLift.py $tDb $qDb $gbdbGenarkDir/quickLift/$qDb.bb +_EOF_ + ); + } else { + $bossScript->add(<<_EOF_ +# Not a GenArk accession -- native-db-style layout (same as +# installLinks()'s native-db branch), whether or not \$tDb is actually a +# real MySQL database (e.g. hs1: a full sequence build, no database). +mkdir -p $liftOverChainDir +rm -f $liftOverChainPath +ln -s $runDir/$liftOverChainFile $liftOverChainPath +tmpFile=`mktemp -t -p /tmp tmpMd5.XXXXXX` +grep -v $liftOverChainFile $liftOverChainDir/md5sum.txt > \$tmpFile || true +md5sum $runDir/$liftOverChainFile | sed -e "s#$runDir/##;" >> \$tmpFile +sort \$tmpFile > $liftOverChainDir/md5sum.txt +rm -f \$tmpFile + +# Link from download area: +mkdir -p $HgAutomate::goldenPath/$tDb/liftOver +rm -f $HgAutomate::goldenPath/$tDb/liftOver/$liftOverChainFile +ln -s $liftOverChainPath $HgAutomate::goldenPath/$tDb/liftOver/ + +# Link from genome browser fileserver: +mkdir -p $HgAutomate::gbdb/$tDb/liftOver $HgAutomate::gbdb/$tDb/quickLift +rm -f $HgAutomate::gbdb/$tDb/liftOver/$liftOverChainFile +ln -s $liftOverChainPath $HgAutomate::gbdb/$tDb/liftOver/ +rm -f $HgAutomate::gbdb/$tDb/quickLift/$qDb.bb $HgAutomate::gbdb/$tDb/quickLift/$qDb.link.bb +ln -s $runDir/$tDb.$qDb.quick.bb $HgAutomate::gbdb/$tDb/quickLift/$qDb.bb +ln -s $runDir/$tDb.$qDb.quickLink.bb $HgAutomate::gbdb/$tDb/quickLift/$qDb.link.bb + +# Register in hgcentral (works fine without a real MySQL database for +# \$tDb -- see hgAddLiftOverChain.c and addQuickLift.py): +hgAddLiftOverChain -minMatch=0.1 -multiple -path=$HgAutomate::gbdb/$tDb/liftOver/$liftOverChainFile $tDb $qDb +$Bin/addQuickLift.py $tDb $qDb $HgAutomate::gbdb/$tDb/quickLift/$qDb.bb _EOF_ ); } - # quickLift bigBed pair: built for any target/query pair regardless of - # $dbExists -- it only needs the quick.chain.txt/quick.link.txt doNet - # already produced, plus $qSizes, no dependency on \$tDb being a real - # database. + # quickLift bigBed pair: built for any target/query pair -- it only + # needs the quick.chain.txt/quick.link.txt doNet already produced, + # plus $qSizes, no dependency on \$tDb being a real database. $bossScript->add(<<_EOF_ bedToBigBed -type=bed6+6 -as=bigChain.as -tab $tDb.$qDb.quick.chain.txt $qSizes $tDb.$qDb.quick.bb bedToBigBed -type=bed4+1 -as=bigLink.as -tab $tDb.$qDb.quick.link.txt $qSizes $tDb.$qDb.quickLink.bb qBases=`ave -col=2 $qSizes | grep "^total" | awk '{printf "%d", \$2}'` qCovered=`bigBedInfo $tDb.$qDb.quickLink.bb | grep "basesCovered" | cut -d' ' -f2 | tr -d ','` qPerCent=`echo \$qCovered \$qBases | awk '{printf "%.3f", 100.0*\$1/\$2}'` printf "%d bases of %d (%s%%) in intersection\\n" "\$qCovered" "\$qBases" "\$qPerCent" > $buildDir/fb.$tDb.quick${QDb}Link.txt rm -f bigChain.as bigLink.as $tDb.$qDb.quick.chain.txt $tDb.$qDb.quick.link.txt _EOF_ ); $bossScript->execute(); } # doLoad @@ -678,84 +745,89 @@ rm -rf run.mm2/paf/ rm -rf axtChain/run/chainRaw/ rm -f axtChain/noClass.net # mashSketch.{a,b}.msh only ever exist here if estimateDivergence() fell # back to a one-off sketch (tSeq/qSeq didn't resolve to a real GenArk # accession or UCSC db -- see AssemblyDivergence.pm's sketch()); for a # normal assembly the sketch lives in its own permanent, shared cache # under /hive/data/genomes/, never here, so this is a no-op in that case: rm -f mashSketch.a.msh mashSketch.b.msh _EOF_ ); $bossScript->execute(); } # doCleanup -sub getSeqAndSizes { - if ($opt_target2Bit) { - $tSeq = $opt_target2Bit +# resolveAssemblySeq($db, $opt2Bit, $optSizes) -> ($seq, $sizes) +# $opt2Bit/$optSizes, if given (-target2Bit etc.), always win. +# Otherwise, if $db looks like a GenArk accession (accessionFromPath()) +# with a real build directory (AsmHub::asmBuildDir()), resolve straight +# to that build tree's own .2bit/.chrom.sizes -- the same +# resolution AssemblyDivergence.pm's sketch() already does for mash, +# just for the actual alignment inputs here. Otherwise falls back to +# the traditional /scratch/data or clusterData/$db/$db.2bit UCSC-db +# location, as before. Doesn't require the result to actually exist -- +# getSeqAndSizes() checks that afterward. +sub resolveAssemblySeq { + my ($db, $opt2Bit, $optSizes) = @_; + my $accession = &accessionFromPath($db); + my $asmBuild = $accession ? &asmBuildDir($accession) : undef; + my $asmId = $asmBuild ? basename($asmBuild) : undef; + + my $seq; + if ($opt2Bit) { + $seq = $opt2Bit; + } elsif ($asmBuild) { + $seq = "$asmBuild/$asmId.2bit"; } else { - # Test assumptions about 2bit and chrom.sizes files. - $tSeq = "/scratch/data/$tDb/$tDb.2bit"; - if (! -e $tSeq) { + $seq = "/scratch/data/$db/$db.2bit"; + if (! -e $seq) { # allow it to exist here too: my $fs = "$HgAutomate::clusterData"; - &HgAutomate::verbose(1, "checking $fs/$tDb/$tDb.2bit\n"); - if (-e "$fs/$tDb/$tDb.2bit") { - $tSeq = "$fs/$tDb/$tDb.2bit"; - } + &HgAutomate::verbose(1, "checking $fs/$db/$db.2bit\n"); + $seq = "$fs/$db/$db.2bit" if (-e "$fs/$db/$db.2bit"); } } - if ($opt_targetSizes) { - $tSizes = $opt_targetSizes; + my $sizes; + if ($optSizes) { + $sizes = $optSizes; + } elsif ($asmBuild) { + $sizes = "$asmBuild/$asmId.chrom.sizes"; } else { - $tSizes = "$HgAutomate::clusterData/$tDb/chrom.sizes"; + $sizes = "$HgAutomate::clusterData/$db/chrom.sizes"; } - if ($opt_query2Bit) { - $qSeq = $opt_query2Bit; - } else { - $qSeq = "/scratch/data/$qDb/$qDb.2bit"; - if (! -e $qSeq) { - # allow it to exist here too: - my $fs = "$HgAutomate::clusterData"; - &HgAutomate::verbose(1, "checking $fs/$qDb/$qDb.2bit\n"); - if (-e "$fs/$qDb/$qDb.2bit") { - $qSeq = "$fs/$qDb/$qDb.2bit"; - } - } - } + return ($seq, $sizes); +} # resolveAssemblySeq - if ($opt_querySizes) { - $qSizes = $opt_querySizes; - } else { - $qSizes = "$HgAutomate::clusterData/$qDb/chrom.sizes"; - } +sub getSeqAndSizes { + ($tSeq, $tSizes) = &resolveAssemblySeq($tDb, $opt_target2Bit, $opt_targetSizes); + ($qSeq, $qSizes) = &resolveAssemblySeq($qDb, $opt_query2Bit, $opt_querySizes); my $problem = 0; foreach my $file ($tSeq, $tSizes, $qSeq, $qSizes) { if (! -e $file) { warn "Error: cannot find required file \"$file\"\n"; $problem = 1; } } if ($problem && !$opt_debug) { warn "Run $base -help for a description of expected files.\n"; exit 1; } -} +} # getSeqAndSizes sub estimateDivergence { # Pick -minimapPreset automatically via AssemblyDivergence.pm's mash # distance between tDb and qDb, unless the user already gave # -minimapPreset explicitly. Cheap (mash sketch+dist on a whole genome # is seconds to low minutes), so we just run it locally rather than # turning it into its own cluster step. if ($minimapPreset) { &HgAutomate::verbose(1, "Using explicit -minimapPreset=$minimapPreset (mash not run).\n"); return; } my $mashFile = "$buildDir/mashDistance.txt"; if (-e $mashFile && ! $opt_regenerateMash) { @@ -800,50 +872,57 @@ &HgAutomate::verbose(1, "mash distance $dist between $tDb and $qDb -> -minimapPreset=$minimapPreset\n"); } # estimateDivergence ######################################################################### # main # Prevent "Suspended (tty input)" hanging: &HgAutomate::closeStdin(); &checkOptions(); &usage(1) if (scalar(@ARGV) != 2); ($tDb, $qDb) = @ARGV; -# may be working on a 2bit file that does not have a database browser -$dbExists = 0; -$dbExists = 1 if (&HgAutomate::databaseExists($dbHost, $tDb)); - &getSeqAndSizes(); $QDb = ucfirst($qDb); $liftOverChainDir = "$HgAutomate::clusterData/$tDb/$HgAutomate::trackBuild/liftOver"; $liftOverChainFile = "${tDb}To${QDb}.over.chain.gz"; $liftOverChainPath = "$liftOverChainDir/$liftOverChainFile"; $chainRam = $opt_chainRam ? $opt_chainRam : $chainRam; $chainCpu = $opt_chainCpu ? $opt_chainCpu : $chainCpu; $minimapCpu = $opt_minimapCpu ? $opt_minimapCpu : $minimapCpu; $minimapSecondaryN = $opt_minimapSecondaryN ? $opt_minimapSecondaryN : $minimapSecondaryN; $minimapSecondaryRatio = $opt_minimapSecondaryRatio ? $opt_minimapSecondaryRatio : $minimapSecondaryRatio; $ramG = $opt_ram ? $opt_ram : $ramG; my $date = `date +%Y-%m-%d`; chomp $date; -$buildDir = $opt_buildDir ? $opt_buildDir : +if ($opt_buildDir) { + $buildDir = $opt_buildDir; +} else { + # GenArk target: build under its own trackData/, same convention + # ottoRequestWatch.sh expects pairwise lastz builds to already be in + # ("...//trackData/lastz.YYYY-MM-DD") -- not under + # clusterData/$tDb/bed/, which only exists for native UCSC databases. + my $tAccession = &accessionFromPath($tDb); + my $tAsmBuild = $tAccession ? &asmBuildDir($tAccession) : undef; + $buildDir = $tAsmBuild ? + "$tAsmBuild/trackData/miniMap2${QDb}.$date" : "$HgAutomate::clusterData/$tDb/$HgAutomate::trackBuild/miniMap2${QDb}.$date"; +} if (! -d $buildDir) { if ($stepper->stepPrecedes('align', $stepper->getStartStep())) { die "$buildDir does not exist; try running again with -buildDir.\n"; } &HgAutomate::mustMkdir($buildDir); } &estimateDivergence(); $stepper->execute(); my $stopStep = $stepper->getStopStep(); my $upThrough = ($stopStep eq 'cleanup') ? "" : " (through the '$stopStep' step)";