code: def ani(fastas, mash_file, sim_threshold, threads):
      
      ANI = Graph()
      # use Mash to estimate ANI
      for fasta in fastas:
          indiv_mash = fasta + '.msh'
          if os.path.isfile(indiv_mash):
              cmp_file = indiv_mash
          else:
              cmp_file = fasta
          mash_cmd = ['/opt/bin/bio/mash', 'dist', cmp_file, mash_file]
          process = subprocess.Popen(mash_cmd, stdout = subprocess.PIPE)
          for pair in process.communicate()[0].splitlines():
              a, b, dist, p, shared = pair.decode().strip().split()
              a = a.rsplit('.', 1)[0].rsplit('/', 1)[-1].rsplit('.contigs')[0]
              b = b.rsplit('.', 1)[0].rsplit('/', 1)[-1].rsplit('.contigs')[0]
              p = float(p)
              similarity = (1 - float(dist)) * 100
              if similarity >= sim_threshold:
                  ANI.add_edge(a, b, si = similarity, pval = p, sharedK = shared)
          process.wait()
      return ANI
docs: Use mash to estimate ANI of genomes
      Input:
          fastas <list[str]>      -- paths to fasta files
          sim_threshold <float>   -- fractional cutoff % identity for cluster joining
          mash_file <str>         -- pasted sketch file of all fastas being compared
          threads <int>           -- number threads for distance estimation