MEDS-DEV 0.0.2__tar.gz → 0.0.4__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 (94) hide show
  1. {meds_dev-0.0.2 → meds_dev-0.0.4}/PKG-INFO +1 -1
  2. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/configs/_build_dataset.yaml +1 -1
  3. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/configs/_extract_task.yaml +5 -2
  4. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/__main__.py +4 -15
  5. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/__main__.py +7 -26
  6. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/__main__.py +7 -3
  7. meds_dev-0.0.4/src/MEDS_DEV/utils.py +131 -0
  8. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV.egg-info/PKG-INFO +1 -1
  9. {meds_dev-0.0.2 → meds_dev-0.0.4}/tests/test_datasets.py +14 -2
  10. meds_dev-0.0.2/src/MEDS_DEV/utils.py +0 -61
  11. {meds_dev-0.0.2 → meds_dev-0.0.4}/.github/ISSUE_TEMPLATE/add-a-dataset.md +0 -0
  12. {meds_dev-0.0.2 → meds_dev-0.0.4}/.github/ISSUE_TEMPLATE/add-a-model.md +0 -0
  13. {meds_dev-0.0.2 → meds_dev-0.0.4}/.github/ISSUE_TEMPLATE/add-a-task.md +0 -0
  14. {meds_dev-0.0.2 → meds_dev-0.0.4}/.github/workflows/code-quality-main.yaml +0 -0
  15. {meds_dev-0.0.2 → meds_dev-0.0.4}/.github/workflows/code-quality-pr.yaml +0 -0
  16. {meds_dev-0.0.2 → meds_dev-0.0.4}/.github/workflows/python-build.yaml +0 -0
  17. {meds_dev-0.0.2 → meds_dev-0.0.4}/.github/workflows/tests.yaml +0 -0
  18. {meds_dev-0.0.2 → meds_dev-0.0.4}/.gitignore +0 -0
  19. {meds_dev-0.0.2 → meds_dev-0.0.4}/.pre-commit-config.yaml +0 -0
  20. {meds_dev-0.0.2 → meds_dev-0.0.4}/LICENSE +0 -0
  21. {meds_dev-0.0.2 → meds_dev-0.0.4}/README.md +0 -0
  22. {meds_dev-0.0.2 → meds_dev-0.0.4}/pyproject.toml +0 -0
  23. {meds_dev-0.0.2 → meds_dev-0.0.4}/setup.cfg +0 -0
  24. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/__init__.py +0 -0
  25. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/configs/__init__.py +0 -0
  26. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/configs/_evaluate_predictions.yaml +0 -0
  27. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/configs/_run_model.yaml +0 -0
  28. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/AUMCdb/README.md +0 -0
  29. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/AUMCdb/predicates.yaml +0 -0
  30. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/MIMIC-IV/README.md +0 -0
  31. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/MIMIC-IV/__init__.py +0 -0
  32. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/MIMIC-IV/dataset.yaml +0 -0
  33. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/MIMIC-IV/predicates.yaml +0 -0
  34. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/MIMIC-IV/requirements.txt +0 -0
  35. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/OMOP/README.md +0 -0
  36. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/OMOP/predicates.yaml +0 -0
  37. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/README.md +0 -0
  38. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/UCLA/README.md +0 -0
  39. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/UCLA/predicates.yaml +0 -0
  40. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/datasets/__init__.py +0 -0
  41. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/evaluation/README.md +0 -0
  42. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/evaluation/__init__.py +0 -0
  43. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/evaluation/__main__.py +0 -0
  44. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/__init__.py +0 -0
  45. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/meds_tab/README.md +0 -0
  46. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/meds_tab/tiny/README.md +0 -0
  47. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/meds_tab/tiny/__init__.py +0 -0
  48. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/meds_tab/tiny/model.yaml +0 -0
  49. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/meds_tab/tiny/requirements.txt +0 -0
  50. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/random_predictor/README.md +0 -0
  51. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/random_predictor/__init__.py +0 -0
  52. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/random_predictor/_config.yaml +0 -0
  53. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/random_predictor/generate_random_predictions.py +0 -0
  54. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/models/random_predictor/model.yaml +0 -0
  55. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/README.md +0 -0
  56. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/__init__.py +0 -0
  57. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/README.md +0 -0
  58. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/blood_chemistry/elevated_creatinine/first_24h.yaml +0 -0
  59. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/blood_chemistry/hyponatremia/first_24h.yaml +0 -0
  60. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/blood_chemistry/metabolic_acidosis/first_24h.yaml +0 -0
  61. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/cbc/anemia/first_24h.yaml +0 -0
  62. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/cbc/leukocytosis/first_24h.yaml +0 -0
  63. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/cbc/thrombocytopenia/first_24h.yaml +0 -0
  64. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/reduced_echo_derived_LVEF_via_ECG.yaml +0 -0
  65. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/abnormal_lab/vital/hypotension/first_24h.yaml +0 -0
  66. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/disease_progression/README.md +0 -0
  67. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/disease_progression/diabetes/README.md +0 -0
  68. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/disease_progression/diabetes/ckd_post_kidney_labs.yaml +0 -0
  69. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/mortality/README.md +0 -0
  70. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/mortality/in_icu/README.md +0 -0
  71. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/mortality/in_icu/first_24h.yaml +0 -0
  72. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/phenotyping/README.md +0 -0
  73. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/phenotyping/outpatient/MI/1y-5y.yaml +0 -0
  74. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/phenotyping/outpatient/MI/README.md +0 -0
  75. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/phenotyping/outpatient/README.md +0 -0
  76. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/readmission/README.md +0 -0
  77. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/readmission/general_hospital/30d.yaml +0 -0
  78. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV/tasks/readmission/general_hospital/README.md +0 -0
  79. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV.egg-info/SOURCES.txt +0 -0
  80. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV.egg-info/dependency_links.txt +0 -0
  81. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV.egg-info/entry_points.txt +0 -0
  82. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV.egg-info/requires.txt +0 -0
  83. {meds_dev-0.0.2 → meds_dev-0.0.4}/src/MEDS_DEV.egg-info/top_level.txt +0 -0
  84. {meds_dev-0.0.2 → meds_dev-0.0.4}/templates/README.md +0 -0
  85. {meds_dev-0.0.2 → meds_dev-0.0.4}/templates/dataset.md +0 -0
  86. {meds_dev-0.0.2 → meds_dev-0.0.4}/templates/model.md +0 -0
  87. {meds_dev-0.0.2 → meds_dev-0.0.4}/templates/results.md +0 -0
  88. {meds_dev-0.0.2 → meds_dev-0.0.4}/templates/task.md +0 -0
  89. {meds_dev-0.0.2 → meds_dev-0.0.4}/tests/__init__.py +0 -0
  90. {meds_dev-0.0.2 → meds_dev-0.0.4}/tests/conftest.py +0 -0
  91. {meds_dev-0.0.2 → meds_dev-0.0.4}/tests/test_evaluation.py +0 -0
  92. {meds_dev-0.0.2 → meds_dev-0.0.4}/tests/test_models.py +0 -0
  93. {meds_dev-0.0.2 → meds_dev-0.0.4}/tests/test_tasks.py +0 -0
  94. {meds_dev-0.0.2 → meds_dev-0.0.4}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: MEDS_DEV
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Summary: Task configuration and helper files for the MEDS-DEV Benchmark
5
5
  Author: Nassim Oufattole
