Project: s41467-024-47447-6 | Function: normalize_intensity_profiles (python)

system: You are an expert Python programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow Python best practices and maintain consistent code style.
Return **only** the complete Python function code.

user: Complete this Python function:

**DESCRIPTION:** Multi-method intensity normalization algorithm supporting min-max scaling, maximum normalization, and custom reference normalization for comparative operando spectroscopy analysis

**KEY TERMS:** {
  "min_max": "linear scaling to [0,1] range",
  "max": "normalization to maximum intensity",
  "normalization_dict": "custom reference values for each peak",
  "intensities": "collected intensity values for statistical processing",
  "normalized_intensity": "processed intensity values for comparison"
}

**CONTEXT CODE:**     # Display the plot
    plt.show()

def peak_shifts(local_maxima_dict):
    # Create an empty dictionary to hold the peak shifts
    peak_shift_dict = {}

    # Iterate over all peaks in the local maxima dictionary
    for peak in set(peak for sublist in local_maxima_dict.values() for peak in sublist.keys()):
        # Create an empty list to hold the peak shifts for this peak
        peak_shifts = []

        reference_position = None  # Initialize the reference position as None

        # Iterate over all spectra
        for spectrum_number, spectrum_peaks in local_maxima_dict.items():
            # Check if the peak exists in the inner dictionary
            if peak in spectrum_peaks:
                # Use the first available peak position as the reference position
                if reference_position is None:
                    reference_position = spectrum_peaks[peak][0]

                # Calculate the peak shift for this spectrum
                peak_position = spectrum_peaks[peak][0]
                peak_shift = peak_position - reference_position

                # Add the peak shift to the list
                peak_shifts.append(peak_shift)

        # Add the list of peak shifts for this peak to the dictionary
        peak_shift_dict[peak] = peak_shifts

    return peak_shift_dict

def plot_peak_shifts(peak_shift_dict):
    # Iterate over all peaks in the peak shift dictionary
    for peak, peak_shifts in peak_shift_dict.items():
        # Create a scatter plot of the peak shifts over the spectrum number
        plt.scatter(range(len(peak_shifts)), peak_shifts, label=f'Peak at {peak}')

    # Add a legend, title, and labels
    plt.legend()
    plt.title("Peak Shifts over Spectrum Number")
    plt.xlabel("Spectrum Number")
    plt.ylabel("Peak Shift")

    # Display the plot
    plt.show()


def normalize_intensity_profiles(intensity_profiles, normalization='min_max'):
    # MASKED: Multi-method intensity normalization algorithm supporting min-max scaling, maximum normalization, and custom reference normalization for comparative operando spectroscopy analysis
    raise NotImplementedError("This function is masked for testing purposes.")

def times_relative(spectra_dict):
    times_relative = {}

    # Bruker format is 13:40:18.889 (GMT+0) // timezone need to be omitted
    start_time_str = spectra_dict[0]['ScSm Data Parameter']['TIM'].split(" ")[0]
    start_time = datetime.strptime(start_time_str, "%H:%M:%S.%f")

    for spectrum_number, spectrum in spectra_dict.items():
        # Same as above, timezone need to be omitted and str converted
        spectrum_time_str = spectrum['ScSm Data Parameter']['TIM'].split(" ")[0]
        spectrum_time = datetime.strptime(spectrum_time_str, "%H:%M:%S.%f")

        # calculation time relative
        spectrum_time_relative = (spectrum_time - start_time).total_seconds() / 60

        # Add the relative time to the dictionary
        times_relative[spectrum_number] = spectrum_time_relative

    return times_relative

def export_data(path_to_export_file, intensity_profiles, normalized_intensity_profiles=None, times_relative=None, max_intensities=None):
    # Initialize empty DataFrame
    df1 = pd.DataFrame()

    # Iterate over the spectra
    for spectrum, peaks in intensity_profiles.items():
        # For each peak, add the wavenumber and intensity as separate columns
        for peak, (wavenumber, intensity) in peaks.items():
            df1.at[spectrum, f'{peak}_wavenumber'] = wavenumber
            df1.at[spectrum, f'{peak}_intensity'] = intensity

    # Check if filename ends with '.xlsx', if not append it
    if not path_to_export_file.endswith('.xlsx'):
        path_to_export_file += '.xlsx'
        
    # Add the current date and time to the filename before '.xlsx'
    filename = path_to_export_file[:-5] + "_" + datetime.now().strftime("%Y%m%d %H%M") + '.xlsx'

    # Get the directory name from the filename
    directory = os.path.dirname(filename)

    # If the directory does not exist, create it
    if not os.path.exists(directory):
        os.makedirs(directory)

    # Write the DataFrame to an Excel file
    with pd.ExcelWriter(filename) as writer:
        df1.to_excel(writer, sheet_name='intensities')
        
        # If a normalized data is provided, create a DataFrame and write it to a second sheet
        if normalized_intensity_profiles is not None:
            df2 = pd.DataFrame()

            # Iterate over the spectra in the second dictionary
            for spectrum, peaks in normalized_intensity_profiles.items():
                for peak, (wavenumber, intensity) in peaks.items():
                    df2.at[spectrum, f'{peak}_wavenumber'] = wavenumber
                    df2.at[spectrum, f'{peak}_intensity'] = intensity

            df2.to_excel(writer, sheet_name='normalized intesities')

        # If times are provided, create a DataFrame and write it to a additional sheet
        if times_relative is not None:
            df3 = pd.DataFrame.from_dict(times_relative, orient='index')

            df3.to_excel(writer, sheet_name='times')

        # If max intensities are provided, create a DataFrame and write it to a additional sheet
        if max_intensities is not None:
            df4 = pd.DataFrame.from_dict(max_intensities, orient='index')

            df4.to_excel(writer, sheet_name='max. intensities')

    print(f"Data exported to {filename}")

def export_spectra(path_to_export_file, spectra_dict, spectra_numbers=None, single_channel=False):
    # Initialize empty DataFrame
    df1 = pd.DataFrame()

    # Iterate over the spectra and add data to the DataFrame
    for spectrum_number, spectrum in spectra_dict.items():
        if spectra_numbers is None or spectrum_number in spectra_numbers:
            x_values = spectrum.get_range("AB")
            y_values = spectrum["AB"][0:len(x_values)]

            # Create a new column for the spectrum
            df1[spectrum_number] = y_values

    # Add the x-values as a separate column
    df1.insert(0, "wavenumbers", x_values)

    # Check if filename ends with '.xlsx', if not append it
    if not path_to_export_file.endswith('.xlsx'):
        path_to_export_file += '.xlsx'
        
    # Add the current date and time to the filename before '.xlsx'


Complete the function implementation replacing "raise NotImplementedError".