Process reference: statistical_analysis
Generated from the docstrings of vaft.process.statistical_analysis:
11 public functions. Each entry is what
vaft.process.describe("statistical_analysis.<name>") prints.
All process categories
Overview
The workflow behind the confinement-scaling study: take a table of shots
with their engineering parameters and energy confinement time, take
natural logarithms, fit ln tau_E = c0 + sum_i c_i ln p_i by ordinary
least squares, and read the scaling exponents off the coefficients.
Everything operates on pandas DataFrames whose columns are named by
the caller; nothing here knows which columns exist except through the
eng_params list it is handed.
Two functions are not statistics and are here for historical reasons:
generate_core_profiles_history_dataframe builds the input table by
running a workflow script, and confinement_time_histogram draws
one. Both are documented as they are; their home is decided by #263.
| Symbol | Meaning | Unit |
|---|---|---|
| tau_E | energy confinement time | s |
| p_i | an engineering parameter | any |
| c_i | the scaling exponent of ``p_i`` | - |
| alpha | significance level | - |
Functions
analyze_significance | Flag which scaling exponents are statistically significant. |
compute_metrics | Goodness-of-fit metrics of the regression in original units. Convention |
confinement_time_histogram | Plot histograms of the scaling parameters in an m x n grid.
|
filter_dataframe | Drop shots with unrealistic loss power and rectify the toroidal field sign. Convention |
generate_core_profiles_history_dataframe | Build the scaling table by running the core-profiles history workflow. |
get_correlation_matrix | Pearson correlation matrix of the log-transformed regressors and target. |
get_individual_correlations | Pearson correlation of each log regressor with the log target. |
get_residuals | Residuals of the log-space fit. |
load_data_from_excel | Load a confinement-scaling table from an Excel file. |
log_transform | Take natural logarithms of the engineering parameters and the target. Convention |
perform_ols_regression | Fit the log-linear scaling by ordinary least squares. Convention |
No function matches.
analyze_significance
Machine-independent
source
analyze_significance(results, alpha=0.05)
Show source vaft/process/statistical_analysis.py, lines 406–446
def analyze_significance(results: RegressionResults,
alpha: float = 0.05) -> Dict[str, bool]:
"""Flag which scaling exponents are statistically significant.
Parameters
----------
results : RegressionResults
A fitted regression [-].
alpha : float, optional
Significance level; a coefficient with ``p < alpha`` is significant
[-].
Returns
-------
dict of str to bool
Parameter name to whether its exponent is significant; a parameter
absent from the fit is ``False`` [-].
Defaults
--------
``alpha = 0.05`` is the conventional literature value, no more.
Applicability
-------------
Machine-independent.
Limitations
-----------
A p-value from a small sample with correlated regressors overstates
significance; see :func:`get_correlation_matrix` before trusting it.
"""
significance = {}
for param in results.eng_params:
param_name = f'ln_{param}'
if param_name in results.pvalues:
pval = results.pvalues[param_name]
significance[param] = pval < alpha
else:
significance[param] = False
return significanceFlag which scaling exponents are statistically significant.
| Name | Type | Unit | Description |
|---|---|---|---|
results | RegressionResults | - | A fitted regression. |
alpha | float, optional | - | Significance level; a coefficient with |
| Returns | |||
| — | dict of str to bool | - | Parameter name to whether its exponent is significant; a parameter absent from the fit is |
Defaults · Applicability · Limitations
Defaults
alpha = 0.05 is the conventional literature value, no more.
Applicability
Machine-independent.
Limitations
A p-value from a small sample with correlated regressors overstates
significance; see get_correlation_matrix before trusting it.
compute_metrics
Machine-independentConvention-sensitive
source
compute_metrics(results, df, target_param='tauE_s')
Goodness-of-fit metrics of the regression in original units.
| Name | Type | Unit | Description |
|---|---|---|---|
results | RegressionResults | - | A fitted regression. |
df | pd.DataFrame | - | The original table the regression was fitted from. |
target_param | str, optional | - | Column name of the confinement time. |
| Returns | |||
| — | dict of str to float | - |
|
Convention
Metrics are in the original units, so R2 here is not the rsquared
of the log fit on the results object; the two differ and both are
reported deliberately. RMSE and MAE carry the target’s unit,
seconds for tauE_s, and are returned as plain floats.
Processing steps · Applicability · Limitations
Processing steps
- Exponentiate the fitted log values to get predicted confinement times.
- Select the actual values at the rows the fit used.
- Compute the metrics with
sklearn.metricsand NumPy.
Applicability
Machine-independent.
Limitations
When the fitted values carry no index the actual values are truncated to the shorter length, which silently misaligns rows if any were dropped.
confinement_time_histogram
Machine-independent
source
confinement_time_histogram(df, eng_params=None, m=None, n=None, figsize=None, bins=30, alpha=0.7, edgecolor='black', **kwargs)
Show source vaft/process/statistical_analysis.py, lines 699–748
def confinement_time_histogram(df: pd.DataFrame,
eng_params: Optional[List[str]] = None,
m: Optional[int] = None,
n: Optional[int] = None,
figsize: Optional[Tuple[float, float]] = None,
bins: Union[int, str] = 30,
alpha: float = 0.7,
edgecolor: str = 'black',
**kwargs):
"""Plot histograms of the scaling parameters in an ``m x n`` grid.
Parameters
----------
df : pd.DataFrame
The scaling table [-].
eng_params : list of str or None, optional
Columns to plot; ``None`` for the renderer's default set [-].
m : int or None, optional
Grid rows [-].
n : int or None, optional
Grid columns [-].
figsize : tuple of (float, float) or None, optional
Figure size in inches [-].
bins : int or str, optional
Histogram bins, as Matplotlib takes them [-].
alpha : float, optional
Bar opacity [-].
edgecolor : str, optional
Bar edge colour [-].
Returns
-------
matplotlib.figure.Figure
The figure, as :func:`vaft.plot.history.confinement_time_histogram`
returns it [-].
Applicability
-------------
Machine-independent.
Limitations
-----------
Rendering lives in :func:`vaft.plot.history.confinement_time_histogram`
(issue #63); this is a compatibility shim that keeps the old call site
and pulls Matplotlib in on call. Its removal is tracked in #263.
"""
from vaft.plot.history import confinement_time_histogram as _render
return _render(df, eng_params=eng_params, m=m, n=n, figsize=figsize,
bins=bins, alpha=alpha, edgecolor=edgecolor, **kwargs)Plot histograms of the scaling parameters in an m x n grid.
| Name | Type | Unit | Description |
|---|---|---|---|
df | pd.DataFrame | - | The scaling table. |
eng_params | list of str or None, optional | - | Columns to plot; |
m | int or None, optional | - | Grid rows. |
n | int or None, optional | - | Grid columns. |
figsize | tuple of (float, float) or None, optional | - | Figure size in inches. |
bins | int or str, optional | - | Histogram bins, as Matplotlib takes them. |
alpha | float, optional | - | Bar opacity. |
edgecolor | str, optional | - | Bar edge colour. |
| Returns | |||
| — | matplotlib.figure.Figure | - | The figure, as |
Applicability · Limitations
Applicability
Machine-independent.
Limitations
Rendering lives in vaft.plot.history.confinement_time_histogram
(issue #63); this is a compatibility shim that keeps the old call site
and pulls Matplotlib in on call. Its removal is tracked in #263.
filter_dataframe
VEST-specificConvention-sensitive
source
filter_dataframe(df)
Show source vaft/process/statistical_analysis.py, lines 126–171
def filter_dataframe(df: pd.DataFrame) -> pd.DataFrame:
"""Drop shots with unrealistic loss power and rectify the toroidal field sign.
Parameters
----------
df : pd.DataFrame
The scaling table; ``Ploss_MW`` and ``Bt_T`` are acted on when present
[-].
Returns
-------
pd.DataFrame
The filtered table [-].
Processing steps
----------------
1. Keep rows with ``Ploss_MW <= 3``.
2. Replace ``Bt_T`` by its absolute value.
Defaults
--------
The 3 MW ceiling is a hard-coded empirical cut from the study; its
derivation is not recorded. It is not a parameter.
Convention
----------
``Bt_T`` is made positive regardless of the field direction actually run,
so the fit sees magnitude only. Any sign convention on the field is
discarded here.
Applicability
-------------
VEST-specific. The ceiling and the column names are the VEST study's.
Limitations
-----------
Assigns into the frame it was given (``df["Bt_T"] = ...``), so the
caller's table may be modified and pandas may warn about a copy.
"""
if 'Ploss_MW' in df.columns:
df = df[df['Ploss_MW'] <= 3]
# Ensure Bt_T is always positive
if 'Bt_T' in df.columns:
df['Bt_T'] = df['Bt_T'].abs()
return dfDrop shots with unrealistic loss power and rectify the toroidal field sign.
| Name | Type | Unit | Description |
|---|---|---|---|
df | pd.DataFrame | - | The scaling table; |
| Returns | |||
| — | pd.DataFrame | - | The filtered table. |
Convention
Bt_T is made positive regardless of the field direction actually run,
so the fit sees magnitude only. Any sign convention on the field is
discarded here.
Processing steps · Defaults · Applicability · Limitations
Processing steps
- Keep rows with
Ploss_MW <= 3. - Replace
Bt_Tby its absolute value.
Defaults
The 3 MW ceiling is a hard-coded empirical cut from the study; its derivation is not recorded. It is not a parameter.
Applicability
VEST-specific. The ceiling and the column names are the VEST study’s.
Limitations
Assigns into the frame it was given (df["Bt_T"] = ...), so the
caller’s table may be modified and pandas may warn about a copy.
generate_core_profiles_history_dataframe
VEST-specific
source
generate_core_profiles_history_dataframe(max_shots=None, Z_eff=2.0)
Build the scaling table by running the core-profiles history workflow.
| Name | Type | Unit | Description |
|---|---|---|---|
max_shots | int or None, optional | - | Stop after this many shots; |
Z_eff | float, optional | - | Effective charge assumed for every shot when computing the ion contribution. |
| Returns | |||
| — | pd.DataFrame | - | One row per shot with the engineering parameters and |
Raises
ImportErrorThe workflow script cannot be found or loaded.ValueErrorThe script returned nothing.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Locate
workflow/automatic_pipeline_3_data_summary/gen_core_profiles_history.pyrelative to this file and load it by path. - Call its
generate_core_profiles_history_excel(max_shots, Z_eff).
Defaults
Z_eff = 2.0 is an assumed value, used because no shot-resolved
measurement exists; its origin is not recorded.
Applicability
VEST-specific. The script reads the VEST database.
Limitations
Loads a workflow script by file path and inserts its directory into
sys.path, which only works from a source checkout and is a
layer-boundary violation: a process function reaching up into a workflow.
Tracked in #263.
Provenance
workflow/automatic_pipeline_3_data_summary/gen_core_profiles_history.py.
get_correlation_matrix
Machine-independent
source
get_correlation_matrix(log_df, eng_params, target_param='tauE_s')
Show source vaft/process/statistical_analysis.py, lines 607–644
def get_correlation_matrix(log_df: pd.DataFrame,
eng_params: List[str],
target_param: str = 'tauE_s') -> pd.DataFrame:
"""Pearson correlation matrix of the log-transformed regressors and target.
Parameters
----------
log_df : pd.DataFrame
Output of :func:`log_transform` [-].
eng_params : list of str
Column names of the engineering parameters [-].
target_param : str, optional
Column name of the confinement time [-].
Returns
-------
pd.DataFrame
The correlation matrix over the available ``ln_`` columns; empty when
fewer than two exist [-].
Applicability
-------------
Machine-independent.
Limitations
-----------
Pairwise-complete, as ``DataFrame.corr`` is; rows are not dropped
consistently across pairs.
"""
cols = [f'ln_{p}' for p in eng_params] + [f'ln_{target_param}']
available_cols = [c for c in cols if c in log_df.columns]
if len(available_cols) < 2:
logger.warning("Not enough columns for correlation matrix")
return pd.DataFrame()
corr_df = log_df[available_cols].corr()
return corr_dfPearson correlation matrix of the log-transformed regressors and target.
| Name | Type | Unit | Description |
|---|---|---|---|
log_df | pd.DataFrame | - | Output of |
eng_params | list of str | - | Column names of the engineering parameters. |
target_param | str, optional | - | Column name of the confinement time. |
| Returns | |||
| — | pd.DataFrame | - | The correlation matrix over the available |
Applicability · Limitations
Applicability
Machine-independent.
Limitations
Pairwise-complete, as DataFrame.corr is; rows are not dropped
consistently across pairs.
get_individual_correlations
Machine-independent
source
get_individual_correlations(log_df, eng_params, target_param='tauE_s')
Show source vaft/process/statistical_analysis.py, lines 647–692
def get_individual_correlations(log_df: pd.DataFrame,
eng_params: List[str],
target_param: str = 'tauE_s') -> Dict[str, float]:
"""Pearson correlation of each log regressor with the log target.
Parameters
----------
log_df : pd.DataFrame
Output of :func:`log_transform` [-].
eng_params : list of str
Column names of the engineering parameters [-].
target_param : str, optional
Column name of the confinement time [-].
Returns
-------
dict of str to float
Parameter name to its correlation with the target; NaN when the
column is missing or fewer than two complete rows exist [-].
Applicability
-------------
Machine-independent.
"""
correlations = {}
target_col = f'ln_{target_param}'
if target_col not in log_df.columns:
logger.warning(f"Target column {target_col} not found")
return correlations
for param in eng_params:
param_col = f'ln_{param}'
if param_col in log_df.columns:
# Remove NaN values for correlation calculation
valid_mask = ~(log_df[param_col].isna() | log_df[target_col].isna())
if valid_mask.sum() > 1:
corr, _ = pearsonr(log_df[param_col][valid_mask],
log_df[target_col][valid_mask])
correlations[param] = corr
else:
correlations[param] = np.nan
else:
correlations[param] = np.nan
return correlationsPearson correlation of each log regressor with the log target.
| Name | Type | Unit | Description |
|---|---|---|---|
log_df | pd.DataFrame | - | Output of |
eng_params | list of str | - | Column names of the engineering parameters. |
target_param | str, optional | - | Column name of the confinement time. |
| Returns | |||
| — | dict of str to float | - | Parameter name to its correlation with the target; NaN when the column is missing or fewer than two complete rows exist. |
Applicability
Applicability
Machine-independent.
get_residuals
Machine-independent
source
get_residuals(results)
Show source vaft/process/statistical_analysis.py, lines 587–604
def get_residuals(results: RegressionResults) -> pd.Series:
"""Residuals of the log-space fit.
Parameters
----------
results : RegressionResults
A fitted regression [-].
Returns
-------
pd.Series
``ln(actual) - ln(fitted)`` per row used in the fit [-].
Applicability
-------------
Machine-independent.
"""
return results.residualsResiduals of the log-space fit.
| Name | Type | Unit | Description |
|---|---|---|---|
results | RegressionResults | - | A fitted regression. |
| Returns | |||
| — | pd.Series | - |
|
Applicability
Applicability
Machine-independent.
load_data_from_excel
Machine-independent
source
load_data_from_excel(filepath)
Show source vaft/process/statistical_analysis.py, lines 89–124
def load_data_from_excel(filepath: str) -> pd.DataFrame:
"""Load a confinement-scaling table from an Excel file.
Parameters
----------
filepath : str
Path to the ``.xlsx`` file; one row per shot, columns as the study
named them [-].
Returns
-------
pd.DataFrame
The table as read, untouched [-].
Raises
------
Exception
Whatever ``pandas.read_excel`` raises, after logging it.
Applicability
-------------
Machine-independent. The tables under
``workflow/automatic_pipeline_3_data_summary/`` are VEST, but nothing here
depends on that.
Provenance
----------
.. [1] The study notebook [NB]_.
"""
try:
df = pd.read_excel(filepath)
logger.info(f"Loaded {len(df)} rows from {filepath}")
return df
except Exception as e:
logger.error(f"Error loading Excel file: {e}")
raiseLoad a confinement-scaling table from an Excel file.
| Name | Type | Unit | Description |
|---|---|---|---|
filepath | str | - | Path to the |
| Returns | |||
| — | pd.DataFrame | - | The table as read, untouched. |
Raises
ExceptionWhateverpandas.read_excelraises, after logging it.
Applicability · Provenance
Applicability
Machine-independent. The tables under
workflow/automatic_pipeline_3_data_summary/ are VEST, but nothing here
depends on that.
Provenance
- The study notebook [NB].
log_transform
Machine-independentConvention-sensitive
source
log_transform(df, eng_params, target_param='tauE_s')
Show source vaft/process/statistical_analysis.py, lines 262–312
def log_transform(df: pd.DataFrame,
eng_params: List[str],
target_param: str = 'tauE_s') -> pd.DataFrame:
"""Take natural logarithms of the engineering parameters and the target.
Parameters
----------
df : pd.DataFrame
The scaling table [-].
eng_params : list of str
Column names of the engineering parameters [-].
target_param : str, optional
Column name of the confinement time [-].
Returns
-------
pd.DataFrame
Columns ``ln_<name>`` for each parameter and the target, same index as
``df``; a missing column becomes all-NaN with a warning [-].
Convention
----------
Natural logarithm, so the fitted coefficients are the exponents of a
power law directly. A value that is not strictly positive has no
logarithm and becomes NaN, to be dropped by :func:`perform_ols_regression`.
Applicability
-------------
Machine-independent.
"""
log_df = pd.DataFrame(index=df.index)
# Log transform engineering parameters
for param in eng_params:
if param in df.columns:
# Handle NaN and non-positive values
valid_mask = (df[param] > 0) & ~np.isnan(df[param])
log_df[f'ln_{param}'] = np.where(valid_mask, np.log(df[param]), np.nan)
else:
logger.warning(f"Parameter {param} not found in DataFrame")
log_df[f'ln_{param}'] = np.nan
# Log transform target parameter
if target_param in df.columns:
valid_mask = (df[target_param] > 0) & ~np.isnan(df[target_param])
log_df[f'ln_{target_param}'] = np.where(valid_mask, np.log(df[target_param]), np.nan)
else:
logger.warning(f"Target parameter {target_param} not found in DataFrame")
log_df[f'ln_{target_param}'] = np.nan
return log_dfTake natural logarithms of the engineering parameters and the target.
| Name | Type | Unit | Description |
|---|---|---|---|
df | pd.DataFrame | - | The scaling table. |
eng_params | list of str | - | Column names of the engineering parameters. |
target_param | str, optional | - | Column name of the confinement time. |
| Returns | |||
| — | pd.DataFrame | - | Columns |
Convention
Natural logarithm, so the fitted coefficients are the exponents of a
power law directly. A value that is not strictly positive has no
logarithm and becomes NaN, to be dropped by perform_ols_regression.
Applicability
Applicability
Machine-independent.
perform_ols_regression
Machine-independentConvention-sensitive
source
perform_ols_regression(df, eng_params, target_param='tauE_s', dropna=True)
Fit the log-linear scaling by ordinary least squares.
| Name | Type | Unit | Description |
|---|---|---|---|
df | pd.DataFrame | - | The scaling table, in original units. |
eng_params | list of str | - | Column names of the engineering parameters to regress on. |
target_param | str, optional | - | Column name of the confinement time. |
dropna | bool, optional | - | Drop rows with any NaN among the regressors or the target. |
| Returns | |||
| — | RegressionResults | - | The fitted |
Convention
The fit is in log space, so the coefficients are exponents and the
residuals are relative errors. Metrics in original units come from
compute_metrics, which exponentiates the fitted values.
Raises
ValueErrorNo rows remain after dropping NaN.
Processing steps · Defaults · Applicability · Provenance
Processing steps
log_transformthe table.- Select the
ln_regressors and theln_target. - Drop rows with NaN, if
dropna. - Add an intercept column and fit
statsmodels.api.OLS.
Defaults
dropna = True is a validated-workflow default; statsmodels would
otherwise raise on NaN.
Applicability
Machine-independent.
Provenance
- The study notebook [NB].