示例#1
0
def readNoiseParameters(input_file):
    """Argument input_file must be path plus prefix to .err file. Return noise parameters from its last iteration."""
    raw_line=""
    try:
        with open(input_file+".err") as f:
            for line in f:
                if line.startswith("#"):
                    continue
                if line.strip()=="":
                    continue
                raw_line=line
    except:
        util.LogError("error", "Could not read noise parameters from %s" % (input_file+".err"))
        return({})
		
    data=[]
    for x in raw_line.split("\t"):
        y=x.strip()
        if y!="":
            data.append(float(y))
    #print data
    if len(data) > 13 : #be sure that we don't get IndexError
        return(dict([("FP",data[1]), ("FN",data[2]), ("sf",data[3]), ("sd",data[4]), ("bpp",data[5]), ("res",data[6]), ("sr",data[13]), ("readparameters",input_file+".errbin")]))
    elif len(data) > 5 : #assume sr is missing in this case, but rest are correct
        return(dict([("FP",data[1]), ("FN",data[2]), ("sf",data[3]), ("sd",data[4]), ("bpp",data[5]), ("res",data[6]), ("readparameters",input_file+".errbin")]))
    else : #bad input_file, data is missing and cannot be trusted
        util.LogError("error", "Could not read noise parameters from %s" % (input_file+".err"))
        return({})
示例#2
0
 def __init__(self, varsP) :
     """sortBNX.__init__: this class is for sorting the input bnx
     for subsequent splitting by the splitBNX class, and eventually
     easier processing with the Pairwise class. The constructor
     (this) will call varsP.runJobs and doAllPipeReport."""
     self.stageName="SortBNX"
     self.varsP = varsP #fewer code modifications below
     self.varsP.sorted_file = self.varsP.bnxFile.replace(".bnx", "_sorted")
     #replace this with checkMinMol; this needs to use sorted file which isn't yet made
     #calculateNPairwise(self.varsP, self.varsP.bnxFile.replace(".bnx","")) #run this here bc it contains check on N mol required to start pipeline
     checkMinMol(self.varsP, self.varsP.bnxFile)
     if self.generateJobList() : #return 0 for success, 1 for skip
         if not util.checkFile(self.varsP.sorted_file+".bnx") : #this happens when accidentally using bypass but no sorted bnx exists--log error
             err = "ERROR: no sorted bnx file found (%s) (check bypass (-B) argument to Pipeline)" % (self.varsP.sorted_file+".bnx")
             self.varsP.updatePipeReport(err+"\n")
             util.LogError("critical", err)
             util.LogStatus("progress", "pipeline", "failure")
             raise RuntimeError
         #calculateNPairwise(self.varsP, self.varsP.sorted_file) #correct varsP.nPairwiseJobs -- already above
         return
     util.LogStatus("progress", "stage_start", self.stageName) #after above bc check if bypass (executeCurrentStage)
     self.varsP.runJobs(self, "SortBNX")
     self.doAllPipeReport()
     if not self.allResultsFound() :
         err = "ERROR: sortBNX failed. Check: "+self.varsP.bnxFile
         self.varsP.updatePipeReport(err+"\n")
         util.LogError("critical", err)
         util.LogStatus("progress", "pipeline", "failure")
         raise RuntimeError
     util.LogStatus("progress", "stage_complete", self.stageName)