6
6
  Author-email: "Matthew B. A. McDermott" <matthew_mcdermott@hms.harvard.edu>, Ethan Steinberg <ethanid@stanford.edu>, Shalmali Joshi <shalmali.joshi@columbia.edu>, "Teya S. Bergamaschi" <teya@mit.edu>, Aleksia Kolo <aleksiak@mit.edu>, Young Sang Choi <young.sang.choi@columbia.edu>, Chao Pang <cp3016@cumc.columbia.edu>, Kamilė Stankevičiūtė <kamile.stankeviciute@cst.cam.ac.uk>, Vincent Jeanselme <vincent.jeanselme@mrc-bsu.cam.ac.uk>, Justin Xu <justin.xu@ndm.ox.ac.uk>
@@ -9,7 +9,7 @@ do_overwrite: False
9
9
 
10
10
  hydra:
11
11
  job:
12
- name: "meds_dev_build_{dataset}_${now:%Y-%m-%d_%H-%M-%S}"
12
+ name: "meds_dev_build_dataset_${now:%Y-%m-%d_%H-%M-%S}"
13
13
  run:
14
14
  dir: "${output_dir}/.logs"
15
15
  help:
@@ -3,13 +3,14 @@ defaults:
3
3
 
4
4
  dataset: ???
5
5
  dataset_dir: ???
