<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def particles_in_range( self, compound, dmax, max_particles=20, particle_kdtree=None, particle_array=None):
 """Find particles within a specified range of another particle. Parameters compound : mb.Compound Reference particle to find other particles in range of dmax : float Maximum distance from 'compound' to look for Particles max_particles : int, optional, default=20 Maximum number of Particles to return particle_kdtree : mb.PeriodicCKDTree, optional KD-tree for looking up nearest neighbors. If not provided, a KD- tree will be generated from all Particles in self particle_array : np.ndarray, shape=(n,), dtype=mb.Compound, optional Array of possible particles to consider for return. If not provided, this defaults to all Particles in self Returns ------- np.ndarray, shape=(n,), dtype=mb.Compound Particles in range of compound according to user-defined limits See Also -------- periodic_kdtree.PerioidicCKDTree : mBuild implementation of kd-trees scipy.spatial.ckdtree : Further details on kd-trees """

        if particle_kdtree is None:
            particle_kdtree = PeriodicCKDTree(
                data=self.xyz, bounds=self.periodicity)
        _, idxs = particle_kdtree.query(
            compound.pos, k=max_particles, distance_upper_bound=dmax)
        idxs = idxs[idxs != self.n_particles]
        if particle_array is None:
            particle_array = np.array(list(self.particles()))
        return particle_array[idxs]