code: def _infer_frequency(df, freq, min_freq_percentage=0.7):
      """Automatically infers frequency of dataframe.
  
      Parameters
      ----------
          df : pd.DataFrame
              Dataframe with columns ``ds`` datestamps and ``y`` time series values
          freq : str
              Data step sizes, i.e. frequency of data recording,
  
              Note
              ----
              Any valid frequency for pd.date_range, such as ``5min``, ``D``, ``MS`` or ``auto``
              (default) to automatically set frequency.
  
          min_freq_percentage : float
              threshold for defining major frequency of data (default: ``0.7``
  
      Returns
      -------
          str
              Valid frequency tag according to major frequency.
  
      """
      frequencies, distribution = get_freq_dist(df["ds"])
      argmax_frequency = frequencies[np.argmax(distribution)]
  
      # exception - monthly df (28, 29, 30 or 31 days freq)
      MONTHLY_FREQUENCIES = [2.4192e15, 2.5056e15, 2.5920e15, 2.6784e15]
      if argmax_frequency in MONTHLY_FREQUENCIES:
          dominant_freq_percentage = _get_dominant_frequency_percentage(
              frequencies, distribution, MONTHLY_FREQUENCIES
          )
          num_freq = 2.6784e15
          inferred_freq = (
              "MS" if pd.to_datetime(df["ds"].iloc[0]).day < 15 else "M"
          )
      # exception - yearly df (365 days freq or 366 days freq)
      elif (
          argmax_frequency == 3.1536e16
          or argmax_frequency == 3.16224e16
      ):
          dominant_freq_percentage = get_dist_considering_two_freqs(
              distribution
          ) / len(df["ds"])
          num_freq = 3.1536e16
          inferred_freq = (
              "YS" if pd.to_datetime(df["ds"].iloc[0]).day < 15 else "Y"
          )
      # exception - quarterly df (most common == 92 days - 3rd,4th quarters and second most common == 91 days 2nd quarter
      # and 1st quarter in leap year)
      elif (
          argmax_frequency == 7.9488e15
          and frequencies[np.argsort(distribution, axis=0)[-2]]
          == 7.8624e15
      ):
          dominant_freq_percentage = get_dist_considering_two_freqs(
              distribution
          ) / len(df["ds"])
          num_freq = 7.9488e15
          inferred_freq = (
              "QS" if pd.to_datetime(df["ds"].iloc[0]).day < 15 else "Q"
          )
      # exception - Business day (most common == day delta and second most common == 3 days delta and second most common
      # is at least 12% of the deltas)
      elif (
          argmax_frequency == 8.64e13
          and frequencies[np.argsort(distribution, axis=0)[-2]]
          == 2.592e14
          and distribution[np.argsort(distribution, axis=0)[-2]]
          / len(df["ds"])
          >= 0.12
      ):
          dominant_freq_percentage = get_dist_considering_two_freqs(
              distribution
          ) / len(df["ds"])
          num_freq = 8.64e13
          inferred_freq = "B"
      # exception - Business hour (most common == hour delta and second most common == 17 hours delta and second most
      # common is at least 8% of the deltas)
      elif (
          argmax_frequency == 3.6e12
          and frequencies[np.argsort(distribution, axis=0)[-2]]
          == 6.12e13
          and distribution[np.argsort(distribution, axis=0)[-2]]
          / len(df["ds"])
          >= 0.08
      ):
          dominant_freq_percentage = get_dist_considering_two_freqs(
              distribution
          ) / len(df["ds"])
          num_freq = 3.6e12
          inferred_freq = "BH"
      else:
          dominant_freq_percentage = distribution.max() / len(df["ds"])
          num_freq = argmax_frequency  # get value of most common diff
          inferred_freq = convert_num_to_str_freq(
              num_freq, df["ds"].iloc[0]
          )
  
      log.info(
          f"Major frequency {inferred_freq} corresponds to {np.round(dominant_freq_percentage * 100, 3)}% of the data."
      )
      ideal_freq_exists = (
          True
          if dominant_freq_percentage >= min_freq_percentage
          else False
      )
      if ideal_freq_exists:
          # if major freq exists
          if (
              freq == "auto" or freq is None
          ):  # automatically set df freq to inferred freq
              freq_str = inferred_freq
              log.info(
                  f"Dataframe freq automatically defined as {freq_str}"
              )
          else:
              freq_str = freq
              if convert_str_to_num_freq(
                  freq
              ) != convert_str_to_num_freq(
                  inferred_freq
              ):  # check if given freq is the major
                  log.warning(
                      f"Defined frequency {freq_str} is different than major frequency {inferred_freq}"
                  )
              else:
                  if freq_str in [
                      "M",
                      "MS",
                      "Q",
                      "QS",
                      "Y",
                      "YS",
                  ]:  # temporary solution for avoiding setting wrong start date
                      freq_str = inferred_freq
                  log.info(
                      f"Defined frequency is equal to major frequency - {freq_str}"
                  )
      else:
          # if ideal freq does not exist
          if freq == "auto" or freq is None:
              log.warning(
                  "The auto-frequency feature is not able to detect the following frequencies: SM, BM, CBM, SMS, BMS, \
                      CBMS, BQ, BQS, BA, or, BAS. If the frequency of the dataframe is any of the mentioned please \
                          define it manually."
              )
              raise ValueError(
                  "Detected multiple frequencies in the timeseries please pre-process data."
              )
          else:
              freq_str = freq
              log.warning(
                  f"Dataframe has multiple frequencies. It will be resampled according to given freq {freq}. Ignore \
                      message if actual frequency is any of the following:  SM, BM, CBM, SMS, BMS, CBMS, BQ, BQS, BA, \
                          or, BAS."
              )
      return freq_str
  
imports: from __future__ import annotations
  import logging
  import math
  from collections import OrderedDict
  from dataclasses import dataclass
  from typing import TYPE_CHECKING, List, Optional, Tuple
  import numpy
  import pandas
label_desc: Use image node_id 30 for calling a global function with example usage: _infer_frequency(df, freq, min_freq_percentage) and returns: freq_str