6
+ dataset_predicates_path: null
6
7
  task: ???
7
8
  output_dir: ???
8
9
  do_overwrite: False
9
10
 
10
11
  hydra:
11
12
  job:
12
- name: "meds_dev_extract_{task}_for_{dataset}_${now:%Y-%m-%d_%H-%M-%S}"
13
+ name: "meds_dev_extract_task_${now:%Y-%m-%d_%H-%M-%S}"
13
14
  run:
14
15
  dir: "${output_dir}/.logs"
15
16
  help:
@@ -22,4 +23,6 @@ hydra:
22
23
 
23
24
  You can specify "dataset" to give the name of the dataset you want to build and "dataset_dir" to point
24
25
  to the extracted dataset on disk, "output_dir" to say where the final, labeled task cohort
25
- should be stored on disk, and "task" to dictate which task should be extracted.
26
+ should be stored on disk, and "task" to dictate which task should be extracted. If you overwrite
27
+ "dataset_predicates_path", then it will look at that location for the predicates file, rather than in
28
+ the MEDS-DEV repository location. This is useful for local datasets.
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
  import shutil
3
- import subprocess
4
3
  from pathlib import Path
5
4
 
6
5
  logger = logging.getLogger(__name__)
@@ -8,7 +7,7 @@ logger = logging.getLogger(__name__)
8
7
  import hydra
9
8
  from omegaconf import DictConfig
10
9
 
11
- from ..utils import temp_env
10
+ from ..utils import run_in_env, temp_env
12
11
  from . import CFG_YAML, DATASETS
13
12
 
14
13
 
@@ -28,7 +27,7 @@ def main(cfg: DictConfig):
28
27
  output_dir.mkdir(parents=True, exist_ok=False)
29
28
 
30
29
  done_fp = output_dir / ".done"
31
- if done_fp.exists(): # pragma: no cover
30
+ if done_fp.is_file(): # pragma: no cover
32
31
  logger.info(f"Output directory {output_dir} already exists and is marked as done.")
33
32
  return
34
33
 
@@ -37,16 +36,6 @@ def main(cfg: DictConfig):
37
36
  with temp_env(cfg, requirements) as (build_temp_dir, env):
38
37
  build_cmd = build_cmd.format(output_dir=cfg.output_dir, temp_dir=str(build_temp_dir.resolve()))
39
38
 
40
- logger.info(f"Running build command: {build_cmd}")
41
- build_command_out = subprocess.run(
42
- build_cmd, shell=True, env=env, cwd=build_temp_dir, capture_output=True
43
- )
44
-
45
- command_errored = build_command_out.returncode != 0
46
- if command_errored:
47
- raise RuntimeError(
48
- f"Build {cfg.dataset} command {build_cmd} failed with exit code "
49
- f"{build_command_out.returncode}:\n{build_command_out.stderr.decode()}"
50
- )
39
+ logger.info(f"Considering running build command: {build_cmd}")
40
+ run_in_env(build_cmd, env, cfg.output_dir, cfg.get("do_overwrite", False), cwd=build_temp_dir)
51
41
  logger.info(f"Build {cfg.dataset} command {build_cmd} completed successfully.")
52
- done_fp.touch()
@@ -1,7 +1,6 @@
1
1
  import itertools
2
2
  import logging
3
3
  import shutil
4
- import subprocess
5
4
  from collections.abc import Generator
6
5
  from pathlib import Path
7
6
 
@@ -14,7 +13,7 @@ from enum import StrEnum, auto
14
13
  import hydra
15
14
  from omegaconf import DictConfig
16
15
 
17
- from ..utils import temp_env
16
+ from ..utils import run_in_env, temp_env
18
17
  from . import CFG_YAML, MODELS
19
18
 
20
19
 
@@ -179,28 +178,10 @@ def main(cfg: DictConfig):
179
178
 
