Module pylars.analysis.breakdown

breakdown.py contains the methods and tools for analysis of an LED ON dataset and functions to compute the breakdown voltage out of V vs Gain plots of LED OFF runs.

Expand source code
r"""`breakdown.py` contains the methods and tools for analysis of an LED ON
dataset and functions to compute the breakdown voltage out of V vs Gain plots
of LED OFF runs.
"""
import copy
from typing import Tuple, Union

import numpy as np
import pandas as pd
import pylars
import pylars.plotting.plotanalysis
import pylars.utils.input
import pylars.utils.output
from pylars.utils.common import get_peak_rough_positions
from scipy import stats
from tqdm import tqdm


class BV_dataset():
    """Object class to hold breakdown voltage related instances and
    methods. Collects all the data and properties of a single MMPC,
    meaning the pair (module, channel) for all the available voltages at
    a certain temperature.
    """

    def __init__(self, run: pylars.utils.input.run, temperature: float,
                 module: int, channel: str,
                 processor: pylars.processing.rawprocessor.run_processor):

        self.run = run
        self.temp = temperature
        self.module = module
        self.channel = channel
        self.process = processor
        self.voltages = self.get_voltages_available()
        self.plots_flag = False

    def set_plots_flag(self, flag: bool) -> None:
        """Set if computing properties makes plots (True) or not (False).
        Assumes a ./figures/ directory exists.

        Args:
            flag (bool): True for plotting stuff, False for not making nice
                pictures (plots) to hang on the wall. Yes, I hang plots on
                my bedroom wall and it looks nice.
        """
        self.plots_flag = flag

    def get_voltages_available(self) -> np.ndarray:
        """Checks the loaded run for which voltages are available for the
        defined temperature.

        Returns:
            np.ndarray: array of the available voltages
        """

        voltages = []
        for _dataset in self.run.datasets:
            if (_dataset.temp == self.temp) and (_dataset.kind == 'BV'):
                voltages.append(_dataset.vbias)
        voltages = np.unique(voltages)

        return voltages

    def load_processed_data(self, force_processing: bool = False) -> None:
        """For all the voltages of a BV_dataset (same temperature) looks
        for already processed files to load. If force_processing=True and
        no saved file is found, processes the dataset with standard
        options (sigma = 5, N_baseline = 50).

        Args:
            force_processing (bool, optional): Flag to force processing
                of raw data in case the processed dataset is not found.
                Defaults to False.

        Returns:
            dict: dictionary with the data df for each voltage as a key.
        """
        self.data = {}
        for _voltage in tqdm(self.voltages,
                             desc=f'Loading processed data for BV ' +
                             f'data at {self.temp}K: ',
                             total=len(self.voltages)):
            try:
                processed_data = pylars.utils.output.processed_dataset(
                    run=self.run,
                    kind='BV',
                    vbias=_voltage,
                    temp=self.temp,
                    path_processed=('/disk/gfs_atp/xenoscope/SiPMs/char_campaign/'
                                    'processed_data/'),
                    process_hash=self.process.hash)
                processed_data.load_data(force=force_processing)

                _df = processed_data.data
                mask = ((_df['module'] == self.module) &
                        (_df['channel'] == self.channel))

                self.data[_voltage] = copy.deepcopy(_df[mask])
            except BaseException:
                print(f'Failed to load dataset for V = {_voltage}. Skipping.')

    def compute_BV_LED_simple(self, LED_position: int,
                              plot: bool = False) -> tuple:
        """Comute BV for a given T dataset with the first no-noise peak
        of the area spectrum given width and position cut.

        Args:
            LED_position (int): number of sample where to center the
                position cut.
            plot (bool, optional): Show the plot, save the plot or only
                compute output. Defaults to False.

        Returns:
            tuple: Calculated BV, error on the fit and r2 of the linear
                regression. Returns on the form `(BV, BV_std, r2)`.
        """

        bias_voltage = []
        good_peaks = []
        v_list = self.voltages

        for i, v in enumerate(v_list):

            # For very low bias voltage the SiPM shows a pulse when the LED
            # shines but it could be not yet in Geiger-Mode.
            if v < 48:
                continue

            _df = self.data[v]
            _cuts = (
                (_df['length'] > 3) &
                (_df['position'] > LED_position - 10) &
                (_df['position'] < LED_position + 20)
            )
            peaks, peak_prop = get_peak_rough_positions(
                _df['area'],
                _cuts,
                bins=np.linspace(0, np.percentile(_df['area'], 99), 1500),
                plot=False)

            if len(peaks > 5):
                # likely there is a nice LED fingerplot dominating everything
                first_good_peak = np.median(_df[_cuts]['area'])

            elif len(peaks) == 0:
                print('Could not compute LED area for V=', v)
                continue
            elif len(peaks) > 0:
                if (peaks[0] > 3500) or (len(peaks) == 1):
                    first_good_peak = peaks[0]
                else:
                    first_good_peak = peaks[1]
            # elif len(peaks) == 0 and peaks[0] > 10000:
            #    spe = peaks[0]
            else:
                print('Could not compute LED area for V=', v)
                continue

            bias_voltage.append(v)
            good_peaks.append(first_good_peak)

        linres = stats.linregress(good_peaks, bias_voltage)

        if plot != False:
            pylars.plotting.plotanalysis.plot_BV_fit(
                plot=f'{self.module}_{self.channel}',
                temperature=self.temp,
                voltages=bias_voltage,
                gains=good_peaks,
                a=linres.slope,  # type: ignore
                b=linres.intercept,  # type: ignore
                _breakdown_v=linres.intercept,  # type: ignore
                _breakdown_v_error=linres.intercept_stderr)  # type: ignore

        return (linres.intercept, linres.intercept_stderr,  # type: ignore
                linres.rvalue**2)  # type: ignore