示例#3
0
    def CheckIfRunning(self, cSession=None, sleepTime=0.05):
        if self.isRunning:
            a = self.poll()
            if self.onCluster:
                while True:
                    try:
                        if not (cSession.jobStatus(self.jobID) in [
                                drmaa.JobState.DONE, drmaa.JobState.FAILED
                        ]):
                            time.sleep(sleepTime)
                            return self.isRunning
                        retval = cSession.wait(self.jobID,
                                               drmaa.Session.TIMEOUT_NO_WAIT)
                        break
                    except (drmaa.DrmCommunicationException), e:
                        # Catch drmaa communication exception, log a warning message and
                        # continue to monitor job.
                        print(
                            "*** CommERROR: %s Could not communicate with the cluster scheduler to check job status."
                            % (str(e)))
                        time.sleep(5)
                #end while True

                #if exit code != 0, restart without delay in checkStdOut bc that can cause Pipeline to wait for hours
                if self.remainingRestarts > 0 and retval.hasExited and retval.exitStatus != 0:
                    if retval.exitStatus == 255:
                        utilities.LogError(
                            "warning",
                            "job ssh failed (exit code %i), restarting, stdout=%s"
                            % (retval.exitStatus, self.expectedStdoutFile))
                        self.remainingRestarts += 1  #never fail a job because of ssh failing: may result in infinite loop, but this would only occur if the cluster cannot run the job at all
                        time.sleep(sleepTime)
                    else:
                        utilities.LogError(
                            "warning",
                            "job has non-zero exit code (%i), restarting, stdout=%s"
                            % (retval.exitStatus, self.expectedStdoutFile))
                    self.restartJobOnCluster()
                    return self.isRunning

                # Check whether the job is successful, if not restart it
                if self.remainingRestarts > 0 and self.expectedStdoutFile:
                    if not utilities.checkStdOut(self.expectedStdoutFile):
                        utilities.LogError(
                            "warning", "job was restarted, see stdout=\"%s\"" %
                            self.expectedStdoutFile)
                        self.restartJobOnCluster()
                        return self.isRunning

                #info = cSession.wait(self.jobID, drmaa.Session.TIMEOUT_WAIT_FOREVER)
                cSession.deleteJobTemplate(self.jTemplate)
                #self.stdErrOutObject = open(self.stdErrOutFile)
                self.StdErrOutFileOpen = True
            #elif not(isinstance(self.poll(),int)):
            elif not (isinstance(a, int)):
                #print a
                return self.isRunning
示例#4
0
 def isBadErrorParams(self, noise, stage):
     #BAD means this:
     # for both stages: sr > 0.1 or sd > 0.1 or sf > 0.5
     # also for stage 0 : sd > 0.1 and sf > 0.35
     # also for stage 1 : sd > 0 and sf > 0.25 (this used to be for both stages)
     assert stage == 0 or stage == 1, "Error: invalid arg to autoNoise.isBadErrorParams"
     badparam = False
     if not noise :
         badparam = True
     elif stage == 0 and (noise["sd"] > 0.1 and noise["sf"] > 0.35) :
         badparam = True
     elif stage == 1 and (noise["sd"] > 0   and noise["sf"] > 0.25) :
         badparam = True
     #add not noise for case of empty dict, which readNoiseParameters will return if it can't read the .err file
     if badparam or noise["sr"] > 0.1 or noise["sd"] > 0.1 or noise["sf"] > 0.5 :
         errstr = "Failed to find usable noise parameters. Try decreasing maprate parameter and/or find a better reference. You can also try disabling auto noise (no -y, or 'Rough assembly' profile) with nominal noise parameters;"
         if noise.has_key("sf") :
             errstr += " sf=%f" % noise["sf"]
         if noise.has_key("sd") :
             errstr += " sd=%f" % noise["sd"]
         if noise.has_key("sr") :
             errstr += " sr=%f" % noise["sr"]
         self.varsP.updatePipeReport(errstr+"\n")
         util.LogError("critical", errstr)
         util.LogStatus("progress", "pipeline", "failure") #possibly redundant with DNPipeline.finalizePipeline
         raise RuntimeError
