Spaces:
Runtime error
Runtime error
| """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) | |