N = 1000
cords = np.random.randint(3, 7, (N, 3))
atoms = np.random.choice(list('HC'), N)
atom_proj = {'H': np.array([[0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 1, 1, 1, 
    0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]]), 'C': np.array([[0, 0, 0, 0, 0, 
    0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0,
    0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]])}

def project_atom(cords, atoms, atom_proj):
    extruded = np.zeros((N, 10, 10))
extruded[list(range(N)), cords[:, (2)], cords[:, (0)]] = 1
grid = np.zeros((10, 10))
for atom, proj in atom_proj.items():
    grid += nd.convolve(extruded[atoms.squeeze() == atom].sum(0), proj,
        mode='constant')
return grid

def OP_simplified(cords, atoms, atom_proj):
    rads = {atom: ((proj.shape[0] - 1) / 2) for atom, proj in atom_proj.
        items()}
grid = np.zeros((10, 10))
for (x, y, z), atom in zip(cords, atoms):
    rad = rads[atom]
grid[z - rad:z + rad + 1, x - rad:x + rad + 1] += atom_proj[atom]
return grid

def OP(cords, atoms, atom_proj):
    grid = np.zeros((10, 10))
for values in zip(cords, atoms):
    atom_shape = np.shape(atom_proj[values[1][0]])
rad = (atom_shape[0] - 1) / 2
grid[values[0][2] - rad:values[0][2] + rad + 1, values[0][0] - rad:values[0
    ][0] + rad + 1] += atom_proj[values[1][0]]
return grid
Projecting Coordinates in Numpy array