//  [python]
def plot_all(self):
        """ Density plots (violin) for main comparisons:
        - ENS per model ablations
        - 5 metrics per model/experiment
        - Split test performance
        - Performance per model across tiles
        - Basemap per model/experiment
        """
        def set_axis_range(plot):
            #does not seem to be properly changing xlim on the subplots
            #unknown cause
            for (row_val, col_val), ax in plot.axes_dict.items():
                if col_val in ["iid_test","ood_test"]:
                    ax.set_xlim(0,20)
                elif col_val == "extreme_test":
                    ax.set_xlim(0,40)
                elif col_val == "seasonal_test":
                    ax.set_xlim(0,140)
            return plot
        if self.pandas_df == None:
            self.create_pandas_df()
        sns.set()
        ##############################
        ### Models plots
        models_path = os.path.join(self.plots_dir,'models')
        os.makedirs(models_path, exist_ok = True)
        violin = sns.catplot(x="experiment", y="score", col="metric", 
                             row="split", kind="violin", split=True, 
                             data=self.pandas_df,
                             scale="count", inner="quartile", bw=.2, cut=0)
        violin.set(ylim=(0, 1))
        violin.set_xticklabels(rotation=90)
        violin.savefig(os.path.join(models_path, 'all.png'), dpi=300)
        print("Model plots exported")
            
        ##############################
        ### Ablation plots
        for model in self.pandas_df.model.unique():
            ablations_path = os.path.join(self.plots_dir,'ablations')
            os.makedirs(ablations_path, exist_ok = True)
            violin = sns.catplot(x="experiment", y="score", col="metric", 
                                 row="split", kind="violin", split=True, 
                                 data=self.pandas_df[self.pandas_df.model == model], 
                                 scale="count", inner="quartile", bw=.2, cut=0)
            violin.set(ylim=(0, 1))
            violin.set_xticklabels(rotation=90)
            violin.savefig(os.path.join(ablations_path, model+'.png'), dpi=300)
        print("Ablation plots exported")
        
        ##############################
        ### Generalization plots
        for model in self.pandas_df.model.unique():
            generalization_path = os.path.join(self.plots_dir,'generalization')
            if not os.path.exists(generalization_path):
                os.makedirs(generalization_path)
            violin = sns.catplot(x="split", y="score", col="metric", 
                                 row="experiment", kind="violin", split=True, 
                                 data=self.pandas_df[self.pandas_df.model == model], 
                                 scale="count", inner="quartile", bw=.2, cut=0)
            violin.set(ylim=(0, 1))
            violin.set_xticklabels(rotation=90)
            violin.savefig(os.path.join(generalization_path, model+'.png'), dpi=300)
        print("Generalization plots exported")
        
        ##############################
        ### Spatial plots (performance across tiles)
        for model in self.pandas_df.model.unique():
            generalization_path = os.path.join(self.plots_dir,'spatial')
            os.makedirs(generalization_path, exist_ok = True)
            violin = sns.catplot(x="tile", y="score", col="metric", 
                                 row="experiment", kind="violin", split=True, 
                                 data=self.pandas_df[self.pandas_df.model == model], 
                                 scale="count", inner="quartile", bw=.2, cut=0)
            violin.set(ylim=(0, 1))
            violin.set_xticklabels(rotation=90, size=4)
            violin.savefig(os.path.join(generalization_path, model+'.png'), dpi=300)
        print("Spatial plots exported")
        
        ##############################
        ### SSIM plots (performance across time steps)
        self.frames_df.dropna(axis=0, inplace=True)
        frames_path = os.path.join(self.plots_dir,'frames')
        os.makedirs(frames_path, exist_ok = True)
        line = sns.relplot(x="frame", y="score", hue="experiment", style="model", col="split",
                           row="channel", kind="line", data=self.frames_df[self.frames_df.metric == 'SSIM'],
                           facet_kws={'sharex': False, 'sharey': False})
        line = set_axis_range(line)
        line.savefig(os.path.join(frames_path, 'ssim_raw_line.png'), dpi=300)
        
        
        violin = sns.catplot(x="frame", y="score", col="split",
                             row="experiment", kind="violin", data=self.frames_df[self.frames_df.metric == 'SSIM'],
                             sharex=False, sharey=False)
        violin = set_axis_range(violin)
        violin.savefig(os.path.join(frames_path, 'ssim_raw_violin.png'), dpi=300)
        print("Framewise SSIM exported")
        
        ##########
        ### MAE plots (performance across time steps)
        line = sns.relplot(x="frame", y="score", hue="experiment", style="model", col="split",
                           row="channel", kind="line", data=self.frames_df[self.frames_df.metric == 'MAD'],
                           facet_kws={'sharex': False, 'sharey': False})
        line = set_axis_range(line)
        line.savefig(os.path.join(frames_path, 'mae_raw_line.png'), dpi=300)
        
        violin = sns.catplot(x="frame", y="score", col="split",
                             row="experiment", kind="violin", data=self.frames_df[self.frames_df.metric == 'MAD'],
                             sharex=False, sharey=False)
        violin = set_axis_range(violin)
        violin.savefig(os.path.join(frames_path, 'mae_raw_violin.png'), dpi=300)
        print("Framewise MAE exported")