def compute_BV_df(df_results: pd.DataFrame,
                  plot: Union[bool, str] = False
                  ) -> Tuple[pd.DataFrame, float, float, float]:
    """Computes the breakdown voltage with a linear fit of gain over
    V points.

    Takes a dataframe with the collumns 'T' (temperature), 'V' (voltage)
    and 'gain' (self-explanatory, c'mon...)

    Args:
        df_results (pd.DataFrame): dataframe with the processed datasets
            calculated gains.
        plot (boolorstr, optional): flag for plotting choice. Defaults to
            False.

    Returns:
        pd.DataFrame: copy of input dataset with the extra collumns 'BV'
            (breakdown voltage) and 'OV' (over-voltage).
    """

    df_results = copy.deepcopy(df_results)  # just to be sure
    temp_list = np.unique(df_results['T'])
    df_results = pd.concat([df_results,
                            pd.Series(np.zeros(len(df_results)), name='BV')
                            ], axis=1
                           )

    for _temp in temp_list:
        volt_list_in_temp = np.unique(
            df_results[df_results['T'] == _temp]['V'])
        gain_list_in_temp = np.unique(
            df_results[df_results['T'] == _temp]['Gain'])

        linres = stats.linregress(gain_list_in_temp, volt_list_in_temp)
        a = linres.slope,  # type: ignore
        b = linres.intercept,  # type: ignore
        b_err = linres.intercept_stderr  # type: ignore
        a = float(a[0])  # why is this needed? Who knows...
        b = float(b[0])
        b_err = float(b_err)

        _breakdown_v = b  # type: ignore
        _breakdown_v_error = b_err  # type: ignore
        # print(_breakdown_v)
        df_results.loc[df_results['T'] == _temp, 'BV'] = _breakdown_v

        if plot != False:
            pylars.plotting.plotanalysis.plot_BV_fit(plot, _temp,
                                                     volt_list_in_temp,
                                                     gain_list_in_temp,
                                                     a, b,
                                                     _breakdown_v,
                                                     _breakdown_v_error)

    df_results['OV'] = df_results['V'] - df_results['BV']

    return df_results, a, _breakdown_v, _breakdown_v_error  # type: ignore