180
179
  with temp_env(cfg, requirements) as (temp_dir, env):
181
180
  for cmd, out_dir in model_commands(cfg, commands, model_dir):
182
- done_file = out_dir / ".done"
183
- if done_file.exists():
184
- logger.info(f"Skipping {cmd} because {done_file} exists.")
185
- continue
186
-
187
- logger.info(f"Running model command: {cmd}")
188
- command_out = subprocess.run(cmd, shell=True, env=env, cwd=temp_dir, capture_output=True)
189
-
190
- command_errored = command_out.returncode != 0
191
- if command_errored:
192
- raise RuntimeError(
193
- f"{cfg.model} command {cmd} failed with exit code "
194
- f"{command_out.returncode}:\n"
195
- f"STDERR:\n{command_out.stderr.decode()}\n"
196
- f"STDOUT:\n{command_out.stdout.decode()}"
197
- )
198
- elif not out_dir.is_dir():
199
- raise RuntimeError(
200
- f"{cfg.model} command {cmd} failed to create output directory {out_dir}.\n"
201
- f"STDERR:\n{command_out.stderr.decode()}\n"
202
- f"STDOUT:\n{command_out.stdout.decode()}"
203
- )
204
- else:
205
- done_file.touch()
181
+ logger.info(f"Considering running model command: {cmd}")
182
+ try:
183
+ run_in_env(cmd, env, out_dir, cfg.get("do_overwrite", False))
184
+ except Exception as e:
185
+ raise ValueError(f"Failed to run {cfg.model} command {cmd}") from e
186
+
206
187
  logger.info(f"Model {cfg.model} finished successfully.")
@@ -16,11 +16,15 @@ logger = logging.getLogger(__name__)
16
16
  def main(cfg: DictConfig):
17
17
  if cfg.task not in TASKS:
18
18
  raise ValueError(f"Task {cfg.task} not currently configured")
19
- if cfg.dataset not in DATASETS:
20
- raise ValueError(f"Dataset {cfg.dataset} not currently configured")
21
19
 
22
20
  task_config_path = TASKS[cfg.task]["criteria_fp"]
23
- dataset_predicates_path = DATASETS[cfg.dataset]["predicates"]
21
+ if cfg.get("dataset_predicates_path", None):
22
+ logger.info(f"Using provided (local) predicates path: {cfg.dataset_predicates_path}")
23
+ dataset_predicates_path = Path(cfg.dataset_predicates_path)
24
+ else:
25
+ if cfg.dataset not in DATASETS:
26
+ raise ValueError(f"Dataset {cfg.dataset} not currently configured")
27
+ dataset_predicates_path = DATASETS[cfg.dataset]["predicates"]
24
28
 
25
29
  if dataset_predicates_path is None:
26
30
  raise ValueError(f"Predicates not found for dataset {cfg.dataset}")
