Source code for driada.utils.naming

[docs] def parse_iabs_filename(filename): """Parse an IABS-style filename to extract experiment metadata. Uses simple 3-part underscore convention: {track}_{animal_id}_{session}[_suffix...] Parameters ---------- filename : str Filename (with or without path) to parse. Returns ------- dict or None Dictionary with keys 'track', 'animal_id', 'session', 'suffix' if successful, None if parsing failed (less than 3 underscore-separated parts). Examples -------- >>> parse_iabs_filename('NOF_H01_1D syn data.npz') {'track': 'NOF', 'animal_id': 'H01', 'session': '1D', 'suffix': 'syn data'} >>> parse_iabs_filename('LNOF_J01_4D_aligned.npz') {'track': 'LNOF', 'animal_id': 'J01', 'session': '4D', 'suffix': 'aligned'} >>> parse_iabs_filename('invalid.npz') None """ from pathlib import Path # Get just the filename without path and extension name = Path(filename).stem # Split by underscore, require at least 3 parts: track_animal_session parts = name.split('_') if len(parts) < 3: return None track = parts[0].upper() animal_id = parts[1].upper() # Session may contain space-separated suffix (e.g., "1D syn data") session_and_suffix = parts[2] if ' ' in session_and_suffix: session, space_suffix = session_and_suffix.split(' ', 1) # Combine with any underscore-separated suffix parts if len(parts) > 3: suffix = space_suffix + '_' + '_'.join(parts[3:]) else: suffix = space_suffix else: session = session_and_suffix suffix = '_'.join(parts[3:]) if len(parts) > 3 else None return { 'track': track, 'animal_id': animal_id, 'session': session.upper(), 'suffix': suffix if suffix else None, }
[docs] def construct_session_name(data_source, exp_params, allow_unknown=True): """Construct standardized session name from experimental parameters. Creates a consistent naming convention for experimental sessions based on the data source and experimental parameters. Supports IABS (Institute for Advanced Brain Studies) and generic lab data sources. Parameters ---------- data_source : str The data source identifier (e.g., 'IABS', 'MyLab', 'NeuroLab'). exp_params : dict Dictionary containing experimental parameters. For IABS, must include keys 'track', 'animal_id', 'session'. For other sources, can include 'name' (takes priority), 'experiment', 'subject' or 'animal_id', 'session', 'date'. allow_unknown : bool, optional Whether to allow unknown track names (IABS only). If False, raises ValueError for unrecognized tracks. Default is True. Returns ------- str Standardized session name following the pattern appropriate for the data source and parameters provided. Raises ------ ValueError If allow_unknown is False and an unknown track is encountered (IABS only). Examples -------- >>> # IABS standard track >>> params = {'track': 'STFP', 'animal_id': 'M123', 'session': '1'} >>> construct_session_name('IABS', params) 'STFP_M123_1' >>> # IABS old track with special naming >>> params = {'track': 'HT', 'animal_id': 'A5', 'session': '3'} >>> construct_session_name('IABS', params) 'A5_HT3' >>> # Generic lab with explicit name >>> construct_session_name('MyLab', {'name': 'pilot_study_001'}) 'pilot_study_001' >>> # Generic lab with standard parameters >>> params = {'experiment': 'maze', 'subject': 'rat42', 'session': 'day3'} >>> construct_session_name('NeuroLab', params) 'maze_rat42_day3' >>> # Generic lab with minimal parameters >>> construct_session_name('Lab1', {'subject': 'mouse5'}) 'mouse5' >>> # Generic lab with no standard parameters (uses timestamp) >>> result = construct_session_name('GenericLab', {}) >>> result.startswith('GenericLab_') and len(result) == 26 # LabName_YYYYMMDD_HHMMSS True Notes ----- For IABS data source: - Old tracks (HT, RT, FS): Use legacy naming patterns - Standard tracks (FcOY, STFP, AP, NOF, Trace, CC): Use {track}_{animal}_{session} - Unknown tracks: Use standard pattern if allow_unknown=True For other data sources: - If 'name' parameter exists, it's used directly - Otherwise combines available standard parameters in order: experiment, subject/animal_id, session, date - If no standard parameters exist, uses data_source name + timestamp""" if data_source == "IABS": track = exp_params["track"] animal_id, session = exp_params["animal_id"], exp_params["session"] # Old tracks with non-standard naming patterns old_track_patterns = { "HT": f"{animal_id}_HT{session}", "RT": f"RT_{animal_id}_{session}D", "FS": f"FS{animal_id}_{session}D", } # Check if it's an old track with special pattern if track in old_track_patterns: return old_track_patterns[track] # For newer tracks, use standard pattern: {track}_{animal_id}_{session} standard_tracks = {"FcOY", "STFP", "AP", "NOF", "Trace", "CC"} if track in standard_tracks: return f"{track}_{animal_id}_{session}" # Unknown track handling if not allow_unknown: raise ValueError(f"Unknown track: {track}!") else: return f"{track}_{animal_id}_{session}" else: # Generic naming for non-IABS data sources # First check if user provided explicit name if "name" in exp_params: return exp_params["name"] # Build name from common parameter patterns name_parts = [] # Try common parameter names in order of preference for key in ["experiment", "subject", "animal_id", "session", "date"]: if key in exp_params: name_parts.append(str(exp_params[key])) if name_parts: # Join with underscore, limiting length for practicality return "_".join(name_parts[:4]) # Max 4 parts to avoid overly long names else: # Fallback: use data source with timestamp import datetime timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") return f"{data_source}_{timestamp}"