示例#5
0
    def checkRequiredCopyNumberArgs(self):
        """Arguments required for copy number are -minlen 150 and -T 9.
        Note that there are many others that are required, but not checked.
        Return True for correct values, False for incorrect
        """
        minlenarg = '-minlen'  #the RefAligner arg
        minlenval = '150'  #the required value
        pvarg = '-T'  #the RefAligner arg
        pvval = '1e-9'  #the required value--assume the format is correct also...
        if not self.jobargs:  #this means the 'alignmolvref' section is not in optargs
            err = "Warning in AlignModule.checkRequiredCopyNumberArgs: missing arguments for %s" % self.stageName
            util.LogError("warning", err)
            self.varsP.updatePipeReport(err + "\n")
            return False
        else:  #have it, make sure it has -T 1e-9
            if not pvarg in self.jobargs:
                err = "Warning in AlignModule.checkRequiredCopyNumberArgs: missing argument %s in arg group %s" % (
                    pvarg, self.stageName)
                util.LogError("warning", err)
                self.varsP.updatePipeReport(err + "\n")
                return False
            pv = self.jobargs[self.jobargs.index(pvarg) + 1]
            if pv != pvval:
                err = "Warning in AlignModule.checkRequiredCopyNumberArgs: argument %s in arg group %s has value %s but required value is %s" % (
                    pvarg, self.stageName, pv, pvval)
                util.LogError("warning", err)
                self.varsP.updatePipeReport(err + "\n")
                return False

        sortgroup = 'bnx_sort'
        sortargs = self.varsP.argsListed(
            sortgroup)  #this is a required stage; make sure it has -minlen 150
        if not minlenarg in sortargs:
            err = "Warning in AlignModule.checkRequiredCopyNumberArgs: missing argument %s in arg group %s" % (
                minlenarg, sortgroup)
            util.LogError("warning", err)
            self.varsP.updatePipeReport(err + "\n")
            return False
        minlen = sortargs[sortargs.index(minlenarg) + 1]
        if minlen != minlenval:
            err = "Warning in AlignModule.checkRequiredCopyNumberArgs: argument %s in arg group %s has value %s but required value is %s" % (
                minlenarg, sortgroup, minlen, minlenval)
            util.LogError("warning", err)
            self.varsP.updatePipeReport(err + "\n")
            return False

        return True
示例#6
0
 def CheckStdout(self, tries=20, delay=5):
     if self.expectedStdoutFile:
         self.stdoutComplete = utilities.checkStdOut(
             self.expectedStdoutFile, tries=tries, delay=delay)
         if not self.stdoutComplete:
             utilities.LogError(
                 "error", "job has not completed, see stdout=\"%s\"" %
                 self.expectedStdoutFile)
示例#7
0
def logOrPrintError(err_msg, varsP=None, warn=True):
    """If varsP, call updatePipeReport, otherwise print. """
    if varsP:
        varsP.updatePipeReport(err_msg + "\n")
        if warn:
            util.LogError("warning",
                          err_msg)  #assume this makes sense only if varsP
    else:
        print err_msg
示例#8
0
    def generateJobList(self) :
        """splitBNX.generateJobList: submit varsP.nPairwiseJobs number of split bnx jobs. """

        sorted_file = self.varsP.sorted_file
        if not util.checkFile(sorted_file+".bnx") :
            err = "ERROR: splitBNX input file (%s) not found; exiting" % self.varsP.sorted_file
            self.varsP.updatePipeReport(err+"\n")
            util.LogError("critical", err)
            util.LogStatus("progress", "pipeline", "failure")
            raise RuntimeError

        N = calculateNPairwise(self.varsP, sorted_file) #move back here (not sortBNX) bc needs to use sorted bnx
        #N = self.varsP.nPairwiseJobs

        self.varsP.updatePipeReport('Splitting BNX\n')
        #splitJobSet=mthread.jobWrapper(self.varsP,jobName,clusterArgs=self.varsP.getClusterArgs('splitting'))
        super(splitBNX, self).__init__(self.varsP, self.stageName, clusterArgs=self.varsP.getClusterArgs('splitting'))

        #should skip the rest and return 1, like in sortBNX, here:
        if not self.varsP.executeCurrentStage:
            return 1 #tell self.__init__ not to continue processing

        self.varsP.updatePipeReport("Splitting"+(" scan-scaled" if self.varsP.doScanScale else "")+" bnx file: %s.bnx\n\n" % self.varsP.sorted_file)

        #calculate threads per job: used to be fixed at 1, now file size / 1.5 GB rounded up. This was too low, add 1.
        threads = max(1, int(math.ceil( os.path.getsize(sorted_file+".bnx")/1.5e9 ))) + 1
        if threads > 1 :
            self.varsP.updatePipeReport("Using %i threads per job\n" % threads)

        #the change in job partitioning breaks backward compatibility and was causing too many problems; make it conditional on refaligner version
        #this is now obsolete: assume binaries are up-to-date
        if False : #self.varsP.refaligner_version < 3995 :
            for partial in range(1,N + 1):
                output_file=self.varsP.bnxFile.replace(".bnx", "_%s_of_%s" %(partial, self.varsP.nPairwiseJobs))
                cargs=[self.varsP.RefAlignerBin, '-f', '-i', sorted_file+".bnx", "-maxthreads", str(threads), "-merge", "-subsetbin", str(partial), str(N), "-bnx", "-o",  output_file]
                if self.varsP.stdoutlog :
                    cargs.extend( ['-stdout', '-stderr'] )
                #print('%d/%d' % (partial, N), cargs)
                expectedResultFile=output_file+".bnx"
                self.addJob(mthread.singleJob(cargs, self.stageName + str(partial), expectedResultFile, self.stageName + str(partial), maxThreads=threads, clusterLogDir=self.varsP.clusterLogDir, expectedStdoutFile=output_file+".stdout"))

        else :
            #change above to single command with -subsetbin 0 N
            output_file=self.varsP.bnxFile.replace(".bnx", "")
            cargs=[self.varsP.RefAlignerBin, '-f', '-i', sorted_file+".bnx", "-maxthreads", str(threads), "-merge", "-subsetbin", "0", str(N), "-bnx", "-o",  output_file]
            if self.varsP.stdoutlog :
                cargs.extend( ['-stdout', '-stderr'] )
            self.addJob(mthread.singleJob(cargs, self.stageName, output_file+".bnx", self.stageName, maxThreads=threads, clusterLogDir=self.varsP.clusterLogDir, expectedStdoutFile=output_file+".stdout"))