@@ -0,0 +1,131 @@
1
+ import contextlib
2
+ import logging
3
+ import os
4
+ import shutil
5
+ import subprocess
6
+ import sys
7
+ import tempfile
8
+ from pathlib import Path
9
+
10
+ from omegaconf import DictConfig
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def get_venv_bin_path(venv_path: str | Path) -> Path:
16
+ """Get the bin/Scripts directory of the virtual environment."""
17
+ if os.name == "nt": # Windows
18
+ return Path(venv_path) / "Scripts"
19
+ else: # Unix-like systems
20
+ return Path(venv_path) / "bin"
21
+
22
+
23
+ @contextlib.contextmanager
24
+ def tempdir_ctx(cfg: DictConfig) -> Path:
25
+ temp_dir = cfg.get("temp_dir", None)
26
+ if temp_dir is None:
27
+ with tempfile.TemporaryDirectory() as temp_dir:
28
+ yield Path(temp_dir)
29
+ else:
30
+ temp_dir = Path(temp_dir)
31
+ temp_dir.mkdir(exist_ok=True, parents=True)
32
+ yield temp_dir
33
+
34
+
35
+ def install_venv(venv_path: Path, requirements: str | Path) -> Path:
36
+ logger.info(f"Installing requirements from {requirements} into virtual environment.")
37
+ subprocess.run([sys.executable, "-m", "venv", str(venv_path)], check=True)
38
+
39
+ venv_bin_path = get_venv_bin_path(venv_path)
40
+ venv_python = venv_bin_path / "python"
41
+ if not venv_python.exists():
42
+ raise RuntimeError(f"Virtual environment python {venv_python} does not exist!")
43
+
44
+ subprocess.run(
45
+ [str(venv_python), "-m", "pip", "install", "-r", str(requirements)],
46
+ check=True,
47
+ )
48
+
49
+ logger.info(f"Installed requirements from {requirements} into virtual environment.")
50
+ return venv_bin_path
51
+
52
+
53
+ @contextlib.contextmanager
54
+ def temp_env(cfg: DictConfig, requirements: str | Path | None) -> tuple[Path, dict]:
55
+ with tempdir_ctx(cfg) as build_temp_dir:
56
+ env = os.environ.copy()
57
+ if requirements is not None:
58
+ venv_path = build_temp_dir / ".venv"
59
+ venv_bin_path = install_venv(venv_path, requirements)
60
+ env["VIRTUAL_ENV"] = str(venv_path.resolve())
61
+ env["PATH"] = f"{str(venv_bin_path.resolve())}{os.pathsep}{env['PATH']}"
62
+
63
+ yield build_temp_dir, env
64
+
65
+
66
+ def run_in_env(
67
+ cmd: str,
68
+ env: dict[str, str],
69
+ output_dir: Path | str,
70
+ do_overwrite: bool = False,
71
+ cwd: Path | str | None = None,
72
+ ) -> subprocess.CompletedProcess:
73
+ if type(output_dir) is str:
74
+ output_dir = Path(output_dir)
75
+
76
+ if do_overwrite and output_dir.exists():
77
+ logger.info(f"Removing existing output directory: {output_dir}")
78
+ shutil.rmtree(output_dir)
79
+
80
+ output_dir.mkdir(parents=True, exist_ok=True)
81
+
82
+ done_file = output_dir / ".done"
83
+ if done_file.is_file():
84
+ logger.info(f"Skipping {cmd} because {done_file} exists.")
85
+ return
86
+
87
+ script_file = output_dir / "cmd.sh"
88
+ script_lines = ["#!/bin/bash"]
89
+
90
+ if env.get("VIRTUAL_ENV", None) is not None:
91
+ script_lines.append(f"source {env['VIRTUAL_ENV']}/bin/activate")
92
+
93
+ script_lines.append(cmd)
94
+ script = "\n".join(script_lines)
95
+
96
+ if script_file.is_file():
97
+ if script_file.read_text() != script:
98
+ raise RuntimeError(
99
+ f"Script file {script_file} already exists and is different from the current script. "
100
+ f"Existing file:\n{script_file.read_text()}\n"
101
+ f"New script:\n{script}"
102
+ "Consider running with do_overwrite=True."
103
+ )
104
+ else:
105
+ logger.info(f"(Matching) script file already exists: {script_file}")
106
+ else:
107
+ script_file.write_text(script)
108
+
109
+ script_file.chmod(0o755)
110
+
111
+ logger.info(f"Running command in {script_file}:\n{script}")
112
+
113
+ runner_kwargs = {"shell": False, "env": env, "capture_output": True}
114
+ if cwd is not None:
115
+ runner_kwargs["cwd"] = cwd
116
+
117
+ command_out = subprocess.run(["bash", str(script_file.resolve())], **runner_kwargs)
118
+
119
+ command_errored = command_out.returncode != 0
120
+ if command_errored:
121
+ raise RuntimeError(
122
+ f"Command failed with exit code "
123
+ f"{command_out.returncode}:\n"
124
+ f"SCRIPT:\n{script}\n"
125
+ f"STDERR:\n{command_out.stderr.decode()}\n"
126
+ f"STDOUT:\n{command_out.stdout.decode()}"
127
+ )
128
+ else:
129
+ done_file.touch()
130
+
131
+ return command_out
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: MEDS_DEV
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Summary: Task configuration and helper files for the MEDS-DEV Benchmark
5
5
  Author: Nassim Oufattole
