code: def estimate_alpha(self, df):
      # print("CROSTON_OPTIONS" , self.mOptions.mCrostonOptions.__dict__)
      method = self.mOptions.mCrostonOptions.mMethod
      if self.mOptions.mCrostonOptions.mAlpha is not None:
          self.mAlpha = self.mOptions.mCrostonOptions.mAlpha
          return
      else:
          # choose the best alpha based on L2
          lPerfs = {}
          lForecastColumnName = "forecast"
          for alpha in np.arange(0.05, 1.0, 0.05):
              forecast_df = self.compute_forecast(df, alpha, method, 1)
              lPerf = tsperf.cPerf()
              lPerf.computeCriterion(
                  forecast_df[self.mCycleResidueName],
                  forecast_df[lForecastColumnName],
                  self.mOptions.mCrostonOptions.mAlphaCriterion,
                  "CROSTON_SEL_" + "_Fit_" + str(alpha),
              )
              lPerfs[alpha] = lPerf.mL2
          self.mAlpha = min(lPerfs, key=lPerfs.get)
          # print(lPerfs)
          # print("CROSTON_OPTIMIZED_ALPHA" , self.mAlpha)
          return
  
file_path: atspy/atspy/TS/Intermittent_Models.py
imports: import numpy
  import pandas
  from .None import SignalDecomposition_AR
  from .None import Utils
  from .None import Perf
  import sys
label_desc: Use image node_id 5 for calling the cCroston_Model obj's underlying member method code with example usage: obj.estimate_alpha(df) without return types