示例#9
0
 def submitClusterJob(self):
     self.jobStarted = False
     while not self.jobStarted:
         try:
             self.jobID = self.cSession.runJob(self.jTemplate)
             self.pid = self.jobID
             self.startTime = time.time()
             self.isRunning = True
             self.jobStarted = True
         except drmaa.errors.DeniedByDrmException:
             utilities.LogError(
                 "warning",
                 "DRMAA exception encountered while submitting job, nativeSpecification=\"%s\""
                 % self.clusterArgs)
             print("Error starting job, nativeSpecification=\"%s\"" %
                   self.clusterArgs)
             sys.stdout.flush()
             time.sleep(100)
示例#10
0
 def __init__(self, varsP, splitname="SplitBNX") :
     """splitBNX.__init__: this class is for splitting the sorted bnx file into
     smaller chunks for easier processing with the Pairwise class. Like the
     sortBNX class, the constructor also calls varsP.runJobs and doAllPipeReport.
     """
     util.LogStatus("progress", "stage_start", splitname)
     self.varsP = varsP #fewer code modifications below
     self.stageName = splitname
     if not self.generateJobList() : #check return value, and runJobs only if False
         self.varsP.runJobs(self, splitname)
     self.doAllPipeReport()
     if not self.allResultsFound() :
         err = "ERROR: splitBNX failed. Check: "+self.varsP.sorted_file+".bnx"
         self.varsP.updatePipeReport(err+"\n")
         util.LogError("critical", err)
         util.LogStatus("progress", "pipeline", "failure")
         raise RuntimeError
     util.LogStatus("progress", "stage_complete", splitname)
示例#11
0
def checkMinMol(varsP, input_file, minmol=2) :
    '''Simplified version of calculateNPairwise which just checks that there are at least minmol molecules.'''
    f=open(input_file, "r")
    count=0
    #length=0
    #site_count=0.0
    for line in f:
        if line[0] == "0":
            #x=line.split()
            count+=1
            #length+=float(x[2])
        #if line[0] == "1":
        #site_count+=len(line.split())-1
        if count > minmol : #this is all we need to check
            break
    f.close()

    #check that we have more than 1 molecule; if not, there's nothing to assemble, so exit
    if count < minmol :
        err = "ERROR in calculateNPairwise: number of molecules (%i) is too few for assembly; check bnx: %s" % (count, input_file)
        varsP.updatePipeReport(err+"\n")
        util.LogError("critical", err)
        util.LogStatus("progress", "pipeline", "failure")
        raise RuntimeError #will be caught in DNPipeline.constructData
