Beispiel #1
0
def pulsar_DM_variation(array, no_of_DM_steps, frequencyList0, FFTsize, fmin,
                        fmax, df, TimeRes, pulsarPeriod, samplesPerPeriod, DM,
                        filename, AverageChannelNumber, time_points,
                        noise_mean, noise_std, beginIndex, endIndex,
                        DM_var_step, roll_number, save_intermediate_data,
                        customDPI):
    '''
    Variation of DM for average pulsar profile with defined step and number of steps
    '''
    # ***   Preparing matrices for variation of DM value   ***
    profiles_varDM = np.zeros((no_of_DM_steps, time_points))
    DM_vector = np.zeros((no_of_DM_steps))

    # ***   Rolling to central position of pulse the whole matrix   ***
    for i in range(FFTsize):
        array[:, i] = np.roll(array[:, i], roll_number)

    # ***   Preparing the vector of DMs to calculate profiles   ***
    for step in range(no_of_DM_steps):
        DM_vector[step] = DM + ((step - int(no_of_DM_steps / 2)) * DM_var_step)

    # ***   Step by step calculate profiles for each DM value as in the main program   ***
    for step in range(no_of_DM_steps):
        # Preparing matrices
        inter_matrix = np.zeros((FFTsize, samplesPerPeriod))
        inter_matrix[:, :] = array.transpose()[:, :]
        # DM compensation
        shiftPar = pulsar_DM_shift_calculation_aver_pulse(
            FFTsize, fmin, fmax, df, TimeRes, DM_vector[step], pulsarPeriod)
        matrix = pulsar_DM_compensation_with_indices_changes(
            inter_matrix, shiftPar)

        del inter_matrix
        # Averaging in frequency
        reducedMatrix = np.array(
            [[0.0 for col in range(samplesPerPeriod)]
             for row in range(int(FFTsize / AverageChannelNumber))])
        for i in range(int(FFTsize / AverageChannelNumber)):
            for j in range(samplesPerPeriod):
                reducedMatrix[i, j] = sum(
                    matrix[i * AverageChannelNumber:(i + 1) *
                           AverageChannelNumber, j])
        frequencyList1 = frequencyList0[::AverageChannelNumber]

        freq_channels, time_points = reducedMatrix.shape
        integrProfile = np.array([])
        integrProfile = (np.sum(reducedMatrix, axis=0))

        for i in range(freq_channels):
            reducedMatrix[i, :] = reducedMatrix[i, :] - np.mean(
                reducedMatrix[i, beginIndex:endIndex])
        # Calcultation of integrated profile
        integrProfile = np.array([])
        integrProfile = (np.sum(reducedMatrix, axis=0))
        integrProfile = (integrProfile - noise_mean) / noise_std
        # Adding the calcultaed average profile to the matrix of profiles
        profiles_varDM[step, :] = integrProfile

    return profiles_varDM, DM_vector
def pulsar_DM_variation(array, no_of_DM_steps, FFTsize, fmin, fmax, df,
                        TimeRes, pulsarPeriod, samplesPerPeriod, DM,
                        noise_mean, noise_std, begin_index, end_index,
                        DM_var_step, roll_number, save_intermediate_data,
                        customDPI):
    '''
    Variation of DM for average pulsar profile with defined step and number of steps
    '''
    # ***   Preparing matrices for variation of DM value   ***
    profiles_varDM = np.zeros((no_of_DM_steps, samplesPerPeriod))
    DM_vector = np.zeros((no_of_DM_steps))

    # ***   Preparing the vector of DMs to calculate profiles   ***
    for step in range(no_of_DM_steps):
        DM_vector[step] = DM + ((step - int(no_of_DM_steps / 2)) * DM_var_step)

    # ***   Step by step calculate profiles for each DM value as in the main program   ***
    for step in range(no_of_DM_steps):

        # Preparing matrices
        matrix = np.zeros((FFTsize, samplesPerPeriod))
        matrix[:, :] = array[:, :]

        # DM compensation
        shiftPar = pulsar_DM_shift_calculation_aver_pulse(
            FFTsize, fmin, fmax, df, TimeRes, DM_vector[step], pulsarPeriod)
        matrix = pulsar_DM_compensation_with_indices_changes(matrix, shiftPar)

        for i in range(FFTsize):
            matrix[i, :] = matrix[i, :] - np.mean(
                matrix[i, begin_index:end_index])

        # Calcultation of integrated profile
        integrated_profile = np.sum(matrix, axis=0)

        integrated_profile = (integrated_profile - noise_mean) / noise_std

        # Adding the calcultaed average profile to the matrix of profiles
        profiles_varDM[step, :] = integrated_profile

    # ***   Rolling to central position of pulse the whole matrix   ***
    profiles_varDM = np.roll(profiles_varDM, roll_number)

    return profiles_varDM, DM_vector
