This function bins the Atoms into fixed-size sections of the protein space in 3D.

def bin_atoms(self):
        '''This function bins the Atoms into fixed-size sections of the protein space in 3D.'''

        # Create the atom bins
        low_point = numpy.array([self.min_x, self.min_y, self.min_z])
        high_point = numpy.array([self.max_x, self.max_y, self.max_z])
        atom_bin_dimensions = numpy.ceil((high_point - low_point) / self.bin_size)
        self.atom_bin_dimensions = (int(atom_bin_dimensions[0]) - 1, int(atom_bin_dimensions[1]) - 1, int(atom_bin_dimensions[2]) - 1)
        atom_bins = []
        for x in range(int(atom_bin_dimensions[0])):
            atom_bins.append([])
            for y in range(int(atom_bin_dimensions[1])):
                atom_bins[x].append([])
                for z in range(int(atom_bin_dimensions[2])):
                    atom_bins[x][y].append(Bin(x, y, z))

        # Assign each Atom to a bin
        for serial_number, atom in self.atoms.iteritems():
            bin_location = numpy.trunc((atom.point - low_point) / self.bin_size)
            bin = atom_bins[int(bin_location[0])][int(bin_location[1])][int(bin_location[2])]
            bin.append(atom)
            atom.set_bin(bin)

        # Sanity_check
        if self.safe_mode:
            num_atoms = 0
            for x in range(int(atom_bin_dimensions[0])):
                for y in range(int(atom_bin_dimensions[1])):
                    for z in range(int(atom_bin_dimensions[2])):
                        num_atoms += len(atom_bins[x][y][z])
            assert(num_atoms == len(self.atoms))

        # Snip empty sections (saves a little space after garbage collection - space savings increase with the number of empty arrays in the matrix)
        blank_section = ()
        for x in range(int(atom_bin_dimensions[0])):
            for y in range(int(atom_bin_dimensions[1])):
                for z in range(int(atom_bin_dimensions[2])):
                    if not atom_bins[x][y][z]:
                        atom_bins[x][y][z] = blank_section

        self.atom_bins = atom_bins