示例#12
0
    def __init__(self, varsP):
        jobName = "reference_process"
        opta_section = "referenceSvdetect"
        default_mres = "2.9"
        mres = "-mres"
        self.varsP = varsP
        usedefault = False
        if self.varsP.argData.has_key(opta_section):  #check if in optargs
            opta = self.varsP.argsListed(opta_section)
            if not mres in opta:  #must have mres
                self.varsP.updatePipeReport(
                    "Warning in referenceProcess: " + mres +
                    " missing in optArguments section " + opta_section + "\n")
                usedefault = True
        else:
            self.varsP.updatePipeReport(
                "Warning in referenceProcess: optArguments section " +
                opta_section + " missing\n")
            usedefault = True
        if usedefault:
            opta = [mres, default_mres]

        mresstr = opta[opta.index(mres) +
                       1]  #get string for mres value for output name
        mresstr = mresstr.replace(".", "")

        if not util.checkDir(self.varsP.refFolder):
            self.varsP.updatePipeReport(
                "ERROR in referenceProcess: could not make output dir %s\n" %
                self.varsP.refFolder)
            return None
        refpref = os.path.basename(
            self.varsP.ref[:self.varsP.ref.rfind(".")]) + "_res" + mresstr
        outarg = os.path.join(
            self.varsP.refFolder,
            refpref)  #refFolder is new output folder for this job
        expectedResultFile = outarg + ".cmap"  #if ref is spots, is this spots?
        args = [
            self.varsP.RefAlignerBin, '-f', '-o', outarg, '-i', self.varsP.ref,
            '-merge'
        ] + opta
        stdoutf = None
        if self.varsP.stdoutlog:
            args.extend(['-stdout', '-stderr'])
            stdoutf = outarg + ".stdout"
        args += ['-maxthreads', str(self.varsP.nThreads)]

        super(referenceProcess,
              self).__init__(self.varsP,
                             jobName,
                             clusterArgs=self.varsP.getClusterArgs("assembly"))

        job = mthread.singleJob(args,
                                jobName,
                                expectedResultFile,
                                jobName,
                                maxThreads=self.varsP.nThreads,
                                clusterLogDir=self.varsP.clusterLogDir,
                                expectedStdoutFile=stdoutf)
        self.addJob(job)

        util.LogStatus("progress", "stage_start", jobName)
        self.varsP.runJobs(self, "referenceProcess")
        self.doAllPipeReport()
        if not self.allResultsFound(
        ):  #this is an error, but we'll continue processing without SV detect
            err = "ERROR in referenceProcess: job failed, disabling SV detect"
            self.varsP.updatePipeReport(err + "\n")
            util.LogError("error", err)
            #self.varsP.runSV = False #no need since this class is used in SVModule
        else:
            self.varsP.refDeresed = expectedResultFile  #store good result for SV detect
            self.varsP.updatePipeReport(
                "referenceProcess: using reference %s for svdetect\n" %
                self.varsP.refDeresed)
        util.LogStatus("progress", "stage_complete", jobName)
