code: def main(self):
          
          logging.info('Preparing metadata')
          # If this script is run as part of a pipeline, the metadata objects will already exist
          if not self.metadata:
              self.filer()
          else:
              self.objectprep()
          # Use the number of metadata objects to calculate the number of cores to use per sample in multi-threaded
          # methods with sequence calls to multi-threaded applications
          try:
              self.threads = int(self.cpus / len(self.metadata)) if self.cpus / len(
                  self.metadata) > 1 else 1
          except (TypeError, ZeroDivisionError):
              self.threads = self.cpus
          logging.info('Reading and formatting primers')
          self.primers()
          logging.info('Baiting .fastq files against primers')
          self.bait()
          logging.info('Baiting .fastq files against previously baited .fastq files')
          self.doublebait()
          logging.info('Assembling contigs from double-baited .fastq files')
          self.assemble_amplicon_spades()
          logging.info('Creating BLAST database')
          self.make_blastdb()
          logging.info('Running BLAST analyses')
          self.blastnthreads()
          logging.info('Parsing BLAST results')
          self.parseblast()
          logging.info('Clearing amplicon files from previous iterations')
          self.ampliconclear()
          logging.info('Creating reports')
          self.reporter()
docs: Run the necessary methods