Convenient constructor that takes in a list of Structure objects to
        perform diffusion analysis.

        Args:
            structures ([Structure]): list of Structure objects (must be
                ordered in sequence of run). E.g., you may have performed
                sequential VASP runs to obtain sufficient statistics.
            specie (Element/Specie): Specie to calculate diffusivity for as a
                String. E.g., "Li".
            temperature (float): Temperature of the diffusion run in Kelvin.
            time_step (int): Time step between measurements.
            step_skip (int): Sampling frequency of the displacements (
                time_step is multiplied by this number to get the real time
                between measurements)
            initial_disp (np.ndarray): Sometimes, you need to iteratively
                compute estimates of the diffusivity. This supplies an
                initial displacement that will be added on to the initial
                displacements. Note that this makes sense only when
                smoothed=False.
            initial_structure (Structure): Like initial_disp, this is used
                for iterative computations of estimates of the diffusivity. You
                typically need to supply both variables. This stipulates the
                initial structure from which the current set of displacements
                are computed.
            \\*\\*kwargs: kwargs supported by the :class:`DiffusionAnalyzer`_. 
                Examples include smoothed, min_obs, avg_nsteps.

def from_structures(cls, structures, specie, temperature,
                        time_step, step_skip, initial_disp=None,
                        initial_structure=None, **kwargs):
        """
        Convenient constructor that takes in a list of Structure objects to
        perform diffusion analysis.

        Args:
            structures ([Structure]): list of Structure objects (must be
                ordered in sequence of run). E.g., you may have performed
                sequential VASP runs to obtain sufficient statistics.
            specie (Element/Specie): Specie to calculate diffusivity for as a
                String. E.g., "Li".
            temperature (float): Temperature of the diffusion run in Kelvin.
            time_step (int): Time step between measurements.
            step_skip (int): Sampling frequency of the displacements (
                time_step is multiplied by this number to get the real time
                between measurements)
            initial_disp (np.ndarray): Sometimes, you need to iteratively
                compute estimates of the diffusivity. This supplies an
                initial displacement that will be added on to the initial
                displacements. Note that this makes sense only when
                smoothed=False.
            initial_structure (Structure): Like initial_disp, this is used
                for iterative computations of estimates of the diffusivity. You
                typically need to supply both variables. This stipulates the
                initial structure from which the current set of displacements
                are computed.
            \\*\\*kwargs: kwargs supported by the :class:`DiffusionAnalyzer`_. 
                Examples include smoothed, min_obs, avg_nsteps.
        """
        p, l = [], []
        for i, s in enumerate(structures):
            if i == 0:
                structure = s
            p.append(np.array(s.frac_coords)[:, None])
            l.append(s.lattice.matrix)
        if initial_structure is not None:
            p.insert(0, np.array(initial_structure.frac_coords)[:, None])
            l.insert(0, initial_structure.lattice.matrix)
        else:
            p.insert(0, p[0])
            l.insert(0, l[0])

        p = np.concatenate(p, axis=1)
        dp = p[:, 1:] - p[:, :-1]
        dp = dp - np.round(dp)
        f_disp = np.cumsum(dp, axis=1)
        c_disp = []
        for i in f_disp:
            c_disp.append( [ np.dot(d, m) for d, m in zip(i, l[1:]) ] )
        disp = np.array(c_disp)

        # If is NVT-AIMD, clear lattice data.
        if np.array_equal(l[0], l[-1]):
            l = np.array([l[0]])
        else:
            l = np.array(l)
        if initial_disp is not None:
            disp += initial_disp[:, None, :]

        return cls(structure, disp, specie, temperature, time_step,
                   step_skip=step_skip, lattices=l, **kwargs)