def compute_BV_DCRds_results(
        results_df: pd.DataFrame, plot: bool) -> pd.DataFrame:
    """Compute BVs for a finished DCR analysis results dataframe.

    Args:
        results_df (pd.DataFrame): DCR analysis result df (without BV)
        plot (bool): save plot of V vs Gain fit.

    Returns:
        pd.DataFrame: a df with all the BV and their std.
    """
    temps = np.unique(results_df['T'])
    BVs = pd.DataFrame(columns=['T', 'module', 'channel', 'BV', 'BV_error'])
    for _temp in temps:
        _select_temp = (results_df['T'] == _temp)
        for mod in np.unique(results_df[_select_temp]['module']):
            _select_mod = (results_df['module'] == mod)
            for ch in np.unique(
                    results_df[_select_temp & _select_mod]['channel']):
                _select = (_select_temp & _select_mod &
                           (results_df['channel'] == ch))
                df = results_df[_select]
                if plot == True:
                    plot_BV = f'BV_mod{mod}_ch{ch}'
                else:
                    plot_BV = False

                try:
                    df, a, bv, bv_err = compute_BV_df(df,  # type: ignore
                                                      plot=plot_BV)
                    BVs = pd.concat([BVs,
                                     pd.DataFrame({'T': [_temp],
                                                   'module': [mod],
                                                   'channel': [ch],
                                                   'BV': [bv],
                                                   'BV_error': [bv_err]})],
                                    ignore_index=True)
                except BaseException:
                    BVs = pd.concat([BVs,
                                    pd.DataFrame({'T': [_temp],
                                                  'module': [mod],
                                                  'channel': [ch],
                                                  'BV': [np.nan],
                                                  'BV_error': [np.nan]})],
                                    ignore_index=True)
    return BVs

Functions

def compute_BV_DCRds_results(results_df: pandas.core.frame.DataFrame, plot: bool) ‑> pandas.core.frame.DataFrame

Compute BVs for a finished DCR analysis results dataframe.

Args

results_df : pd.DataFrame
DCR analysis result df (without BV)
plot : bool
save plot of V vs Gain fit.

Returns

pd.DataFrame
a df with all the BV and their std.
Expand source code
def compute_BV_DCRds_results(
        results_df: pd.DataFrame, plot: bool) -> pd.DataFrame:
    """Compute BVs for a finished DCR analysis results dataframe.

    Args:
        results_df (pd.DataFrame): DCR analysis result df (without BV)
        plot (bool): save plot of V vs Gain fit.

    Returns:
        pd.DataFrame: a df with all the BV and their std.
    """
    temps = np.unique(results_df['T'])
    BVs = pd.DataFrame(columns=['T', 'module', 'channel', 'BV', 'BV_error'])
    for _temp in temps:
        _select_temp = (results_df['T'] == _temp)
        for mod in np.unique(results_df[_select_temp]['module']):
            _select_mod = (results_df['module'] == mod)
            for ch in np.unique(
                    results_df[_select_temp & _select_mod]['channel']):
                _select = (_select_temp & _select_mod &
                           (results_df['channel'] == ch))
                df = results_df[_select]
                if plot == True:
                    plot_BV = f'BV_mod{mod}_ch{ch}'
                else:
                    plot_BV = False

                try:
                    df, a, bv, bv_err = compute_BV_df(df,  # type: ignore
                                                      plot=plot_BV)
                    BVs = pd.concat([BVs,
                                     pd.DataFrame({'T': [_temp],
                                                   'module': [mod],
                                                   'channel': [ch],
                                                   'BV': [bv],
                                                   'BV_error': [bv_err]})],
                                    ignore_index=True)
                except BaseException:
                    BVs = pd.concat([BVs,
                                    pd.DataFrame({'T': [_temp],
                                                  'module': [mod],
                                                  'channel': [ch],
                                                  'BV': [np.nan],
                                                  'BV_error': [np.nan]})],
                                    ignore_index=True)
    return BVs
def compute_BV_df(df_results: pandas.core.frame.DataFrame, plot: Union[bool, str] = False) ‑> Tuple[pandas.core.frame.DataFrame, float, float, float]

Computes the breakdown voltage with a linear fit of gain over V points.