Beispiel #3
0
def pulsar_incoherent_dedispersion(
        common_path, filename, pulsar_name, average_const, profile_pic_min,
        profile_pic_max, cleaning_Iana, cleaning, no_of_iterations,
        std_lines_clean, pic_in_line, std_pixels_clean, SpecFreqRange,
        freqStart, freqStop, save_profile_txt, save_compensated_data,
        customDPI, colormap):

    previousTime = time.time()
    currentTime = time.strftime("%H:%M:%S")
    currentDate = time.strftime("%d.%m.%Y")

    rc('font', size=6, weight='bold')
    data_filename = common_path + filename

    # *** Creating a folder where all pictures and results will be stored (if it doesn't exist) ***
    newpath = 'RESULTS_pulsar_single_pulses_' + pulsar_name + '_' + filename
    if not os.path.exists(newpath):
        os.makedirs(newpath)

    # Path to timeline file to be analyzed:
    time_line_file_name = common_path + filename[-31:-13] + '_Timeline.txt'

    if save_profile_txt > 0:
        # *** Creating a name for long timeline TXT file ***
        profile_file_name = newpath + '/' + filename + '_time_profile.txt'
        profile_txt_file = open(
            profile_file_name,
            'w')  # Open and close to delete the file with the same name
        profile_txt_file.close()

    # *** Opening DAT datafile ***
    file = open(data_filename, 'rb')

    # reading FHEADER
    df_filesize = os.stat(data_filename).st_size  # Size of file
    df_filename = file.read(32).decode('utf-8').rstrip(
        '\x00')  # Initial data file name
    file.close()

    receiver_type = df_filename[-4:]

    # Reading file header to obtain main parameters of the file
    if receiver_type == '.adr':
        [TimeRes, fmin, fmax, df, frequency_list,
         FFTsize] = FileHeaderReaderADR(data_filename, 0, 1)

    if receiver_type == '.jds':
        [
            df_filename, df_filesize, df_system_name, df_obs_place,
            df_description, CLCfrq, df_creation_timeUTC, sp_in_file,
            ReceiverMode, Mode, Navr, TimeRes, fmin, fmax, df, frequency_list,
            FFTsize, dataBlockSize
        ] = FileHeaderReaderJDS(data_filename, 0, 1)

    # Manually set frequencies for two channels mode
    if int(CLCfrq / 1000000) == 33:
        #FFTsize = 8192
        fmin = 16.5
        fmax = 33.0
        frequency_list = np.linspace(fmin, fmax, FFTsize)

    sp_in_file = int(
        ((df_filesize - 1024) / (len(frequency_list) * 8)
         ))  # the second dimension of the array: file size - 1024 bytes

    pulsar_ra, pulsar_dec, DM, p_bar = catalogue_pulsar(pulsar_name)

    # ************************************************************************************
    #                             R E A D I N G   D A T A                                *
    # ************************************************************************************

    # Time line file reading
    timeline, dt_timeline = time_line_file_reader(time_line_file_name)

    # Selecting the frequency range of data to be analyzed
    if SpecFreqRange == 1:
        A = []
        B = []
        for i in range(len(frequency_list)):
            A.append(abs(frequency_list[i] - freqStart))
            B.append(abs(frequency_list[i] - freqStop))
        ifmin = A.index(min(A))
        ifmax = B.index(min(B))
        shift_vector = DM_full_shift_calc(ifmax - ifmin, frequency_list[ifmin],
                                          frequency_list[ifmax],
                                          df / pow(10, 6), TimeRes, DM,
                                          receiver_type)
        print(' Number of frequency channels:  ', ifmax - ifmin)

    else:
        shift_vector = DM_full_shift_calc(
            len(frequency_list) - 4, fmin, fmax, df / pow(10, 6), TimeRes, DM,
            receiver_type)
        print(' Number of frequency channels:  ', len(frequency_list) - 4)
        ifmin = 0
        ifmax = int(len(frequency_list) - 4)

    if save_compensated_data > 0:
        with open(data_filename, 'rb') as file:
            file_header = file.read(1024)  # Data file header read

        # *** Creating a binary file with data for long data storage ***
        new_data_file_name = pulsar_name + '_DM_' + str(DM) + '_' + filename
        new_data_file = open(new_data_file_name, 'wb')
        new_data_file.write(file_header)
        new_data_file.seek(624)  # Lb place in header
        new_data_file.write(np.int32(ifmin).tobytes())
        new_data_file.seek(628)  # Hb place in header
        new_data_file.write(np.int32(ifmax).tobytes())
        new_data_file.seek(632)  # Wb place in header
        new_data_file.write(
            np.int32(ifmax -
                     ifmin).tobytes())  # bytes([np.int32(ifmax - ifmin)]))
        new_data_file.close()

        # *** Creating a name for long timeline TXT file ***
        new_TLfile_name = pulsar_name + '_DM_' + str(
            DM) + '_' + data_filename[:-13] + '_Timeline.txt'
        new_TLfile = open(
            new_TLfile_name,
            'w')  # Open and close to delete the file with the same name
        new_TLfile.close()

        del file_header

    max_shift = np.abs(shift_vector[0])

    if SpecFreqRange == 1:
        buffer_array = np.zeros((ifmax - ifmin, 2 * max_shift))
    else:
        buffer_array = np.zeros((len(frequency_list) - 4, 2 * max_shift))

    num_of_blocks = int(sp_in_file / (1 * max_shift))

    print(' Number of spectra in file:     ', sp_in_file, ' ')
    print(' Maximal shift is:              ', max_shift, ' pixels ')
    print(' Number of blocks in file:      ', num_of_blocks, ' ')
    print(' Dispersion measure:            ', DM, ' pc / cm3 \n')
    print(' Pulsar name:                   ', pulsar_name, '  \n')

    if receiver_type == '.jds':
        num_frequencies_initial = len(frequency_list) - 4

    frequency_list_initial = np.empty_like(frequency_list)
    frequency_list_initial[:] = frequency_list[:]

    dat_file = open(data_filename, 'rb')
    dat_file.seek(1024)  # Jumping to 1024 byte from file beginning

    for block in range(num_of_blocks):  # main loop by number of blocks in file

        print(
            '\n * Data block # ', block + 1, ' of ', num_of_blocks,
            '\n ******************************************************************'
        )

        # Time line arrangements:
        fig_time_scale = []
        fig_date_time_scale = []
        for i in range(block * max_shift, (block + 1) * max_shift
                       ):  # Shows the time of pulse end (at lowest frequency)
            fig_time_scale.append(timeline[i][11:23])
            fig_date_time_scale.append(timeline[i][:])
        print(' Time: ', fig_time_scale[0], ' - ', fig_time_scale[-1],
              ', number of points: ', len(fig_time_scale))

        # Data block reading
        if receiver_type == '.jds':
            data = np.fromfile(dat_file,
                               dtype=np.float64,
                               count=(num_frequencies_initial + 4) * 1 *
                               max_shift)  # 2
            data = np.reshape(data,
                              [(num_frequencies_initial + 4), 1 * max_shift],
                              order='F')  # 2
            data = data[:
                        num_frequencies_initial, :]  # To delete the last channels of DSP data where time is stored

        # Cutting the array in predefined frequency range
        if SpecFreqRange == 1:
            data, frequency_list, fi_start, fi_stop = specify_frequency_range(
                data, frequency_list_initial, freqStart, freqStop)
            num_frequencies = len(frequency_list)
        else:
            num_frequencies = num_frequencies_initial

        # Normalization of data
        Normalization_lin(data, num_frequencies, 1 * max_shift)

        nowTime = time.time()
        print('\n  *** Preparation of data took:              ',
              round((nowTime - previousTime), 2), 'seconds ')
        previousTime = nowTime

        if cleaning_Iana > 0:
            data = survey_cleaning(
                data)  # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        if cleaning > 0:

            # Cleaning vertical and horizontal lines of RFI
            data, mask, cleaned_pixels_num = clean_lines_of_pixels(
                data, no_of_iterations, std_lines_clean, pic_in_line)

            plt.figure(1, figsize=(10.0, 6.0))
            plt.subplots_adjust(left=None,
                                bottom=0,
                                right=None,
                                top=0.86,
                                wspace=None,
                                hspace=None)
            ImA = plt.imshow(mask, aspect='auto', vmin=0, vmax=1, cmap='Greys')
            plt.title('Full log initial data',
                      fontsize=10,
                      fontweight='bold',
                      style='italic',
                      y=1.025)
            plt.ylabel('One dimension', fontsize=10, fontweight='bold')
            plt.xlabel('Second dimensions', fontsize=10, fontweight='bold')
            plt.colorbar()
            plt.yticks(fontsize=8, fontweight='bold')
            plt.xticks(fontsize=8, fontweight='bold')
            pylab.savefig(newpath + '/00_10' + ' fig. ' + str(block + 1) +
                          ' - Result mask after lines cleaning.png',
                          bbox_inches='tight',
                          dpi=300)
            plt.close('all')

            # Cleaning remaining 1 pixel splashes of RFI
            data, mask, cleaned_pixels_num = array_clean_by_STD_value(
                data, std_pixels_clean)

            plt.figure(1, figsize=(10.0, 6.0))
            plt.subplots_adjust(left=None,
                                bottom=0,
                                right=None,
                                top=0.86,
                                wspace=None,
                                hspace=None)
            ImA = plt.imshow(mask, aspect='auto', vmin=0, vmax=1, cmap='Greys')
            plt.title('Full log initial data',
                      fontsize=10,
                      fontweight='bold',
                      style='italic',
                      y=1.025)
            plt.ylabel('One dimension', fontsize=10, fontweight='bold')
            plt.xlabel('Second dimensions', fontsize=10, fontweight='bold')
            plt.colorbar()
            plt.yticks(fontsize=8, fontweight='bold')
            plt.xticks(fontsize=8, fontweight='bold')
            pylab.savefig(newpath + '/00_11' + ' fig. ' + str(block + 1) +
                          ' - Mask after fine STD cleaning.png',
                          bbox_inches='tight',
                          dpi=300)
            plt.close('all')

            nowTime = time.time()
            print('\n  *** Normalization and cleaning took:       ',
                  round((nowTime - previousTime), 2), 'seconds ')
            previousTime = nowTime
        '''
        # Logging the data
        with np.errstate(invalid='ignore'):
            data[:,:] = 10 * np.log10(data[:,:])
        data[np.isnan(data)] = 0

        # Normalizing log data
        data = data - np.mean(data)
        '''

        # Dispersion delay removing
        data_space = np.zeros((num_frequencies, 2 * max_shift))
        data_space[:, max_shift:] = data[:, :]
        temp_array = pulsar_DM_compensation_with_indices_changes(
            data_space, shift_vector)
        del data, data_space

        nowTime = time.time()
        # print('\n  *** Dispersion compensation took:          ', round((nowTime - previousTime), 2), 'seconds ')
        print('\n  *** Dispersion delay removing took:        ',
              round((nowTime - previousTime), 2), 'seconds ')
        previousTime = nowTime

        # Adding the next data block
        buffer_array += temp_array

        # Making and filling the array with fully ready data for plotting and saving to a file
        array_compensated_DM = buffer_array[:, 0:max_shift]

        if block > 0:
            # Saving data with compensated DM to DAT file
            if save_compensated_data > 0 and block > 0:
                temp = array_compensated_DM.transpose().copy(order='C')
                new_data_file = open(new_data_file_name, 'ab')
                new_data_file.write(temp)
                new_data_file.close()

                # Saving time data to ling timeline file
                with open(new_TLfile_name, 'a') as new_TLfile:
                    for i in range(max_shift):
                        new_TLfile.write((fig_date_time_scale[i][:]))  # str

            # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            # Logging the data
            with np.errstate(divide='ignore'):
                array_compensated_DM[:, :] = 10 * np.log10(
                    array_compensated_DM[:, :])
            array_compensated_DM[array_compensated_DM == -np.inf] = 0

            # Normalizing log data
            array_compensated_DM = array_compensated_DM - np.mean(
                array_compensated_DM)
            # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            # Preparing single averaged data profile for figure
            profile = array_compensated_DM.mean(axis=0)[:]
            profile = profile - np.mean(profile)

            # Save full profile to TXT file
            if save_profile_txt > 0:
                profile_txt_file = open(profile_file_name, 'a')
                for i in range(len(profile)):
                    profile_txt_file.write(str(profile[i]) + ' \n')
                profile_txt_file.close()

            # Averaging of the array with pulses for figure
            averaged_array = average_some_lines_of_array(
                array_compensated_DM, int(num_frequencies / average_const))
            freq_resolution = (df *
                               int(num_frequencies / average_const)) / 1000.
            max_time_shift = max_shift * TimeRes

            # NEW start
            averaged_array = averaged_array - np.mean(averaged_array)
            # NEW stop

            plot_ready_data(profile, averaged_array, frequency_list,
                            num_frequencies, fig_time_scale, newpath, filename,
                            pulsar_name, DM, freq_resolution, TimeRes,
                            max_time_shift, block, num_of_blocks - 1, block,
                            profile_pic_min, profile_pic_max, df_description,
                            colormap, customDPI, currentDate, currentTime,
                            Software_version)

        # Rolling temp_array to put current data first
        buffer_array = np.roll(buffer_array, -max_shift)
        buffer_array[:, max_shift:] = 0

    dat_file.close()

    # Fourier analysis of the obtained time profile of pulses
    if save_profile_txt > 0:
        print('\n\n  *** Making Fourier transform of the time profile...')
        pulsar_pulses_time_profile_FFT(newpath + '/',
                                       filename + '_time_profile.txt',
                                       pulsar_name, TimeRes, profile_pic_min,
                                       profile_pic_max, customDPI, colormap)

    return new_data_file_name
