To calculate curvatures and tangent vectors along the helical axis.

        The curvature and tangent vectors are calculated using Frenet-Serret formula.
        The calculated values are stored in ``DNA.data`` dictionary and also in HDF5 file.

        Parameters
        ----------
        step_range : bool
            * ``step_range = True`` : Calculate curvature and tangent vectors for the given range of base-steps
            * ``step_range = False``: Calculate curvature and tangent vectors for entire DNA. If smoothed helical-axis of any base-step will be found to be not available, error will be raised.

        step : list
            List containing lower and higher limit of base-steps range.
                * This option only works with ``step_range=True``.
                * This list should not contain more than two number.
                * First number should be less than second number.

            Example for base-step 4 to 15:
                ``step = [4,15]         # step_range = True``

        store_tangent : bool
            * ``store_tangent = True`` : The calculated tangent vectors will be stored for later use.
            * ``store_tangent = False``:  The calculated tangent vectors will be discarded.

            In case of HDF5 file, calculated tangents will be stored in this
            file and it will not add cost to memory. However, without HDF5 file,
            storing tangents in ``DNA.data`` will be expansive for memory.

def calculate_curvature_tangent(self, step_range=False, step=None, store_tangent=False):
        """To calculate curvatures and tangent vectors along the helical axis.

        The curvature and tangent vectors are calculated using Frenet-Serret formula.
        The calculated values are stored in ``DNA.data`` dictionary and also in HDF5 file.

        Parameters
        ----------
        step_range : bool
            * ``step_range = True`` : Calculate curvature and tangent vectors for the given range of base-steps
            * ``step_range = False``: Calculate curvature and tangent vectors for entire DNA. If smoothed helical-axis of any base-step will be found to be not available, error will be raised.

        step : list
            List containing lower and higher limit of base-steps range.
                * This option only works with ``step_range=True``.
                * This list should not contain more than two number.
                * First number should be less than second number.

            Example for base-step 4 to 15:
                ``step = [4,15]         # step_range = True``

        store_tangent : bool
            * ``store_tangent = True`` : The calculated tangent vectors will be stored for later use.
            * ``store_tangent = False``:  The calculated tangent vectors will be discarded.

            In case of HDF5 file, calculated tangents will be stored in this
            file and it will not add cost to memory. However, without HDF5 file,
            storing tangents in ``DNA.data`` will be expansive for memory.

        """

        if not self.smooth_axis:
            raise ValueError(
                "The helical axis is not smooth. At first, smooth the axis using generate_smooth_axis() method as described in http://rjdkmr.github.io/do_x3dna/apidoc.html#dnaMD.DNA.generate_smooth_axis.")

        if (step_range) and (step == None):
            raise ValueError(
                "See, documentation for step  and step_range usage!!!")

        if step_range:
            if (len(step) != 2):
                raise ValueError("See, documentation for step usage!!!")

            if step[0] > step[1]:
                raise ValueError("See, documentation for step usage!!!")

            X, bp_idx = self.get_parameters(
                'helical x-axis smooth', step, bp_range=True)
            Y, bp_idx = self.get_parameters(
                'helical y-axis smooth', step, bp_range=True)
            Z, bp_idx = self.get_parameters(
                'helical z-axis smooth', step, bp_range=True)
        else:
            X, bp_idx = self.get_parameters(
                'helical x-axis smooth', [1, self.num_step], bp_range=True)
            Y, bp_idx = self.get_parameters(
                'helical y-axis smooth', [1, self.num_step], bp_range=True)
            Z, bp_idx = self.get_parameters(
                'helical z-axis smooth', [1, self.num_step], bp_range=True)

        X = np.asarray(X).T
        Y = np.asarray(Y).T
        Z = np.asarray(Z).T

        curvature, tangent = [], []

        for i in range(len(self.time)):

            # Curvature calculation
            xyz = np.vstack((X[i], Y[i], Z[i])).T
            T, N, B, k_temp, t_temp = frenet_serret(xyz)

            curvature.append(k_temp.flatten())

            if(store_tangent):
                tangent.append(T)

        curvature = np.asarray(curvature).T
        for i in range(len(bp_idx)):
            bp_num = str( bp_idx[i]+self.startBP )
            self._set_data(curvature[i], 'bps', bp_num, 'curvature',  scaleoffset=3)

        if(store_tangent):
            tangent = np.asarray(tangent)
            final_tan = []
            for i in range(len(tangent[0])):
                temp = []
                for j in range(len(tangent)):
                    temp.append(tangent[j][i])
                final_tan.append(np.asarray(temp))

            for i in range(len(bp_idx)):
                bp_num = str( bp_idx[i]+self.startBP )
                self._set_data(np.asarray(final_tan[i]), 'bps', bp_num, 'tangent',  scaleoffset=3)