示例#13
0
    def __init__(self, varsP) :
        """splitBNX.__init__: this class is for sorting the input bnx
        for subsequent splitting by the splitBNX class, and eventually
        easier processing with the Pairwise class. The constructor
        (this) will call varsP.runJobs and doAllPipeReport, then
        instantiate splitBNX, which will do all the splitting required
        for the Pairwise class.
        """
        self.stageName = "Autonoise0"
        self.varsP = varsP #fewer code modifications below
        
        util.LogStatus("progress", "stage_start", self.stageName) #after above bc check if bypass (executeCurrentStage)

        self.output_folder = os.path.join(self.varsP.contigFolder, "auto_noise")
        if not util.checkDir(self.output_folder) : #will make if not exist, only returns False if already exists or can't make
            print "ERROR in autoNoise: bad dir:", self.output_folder
            raise RuntimeError
	    
        # We use assembly section here because the memory usage is higher than pairwise, while the jobs are quite short.
        #sortJobSet=mthread.jobWrapper(self.varsP,jobName,clusterArgs=self.varsP.getClusterArgs('assembly'))
        super(autoNoise, self).__init__(self.varsP, self.stageName, clusterArgs=self.varsP.getClusterArgs("assembly"))

        bnxfile = self.varsP.bnxFile if varsP.noiseOnly else self.varsP.sorted_file+".bnx"
        #was return if generateJobListChar, but need to get readparameters if bypass
        if not self.generateJobListChar({}, bnxfile, "autoNoise0") : #return 0 for success, 1 for skip
            self.varsP.runJobs(self, "AutoNoise0")
            self.doAllPipeReport()
        if not self.allResultsFound() :
            self.varsP.updatePipeReport("ERROR: AutoNoise0 failed. Check: "+self.output_file+".stdout\n")
            raise RuntimeError
        util.LogStatus("progress", "stage_complete", self.stageName)
            
        self.varsP.noise0 = readNoiseParameters(self.output_file)
	self.isBadErrorParams(self.varsP.noise0, 0)

        self.stageName = "Autonoise1"
        self.groupName = self.stageName #fix so that LogStatus call in MultiThreading.multiThreadRunJobs
        util.LogStatus("progress", "stage_start", self.stageName)

        self.clearJobs()
        
	self.varsP.replaceParam("noise0", "-readparameters", self.output_file+".errbin")

        #need to call again to set self.output_file
        if not self.generateJobListChar(self.varsP.noise0, bnxfile, "autoNoise1") : #return 0 for success, 1 for skip
            self.varsP.runJobs(self, "AutoNoise1")
            self.doAllPipeReport()
        if not self.allResultsFound() :
            self.varsP.updatePipeReport("ERROR: AutoNoise1 failed. Check: "+self.output_file+".stdout\n")
            raise RuntimeError
            
        self.varsP.noise1 = readNoiseParameters(self.output_file)
        
	infoReport="Automatically determined noise parameters:\n"
        klist = ["FP", "FN", "sf", "sd", "sr", "bpp", "readparameters"] #hardcoding parameters is kind of bad, but it fixes the order without using OrderedDict.
        for v in klist :
            if not self.varsP.noise1.has_key(v) :
                continue
            param=str(self.varsP.noise1[v])
            util.LogStatus("parameter", "auto_"+v, param)
            infoReport+=v+":"+param+"\n"
            self.varsP.replaceParam("noise0", "-"+v, param)
        self.varsP.updateInfoReport(infoReport + '\n')
        self.isBadErrorParams(self.varsP.noise1, 1)

        if self.varsP.doScanScale : #change the sorted_file to the rescaled bnx file
            rescaledbnx = self.output_file + self.varsP.rescaleSuffix #no ".bnx" in suffix
            if not util.checkFile(rescaledbnx+".bnx") : #not found--not an error if bnx 0.1 is used
                err = "Warning: scan scaled bnx not found after autoNoise1; not performing scan scaling--check that bnx 1.0 or later used in input"
                self.varsP.updatePipeReport( err+"\n\n" )
                util.LogError("warning", err)
                self.varsP.doScanScale = False
            else : #log that scan scaling is used
                self.varsP.updatePipeReport( "Using scan scaled bnx: "+rescaledbnx+".bnx\n\n" )
                util.LogStatus("parameter", "scanscaled_bnx", rescaledbnx+".bnx")
                self.varsP.sorted_file = rescaledbnx #this variable is used in splitBNX (PairwiseModule.py)
            
        util.LogStatus("progress", "stage_complete", self.stageName)