Beispiel #4
0
def averge_profile_analysis(type, matrix, filename, freq_num, min, fmax, df, frequency_list,
                            TimeRes, samples_per_period, DM, no_of_DM_steps, pulsarPeriod,
                            save_intermediate_data, AverageChannelNumber, record_date_time,
                            pulsar_name, telescope, Software_version, Software_name, currentTime,
                            currentDate, df_filename, df_obs_place, df_description, ReceiverMode,
                            df_system_name):

    fig_number = '0' if type == 'first' else '1'
    DM_type = 'initial' if type == 'first' else 'optimal'

    #  Calculation of shift in pixels to compensate dispersion
    shift_param = pulsar_DM_shift_calculation_aver_pulse(freq_num, fmin, fmax, df, TimeRes, DM, pulsarPeriod)

    #  Saving shift parameter for dispersion delay compensation vs. frequency to file and plot
    if save_intermediate_data == 1:

        shift_paramTXT = open(result_path+'/Shift parameter (' + DM_type + ').txt', "w")
        for i in range(freq_num):
            shift_paramTXT.write(str(fmin + df * i)+'   '+str(shift_param[i])+' \n' )
        shift_paramTXT.close()

        plot1D(shift_param, result_path + '/' + fig_number + '3.1 - Shift parameter (' + DM_type + ' DM).png', 'Shift parameter', 'Shift parameter', 'Shift parameter', 'Frequency channel number', customDPI)

    #  Compensation of dispersion delay
    matrix = pulsar_DM_compensation_with_indices_changes (matrix, shift_param)

    #  Plot of the data with DM compensation but without data reduction
    if save_intermediate_data == 1:
        plot2D(matrix, result_path + '/' + fig_number + '1.3 - Dedispersed data.png', frequency_list, colormap, 'Dedispersed pulsar pulse \n File: '+filename, customDPI)

    #  Integrated over band pulsar profile in time (matrix sum in one dimension)
    integrated_profile = (np.sum(matrix, axis = 0))

    #  Specifying the noise segment to calculate SNR
    print ('\n  * Check the noise segment and close the plot, then enter needed data ')

    plt.figure()
    plt.plot(integrated_profile)
    plt.xlabel('Phase of pulsar period')
    plt.ylabel('Data')
    if save_intermediate_data == 1:
        pylab.savefig(result_path + '/' + fig_number + '4 - Raw integrated data to find pulse.png', bbox_inches='tight', dpi = 250)
    plt.show()
    plt.close('all')

    #  Manual input of the first and last index of noise segment in integrated plot
    begin_index  = int(input('\n    First index of noise segment:           '))
    end_index    = int(input('\n    Last index of noise segment:            '))


    #  Mean value extraction from the matrix
    for i in range (freq_num):
        matrix[i,:] = matrix[i,:] - np.mean(matrix[i, begin_index : end_index])

    integrated_profile = (np.sum(matrix, axis = 0))

    #  Calculation of SNR
    noise = integrated_profile[begin_index : end_index]
    noise_mean = np.mean(noise)
    noise_std = np.std(noise)
    integrated_profile = (integrated_profile - noise_mean)/noise_std

    #  Calculation of number of points to roll the pulse to the centre of the plot
    roll_number = int((len(integrated_profile)/2) - np.argmax(integrated_profile))

    # ***   Rolling the pulse to the center of the plot  ***
    integrated_profile = np.roll(integrated_profile, roll_number) # Rolling the vector to make the pulse in the center
    SNRinitMax = np.max(integrated_profile)

    # ***   Plotting and saving the SNR curve  ***
    plot1D(integrated_profile, result_path + '/' + fig_number + '5 - SNR.png', 'Averaged profile for DM = ' + str(round(DM, 3)), 'Averaged pulse profile in band ' + str(round(frequency_list[0],3)) + ' - ' + str(round(frequency_list[len(frequency_list)-1],3)) + ' MHz \n File: '+filename, 'SNR', 'Phase of pulsar period', customDPI)

    # ***   Calculations of DM variation  ***

    if type == 'final' and frequency_band_cut == 1:     # Plot profiles in small frequency bands?
        array = np.zeros((freq_num, samples_per_period))
        array[:,:] = matrix[:,:]

        analysis_in_frequency_bands(array, frequency_list, frequency_cuts, samples_per_period, filename, begin_index, end_index, roll_number)


    previousTime = time.time()

    # Integrated profiles with DM variation calculation
    profiles_varDM, DM_vector = pulsar_DM_variation(initial_matrix, no_of_DM_steps, freq_num, fmin, fmax, df, TimeRes, pulsarPeriod, samples_per_period, DM, noise_mean, noise_std, begin_index, end_index, DM_var_step, roll_number, save_intermediate_data, customDPI)



    #**************************************************************************
    #         Calculation the accuracy of optimal DM determination
    #**************************************************************************
    if type == 'final':
        # Profile of maximal SNR for each DM value
        max_profile_var_DM = np.max(profiles_varDM, axis = 1)

        # Index of the optimal DM value in vector
        max_x = np.argmax(max_profile_var_DM)

        # Indexes of optimal DM value with errer interval
        indexes = np.where(max_profile_var_DM >= np.max(max_profile_var_DM) * 0.95)
        x_index_min = indexes[0][0] - 1 if indexes[0][0] > 0 else indexes[0][0] # Minimal index
        x_index_max = indexes[0][len(indexes[0])-1] + 1 if indexes[0][len(indexes[0])-1] < len(max_profile_var_DM)-1 else indexes[0][len(indexes[0])-1] # Maximal index
        diff_max = np.abs(x_index_max - max_x) # Index error to upper limit
        diff_min = np.abs(x_index_min - max_x) # Index error to lower limit
        index_error = np.max([diff_max, diff_min])
        DM_error = index_error * DM_var_step
        print ('\n\n  Error of optimal DM determination is ',index_error,' steps, or ',DM_error,' pc / cm3')

        # Figure optimal DM determination error
        rc('font', size = 7, weight='bold')
        fig = plt.figure(1, figsize = (10.0, 6.0))
        ax1 = fig.add_subplot(111)
        ax1.plot(DM_vector - DM, max_profile_var_DM, label = 'Max of SNR profile vs. DM')
        ax1.axvline(x = DM_vector[max_x] - DM, color = 'C4', linestyle = '-', linewidth = 1.0)
        ax1.axvline(x = DM_vector[x_index_min] - DM, color = 'C1', linestyle = '-', linewidth = 1.0)
        ax1.axvline(x = DM_vector[x_index_max] - DM, color = 'C1', linestyle = '-', linewidth = 1.0)
        ax1.axhline(y = max_profile_var_DM[max_x] * 0.95, label = 'Max error = '+str(np.round(DM_error,4))+r' $\mathrm{pc \cdot cm^{-3}}$', color = 'r', linestyle = '-', linewidth = 0.5)
        ax1.legend(loc = 'upper right')
        ax1.set_xlabel(r'$\mathrm{\Delta DM}$', fontsize = 7, fontweight='bold')
        ax1.set_ylabel('Max SNR', fontsize = 7, fontweight='bold')
        ax2 = ax1.twiny()
        ax2.set_xlabel('DM value', fontsize = 7, fontweight='bold')
        ax2.set_xlim(ax1.get_xlim())
        text = ax2.get_xticks().tolist()
        for i in range(len(text)-1):
            k = np.float(text[i])
            text[i] = k + DM
        ax2.set_xticklabels(np.round(text, 4))
        fig.subplots_adjust(top=0.90)
        fig.suptitle('Maxima of SNR profiles vs. DM variation \n File: '+filename, fontsize = 10, fontweight = 'bold', style = 'italic', y = 1.025)
        pylab.savefig(result_path + '/' + fig_number + '6 - SNR vs DM.png', bbox_inches='tight', dpi = customDPI)
        plt.close('all')

    # **************************************************************************

    # **************************************************************************
    #         Averaging data in frequency domain for final figure
    # **************************************************************************
    if type == 'final':
        reduced_array, reduced_frequency_list = averaging_in_frequency(matrix, freq_num,
                                                                       samples_per_period,
                                                                       AverageChannelNumber,
                                                                       roll_number, result_path,
                                                                       filename,
                                                                       save_intermediate_data)

    # **************************************************************************

    nowTime = time.time() #                               '
    print ('\n  DM variation took ', round((nowTime - previousTime), 2), 'seconds (',round((nowTime - previousTime)/60, 2), 'min. )')
    previousTime = nowTime

    # Preparing indexes for showing the maximal SNR value and its coordinates
    DM_steps_real, time_points = profiles_varDM.shape
    phase_vector = np.linspace(0, 1, num = time_points)
    optimal_DM_indexes = np.unravel_index(np.argmax(profiles_varDM, axis=None), profiles_varDM.shape)
    optimal_DM_index = optimal_DM_indexes[0]
    optimal_pulse_phase = optimal_DM_indexes[1]
    MAXpointX = phase_vector[optimal_pulse_phase]
    MAXpointY = - (DM_vector[optimal_DM_index] - DM)
    DMoptimal = round(DM_vector[optimal_DM_index], 5)

    print(' \n\n ')
    print('    Initial DM (from file) =               ', DM, ' pc / cm3')
    print('    Optimal DM =                           ', DMoptimal, ' pc / cm3  \n')
    print('    SNR for current DM =                   ', round(SNRinitMax, 3))
    #print('    SNR averaged in time for initial DM  = ', round(SNRinitDMtimeAver, 3), ' \n')


    # Saving integrated profiles with DM variation calculation to TXT file
    if save_intermediate_data == 1 and type == 'final':
        DM_Var_TXT = open(result_path + '/Average profile vs DM 2D (' + DM_type + ' DM).txt', "w")
        for step in range(DM_steps_real-1):
            DM_Var_TXT.write(''.join(format(DM_vector[step], "8.5f")) + '   '.join(format(profiles_varDM[step, i], "12.5f") for i in range(time_points)) + ' \n')
        DM_Var_TXT.close()




    rc('font', size = 7, weight='bold')
    fig = plt.figure(1, figsize = (10.0, 6.0))
    ax1 = fig.add_subplot(111)
    fig.subplots_adjust(left = None, bottom = None, right = None, top = 0.86, wspace = None, hspace = None)
    im1 = ax1.imshow(np.flipud(profiles_varDM), aspect = 'auto', vmin = np.min(profiles_varDM), vmax = np.max(profiles_varDM), extent=[0,1,DM_vector[0]-DM,DM_vector[no_of_DM_steps-1]-DM], cmap=colormap) #
    ax1.set_title('Pulse profile vs DM in band ' + str(round(frequency_list[0], 3)) + ' - ' + str(round(frequency_list[len(frequency_list)-1],3)) + ' MHz \n File: ' + filename, fontweight = 'bold', y=1.025) # , fontsize = 8 , style='italic'
    ax2 = ax1.twinx()
    ax1.yaxis.set_label_coords(-0.04, 1.01)
    ax2.yaxis.set_label_coords( 1.04, 1.03)
    ax1.set_xlabel('Phase of pulsar period', fontsize = 7, fontweight='bold')
    ax1.set_ylabel(r'$\mathrm{\Delta DM}$', rotation = 0)
    ax2.set_ylabel('DM', rotation = 0, fontsize = 7, fontweight='bold') #
    ax2.set_ylim(ax1.get_ylim())
    text = ax2.get_yticks().tolist()
    for i in range(len(text)-1):
        k = np.float(text[i])
        text[i] = DM + k
    ax2.set_yticklabels(np.round(text, 4))
    fig.colorbar(im1, ax = ax1, pad = 0.1)
    fig.text(0.76, 0.89,'Current SNR \n    '+str(round(SNRinitMax, 3)), fontsize=7, fontweight='bold', transform=plt.gcf().transFigure)
    fig.text(0.75, 0.05, '    Current DM  \n'+str(round(DM, 4))+r' $\mathrm{pc \cdot cm^{-3}}$', fontsize=7, fontweight='bold', transform=plt.gcf().transFigure)
    pylab.savefig(result_path + '/' + fig_number + '8 - SNR vs DM.png', bbox_inches='tight', dpi = customDPI)

    endTime = time.time()    # Stop timer of calculations because next figure will popup and wait for response of user

    ax1.axhline(y = 0, color = 'r', linestyle = '-', linewidth = 0.4)
    ax1.axvline(x = 0.5 + (0.5/samples_per_period), color = 'r', linestyle = '-', linewidth = 0.4)
    ax1.plot(MAXpointX, - MAXpointY, marker = 'o', markersize = 1.5, color = 'chartreuse')
    pylab.savefig(result_path + '/' + fig_number + '7 - SNR vs DM.png', bbox_inches='tight', dpi = customDPI)
    if type == 'first': plt.show()
    plt.close('all')





    if type == 'final':
        # Final figure with full information
        fig = plt.figure(constrained_layout=True, figsize = (12.0, 6.75))
        gs = GridSpec(2, 3, figure=fig)
        rc('font', size=7, weight='bold')

        ax1 = fig.add_subplot(gs[0, 0]) # [0, :-1]
        ax1.plot(integrated_profile)
        ax1.set_xlim(xmin=0, xmax=samples_per_period)
        ax1.set_ylabel(r'$\mathrm{T_{pulsar}\, /\, T_{sys}}$', fontsize=7, fontweight='bold')
        ax1.set_xlabel('Phase of pulsar period in samples', fontsize=7, fontweight='bold')
        ax1.set_title('Average profile in band', fontsize=8, fontweight='bold')

        ax2 = fig.add_subplot(gs[1, 0]) #[1, :-1]
        ax2.imshow(np.flipud(reduced_array), aspect='auto',vmin = np.min(reduced_array), vmax = np.max(reduced_array)/10, extent=[0, 1, reduced_frequency_list[0] , reduced_frequency_list[-1]], cmap=colormap)
        ax2.set_ylabel('Frequency, MHz', fontsize=7, fontweight='bold')
        ax2.set_xlabel('Phase of pulsar period', fontsize=7, fontweight='bold')
        ax2.set_title('Pulse profiles in ' + str(np.round(reduced_frequency_list[1] - reduced_frequency_list[0], 3)) + ' MHz bands', fontsize=8, fontweight='bold')

        ax3 = fig.add_subplot(gs[0:, 1])
        im3 = ax3.imshow(np.flipud(profiles_varDM), aspect='auto', vmin=np.min(profiles_varDM), vmax=np.max(profiles_varDM), extent=[0, 1, DM_vector[0] - DM, DM_vector[no_of_DM_steps - 1] - DM], cmap=colormap)
        ax3.set_ylabel(r'$\mathrm{\Delta DM, pc \cdot cm^{-3}}$')
        ax3.set_xlabel('Phase of pulsar period', fontsize=7, fontweight='bold')
        ax3.set_title('Pulse profile vs DM', fontsize=8, fontweight='bold')
        fig.colorbar(im3, ax=ax3, aspect=50, pad=0.001)

        ax4 = fig.add_subplot(gs[0:, -1])
        ax4.axis('off')

        fig.suptitle('Pulsar '+ pulsar_name +' in band ' + str(round(frequency_list[0], 1)) + ' - ' + str(round(frequency_list[-1], 1)) + ' MHz \n File: ' + filename, fontsize=10, fontweight='bold')
        fig.text(0.03, 0.960, pulsar_name + '\n' + str(record_date_time[:10])+' '+telescope, fontsize=10, transform=plt.gcf().transFigure)

        fig.text(0.72, 0.880, 'Pulsar name: ' + pulsar_name, fontsize=10, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.845, r'$\mathrm{T_{pulsar}\, /\, T_{sys}}:~$' +str(round(SNRinitMax, 3)), fontsize=10, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.810, 'DM: '+str(round(DM, 4)) + r' $\mathrm{\pm}$ '+ str(np.round(DM_error,4)) + r' $\mathrm{pc \cdot cm^{-3}}$', fontsize=10, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.775, 'Date: ' + str(record_date_time[:10]) , fontsize=10, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.740, 'Start time: ' + str(record_date_time[11:19])+ ' UTC', fontsize=10, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.705, 'Duration: ', fontsize=10, fontweight='bold', transform=plt.gcf().transFigure)

        fig.text(0.72, 0.670, 'Period: '+str(np.round(pulsarPeriod,6))+' s.', fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.640, 'Time resolution: '+str(np.round(TimeRes*1000,4))+' ms.', fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.610, 'Number of samples per period: ' + str(samples_per_period), fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.580, 'DM from catalogue: ', fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.550, r'$\mathrm{RA_{J2000}}: $', fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.520, r'$\mathrm{DEC_{J2000}}: $', fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)

        fig.text(0.72, 0.490, 'Initial data file name: ' + df_filename, fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.460, 'Receiver mode: ' + str(ReceiverMode), fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.430, 'Receiver ID: ' + str(df_system_name), fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.400, 'Observation place: ', fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.370, df_obs_place, fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.340, 'Observation description: ', fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)
        fig.text(0.72, 0.310, df_description, fontsize=9, fontweight='bold', transform=plt.gcf().transFigure)

        fig.text(0.85, -0.015, 'Processed '+currentDate+ ' at '+currentTime, fontsize=6, transform=plt.gcf().transFigure)
        fig.text(0.02, -0.015, 'Software version: '+Software_version+', [email protected], IRA NASU', fontsize=6, transform=plt.gcf().transFigure)

        pylab.savefig(result_path + '/Total result.png', bbox_inches='tight', dpi=customDPI)
        plt.show()
        plt.close('all')





    print ('\n\n  In band calculations and DM variation lasted for ', round((endTime - startTime),3), 'seconds (',
                                                    round((endTime - startTime)/60, 2), 'min. ) \n\n')
    return DMoptimal
