docs: def alignment_to_reads(
      sam_merged,
      output_dir,
      parameters=DEFAULT_PARAMETERS,
      save_memory=True,
      *bin_fasta
  ):
      """Generate reads from ambiguous alignment file
  
      Extract reads found to be mapping an input FASTA bin.
      If one read maps, the whole pair is extracted and written
      to the output paired-end FASTQ files. Reads that mapped
      and weren't part of a pair are kept in a third 'single'
      file for people who need it (e.g. to get extra paired reads
      by fetching the opposite one from the original FASTQ library).
  
      Parameters
      ----------
      sam_merged : file, str or pathlib.Path
          The input alignment file in SAM/BAM format to be processed.
      output_dir : str or pathlib.Path
          The output directory to write the network and chunk data into.
      parameters : dict, optional
          Parameters for the network to read conversion, similar to
          alignment_to_network.
      save_memory : bool, optional
          Whether to keep the read names into memory or write them in different
          files, which takes longer but may prevent out-of-memory crashes.
          Default is True.
      `*bin_fasta` : file, str or pathlib.Path
          The bin FASTA files with appropriately named records.
  
      Returns
      -------
      A dictionary of files with read names for each bin if save_memory is True,
      and a dictionary of the read names lists themselves otherwise.
  
  
      Note
      ----
      This will throw an IOError ('close failed in file object destructor') on
      exit with older versions of pysam for some reason. It's harmless but
      you may consider upgrading to a later version of pysam if it comes up in
      a pipeline.
      """
  
      #   Just in case file objects are sent as input
      def get_file_string(file_thing):
          try:
              file_string = file_thing.name
          except AttributeError:
              file_string = str(file_thing)
          return file_string
  
      #   Global set of chunks against which reads are required to
      #   map - we store them in a tuple that keeps track of the
      #   original bin each chunk came from so we can reattribute the reads later
  
      bin_chunks = set()
      for bin_file in bin_fasta:
          for record in SeqIO.parse(bin_file, "fasta"):
              bin_chunks.add((get_file_string(bin_file), record.id))
  
      chunk_size = int(parameters["chunk_size"])
  
      mapq_threshold = int(parameters["mapq_threshold"])
  
      def read_name(read):
          return read.query_name.split()[0]
  
      #   Since reading a huge BAM file can take up a
      #   lot of time and resources, we only do it once
      #   but that requires opening fastq files for writing
      #   as matching reads get detected along the
      #   bam and keeping track of which ones are
      #   currently open.
  
      def get_base_name(bin_file):
  
          base_name = ".".join(os.path.basename(bin_file).split(".")[:-1])
  
          output_path = os.path.join(
              output_dir, "{}.readnames".format(base_name)
          )
  
          return output_path
  
      if save_memory:
          opened_files = dict()
      else:
          read_names = dict()
  
      with pysam.AlignmentFile(sam_merged, "rb") as alignment_merged_handle:
  
          for (my_read_name, alignment_pool) in itertools.groupby(
              alignment_merged_handle, read_name
          ):
  
              for my_alignment in alignment_pool:
  
                  relative_position = my_alignment.reference_start
                  contig_name = my_alignment.reference_name
  
                  chunk_position = relative_position // chunk_size
  
                  # The 'chunk name' is used to detect macthing positions
                  chunk_name = "{}_{}".format(contig_name, chunk_position)
  
                  # But such matching positions have to map acceptably
                  quality_test = my_alignment.mapping_quality > mapq_threshold
  
                  for bin_file in bin_fasta:
                      chunk_tuple = (bin_file, chunk_name)
                      if chunk_tuple in bin_chunks and quality_test:
                          if save_memory:
                              output_path = get_base_name(bin_file)
                              try:
                                  output_handle = opened_files[bin_file]
                              except KeyError:
                                  output_handle = open(output_path, "w")
                                  opened_files[bin_file] = output_handle
  
                              output_handle.write("@{}\n".format(my_read_name))
  
                          else:
                              try:
                                  read_names[my_read_name].append(bin_file)
                              except KeyError:
                                  read_names[my_read_name] = [bin_file]
  
      for file_handle in opened_files.values():
          file_handle.close()
      #   Return unpaired file names for pair_unpaired_reads() to process
      if save_memory:
          return opened_files.keys()
      else:
          return read_names