Coverage for ibllib/pipes/scan_fix_passive_files.py: 97%
63 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-17 15:25 +0000
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-17 15:25 +0000
1#!/usr/bin/env python
2# -*- coding:utf-8 -*-
3# @Author: Niccolò Bonacchi
4# @Date: Thursday, September 24th 2020, 2:10:29 pm
5import json
6import logging
7import shutil
8from pathlib import Path, PureWindowsPath
10from one.alf.path import get_session_path
12log = logging.getLogger("ibllib")
15def load_settings_file(filepath, key=None):
16 filepath = Path(filepath) 1cba
17 if filepath.stat().st_size == 0: 1cba
18 return 1cba
20 with open(filepath, "r") as f: 1cba
21 settings = json.load(f) 1cba
22 return settings.get(key, None) if key else settings 1cba
25def find_pairs(root_data_folder):
26 """Find all passive sessions that needs transfer and where to"""
27 root_data_folder = Path(root_data_folder) 1cba
28 settings_files = list(root_data_folder.rglob("_iblrig_taskSettings.raw.json")) 1cba
29 n_settings_files = len(settings_files) 1cba
30 if n_settings_files == 0: 1cba
31 log.warning(f"Found {n_settings_files} sessions")
32 else:
33 log.info(f"Found {n_settings_files} sessions") 1cba
35 # Load the corresponding ephys session path form settings file if exists
36 pairs = [] 1cba
37 for sf in settings_files: 1cba
38 # Get session path form settings file
39 source_spath = get_session_path(sf) 1cba
40 if source_spath is None: 1cba
41 continue
42 # Find the root_data_path for session
43 subjects_folder_path = Path(*Path(source_spath).parts[:-3]) 1cba
44 # Load reference to corresponding ephys session (ces) which comes in windows format
45 ces = load_settings_file(sf, key="CORRESPONDING_EPHYS_SESSION") 1cba
46 # if CORRESPONDING_EPHYS_SESSION does not exist, it's not a passive session
47 if ces is None: 1cba
48 continue 1cba
49 # Convert windows path to corresponding session name (csn) in native Path format
50 csn = Path(*PureWindowsPath(ces).parts[-3:]) 1cba
51 target_spath = subjects_folder_path / csn 1cba
53 pairs.append((source_spath, target_spath)) 1cba
54 # Remove sessions that are already transferred i.e. source and destination files are equal
55 from_to_pairs = [(x, y) for x, y in pairs if x != y] 1cba
56 n_pairs = len(from_to_pairs) 1cba
57 if n_pairs == 0: 1cba
58 log.warning(f"Found {n_pairs} passive sessions to move") 1a
59 else:
60 log.info(f"Found {n_pairs} passive sessions to move") 1cba
62 return from_to_pairs 1cba
65def move_rename_pairs(from_to_pairs):
66 """"""
67 moved_ok = [] 1ba
68 for i, (src, dst) in enumerate(from_to_pairs): 1ba
69 src = Path(src) 1ba
70 dst = Path(dst) 1ba
71 log.info(f"Moving {i + 1} of {len(from_to_pairs)}: \n{src}\n--> {dst}") 1ba
72 try: 1ba
73 shutil.move(str(src / "raw_behavior_data"), str(dst / "raw_passive_data")) 1ba
74 ffile = src.joinpath("passive_data_for_ephys.flag") 1ba
75 if ffile.exists(): 1ba
76 ffile.unlink() 1ba
77 ffile.parent.rmdir() 1ba
78 moved_ok.append(True) 1ba
79 except BaseException as e: 1b
80 log.error(f"Failed to move {src} to {dst}:\n {e}") 1b
81 moved_ok.append(False) 1b
82 continue 1b
83 log.info(f"Moved {sum(moved_ok)} of {len(from_to_pairs)}") 1ba
84 return moved_ok 1ba
87def execute(root_data_folder, dry=True):
88 from_to_pairs = find_pairs(root_data_folder) 1a
89 if dry: 1a
90 return from_to_pairs, [False] * len(from_to_pairs) 1a
91 moved_ok = move_rename_pairs(from_to_pairs) 1a
92 return from_to_pairs, moved_ok 1a