def coherent_wf_to_wf_dedispersion(DM, fname, no_of_points_for_fft_dedisp):
    """
    function reads waveform data in wf32 format, makes FFT, cuts the symmetrical half of the spectra and shifts the
    lines of complex data to provide coherent dedispersion. Then a symmetrcal part of spectra are made and joined
    to the shifted one, inverse FFT as applied and data are stored in waveform wf32 format
    Input parameters:
        DM -                            dispersion measure to compensate
        fname -                         name of file with initial wf32 data
        no_of_points_for_fft_dedisp -   number of waveform data points to use for FFT
    Output parameters:
        file_data_name -                name of file with processed data
    """

    #  *** Data file header read ***
    [
        df_filename, df_filesize, df_system_name, df_obs_place, df_description,
        clock_freq, df_creation_timeUTC, Channel, ReceiverMode, Mode, Navr,
        time_resolution, fmin, fmax, df, frequency_list, freq_points_num,
        data_block_size
    ] = FileHeaderReaderJDS(fname, 0, 0)

    # Manually set frequencies for one channel mode
    freq_points_num = int(no_of_points_for_fft_dedisp / 2)

    # Manually set frequencies for 33 MHz clock frequency
    if int(clock_freq / 1000000) == 33:
        fmin = 16.5
        fmax = 33.0
        df = 16500000 / freq_points_num

    # Create long data files and copy first data file header to them

    with open(fname, 'rb') as file:
        # *** Data file header read ***
        file_header = file.read(1024)

        # Removing old DM from file name and updating it to current value
        if fname.startswith('DM_'):
            prev_dm_str = fname.split('_')[1]
            prev_dm = np.float32(prev_dm_str)
            new_dm = prev_dm + DM
            n = len('DM_' + prev_dm_str + '_')
            file_data_name = 'DM_' + str(np.round(new_dm, 6)) + '_' + fname[n:]
        else:
            file_data_name = 'DM_' + str(np.round(DM, 6)) + '_' + fname

        # *** Creating a binary file with data for long data storage ***
        file_data = open(file_data_name, 'wb')
        file_data.write(file_header)
        file_data.close()
        del file_header

        # *** Creating a new timeline TXT file for results ***
        new_tl_file_name = file_data_name.split("_Data_ch",
                                                1)[0] + '_Timeline.wtxt'
        new_tl_file = open(
            new_tl_file_name,
            'w')  # Open and close to delete the file with the same name
        new_tl_file.close()

        # Calculation of the time shifts
        shift_vector = DM_full_shift_calc(freq_points_num, fmin, fmax,
                                          df / pow(10, 6), time_resolution, DM,
                                          'jds')
        max_shift = np.abs(shift_vector[0])

        # Preparing buffer array
        buffer_array = np.zeros((freq_points_num, 2 * max_shift),
                                dtype='complex64')

        print(' Maximal shift is:                            ', max_shift,
              ' pixels ')
        print(' Dispersion measure:                          ', DM,
              ' pc / cm3 ')

        # Calculation of number of blocks and number of spectra in the file
        no_of_spectra_in_bunch = max_shift.copy()
        no_of_bunches_per_file = int(
            np.ceil(
                (df_filesize - 1024) /
                (no_of_spectra_in_bunch * no_of_points_for_fft_dedisp * 4)))

        # Real time resolution of spectra
        fine_clock_freq = (int(clock_freq / 1000000.0) * 1000000.0)
        real_spectra_dt = float(no_of_points_for_fft_dedisp / fine_clock_freq)
        real_spectra_df = float(
            (fine_clock_freq / 2) / (no_of_points_for_fft_dedisp / 2))

        print(' Number of spectra in bunch:                  ',
              no_of_spectra_in_bunch)
        print(' Number of bunches to read in file:           ',
              no_of_bunches_per_file)
        print(' Time resolution of calculated spectra:       ',
              round(real_spectra_dt * 1000, 3), ' ms')
        print(' Frequency resolution of calculated spectra:  ',
              round(real_spectra_df / 1000, 3), ' kHz \n')

        # !!! Fake timing. Real timing to be done!!!
        # *** Reading timeline file ***
        old_tl_file_name = fname.split("_Data_ch", 1)[0] + '_Timeline.wtxt'
        old_tl_file = open(old_tl_file_name, 'r')
        new_tl_file = open(
            new_tl_file_name,
            'w')  # Open and close to delete the file with the same name

        file.seek(1024)  # Jumping to 1024 byte from file beginning

        # bar = IncrementalBar(' Coherent dispersion delay removing: ', max=no_of_bunches_per_file - 1,
        bar = IncrementalBar(' Coherent dispersion delay removing: ',
                             max=no_of_bunches_per_file,
                             suffix='%(percent)d%%')
        bar.start()

        # for bunch in range(no_of_bunches_per_file - 1):
        for bunch in range(no_of_bunches_per_file):

            # Trying to read all the file, not only integer number of bunches
            if bunch >= no_of_bunches_per_file - 1:
                no_of_spectra_in_bunch = int(
                    ((df_filesize - 1024) -
                     bunch * max_shift * no_of_points_for_fft_dedisp * 4) /
                    (no_of_points_for_fft_dedisp * 4))
                # print('\n  Bunch No ', str(bunch+1), ' of ', no_of_bunches_per_file, ' bunches')
                # print('\n  Number of spectra in the last bunch is: ', no_of_spectra_in_bunch)
                # print('\n  Maximal shift is:                       ', max_shift)

            # Read time from timeline file for the bunch
            time_scale_bunch = []
            for line in range(no_of_spectra_in_bunch):
                time_scale_bunch.append(str(old_tl_file.readline()))

            # Reading and reshaping all data with time data
            wf_data = np.fromfile(file,
                                  dtype='f4',
                                  count=no_of_spectra_in_bunch *
                                  no_of_points_for_fft_dedisp)
            '''
            fig = plt.figure(figsize=(9, 5))
            ax1 = fig.add_subplot(111)
            ax1.plot(wf_data, linestyle='-', linewidth='1.00', label='Initial waveform')
            ax1.legend(loc='upper right', fontsize=6)
            ax1.grid(b=True, which='both', color='silver', linestyle='-')
            ax1.set_ylabel('Intensity, a.u.', fontsize=6, fontweight='bold')
            pylab.savefig('00_Initial_waveform_' + str(bunch) + '.png', bbox_inches='tight', dpi=160)
            plt.close('all')
            '''

            wf_data = np.reshape(
                wf_data, [no_of_points_for_fft_dedisp, no_of_spectra_in_bunch],
                order='F')

            # preparing matrices for spectra
            spectra = np.zeros(
                (no_of_points_for_fft_dedisp, no_of_spectra_in_bunch),
                dtype='complex64')

            # Calculation of spectra
            for i in range(no_of_spectra_in_bunch):
                spectra[:, i] = np.fft.fft(wf_data[:, i])
            del wf_data
            '''
            fig = plt.figure(figsize=(9, 5))
            ax1 = fig.add_subplot(111)
            ax1.plot(10 * np.log10(np.power(np.abs(spectra[:, 0]), 2)), linestyle='-', linewidth='1.00',
                     label='Initial spectra before cut')
            ax1.legend(loc='upper right', fontsize=6)
            ax1.grid(b=True, which='both', color='silver', linestyle='-')
            ax1.set_ylabel('Intensity, a.u.', fontsize=6, fontweight='bold')
            pylab.savefig('00a_Initial_doubled_imm_spectra' + str(bunch) + '.png', bbox_inches='tight', dpi=160)
            plt.close('all')
            '''

            # Cut half of the spectra
            spectra = spectra[int(no_of_points_for_fft_dedisp / 2):, :]
            ''' # making figures
            fig = plt.figure(figsize=(9, 5))
            ax1 = fig.add_subplot(111)
            ax1.imshow(np.flipud(10*np.log10(np.power(np.abs(spectra), 2))), aspect='auto', cmap='jet')
            ax1.set_ylabel('Frequency points', fontsize=6, fontweight='bold')
            ax1.set_xlabel('Time points', fontsize=6, fontweight='bold')
            pylab.savefig('01_Initial_spectra_' + str(bunch) + '.png', bbox_inches='tight', dpi=160)
            plt.close('all')

            fig = plt.figure(figsize=(9, 5))
            ax1 = fig.add_subplot(111)
            ax1.plot(10*np.log10(np.power(np.abs(spectra[:, 0]), 2)), linestyle='-', linewidth='1.00', label='Initial waveform')
            ax1.legend(loc='upper right', fontsize=6)
            ax1.grid(b=True, which='both', color='silver', linestyle='-')
            ax1.set_ylabel('Intensity, a.u.', fontsize=6, fontweight='bold')
            pylab.savefig('02_Initial_imm_spectra' + str(bunch) + '.png', bbox_inches='tight', dpi=160)
            plt.close('all')
            '''

            #  Dispersion delay removing
            data_space = np.zeros((freq_points_num, 2 * max_shift),
                                  dtype='complex64')

            # if it is the last bunch - use only availble data
            if bunch >= no_of_bunches_per_file - 1:
                data_space[:, max_shift:max_shift +
                           no_of_spectra_in_bunch] = spectra[:, :]
            else:
                data_space[:, max_shift:] = spectra[:, :]

            data_space = pulsar_DM_compensation_with_indices_changes(
                data_space, shift_vector)
            del spectra

            # Adding the next data block
            buffer_array += data_space

            # Making and filling the array with fully ready data for plotting and saving to a file
            if bunch >= no_of_bunches_per_file - 1:
                array_compensated_dm = buffer_array[:,
                                                    0:no_of_spectra_in_bunch]
            else:
                array_compensated_dm = buffer_array[:, 0:max_shift]

            if bunch > 0:

                # Saving time data to a new file
                for i in range(len(time_scale_bunch)):
                    new_tl_file.write((time_scale_bunch[i][:]) + '')

                # Saving data with compensated DM
                spectra = array_compensated_dm  # .copy()
                '''
                # making figures
                fig = plt.figure(figsize=(9, 5))
                ax1 = fig.add_subplot(111)
                ax1.imshow(np.flipud(10*np.log10(np.power(np.abs(spectra), 2))), aspect='auto', cmap='jet')
                ax1.set_ylabel('Frequency points', fontsize=6, fontweight='bold')
                ax1.set_xlabel('Time points', fontsize=6, fontweight='bold')
                pylab.savefig('03_Compensated_spectra_' + str(bunch) + '.png', bbox_inches='tight', dpi=160)
                plt.close('all')

                fig = plt.figure(figsize=(9, 5))
                ax1 = fig.add_subplot(111)
                ax1.plot(10*np.log10(np.power(np.abs(spectra[:,0]), 2)), linestyle='-', linewidth='1.00', label='Initial waveform')
                ax1.legend(loc='upper right', fontsize=6)
                ax1.grid(b=True, which='both', color='silver', linestyle='-')
                ax1.set_ylabel('Intensity, a.u.', fontsize=6, fontweight='bold')
                pylab.savefig('04_Compensated_imm_spectra' + str(bunch) + '.png', bbox_inches='tight', dpi=160)
                plt.close('all')
                '''

                wf_data = np.zeros(
                    (no_of_points_for_fft_dedisp, no_of_spectra_in_bunch))

                # Add lost half of the spectra

                second_spectra_half = spectra.copy()
                second_spectra_half = np.flipud(second_spectra_half)
                spectra = np.concatenate((second_spectra_half, spectra),
                                         axis=0)  # Changed places!!!
                '''
                fig = plt.figure(figsize=(9, 5))
                ax1 = fig.add_subplot(111)
                ax1.plot(10*np.log10(np.power(np.abs(spectra[:,0]), 2)), linestyle='-', linewidth='1.00', label='Initial waveform')
                ax1.legend(loc='upper right', fontsize=6)
                ax1.grid(b=True, which='both', color='silver', linestyle='-')
                ax1.set_ylabel('Intensity, a.u.', fontsize=6, fontweight='bold')
                pylab.savefig('05_Compensated_doubled_imm_spectra' + str(bunch) + '.png', bbox_inches='tight', dpi=160)
                plt.close('all')
                '''

                # Making IFFT
                for i in range(no_of_spectra_in_bunch):
                    wf_data[:, i] = np.real(np.fft.ifft(spectra[:, i]))
                del spectra

                # Reshaping the waveform to single dimension (real)
                wf_data = np.reshape(
                    wf_data,
                    [no_of_points_for_fft_dedisp * no_of_spectra_in_bunch, 1],
                    order='F')
                ''' # making figures
                fig = plt.figure(figsize=(9, 5))
                ax1 = fig.add_subplot(111)
                ax1.plot(wf_data, linestyle='-', linewidth='1.00', label='Initial waveform')
                ax1.legend(loc='upper right', fontsize=6)
                ax1.grid(b=True, which='both', color='silver', linestyle='-')
                ax1.set_ylabel('Intensity, a.u.', fontsize=6, fontweight='bold')
                pylab.savefig('06_Compensated_waveform_' + str(bunch) + '.png', bbox_inches='tight', dpi=160)
                plt.close('all')
                '''

                # Saving waveform data to wf32 file
                file_data = open(file_data_name, 'ab')
                file_data.write(
                    np.float32(wf_data).transpose().copy(order='C'))
                file_data.close()

                # !!! Saving time data to timeline file !!!

            # Rolling temp_array to put current data first
            buffer_array = np.roll(buffer_array, -max_shift)
            buffer_array[:, max_shift:] = 0

            bar.next()

        bar.finish()
        old_tl_file.close()
        new_tl_file.close()

    return file_data_name
        #plot2Da(data_log, newpath+'/03 '+ ' fig. ' +str(block+1)+'- Full log cleaned data.png', frequency_list, np.min(data_log), np.max(data_log), colormap, 'Full log initial data', customDPI)
        #plot1D(data_log[:,1], newpath+'/04a '+ ' fig. ' +str(block+1)+'- Cleaned data single specter.png', 'Label', 'Initial data specter', 'Frequency, MHz', 'Amplitude, AU', customDPI)
        #plot1D(data_log[1,:], newpath+'/04b '+ ' fig. ' +str(block+1)+'- Cleaned data single channel.png', 'Label', 'Initial data channel', 'Time, spectra counts', 'Amplitude, AU', customDPI)


        nowTime = time.time() #                                '
        print ('\n  *** Time before dispersion compensation:   ', round((nowTime - previousTime), 2), 'seconds ')
        previousTime = nowTime


        # Creation of big array for correct dispersion compensation and adding the next data block
        temp_array = np.zeros((num_frequencies, 4 * max_shift))
        temp_array[:, 4 * max_shift - num_spectra : 4 * max_shift] = data_log[:,:]
        del data_log
        temp_array = pulsar_DM_compensation_with_indices_changes(temp_array, shift_vector[0: num_frequencies])

        nowTime = time.time()
        print ('\n  *** Dispersion compensation took:          ', round((nowTime - previousTime), 2), 'seconds ')
        previousTime = nowTime


        plot2Da(temp_array, newpath+'/05 '+ ' fig. ' +str(block+1)+'- DM compensated data.png', frequency_list, np.min(temp_array), np.max(temp_array), colormap, 'DM compensated data', customDPI)

        # Rolling temp_array to put current data first
        if block == 0:
            temp_array = np.roll(temp_array, - num_spectra)
            buffer_array += temp_array
        else:
            temp_array = np.roll(temp_array, - max_shift)
            buffer_array += temp_array
