code: def analyze(
      problem,
      X,
      Y,
      second_order=False,
      print_to_console=False,
      seed=None,
  ):
      """Perform a fractional factorial analysis
  
      Returns a dictionary with keys 'ME' (main effect) and 'IE' (interaction
      effect). The techniques bulks out the number of parameters with dummy
      parameters to the nearest 2**n.  Any results involving dummy parameters
      could indicate a problem with the model runs.
  
  
      Notes
      -----
      Compatible with:
          `ff` : :func:`SALib.sample.ff.sample`
  
  
      Examples
      --------
          >>> X = sample(problem)
          >>> Y = X[:, 0] + (0.1 * X[:, 1]) + ((1.2 * X[:, 2]) * (0.2 + X[:, 0]))
          >>> analyze(problem, X, Y, second_order=True, print_to_console=True)
  
  
      Parameters
      ----------
      problem: dict
          The problem definition
      X: numpy.matrix
          The NumPy matrix containing the model inputs
      Y: numpy.array
          The NumPy array containing the model outputs
      second_order: bool, default=False
          Include interaction effects
      print_to_console: bool, default=False
          Print results directly to console
      seed : int
          Seed to generate a random number
  
  
      Returns
      -------
      Si: dict
          A dictionary of sensitivity indices, including main effects ``ME``,
          and interaction effects ``IE`` (if ``second_order`` is True)
  
  
      References
      ----------
      1. Saltelli, A., Ratto, M., Andres, T., Campolongo, F.,
             Cariboni, J., Gatelli, D.,
             Saisana, M., Tarantola, S., 2008.
             Global Sensitivity Analysis: The Primer.
             Wiley, West Sussex, U.K.
             http://doi.org/10.1002/9780470725184
      """
      if seed:
          np.random.seed(seed)
  
      problem = extend_bounds(problem)
      num_vars = problem["num_vars"]
  
      X = generate_contrast(problem)
  
      main_effect = (1.0 / (2 * num_vars)) * np.dot(Y, X)
  
      Si = ResultDict((k, [None] * num_vars) for k in ["names", "ME"])
      Si["ME"] = main_effect
      Si["names"] = problem["names"]
  
      if second_order:
          interaction_names, interaction_effects = interactions(
              problem, Y
          )
          Si["interaction_names"] = interaction_names
          Si["IE"] = interaction_effects
  
      Si.to_df = MethodType(to_df, Si)
  
      if print_to_console:
          for S in Si.to_df():
              print(S)
  
      return Si
  
file_path: SALib/src/SALib/analyze/ff.py
imports: import numpy
  from .None import common_args
  import pandas
  from types import MethodType
  from SALib.util import read_param_file, ResultDict
  from SALib.sample.ff import generate_contrast, extend_bounds
label_desc: Use image node_id 1 for calling a global function with example usage: analyze(problem, X, Y, second_order, print_to_console, seed) and returns: Si