Read parameters from do_x3dna file.

    It is the main function, which is used to read and extract the parameters
    values from the do_x3dna output files.

    Parameters
    ----------
    FileName : str
        Parameter file produced from do_x3dna.
    parameters : list
        List of column indices that has to be extracted. indices here start
        with one.

    bp : 1D list or array
        base-pairs to analyze
        Example: ::

            bp = [6]                                # bp_range = False
            bp = [4,15]                             # bp_range = True
            bp = range(4,15)                        # bp_range = False
            bp = np.arange(4,15)                    # bp_range = False
            bp = [2,5,6,7,9,12,18]                  # bp_range = False
    bp_range : bool
        ``Default=True``: As shown above, if ``True``, bp is taken as a range otherwise list or numpy array.
    word : bool
        In some parameters, in place of value, ``'---'`` is present in the file.
        If parameter values contain this, use ``True``.
    startBP : int
        Number ID of first base-pair.

    Returns
    -------
    data : 3D array
        Extracted parameters as a 3D array of shape (bp, parameters, time).
    time : 1D array
        Time of each frame

def read_param_file(FileName, parameters, bp, bp_range, word=False, startBP=1):
    """ Read parameters from do_x3dna file.

    It is the main function, which is used to read and extract the parameters
    values from the do_x3dna output files.

    Parameters
    ----------
    FileName : str
        Parameter file produced from do_x3dna.
    parameters : list
        List of column indices that has to be extracted. indices here start
        with one.

    bp : 1D list or array
        base-pairs to analyze
        Example: ::

            bp = [6]                                # bp_range = False
            bp = [4,15]                             # bp_range = True
            bp = range(4,15)                        # bp_range = False
            bp = np.arange(4,15)                    # bp_range = False
            bp = [2,5,6,7,9,12,18]                  # bp_range = False
    bp_range : bool
        ``Default=True``: As shown above, if ``True``, bp is taken as a range otherwise list or numpy array.
    word : bool
        In some parameters, in place of value, ``'---'`` is present in the file.
        If parameter values contain this, use ``True``.
    startBP : int
        Number ID of first base-pair.

    Returns
    -------
    data : 3D array
        Extracted parameters as a 3D array of shape (bp, parameters, time).
    time : 1D array
        Time of each frame
    """

    sys.stdout.write("\nReading file : %s\n" % FileName)
    sys.stdout.flush()

    def get_frame_data(block, parameters, bp_idx):
        block = np.array(block).T
        temp_data = (block[parameters, :])[:, bp_idx].copy()
        return temp_data

    def get_time(line):
        dummy, temp_time = line.split('=')
        return float( temp_time )

    infile = open(FileName, 'r')
    data = []
    time = []
    frame_number = 0

    bp_idx, param_idx = get_idx_of_bp_parameters(bp, parameters, bp_range, startBP=startBP)

    block = []
    for line in infile:

        # Removing last new line character
        line = line.rstrip('\n')

        # Skipping blank/empty line
        if not line.strip():
            continue

        # Getting Time tag and time => Starting of new frame
        if(re.match('# Time', line) != None):

            if((frame_number < 100) and (frame_number % 10 == 0)) or ((frame_number < 1000) and (frame_number % 100 == 0)) or ((frame_number < 10000) and (frame_number % 1000 == 0)) or ((frame_number < 100000) and (frame_number % 10000 == 0)) or ((frame_number < 1000000) and (frame_number % 100000 == 0)):
                sys.stdout.write("\rReading frame %d" % frame_number)
                sys.stdout.flush()

            frame_number += 1

            # if(frame_number==5000):
            # break

            # Getting time
            time.append(get_time(line))

            # Getting parameters/values for base-pairs
            if(len(block) > 0):
                data.append(get_frame_data(block, param_idx, bp_idx))
            block = []
            continue

        # Skipping other lines starting with '#' tag
        if(re.match('#', line) != None):
            continue

        if not word:
            block.append(list(map(float, line.split())))
        else:
            temp = []
            split_line = line.split()
            for word in split_line:
                if word != '---':
                    temp.append(float(word))
                else:
                    temp.append(None)
            block.append(temp)

    # For last frame
    data.append(get_frame_data(block, param_idx, bp_idx))
    block = []
    data_transpose = np.array(data).T

    sys.stdout.write(
        "\nFinished reading.... Total number of frame read =  %d\n" % frame_number)
    sys.stdout.flush()

    return data_transpose, time