r"""Deformation energy of the input DNA using Global elastic properties

        It can be used to calculated deformation energy of a input DNA with reference to the DNA present in the current
        object.

        The deformation free energy is calculated using elastic matrix as follows

        .. math::

            G = \frac{1}{2L_0}\mathbf{xKx^T}


        .. math::
            \mathbf{x} =  \begin{bmatrix}
                    (\theta^{x} - \theta^{x}_0)    & (\theta^{y} - \theta^{y}_0) & (L - L_0) & (\phi - \phi_0)
                          \end{bmatrix}


        .. currentmodule:: dnaMD


        Parameters
        ----------
        bp : list
            List of two base-steps forming the DNA segment.
            For example: with ``bp=[5, 50]``, 5-50 base-step segment will be considered.
        complexDna : :class:`dnaMD.DNA`
            Input :class:`dnaMD.DNA` instance for which deformation energy will be calculated.
        freeDnaFrames : list
            To select a trajectory segment of current (free) DNA data.
            List of two trajectory frames between which parameters will be extracted. It can be used to select portions
            of the trajectory. For example, with ``frames=[100, 1000]``, 100th to 1000th frame of the trajectory will be
            considered.
        boundDnaFrames : list
            To select a trajectory segment of input (bound) DNA data.
            List of two trajectory frames between which parameters will be extracted. It can be used to select portions
            of the trajectory. For example, with ``frames=[100, 1000]``, 100th to 1000th frame of the trajectory will be
            considered.
        paxis : str
            Axis parallel to global helical-axis(``'X'``, or ``'Y'`` or ``'Z'``). Only require when bending motions are
            included in the calculation.
        which : str or list
            For which motions, energy should be calculated. It should be either a list containing terms listed below or
            "all" for all energy terms.

            Following keywords are available:
                * ``'full'`` : Use entire elastic matrix -- all motions with their coupling
                * ``'diag'`` : Use diagonal of elastic matrix -- all motions but no coupling
                * ``'b1'`` : Only bending-1 motion
                * ``'b2'`` : Only bending-2 motion
                * ``'stretch'`` : Only stretching motion
                * ``'twist'`` : Only Twisting motions
                * ``'st_coupling'`` : Only stretch-twist coupling motion
                * ``'bs_coupling'`` : Only Bending and stretching coupling
                * ``'bt_coupling'`` : Only Bending and Twisting coupling
                * ``'bb_coupling'`` : Only bending-1 and bending-2 coupling
                * ``'bend'`` : Both bending motions with their coupling
                * ``'st'`` : Stretching and twisting motions with their coupling
                * ``'bs'`` : Bending (b1, b2) and stretching motions with their coupling
                * ``'bt'`` : Bending (b1, b2) and twisting motions with their coupling
        masked : bool
            ``Default=False``. To skip specific frames/snapshots.
            ``DNA.mask`` array should be set to use this functionality.
            This array contains boolean (either ``True`` or ``False``) value
            for each frame to mask the frames. Presently, mask array is
            automatically generated during :meth:`dnaMD.DNA.generate_smooth_axis` to
            skip those frames where 3D fitting curve was not successful within
            the given criteria.

        outFile : str
            Output file in csv format.

        Returns
        -------
        time : numpy.ndarray
            1D array containing time values.

        energy : OrderedDict of numpy.ndarray
            Dictionary of 1D array of shape (nframes) containing energy terms requested for DNA.

def getGlobalDeformationEnergy(self, bp, complexDna, freeDnaFrames=None, boundDnaFrames=None, paxis='Z',
                                   which='all', masked=False, outFile=None):
        r"""Deformation energy of the input DNA using Global elastic properties

        It can be used to calculated deformation energy of a input DNA with reference to the DNA present in the current
        object.

        The deformation free energy is calculated using elastic matrix as follows

        .. math::

            G = \frac{1}{2L_0}\mathbf{xKx^T}


        .. math::
            \mathbf{x} =  \begin{bmatrix}
                    (\theta^{x} - \theta^{x}_0)    & (\theta^{y} - \theta^{y}_0) & (L - L_0) & (\phi - \phi_0)
                          \end{bmatrix}


        .. currentmodule:: dnaMD


        Parameters
        ----------
        bp : list
            List of two base-steps forming the DNA segment.
            For example: with ``bp=[5, 50]``, 5-50 base-step segment will be considered.
        complexDna : :class:`dnaMD.DNA`
            Input :class:`dnaMD.DNA` instance for which deformation energy will be calculated.
        freeDnaFrames : list
            To select a trajectory segment of current (free) DNA data.
            List of two trajectory frames between which parameters will be extracted. It can be used to select portions
            of the trajectory. For example, with ``frames=[100, 1000]``, 100th to 1000th frame of the trajectory will be
            considered.
        boundDnaFrames : list
            To select a trajectory segment of input (bound) DNA data.
            List of two trajectory frames between which parameters will be extracted. It can be used to select portions
            of the trajectory. For example, with ``frames=[100, 1000]``, 100th to 1000th frame of the trajectory will be
            considered.
        paxis : str
            Axis parallel to global helical-axis(``'X'``, or ``'Y'`` or ``'Z'``). Only require when bending motions are
            included in the calculation.
        which : str or list
            For which motions, energy should be calculated. It should be either a list containing terms listed below or
            "all" for all energy terms.

            Following keywords are available:
                * ``'full'`` : Use entire elastic matrix -- all motions with their coupling
                * ``'diag'`` : Use diagonal of elastic matrix -- all motions but no coupling
                * ``'b1'`` : Only bending-1 motion
                * ``'b2'`` : Only bending-2 motion
                * ``'stretch'`` : Only stretching motion
                * ``'twist'`` : Only Twisting motions
                * ``'st_coupling'`` : Only stretch-twist coupling motion
                * ``'bs_coupling'`` : Only Bending and stretching coupling
                * ``'bt_coupling'`` : Only Bending and Twisting coupling
                * ``'bb_coupling'`` : Only bending-1 and bending-2 coupling
                * ``'bend'`` : Both bending motions with their coupling
                * ``'st'`` : Stretching and twisting motions with their coupling
                * ``'bs'`` : Bending (b1, b2) and stretching motions with their coupling
                * ``'bt'`` : Bending (b1, b2) and twisting motions with their coupling
        masked : bool
            ``Default=False``. To skip specific frames/snapshots.
            ``DNA.mask`` array should be set to use this functionality.
            This array contains boolean (either ``True`` or ``False``) value
            for each frame to mask the frames. Presently, mask array is
            automatically generated during :meth:`dnaMD.DNA.generate_smooth_axis` to
            skip those frames where 3D fitting curve was not successful within
            the given criteria.

        outFile : str
            Output file in csv format.

        Returns
        -------
        time : numpy.ndarray
            1D array containing time values.

        energy : OrderedDict of numpy.ndarray
            Dictionary of 1D array of shape (nframes) containing energy terms requested for DNA.

        """
        if self.esType == 'BST':
            energyTerms = self.enGlobalTypes
        else:
            energyTerms = self.enGlobalTypes[:5]

        if isinstance(which, str):
            if which != 'all':
                raise ValueError('Either use "all" or use list of terms from this {0} list \n.'.format(energyTerms))
            else:
                which = energyTerms
        elif isinstance(which, list):
            for key in which:
                if key not in energyTerms:
                    raise ValueError('{0} is not a supported keyword.\n Use from the following list: \n{1}'.format(
                        which, energyTerms))
        else:
            raise ValueError('Either use "all" or use list of terms from this {0} list \n.'.format(
                energyTerms))

        if self.esType == 'BST':
            means, esMatrix = self.getStretchTwistBendModulus(bp, frames=freeDnaFrames, masked=masked,
                                                              matrix=True, paxis=paxis)
        else:
            means, esMatrix = self.getStretchTwistModulus(bp, frames=freeDnaFrames, masked=masked, matrix=True)

        esMatrix = 2.5 * esMatrix          # Convert kT to kJ/mol
        time, array = self.extractGlobalParameters(complexDna, bp, frames=boundDnaFrames, paxis=paxis, masked=masked)

        # Initialize energy dictionary
        energyOut = OrderedDict()
        for key in which:
            energyOut[key] = []

        for i in range(array[0].shape[0]):
            vec = array[:, i]
            diff = vec - means
            for key in which:
                if self.esType == 'BST':
                    t_energy = self._calcEnergyBendStretchTwist(diff, esMatrix, key)
                else:
                    t_energy = self._calcEnergyStretchTwist(diff, esMatrix, key)
                energyOut[key].append(t_energy)

        for key in which:
            energyOut[key] = np.asarray(energyOut[key])

        # Write output file
        if outFile is not None:
            with open(outFile, 'w') as fout:
                fout.write('#Time')
                for name in which:
                    fout.write(', {0}'.format(name))
                fout.write('\n')
                for t in range(len(time)):
                    fout.write('{0:.3f}'.format(time[t]))
                    for name in which:
                        fout.write(', {0:.5f}'.format(energyOut[name][t]))
                    fout.write('\n')

        return time, energyOut