示例#14
0
    def generateJobList(self):
        """AlignModule.generateJobList: create RefAligner jobs for aligning molecules to contigs.
        """
        #for runAlignMol, this method is called but not used: exit if RefAlignerBin is empty
        if not self.varsP.RefAlignerBin:
            return

        #the contigs are obtained from varsP.latestMergedCmap--check its validity, a return will mean no jobs, and no jobs is now handled in multiThreadRunJobs.
        if not self.doref and (
                not self.varsP.latestMergedCmap
                or not util.checkCmap(self.varsP.latestMergedCmap)):
            err = "Error in AlignModule.generateJobList: varsP.latestMergedCmap is not set or not valid cmap; skipping %s" % self.stageName
            self.varsP.updatePipeReport(err + "\n")
            util.LogError("error", err)
            return

        #Note: noise parameters should be fixed becuase when bnx is split, -M
        # would find different parameters for different contigs. Use noise0.

        baseargs = [self.varsP.RefAlignerBin]
        if not self.doref:
            baseargs += ['-ref', self.varsP.latestMergedCmap
                         ]  #reference is latest merged cmap
            mappref = os.path.split(self.varsP.latestMergedCmap)[1]
            mappref = mappref[:mappref.find(".")]
        else:
            baseargs += ['-ref', self.varsP.ref]
            mappref = self.stageName  #use stageName also for output filename

        noiseargs = self.varsP.argsListed('noise0')
        haverefargs = False
        try:  #argsListed does not check key
            refargs = self.varsP.argsListed(self.stageName)  #'alignmolvref'
            haverefargs = True
        except KeyError:  #this is same as old behavior
            #refargs = self.varsP.argsListed('noise0') + self.varsP.argsListed(self.argStageName) #old
            refargs = self.varsP.argsListed(self.argStageName)  #new
        #refargs = noiseargs + refargs

        if haverefargs:
            self.jobargs = refargs

        #single job with bnxin (constructor)
        if self.bnxin:
            outarg = os.path.join(self.alignTarget, mappref)
            self.outFileList.append(outarg)  #file prefixes
            jobargs = baseargs + ['-o', outarg]
            jobargs += ['-i', self.bnxin]

            stdoutf = None
            if self.varsP.stdoutlog:  #remember, these must be after -o
                jobargs.extend(['-f', '-stdout', '-stderr'])
                stdoutf = outarg + ".stdout"
            jobargs += ['-maxthreads', str(self.varsP.maxthreads)]
            #add noise0 before alignmol (stageName) so that the latter can override the former
            jobargs += noiseargs
            jobargs.extend(['-output-veto-filter', 'intervals.txt$'
                            ])  #this feature not in old RefAligner
            jobargs += refargs

            s1Job = mthread.singleJob(jobargs,
                                      self.stageName,
                                      outarg + ".xmap",
                                      self.stageName,
                                      maxThreads=self.varsP.maxthreads,
                                      clusterLogDir=self.varsP.clusterLogDir,
                                      expectedStdoutFile=stdoutf)
            self.addJob(s1Job)
            return  #and this is the only job

        #loop over the split bnxs, make one job per bnx
        for idx in range(1, self.varsP.nPairwiseJobs + 1):

            outarg = os.path.join(self.alignTarget, mappref + "_" + str(idx))
            self.outFileList.append(outarg)  #file prefixes
            jobargs = baseargs + ['-o', outarg]
            idxstr = "_%s_of_%s" % (idx, self.varsP.nPairwiseJobs)
            jobargs += [
                '-i',
                self.varsP.bnxFile.replace(".bnx", idxstr + ".bnx")
            ]

            stdoutf = None
            if self.varsP.stdoutlog:  #remember, these must be after -o
                jobargs.extend(['-f', '-stdout', '-stderr'])
                stdoutf = outarg + ".stdout"
            jobargs += ['-maxthreads', str(self.varsP.maxthreads)]
            #add noise0 before alignmol (stageName) so that the latter can override the former
            jobargs += noiseargs
            #if idx != 1 : #keep _r for first job only -- copied from SVModule
            #    jobargs.extend( ['-output-veto-filter', '_r.cmap$'] ) #need this for copy number; do NOT veto
            jobargs.extend(['-output-veto-filter', 'intervals.txt$'
                            ])  #this feature not in old RefAligner
            jobargs += refargs

            s1Job = mthread.singleJob(jobargs,
                                      self.stageName + idxstr,
                                      outarg + ".xmap",
                                      self.stageName + idxstr,
                                      maxThreads=self.varsP.maxthreads,
                                      clusterLogDir=self.varsP.clusterLogDir,
                                      expectedStdoutFile=stdoutf)
            self.addJob(s1Job)