classdef flywheel_matlab_helpers % FLYWHEEL_MATLAB_HELPERS - Utility functions for using Python flywheel-sdk % from MATLAB % % This helper class provides convenience functions to simplify working with % the Python flywheel-sdk from MATLAB, abstracting away common type conversion % and interoperability patterns. % % Usage: % fw = flywheel_matlab_helpers.create_client('your-api-key'); % updates = flywheel_matlab_helpers.to_py_dict('label', 'New Name'); % projects = flywheel_matlab_helpers.iter_all(fw.projects.iter()); methods(Static) function dict = to_py_dict(varargin) % TO_PY_DICT Create Python dictionary from key-value pairs % % Syntax: % dict = flywheel_matlab_helpers.to_py_dict(key1, val1, key2, val2, ...) % % Examples: % d = flywheel_matlab_helpers.to_py_dict('label', 'test', 'age', 30); % metadata = flywheel_matlab_helpers.to_py_dict('Modality', 'MR'); dict = py.dict(pyargs(varargin{:})); end function list = to_py_list(matlab_array) % TO_PY_LIST Convert MATLAB array to Python list % % Syntax: % list = flywheel_matlab_helpers.to_py_list(matlab_array) % % Examples: % pylist = flywheel_matlab_helpers.to_py_list([1, 2, 3]); % pylist = flywheel_matlab_helpers.to_py_list({'a', 'b', 'c'}); if iscell(matlab_array) list = py.list(matlab_array); else list = py.list(num2cell(matlab_array)); end end function cell_array = from_py_list(py_list) % FROM_PY_LIST Convert Python list/generator to MATLAB cell array % % Syntax: % cell_array = flywheel_matlab_helpers.from_py_list(py_list) % % Examples: % results = fw.projects.find('label=~MRI'); % projects = flywheel_matlab_helpers.from_py_list(results); % Convert to Python list first if it's a generator if ~isa(py_list, 'py.list') py_list = py.list(py_list); end cell_array = cell(py_list); end function str = safe_string(py_obj) % SAFE_STRING Safely convert Python object to MATLAB string % Handles None/empty values gracefully % % Syntax: % str = flywheel_matlab_helpers.safe_string(py_obj) % % Examples: % label = flywheel_matlab_helpers.safe_string(project.label); if isempty(py_obj) || isa(py_obj, 'py.NoneType') str = ''; else str = string(py_obj); end end function fw = create_client(api_key) % CREATE_CLIENT Initialize Flywheel client % % Syntax: % fw = flywheel_matlab_helpers.create_client() % Uses saved credentials % fw = flywheel_matlab_helpers.create_client(api_key) % % Examples: % fw = flywheel_matlab_helpers.create_client('my-api-key'); % fw = flywheel_matlab_helpers.create_client(); % Default credentials fw_module = py.importlib.import_module('flywheel'); if nargin < 1 fw = fw_module.Client(); else fw = fw_module.Client(api_key); end fw = py.getattr(fw, '_fw'); end function items = iter_all(iterator) % ITER_ALL Consume Python iterator and return all items as cell array % WARNING: Use with caution for large result sets as this loads % all items into memory at once % % Syntax: % items = flywheel_matlab_helpers.iter_all(iterator) % % Examples: % all_sessions = flywheel_matlab_helpers.iter_all(fw.sessions.iter()); % all_projects = flywheel_matlab_helpers.iter_all(fw.projects.iter()); items = cell(py.list(iterator)); end function page = paginated_find(container, filter, page_num, page_size) % PAGINATED_FIND Manual pagination for large result sets % More memory-efficient than iter_all for large datasets % % Syntax: % page = paginated_find(container, filter, page_num, page_size) % % Inputs: % container - Flywheel container (e.g., fw.sessions, fw.projects) % filter - Filter string (optional, can be empty) % page_num - Page number (1-indexed, default: 1) % page_size - Items per page (default: 100) % % Examples: % page1 = flywheel_matlab_helpers.paginated_find(... % fw.sessions, 'project.label=~MRI', 1, 100); % page2 = flywheel_matlab_helpers.paginated_find(... % fw.sessions, 'project.label=~MRI', 2, 100); % all_page1 = flywheel_matlab_helpers.paginated_find(... % fw.projects, '', 1, 50); if nargin < 4 page_size = 100; end if nargin < 3 page_num = 1; end offset = (page_num - 1) * page_size; if nargin < 2 || isempty(filter) results = container.find(pyargs(... 'limit', int32(page_size), ... 'skip', int32(offset))); else results = container.find(filter, pyargs(... 'limit', int32(page_size), ... 'skip', int32(offset))); end page = cell(py.list(results)); end function all_items = find_all_paginated(container, filter, page_size) % FIND_ALL_PAGINATED Fetch all items using automatic pagination % Keeps memory usage lower than iter_all by processing in chunks % % Syntax: % all_items = find_all_paginated(container, filter, page_size) % % Inputs: % container - Flywheel container (e.g., fw.sessions) % filter - Filter string (optional) % page_size - Items per page (default: 100) % % Examples: % sessions = flywheel_matlab_helpers.find_all_paginated(... % fw.sessions, 'project.label=~MRI', 50); if nargin < 3 page_size = 100; end all_items = {}; page_num = 1; while true page = flywheel_matlab_helpers.paginated_find(... container, filter, page_num, page_size); if isempty(page) break; end all_items = [all_items; page]; %#ok if length(page) < page_size % Last page break; end page_num = page_num + 1; end end function result = try_get_property(py_obj, property_name, default_value) % TRY_GET_PROPERTY Safely access Python object property % Returns default value if property does not exist or is None % % Syntax: % result = try_get_property(py_obj, property_name, default_value) % % Examples: % age = flywheel_matlab_helpers.try_get_property(session, 'age', 0); % desc = flywheel_matlab_helpers.try_get_property(proj, 'description', ''); if nargin < 3 default_value = []; end try prop_value = py_obj.(property_name); if isempty(prop_value) || isa(prop_value, 'py.NoneType') result = default_value; else result = prop_value; end catch result = default_value; end end function setup_check() % SETUP_CHECK Verify MATLAB-Python-Flywheel setup % Prints diagnostic information about the environment % % Examples: % flywheel_matlab_helpers.setup_check(); fprintf('=== MATLAB-Python-Flywheel Setup Check ===\n\n'); % Check Python configuration pe = pyenv; fprintf('Python Version: %s\n', string(pe.Version)); fprintf('Python Executable: %s\n', string(pe.Executable)); fprintf('Python Status: %s\n\n', string(pe.Status)); % Try importing flywheel try fw_module = py.importlib.import_module('flywheel'); % Get version using importlib.metadata (Python 3.8+) metadata_module = py.importlib.import_module('importlib.metadata'); sdk_version = string(metadata_module.version('flywheel-sdk')); fprintf('flywheel-sdk installed: version %s\n', version); catch ME fprintf('flywheel-sdk not found\n'); fprintf(' Error: %s\n', ME.message); fprintf(' Install with: pip install flywheel-sdk\n\n'); return; end % Check if client can be created try fw = fw_module.Client(); fprintf('Flywheel client created successfully\n'); % Try getting user info try user = fw.get_current_user(); fprintf('Authenticated as: %s %s (%s)\n', ... string(user.firstname), ... string(user.lastname), ... string(user.email)); catch fprintf('Client created but not authenticated\n'); fprintf(' Configure credentials or provide API key\n'); end catch ME fprintf('Failed to create Flywheel client\n'); fprintf(' Error: %s\n', ME.message); end fprintf('\n=== Setup check complete ===\n'); end end end