pythonflex 0.2.1__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {pythonflex-0.2.1 → pythonflex-0.2.3}/PKG-INFO +1 -1
  2. {pythonflex-0.2.1 → pythonflex-0.2.3}/pyproject.toml +1 -1
  3. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/utils.py +47 -26
  4. {pythonflex-0.2.1 → pythonflex-0.2.3}/.gitignore +0 -0
  5. {pythonflex-0.2.1 → pythonflex-0.2.3}/.python-version +0 -0
  6. {pythonflex-0.2.1 → pythonflex-0.2.3}/README.md +0 -0
  7. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/__init__.py +0 -0
  8. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/analysis.py +0 -0
  9. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/dataset/liver_cell_lines_500_genes.csv +0 -0
  10. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/dataset/melanoma_cell_lines_500_genes.csv +0 -0
  11. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/dataset/neuroblastoma_cell_lines_500_genes.csv +0 -0
  12. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/gold_standard/CORUM.parquet +0 -0
  13. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/gold_standard/GOBP.parquet +0 -0
  14. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/gold_standard/PATHWAY.parquet +0 -0
  15. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/gold_standard/corum.csv +0 -0
  16. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/gold_standard/gobp.csv +0 -0
  17. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/data/gold_standard/pathway.csv +0 -0
  18. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/examples/basic_usage.py +0 -0
  19. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/examples/dataset_filtering.py +0 -0
  20. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/examples/test.py +0 -0
  21. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/logging_config.py +0 -0
  22. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/plotting.py +0 -0
  23. {pythonflex-0.2.1 → pythonflex-0.2.3}/src/pythonflex/preprocessing.py +0 -0
  24. {pythonflex-0.2.1 → pythonflex-0.2.3}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonflex
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: pythonFLEX is a benchmarking toolkit for evaluating CRISPR screen results against biological gold standards. The toolkit computes gene-level and complex-level performance metrics, helping researchers systematically assess the biological relevance and resolution of their CRISPR screening data.
5
5
  Author-email: Yasir Demirtaş <tyasird@hotmail.com>
6
6
  Requires-Python: >=3.9
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pythonflex"
3
- version = "0.2.1"
3
+ version = "0.2.3"
4
4
  description = "pythonFLEX is a benchmarking toolkit for evaluating CRISPR screen results against biological gold standards. The toolkit computes gene-level and complex-level performance metrics, helping researchers systematically assess the biological relevance and resolution of their CRISPR screening data."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -9,19 +9,7 @@ import pandas as pd
9
9
  TMP_ROOT = ".tmp"
10
10
  VALID_EXTS = {".feather", ".parquet", ".npy", ".pkl"}
11
11
 
12
- # Minimal fix - just patch the problematic save
13
- original_to_feather = pd.DataFrame.to_feather
14
- def safe_to_feather(self, path, **kwargs):
15
- try:
16
- return original_to_feather(self, path, **kwargs)
17
- except ValueError as e:
18
- if "feather does not support serializing" in str(e):
19
- # FIXED: Better path handling
20
- parquet_path = os.path.splitext(path)[0] + '.parquet'
21
- self.to_parquet(parquet_path, **kwargs)
22
- else:
23
- raise
24
- pd.DataFrame.to_feather = safe_to_feather
12
+ # REMOVE THE MONKEY PATCH FROM HERE - it should be in your main script!
25
13
 
26
14
  # Helper to sanitize names (make filesystem-safe)
27
15
  def _sanitize(name):
@@ -40,7 +28,7 @@ def _safe_path(category, name=None, ext=".pkl"):
40
28
  safe_name = _sanitize(name) if name else "data"
41
29
  return os.path.join(dir_path, f"{safe_name}{ext}")
42
30
 
43
- # Save function
31
+ # Save function - with built-in parquet fallback
44
32
  def dsave(data, category, name=None, path=None): # 'path' ignored for compatibility with old code
45
33
  # If data is dict and no name, recurse on each item
46
34
  if name is None and isinstance(data, dict):
@@ -50,14 +38,41 @@ def dsave(data, category, name=None, path=None): # 'path' ignored for compatibi
50
38
 
51
39
  # Choose best extension based on type
52
40
  if isinstance(data, pd.DataFrame):