6
6
  Author-email: "Matthew B. A. McDermott" <matthew_mcdermott@hms.harvard.edu>, Ethan Steinberg <ethanid@stanford.edu>, Shalmali Joshi <shalmali.joshi@columbia.edu>, "Teya S. Bergamaschi" <teya@mit.edu>, Aleksia Kolo <aleksiak@mit.edu>, Young Sang Choi <young.sang.choi@columbia.edu>, Chao Pang <cp3016@cumc.columbia.edu>, Kamilė Stankevičiūtė <kamile.stankeviciute@cst.cam.ac.uk>, Vincent Jeanselme <vincent.jeanselme@mrc-bsu.cam.ac.uk>, Justin Xu <justin.xu@ndm.ox.ac.uk>
@@ -27,5 +27,17 @@ def test_datasets_configured(demo_dataset):
27
27
  assert demo_dataset_dir.exists(), f"Output directory not found for {dataset_name}"
28
28
  data_subdir = demo_dataset_dir / "data"
29
29
  metadata_subdir = demo_dataset_dir / "metadata"
30
- assert data_subdir.exists(), f"Data directory not found for {dataset_name}"
31
- assert metadata_subdir.exists(), f"Metadata directory not found for {dataset_name}"
30
+
31
+ if not data_subdir.is_dir() or not metadata_subdir.is_dir():
32
+ err_str = [
33
+ f"Either data/ or metadata/ is not a directory for {dataset_name}.",
34
+ f"Demo dataset directory: {demo_dataset_dir}",
35
+ "Directory contents:",
36
+ ]
37
+ for f in demo_dataset_dir.rglob("*"):
38
+ err_str.append(f" - {f}")
39
+ if f.suffix == ".log":
40
+ err_str.append(" Log contents:")
41
+ err_str.append(f" {f.read_text()}")
42
+
43
+ raise AssertionError("\n".join(err_str))
@@ -1,61 +0,0 @@
1
- import contextlib
2
- import logging
3
- import os
4
- import subprocess
5
- import sys
6
- import tempfile
7
- from pathlib import Path
8
-
9
- from omegaconf import DictConfig
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
-
14
- def get_venv_bin_path(venv_path: str | Path) -> Path:
15
- """Get the bin/Scripts directory of the virtual environment."""
16
- if os.name == "nt": # Windows
17
- return Path(venv_path) / "Scripts"
18
- else: # Unix-like systems
19
- return Path(venv_path) / "bin"
20
-
21
-
22
- @contextlib.contextmanager
23
- def tempdir_ctx(cfg: DictConfig) -> Path:
24
- temp_dir = cfg.get("temp_dir", None)
25
- if temp_dir is None:
26
- with tempfile.TemporaryDirectory() as temp_dir:
27
- yield Path(temp_dir)
28
- else:
29
- temp_dir = Path(temp_dir)
30
- temp_dir.mkdir(exist_ok=True, parents=True)
31
- yield temp_dir
32
-
33
-
34
- def install_venv(venv_path: Path, requirements: str | Path) -> Path:
35
- logger.info(f"Installing requirements from {requirements} into virtual environment.")
36
- subprocess.run([sys.executable, "-m", "venv", str(venv_path)], check=True)
37
-
38
- venv_bin_path = get_venv_bin_path(venv_path)
39
- venv_python = venv_bin_path / "python"
40
- if not venv_python.exists():
41
- raise RuntimeError(f"Virtual environment python {venv_python} does not exist!")
42
-
43
- subprocess.run(
44
- [str(venv_python), "-m", "pip", "install", "-r", str(requirements)],
45
- check=True,
46
- )
47
-
48
- logger.info(f"Installed requirements from {requirements} into virtual environment.")
49
- return venv_bin_path
50
-
51
-
52
- @contextlib.contextmanager
53
- def temp_env(cfg: DictConfig, requirements: str | Path | None) -> tuple[Path, dict]:
54
- with tempdir_ctx(cfg) as build_temp_dir:
55
- env = os.environ.copy()
56
- if requirements is not None:
57
- venv_path = build_temp_dir / ".venv"
58
- venv_bin_path = install_venv(venv_path, requirements)
59
- env["PATH"] = f"{str(venv_bin_path)}{os.pathsep}{env['PATH']}"
60
-
61
- yield build_temp_dir, env
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes