<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 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