Source code for pycequeau.core.matlab_utils

"""Utilities for converting between Python data and MATLAB (.mat) formats."""

from __future__ import annotations

import numpy as np
import pandas as pd
from scipy.io.matlab import mat_struct



[docs] def to_mat_compatible(value): """Recursively convert Python containers to scipy.savemat-compatible values.""" if isinstance(value, dict): return {k: to_mat_compatible(v) for k, v in value.items()} if isinstance(value, (set, tuple)): value = list(value) if isinstance(value, list): if not value: return np.array([]) if all(isinstance(v, (int, float, np.integer, np.floating, bool)) for v in value): return np.asarray(value) return np.array([to_mat_compatible(v) for v in value], dtype=object) return value
[docs] def dataframe_to_struct_array(df: pd.DataFrame) -> np.ndarray: """Convert DataFrame to MATLAB struct-array layout (1xN struct).""" field_names = [str(col) for col in df.columns] struct_dtype = np.dtype([(name, object) for name in field_names]) struct_arr = np.empty((1, len(df)), dtype=struct_dtype) for row_idx, (_, row) in enumerate(df.iterrows()): for field in field_names: struct_arr[field][0, row_idx] = mat_field_value(row[field]) return struct_arr
[docs] def mat_field_value(value): """Normalize a single table value to MATLAB-friendly field content.""" if isinstance(value, (set, tuple)): value = list(value) if isinstance(value, (np.ndarray, pd.Series)): arr = np.asarray(value) if arr.dtype == object: return np.array([mat_field_value(v) for v in arr], dtype=object) return arr if isinstance(value, list): if all(isinstance(v, (int, float, np.integer, np.floating, bool)) for v in value): return np.asarray(value) return np.array([mat_field_value(v) for v in value], dtype=object) if isinstance(value, np.generic): return value.item() return value
[docs] def mat_to_py(value): """Recursively convert scipy.loadmat objects into plain Python containers.""" # scipy.io MATLAB struct: use vars() (public __dict__) instead of _fieldnames if isinstance(value, mat_struct): return { k: mat_to_py(v) for k, v in vars(value).items() if not k.startswith("_") } if isinstance(value, np.ndarray): if value.dtype == object: return [mat_to_py(v) for v in value.tolist()] return value.tolist() return value