<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def model(self, data, ind_col=None, dep_col=None, project_ind_col=None, baseline_period=[None, None], projection_period=None, exclude_time_period=None, alphas=np.logspace(-4,1,30), cv=3, plot=True, figsize=None, custom_model_func=None):
 """ Split data into baseline and projection periods, run models on them and display metrics & plots. Parameters data : pd.DataFrame() Dataframe to model. ind_col : list(str) Independent column(s) of dataframe. Defaults to all columns except the last. dep_col : str Dependent column of dataframe. project_ind_col : list(str) Independent column(s) to use for projection. If none, use ind_col. baseline_period : list(str) List of time periods to split the data into baseline periods. It needs to have a start and an end date. projection_period : list(str) List of time periods to split the data into projection periods. It needs to have a start and an end date. exclude_time_period : list(str) List of time periods to exclude for modeling. alphas : list(int) List of alphas to run regression on. cv : int Number of folds for cross-validation. plot : bool Specifies whether to save plots or not. figsize : tuple Size of the plots. custom_model_func : function Model with specific hyper-parameters provided by user. Returns ------- dict Metrics of the optimal/best model. """


        # Check to ensure data is a pandas dataframe
        if not isinstance(data, pd.DataFrame):
            raise SystemError('data has to be a pandas dataframe.')
        
        # Create instance
        model_data_obj = Model_Data(data, ind_col, dep_col, alphas, cv, exclude_time_period, baseline_period, projection_period)

        # Split data into baseline and projection
        model_data_obj.split_data()

        # Logging
        self.result['Model'] = {
            'Independent Col': ind_col,
            'Dependent Col': dep_col,
            'Projection Independent Col': project_ind_col,
            'Baseline Period': baseline_period,
            'Projection Period': projection_period,
            'Exclude Time Period': exclude_time_period,
            'Alphas': list(alphas),
            'CV': cv,
            'Plot': plot,
            'Fig Size': figsize
        }

        # Runs all models on the data and returns optimal model
        all_metrics = model_data_obj.run_models()
        self.result['Model']['All Model\'s Metrics'] = all_metrics

        # CHECK: Define custom model's parameter and return types in documentation.
        if custom_model_func:
            self.result['Model']['Custom Model\'s Metrics'] = model_data_obj.custom_model(custom_model_func)

        # Fit optimal model to data
        self.result['Model']['Optimal Model\'s Metrics'] = model_data_obj.best_model_fit()

        if plot:

            # Use project_ind_col if projecting into the future (no input data other than weather data)
            input_col = model_data_obj.input_col if not project_ind_col else project_ind_col
            fig, y_true, y_pred = self.plot_data_obj.baseline_projection_plot(model_data_obj.y_true, model_data_obj.y_pred, 
                                                            model_data_obj.baseline_period, model_data_obj.projection_period,
                                                            model_data_obj.best_model_name, model_data_obj.best_metrics['adj_r2'],
                                                            model_data_obj.original_data,
                                                            input_col, model_data_obj.output_col,
                                                            model_data_obj.best_model,
                                                            self.result['Site'])

            fig.savefig(self.results_folder_name + '/baseline_projection_plot-' + str(self.get_global_count()) + '.png')
            
            if not y_true.empty and not y_pred.empty:
                saving_absolute = (y_pred - y_true).sum()
                saving_perc = (saving_absolute / y_pred.sum()) * 100
                self.result['Energy Savings (%)'] = float(saving_perc)
                self.result['Energy Savings (absolute)'] = saving_absolute

                # Temporary
                self.project_df['true'] = y_true
                self.project_df['pred'] = y_pred

                # Calculate uncertainity of savings
                self.result['Uncertainity'] = self.uncertainity_equation(model_data_obj, y_true, y_pred, 0.9)
            
            else:
                print('y_true: ', y_true)
                print('y_pred: ', y_pred)
                print('Error: y_true and y_pred are empty. Default to -1.0 savings.')
                self.result['Energy Savings (%)'] = float(-1.0)
                self.result['Energy Savings (absolute)'] = float(-1.0)
        
        return self.best_metrics