"""Load and normalize thematic analysis CSV data.""" import os import pandas as pd # Base path: one level up from src/ BASE = os.path.join(os.path.dirname(__file__), "..") KRIUKOWTA_DIR = os.path.join(BASE, "KriukowTA") ZAMBRANOTA_DIR = os.path.join(BASE, "ZambranoTA") BRAUNCLARKETA_DIR = os.path.join(BASE, "BraunClarkeTA") GOOGLEFORM_DIR = os.path.join(BASE, "GoogleForm") # Default encoding for CSV files (handles BOM and special characters) CSV_ENCODING = "utf-8-sig" def load_videota_initial_coding(): """Load KriukowTA Initial Coding data.""" path = os.path.join(KRIUKOWTA_DIR, "VideoTA - InitialCoding.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_videota_focused_coding(): """Load KriukowTA Focused Coding (Axial Coding) data.""" path = os.path.join(KRIUKOWTA_DIR, "VideoTA - FocusedCoding(Axial Coding).csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_videota_mapping_evidence(): """Load KriukowTA Mapping & Evidence data.""" path = os.path.join(KRIUKOWTA_DIR, "VideoTA - Mapping&Evidence.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_videota_moscow(): """Load KriukowTA MoSCoW prioritization data.""" path = os.path.join(KRIUKOWTA_DIR, "VideoTA - MoSCoW.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_zambranota_coded_dataset(): """Load ZambranoTA Coded Dataset.""" path = os.path.join(ZAMBRANOTA_DIR, "ZambranoTA - CodedDataset.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_zambranota_initial_codebook(): """Load ZambranoTA Initial Codebook.""" path = os.path.join(ZAMBRANOTA_DIR, "ZambranoTA - InitialCodeBook.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_zambranota_refined_codebook(): """Load ZambranoTA Refined Codebook.""" path = os.path.join(ZAMBRANOTA_DIR, "ZambranoTA - RefinedCodeBook.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_zambranota_theme_frequency(): """Load ZambranoTA Theme Frequency Distribution.""" path = os.path.join(ZAMBRANOTA_DIR, "ZambranoTA - ThemeFrequencyDistribution.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_zambranota_moscow(): """Load ZambranoTA MoSCoW prioritization data.""" path = os.path.join(ZAMBRANOTA_DIR, "ZambranoTA - MoSCoW.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_zambranota_qualitative_analysis(): """Load ZambranoTA Qualitative Analysis.""" path = os.path.join(ZAMBRANOTA_DIR, "ZambranoTA - QualitativeAnalysis.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_braunclarke_ta(): """Load Braun-Clarke Thematic Analysis.""" path = os.path.join(BRAUNCLARKETA_DIR, "BraunClarkeTA - Braun_Clarke.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_braunclarke_moscow(): """Load Braun-Clarke MoSCoW prioritization data.""" path = os.path.join(BRAUNCLARKETA_DIR, "BraunClarkeTA - Braun_ClarkeMoSCoW.csv") if not os.path.exists(path): return pd.DataFrame() try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return pd.DataFrame() def load_google_form(): """Load Google Form responses CSV. Returns None if file not found (optional data).""" import glob if not os.path.exists(GOOGLEFORM_DIR): return None # Try multiple patterns to be more flexible patterns = [ os.path.join(GOOGLEFORM_DIR, "*Form*Responses*.csv"), os.path.join(GOOGLEFORM_DIR, "*responses*.csv"), os.path.join(GOOGLEFORM_DIR, "*.csv"), ] files = [] for pattern in patterns: files = glob.glob(pattern, recursive=False) if files: break if not files: return None path = files[0] try: df = pd.read_csv(path, encoding=CSV_ENCODING) return df.dropna(how="all") except Exception: return None def participant_count(s): """Parse 'P1, P4, P6' or 'P1/P14' or 'Participant 1, Participant 2' into count.""" if pd.isna(s) or not str(s).strip(): return 0 s = str(s).replace("/", ",").replace(" and ", ",") # Handle both "P1" and "Participant 1" formats parts = [x.strip() for x in s.split(",") if "P" in x or "participant" in x.lower() or x.strip().replace("#", "").isdigit()] # Unique participant IDs seen = set() for p in parts: # Extract numbers n = "".join(c for c in p if c.isdigit()) if n: seen.add(n) return len(seen)