plt.yticks(fontsize=6, fontweight='bold')
pylab.savefig(newpath + '/02 data integrated over time and over frequency.png',
              bbox_inches='tight',
              dpi=250)
plt.close('all')

plot2Da(buffer_array, newpath + '/fig. 1 - averaged data.png', frequency_list,
        -3, 2, colormap, 'averaged data', customDPI)

shift_vector = pulsar_DM_shift_calculation_aver_pulse(len(frequency_list),
                                                      fmin, fmax,
                                                      df / pow(10, 6), TimeRes,
                                                      DM, pulsar_period)

# Dispersion compensation
buffer_array = pulsar_DM_compensation_with_indices_changes(
    buffer_array, shift_vector)

plot2Da(buffer_array, newpath + '/fig. 1 - dedispersed averaged data.png',
        frequency_list, -3, 2, colormap, 'averaged data', customDPI)

AverageChannelNumber = 128
reduced_matrix = np.array(
    [[0.0 for col in range(samples_per_period)]
     for row in range(int(len(frequency_list) / AverageChannelNumber))])
for i in range(int(len(frequency_list) / AverageChannelNumber)):
    for j in range(samples_per_period):
        reduced_matrix[i,
                       j] = sum(buffer_array[i * AverageChannelNumber:(i + 1) *
                                             AverageChannelNumber, j])

plot2Da(reduced_matrix, newpath + '/fig. 2 - twice averaged data.png',