Takes a dataframe with the collumns 'T' (temperature), 'V' (voltage) and 'gain' (self-explanatory, c'mon…)

Args

df_results : pd.DataFrame
dataframe with the processed datasets calculated gains.
plot : boolorstr, optional
flag for plotting choice. Defaults to False.

Returns

pd.DataFrame
copy of input dataset with the extra collumns 'BV' (breakdown voltage) and 'OV' (over-voltage).
Expand source code
def compute_BV_df(df_results: pd.DataFrame,
                  plot: Union[bool, str] = False
                  ) -> Tuple[pd.DataFrame, float, float, float]:
    """Computes the breakdown voltage with a linear fit of gain over
    V points.

    Takes a dataframe with the collumns 'T' (temperature), 'V' (voltage)
    and 'gain' (self-explanatory, c'mon...)

    Args:
        df_results (pd.DataFrame): dataframe with the processed datasets
            calculated gains.
        plot (boolorstr, optional): flag for plotting choice. Defaults to
            False.

    Returns:
        pd.DataFrame: copy of input dataset with the extra collumns 'BV'
            (breakdown voltage) and 'OV' (over-voltage).
    """

    df_results = copy.deepcopy(df_results)  # just to be sure
    temp_list = np.unique(df_results['T'])
    df_results = pd.concat([df_results,
                            pd.Series(np.zeros(len(df_results)), name='BV')
                            ], axis=1
                           )

    for _temp in temp_list:
        volt_list_in_temp = np.unique(
            df_results[df_results['T'] == _temp]['V'])
        gain_list_in_temp = np.unique(
            df_results[df_results['T'] == _temp]['Gain'])

        linres = stats.linregress(gain_list_in_temp, volt_list_in_temp)
        a = linres.slope,  # type: ignore
        b = linres.intercept,  # type: ignore
        b_err = linres.intercept_stderr  # type: ignore
        a = float(a[0])  # why is this needed? Who knows...
        b = float(b[0])
        b_err = float(b_err)

        _breakdown_v = b  # type: ignore
        _breakdown_v_error = b_err  # type: ignore
        # print(_breakdown_v)
        df_results.loc[df_results['T'] == _temp, 'BV'] = _breakdown_v

        if plot != False:
            pylars.plotting.plotanalysis.plot_BV_fit(plot, _temp,
                                                     volt_list_in_temp,
                                                     gain_list_in_temp,
                                                     a, b,
                                                     _breakdown_v,
                                                     _breakdown_v_error)

    df_results['OV'] = df_results['V'] - df_results['BV']

    return df_results, a, _breakdown_v, _breakdown_v_error  # type: ignore

Classes

class BV_dataset (run: run, temperature: float, module: int, channel: str, processor: run_processor)

Object class to hold breakdown voltage related instances and methods. Collects all the data and properties of a single MMPC, meaning the pair (module, channel) for all the available voltages at a certain temperature.

Expand source code
class BV_dataset():
    """Object class to hold breakdown voltage related instances and
    methods. Collects all the data and properties of a single MMPC,
    meaning the pair (module, channel) for all the available voltages at
    a certain temperature.
    """

    def __init__(self, run: pylars.utils.input.run, temperature: float,
                 module: int, channel: str,
                 processor: pylars.processing.rawprocessor.run_processor):

        self.run = run
        self.temp = temperature
        self.module = module
        self.channel = channel
        self.process = processor
        self.voltages = self.get_voltages_available()
        self.plots_flag = False

    def set_plots_flag(self, flag: bool) -> None:
        """Set if computing properties makes plots (True) or not (False).
        Assumes a ./figures/ directory exists.

        Args:
            flag (bool): True for plotting stuff, False for not making nice
                pictures (plots) to hang on the wall. Yes, I hang plots on
                my bedroom wall and it looks nice.
        """
        self.plots_flag = flag

    def get_voltages_available(self) -> np.ndarray:
        """Checks the loaded run for which voltages are available for the
        defined temperature.

        Returns:
            np.ndarray: array of the available voltages
        """

        voltages = []
        for _dataset in self.run.datasets:
            if (_dataset.temp == self.temp) and (_dataset.kind == 'BV'):
                voltages.append(_dataset.vbias)
        voltages = np.unique(voltages)

        return voltages

    def load_processed_data(self, force_processing: bool = False) -> None:
        """For all the voltages of a BV_dataset (same temperature) looks
        for already processed files to load. If force_processing=True and
        no saved file is found, processes the dataset with standard
        options (sigma = 5, N_baseline = 50).

        Args:
            force_processing (bool, optional): Flag to force processing
                of raw data in case the processed dataset is not found.
                Defaults to False.

        Returns:
            dict: dictionary with the data df for each voltage as a key.
        """
        self.data = {}
        for _voltage in tqdm(self.voltages,
                             desc=f'Loading processed data for BV ' +
                             f'data at {self.temp}K: ',
                             total=len(self.voltages)):
            try:
                processed_data = pylars.utils.output.processed_dataset(
                    run=self.run,
                    kind='BV',
                    vbias=_voltage,
                    temp=self.temp,
                    path_processed=('/disk/gfs_atp/xenoscope/SiPMs/char_campaign/'
                                    'processed_data/'),
                    process_hash=self.process.hash)
                processed_data.load_data(force=force_processing)

                _df = processed_data.data
                mask = ((_df['module'] == self.module) &
                        (_df['channel'] == self.channel))

                self.data[_voltage] = copy.deepcopy(_df[mask])
            except BaseException:
                print(f'Failed to load dataset for V = {_voltage}. Skipping.')

    def compute_BV_LED_simple(self, LED_position: int,
                              plot: bool = False) -> tuple:
        """Comute BV for a given T dataset with the first no-noise peak
        of the area spectrum given width and position cut.

        Args:
            LED_position (int): number of sample where to center the
                position cut.
            plot (bool, optional): Show the plot, save the plot or only
                compute output. Defaults to False.

        Returns:
            tuple: Calculated BV, error on the fit and r2 of the linear
                regression. Returns on the form `(BV, BV_std, r2)`.
        """

        bias_voltage = []
        good_peaks = []
        v_list = self.voltages

        for i, v in enumerate(v_list):

            # For very low bias voltage the SiPM shows a pulse when the LED
            # shines but it could be not yet in Geiger-Mode.
            if v < 48:
                continue

            _df = self.data[v]
            _cuts = (
                (_df['length'] > 3) &
                (_df['position'] > LED_position - 10) &
                (_df['position'] < LED_position + 20)
            )
            peaks, peak_prop = get_peak_rough_positions(
                _df['area'],
                _cuts,
                bins=np.linspace(0, np.percentile(_df['area'], 99), 1500),
                plot=False)

            if len(peaks > 5):
                # likely there is a nice LED fingerplot dominating everything
                first_good_peak = np.median(_df[_cuts]['area'])

            elif len(peaks) == 0:
                print('Could not compute LED area for V=', v)
                continue
            elif len(peaks) > 0:
                if (peaks[0] > 3500) or (len(peaks) == 1):
                    first_good_peak = peaks[0]
                else:
                    first_good_peak = peaks[1]
            # elif len(peaks) == 0 and peaks[0] > 10000:
            #    spe = peaks[0]
            else:
                print('Could not compute LED area for V=', v)
                continue

            bias_voltage.append(v)
            good_peaks.append(first_good_peak)

        linres = stats.linregress(good_peaks, bias_voltage)

        if plot != False:
            pylars.plotting.plotanalysis.plot_BV_fit(
                plot=f'{self.module}_{self.channel}',
                temperature=self.temp,
                voltages=bias_voltage,
                gains=good_peaks,
                a=linres.slope,  # type: ignore
                b=linres.intercept,  # type: ignore
                _breakdown_v=linres.intercept,  # type: ignore
                _breakdown_v_error=linres.intercept_stderr)  # type: ignore

        return (linres.intercept, linres.intercept_stderr,  # type: ignore
                linres.rvalue**2)  # type: ignore

Methods

def compute_BV_LED_simple(self, LED_position: int, plot: bool = False) ‑> tuple

Comute BV for a given T dataset with the first no-noise peak of the area spectrum given width and position cut.

Args

LED_position : int
number of sample where to center the position cut.
plot : bool, optional
Show the plot, save the plot or only compute output. Defaults to False.

Returns

tuple
Calculated BV, error on the fit and r2 of the linear regression. Returns on the form (BV, BV_std, r2).
Expand source code
def compute_BV_LED_simple(self, LED_position: int,
                          plot: bool = False) -> tuple:
    """Comute BV for a given T dataset with the first no-noise peak
    of the area spectrum given width and position cut.

    Args:
        LED_position (int): number of sample where to center the
            position cut.
        plot (bool, optional): Show the plot, save the plot or only
            compute output. Defaults to False.

    Returns:
        tuple: Calculated BV, error on the fit and r2 of the linear
            regression. Returns on the form `(BV, BV_std, r2)`.
    """

    bias_voltage = []
    good_peaks = []
    v_list = self.voltages

    for i, v in enumerate(v_list):

        # For very low bias voltage the SiPM shows a pulse when the LED
        # shines but it could be not yet in Geiger-Mode.
        if v < 48:
            continue

        _df = self.data[v]
        _cuts = (
            (_df['length'] > 3) &
            (_df['position'] > LED_position - 10) &
            (_df['position'] < LED_position + 20)
        )
        peaks, peak_prop = get_peak_rough_positions(
            _df['area'],
            _cuts,
            bins=np.linspace(0, np.percentile(_df['area'], 99), 1500),
            plot=False)

        if len(peaks > 5):
            # likely there is a nice LED fingerplot dominating everything
            first_good_peak = np.median(_df[_cuts]['area'])

        elif len(peaks) == 0:
            print('Could not compute LED area for V=', v)
            continue
        elif len(peaks) > 0:
            if (peaks[0] > 3500) or (len(peaks) == 1):
                first_good_peak = peaks[0]
            else:
                first_good_peak = peaks[1]
        # elif len(peaks) == 0 and peaks[0] > 10000:
        #    spe = peaks[0]
        else:
            print('Could not compute LED area for V=', v)
            continue

        bias_voltage.append(v)
        good_peaks.append(first_good_peak)

    linres = stats.linregress(good_peaks, bias_voltage)

    if plot != False:
        pylars.plotting.plotanalysis.plot_BV_fit(
            plot=f'{self.module}_{self.channel}',
            temperature=self.temp,
            voltages=bias_voltage,
            gains=good_peaks,
            a=linres.slope,  # type: ignore
            b=linres.intercept,  # type: ignore
            _breakdown_v=linres.intercept,  # type: ignore
            _breakdown_v_error=linres.intercept_stderr)  # type: ignore

    return (linres.intercept, linres.intercept_stderr,  # type: ignore
            linres.rvalue**2)  # type: ignore
def get_voltages_available(self) ‑> numpy.ndarray

Checks the loaded run for which voltages are available for the defined temperature.

Returns

np.ndarray
array of the available voltages
Expand source code
def get_voltages_available(self) -> np.ndarray:
    """Checks the loaded run for which voltages are available for the
    defined temperature.

    Returns:
        np.ndarray: array of the available voltages
    """

    voltages = []
    for _dataset in self.run.datasets:
        if (_dataset.temp == self.temp) and (_dataset.kind == 'BV'):
            voltages.append(_dataset.vbias)
    voltages = np.unique(voltages)

    return voltages
def load_processed_data(self, force_processing: bool = False) ‑> NoneType

For all the voltages of a BV_dataset (same temperature) looks for already processed files to load. If force_processing=True and no saved file is found, processes the dataset with standard options (sigma = 5, N_baseline = 50).

Args

force_processing : bool, optional
Flag to force processing of raw data in case the processed dataset is not found. Defaults to False.

Returns

dict
dictionary with the data df for each voltage as a key.
Expand source code
def load_processed_data(self, force_processing: bool = False) -> None:
    """For all the voltages of a BV_dataset (same temperature) looks
    for already processed files to load. If force_processing=True and
    no saved file is found, processes the dataset with standard
    options (sigma = 5, N_baseline = 50).

    Args:
        force_processing (bool, optional): Flag to force processing
            of raw data in case the processed dataset is not found.
            Defaults to False.

    Returns:
        dict: dictionary with the data df for each voltage as a key.
    """
    self.data = {}
    for _voltage in tqdm(self.voltages,
                         desc=f'Loading processed data for BV ' +
                         f'data at {self.temp}K: ',
                         total=len(self.voltages)):
        try:
            processed_data = pylars.utils.output.processed_dataset(
                run=self.run,
                kind='BV',
                vbias=_voltage,
                temp=self.temp,
                path_processed=('/disk/gfs_atp/xenoscope/SiPMs/char_campaign/'
                                'processed_data/'),
                process_hash=self.process.hash)
            processed_data.load_data(force=force_processing)

            _df = processed_data.data
            mask = ((_df['module'] == self.module) &
                    (_df['channel'] == self.channel))

            self.data[_voltage] = copy.deepcopy(_df[mask])
        except BaseException:
            print(f'Failed to load dataset for V = {_voltage}. Skipping.')
def set_plots_flag(self, flag: bool) ‑> NoneType

Set if computing properties makes plots (True) or not (False). Assumes a ./figures/ directory exists.

Args

flag : bool
True for plotting stuff, False for not making nice pictures (plots) to hang on the wall. Yes, I hang plots on my bedroom wall and it looks nice.
Expand source code
def set_plots_flag(self, flag: bool) -> None:
    """Set if computing properties makes plots (True) or not (False).
    Assumes a ./figures/ directory exists.

    Args:
        flag (bool): True for plotting stuff, False for not making nice
            pictures (plots) to hang on the wall. Yes, I hang plots on
            my bedroom wall and it looks nice.
    """
    self.plots_flag = flag