53
- ext = ".feather"
54
- save_func = lambda p: data.to_feather(p)
41
+ # Try Feather first, fallback to Parquet if it fails
42
+ target_feather = _safe_path(category, name, ".feather")
43
+ target_parquet = _safe_path(category, name, ".parquet")
44
+
45
+ # Try Feather first
46
+ try:
47
+ with tempfile.NamedTemporaryFile(dir=os.path.dirname(target_feather), delete=False, suffix='.feather') as tf:
48
+ tmp_path = tf.name
49
+ tf.close()
50
+ data.to_feather(tmp_path)
51
+ os.replace(tmp_path, target_feather)
52
+ return
53
+ except ValueError as e:
54
+ if "feather does not support serializing" in str(e):
55
+ print(f"Feather failed for {name}, using Parquet instead")
56
+ # Clean up failed feather temp file
57
+ if os.path.exists(tmp_path):
58
+ os.unlink(tmp_path)
59
+
60
+ # Save as Parquet
61
+ with tempfile.NamedTemporaryFile(dir=os.path.dirname(target_parquet), delete=False, suffix='.parquet') as tf:
62
+ tmp_path = tf.name
63
+ tf.close()
64
+ data.to_parquet(tmp_path)
65
+ os.replace(tmp_path, target_parquet)
66
+ return
67
+ else:
68
+ raise
69
+
55
70
  elif isinstance(data, np.ndarray):
56
71
  ext = ".npy"
57
72
  save_func = lambda p: np.save(p, data, allow_pickle=False)
58
73
  else:
59
74
  ext = ".pkl"
60
- save_func = lambda p: joblib.dump(data, p, compress=0) # Add compress=3 if needed
75
+ save_func = lambda p: joblib.dump(data, p, compress=0)
61
76
 
62
77
  target = _safe_path(category, name, ext)
63
78
 
@@ -68,7 +83,7 @@ def dsave(data, category, name=None, path=None): # 'path' ignored for compatibi
68
83
  save_func(tmp_path)
69
84
  os.replace(tmp_path, target) # Atomic move
70
85
 
71
- # Load function - FIXED: Added parquet support
86
+ # Load function - with parquet support and better error handling
72
87
  def dload(category, name=None, path=None): # 'path' ignored for compatibility
73
88
  dir_path = os.path.join(TMP_ROOT, _sanitize(category))
74
89
 
@@ -86,7 +101,7 @@ def dload(category, name=None, path=None): # 'path' ignored for compatibility
86
101
  try:
87
102
  if filename.endswith(".feather"):
88
103
  out[k] = pd.read_feather(full_path)
89
- elif filename.endswith(".parquet"): # ADDED
104
+ elif filename.endswith(".parquet"):
90
105
  out[k] = pd.read_parquet(full_path)
91
106
  elif filename.endswith(".npy"):
92
107
  out[k] = np.load(full_path, mmap_mode="r") # MMap for perf
@@ -97,21 +112,27 @@ def dload(category, name=None, path=None): # 'path' ignored for compatibility
97
112
  os.remove(full_path) # Delete corrupted file
98
113
  return out
99
114
 
100
- # Load specific name (try extensions in order)
101
- for ext in VALID_EXTS:
115
+ # Load specific name (try extensions in order - prefer parquet for reliability)
116
+ preferred_order = [".parquet", ".feather", ".npy", ".pkl"]
117
+
118
+ for ext in preferred_order:
119
+ if ext not in VALID_EXTS:
120
+ continue
102
121
  target = _safe_path(category, name, ext)
103
122
  if os.path.exists(target):
104
123
  try:
105
124
  if ext == ".feather":
106
125
  return pd.read_feather(target)
107
- elif ext == ".parquet": # ADDED
126
+ elif ext == ".parquet":
108
127
  return pd.read_parquet(target)
109
128
  elif ext == ".npy":
110
129
  return np.load(target, mmap_mode="r") # MMap for perf
111
130
  elif ext == ".pkl":
112
131
  return joblib.load(target, mmap_mode="r") # MMap for perf
113
- except (EOFError, ValueError, OSError):
114
- print(f"Warning: '{target}' is corrupted. Deleting and returning {{}}...")
115
- os.remove(target)
116
- return {}
132
+ except (EOFError, ValueError, OSError) as e:
133
+ print(f"Warning: '{target}' is corrupted ({e}). Trying next format...")
134
+ os.remove(target) # Delete corrupted file
135
+ continue # Try next format instead of returning {}
136
+
137
+ print(f"Warning: No valid file found for {category}/{name}")
117
138
  return {}
File without changes
File without changes
File without changes
File without changes