docs: def launch_workflow(seqs_fp, working_dir, mean_error, error_dist,
                      indel_prob, indel_max, trim_length, left_trim_length,
                      min_size, ref_fp, ref_db_fp, threads_per_sample=1,
                      sim_thresh=None, coverage_thresh=None):
      """Launch full deblur workflow for a single post split-libraries fasta file
  
      Parameters
      ----------
      seqs_fp: string
          a post split library fasta file for debluring
      working_dir: string
          working directory path
      mean_error: float
          mean error for original sequence estimate
      error_dist: list
          list of error probabilities for each hamming distance
      indel_prob: float
          insertion/deletion (indel) probability
      indel_max: integer
          maximal indel number
      trim_length: integer
          sequence trim length
      left_trim_length: integer
          trim the first n reads
      min_size: integer
          upper limit on sequence abundance (discard sequences below limit)
      ref_fp: tuple
          filepath(s) to FASTA reference database for artifact removal
      ref_db_fp: tuple
          filepath(s) to SortMeRNA indexed database for artifact removal
      threads_per_sample: integer, optional
          number of threads to use for SortMeRNA/mafft/vsearch
          (0 for max available)
      sim_thresh: float, optional
          the minimal similarity for a sequence to the database.
          if None, take the defaults (0.65 for negate=False,
          0.95 for negate=True)
      coverage_thresh: float, optional
          the minimal coverage for alignment of a sequence to the database.
          if None, take the defaults (0.3 for negate=False, 0.95 for negate=True)
  
      Return
      ------
      output_no_chimers_fp : string
          filepath to fasta file with no chimeras of None if error encountered
      """
      logger = logging.getLogger(__name__)
      logger.info('--------------------------------------------------------')
      logger.info('launch_workflow for file %s' % seqs_fp)
  
      # Step 1: Trim sequences to specified length
      output_trim_fp = join(working_dir, "%s.trim" % basename(seqs_fp))
      with open(output_trim_fp, 'w') as out_f:
          for label, seq in trim_seqs(
                  input_seqs=sequence_generator(seqs_fp),
                  trim_len=trim_length,
                  left_trim_len=left_trim_length):
              out_f.write(">%s\n%s\n" % (label, seq))
      # Step 2: Dereplicate sequences
      output_derep_fp = join(working_dir,
                             "%s.derep" % basename(output_trim_fp))
      dereplicate_seqs(seqs_fp=output_trim_fp,
                       output_fp=output_derep_fp,
                       min_size=min_size, threads=threads_per_sample)
      # Step 3: Remove artifacts
      output_artif_fp, num_seqs_left, _ = remove_artifacts_seqs(seqs_fp=output_derep_fp,
                                                                ref_fp=ref_fp,
                                                                working_dir=working_dir,
                                                                ref_db_fp=ref_db_fp,
                                                                negate=True,
                                                                threads=threads_per_sample,
                                                                sim_thresh=sim_thresh)
      if not output_artif_fp:
          warnings.warn('Problem removing artifacts from file %s' %
                        seqs_fp, UserWarning)
          logger.warning('remove artifacts failed, aborting')
          return None
      # Step 4: Multiple sequence alignment
      if num_seqs_left > 1:
          output_msa_fp = join(working_dir,
                               "%s.msa" % basename(output_artif_fp))
          alignment = multiple_sequence_alignment(seqs_fp=output_artif_fp,
                                                  threads=threads_per_sample)
          if not alignment:
              warnings.warn('Problem performing multiple sequence alignment '
                            'on file %s' % seqs_fp, UserWarning)
              logger.warning('msa failed. aborting')
              return None
      elif num_seqs_left == 1:
          # only one sequence after remove artifacts (but could be many reads)
          # no need to run MSA - just use the pre-msa file as input for next step
          output_msa_fp = output_artif_fp
      else:
          err_msg = ('No sequences left after artifact removal in '
                     'file %s' % seqs_fp)
          warnings.warn(err_msg, UserWarning)
          logger.warning(err_msg)
          return None
      # Step 5: Launch deblur
      output_deblur_fp = join(working_dir,
                              "%s.deblur" % basename(output_msa_fp))
      with open(output_deblur_fp, 'w') as f:
          seqs = deblur(sequence_generator(output_msa_fp), mean_error,
                        error_dist, indel_prob, indel_max)
          if seqs is None:
              warnings.warn('multiple sequence alignment file %s contains '
                            'no sequences' % output_msa_fp, UserWarning)
              logger.warn('no sequences returned from deblur for file %s' %
                          output_msa_fp)
              return None
          for s in seqs:
              # remove '-' from aligned sequences
              s.sequence = s.sequence.replace('-', '')
              f.write(s.to_fasta())
      # Step 6: Chimera removal
      output_no_chimeras_fp = remove_chimeras_denovo_from_seqs(
          output_deblur_fp, working_dir, threads=threads_per_sample)
      logger.info('finished processing file')
      return output_no_chimeras_fp