github-actions[bot] Claude Sonnet 5 commited on
Commit
6fa59b9
·
1 Parent(s): 1894277

Fix long-range task categorization and seq-length lookup bugs

Browse files

variant_effect_causal_eqtl was missing from TASK_TO_CATEGORY, so PR #35's
new long-range rows were silently bucketed into "Other". AUPRC (also added
in PR #35) wasn't in CLASSIFICATION_METRICS, so it never surfaced as a
selectable metric. task_seq_lengths.json keys were mixed-case (H2AFZ, ...)
against the lowercased task_name used everywhere else, so histone-mark
task_seq_length was NaN; compute_seq_lengths.py now lowercases on write and
adds the anchor-centered pooling window lengths for the three long-range
tasks, which aren't measurable via the short-range HF dataset it queries.

Also bind the dev server to 0.0.0.0 so it's reachable outside localhost.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

app.py CHANGED
@@ -555,4 +555,4 @@ with gr.Blocks(title="DNA Benchmark Leaderboard", theme=gr.themes.Soft()) as dem
555
 
556
 
557
  if __name__ == "__main__":
558
- demo.launch(share=False)
 
555
 
556
 
557
  if __name__ == "__main__":
558
+ demo.launch(share=False, server_name="0.0.0.0")
src/constants.py CHANGED
@@ -9,7 +9,9 @@ TASK_CATEGORIES: dict[str, list[str]] = {
9
  "promoter": ["promoter_all", "promoter_tata", "promoter_no_tata"],
10
  "enhancer": ["enhancers", "enhancers_types"],
11
  "splice_site": ["splice_sites_all", "splice_sites_donors", "splice_sites_acceptors"],
12
- "variant_effect": ["variant_effect_pathogenic_clinvar", "variant_effect_pathogenic_omim"],
 
 
13
  "rna_expression": ["bulk_rna_expression"],
14
  }
15
 
@@ -29,6 +31,7 @@ CLASSIFICATION_METRICS: dict[str, str] = {
29
  "accuracy_test": "Accuracy",
30
  "weighted_f1_test": "Weighted F1",
31
  "macro_f1_test": "Macro F1",
 
32
  }
33
 
34
  CATEGORY_DISPLAY_NAMES: dict[str, str] = {
 
9
  "promoter": ["promoter_all", "promoter_tata", "promoter_no_tata"],
10
  "enhancer": ["enhancers", "enhancers_types"],
11
  "splice_site": ["splice_sites_all", "splice_sites_donors", "splice_sites_acceptors"],
12
+ "variant_effect": [
13
+ "variant_effect_pathogenic_clinvar", "variant_effect_pathogenic_omim", "variant_effect_causal_eqtl",
14
+ ],
15
  "rna_expression": ["bulk_rna_expression"],
16
  }
17
 
 
31
  "accuracy_test": "Accuracy",
32
  "weighted_f1_test": "Weighted F1",
33
  "macro_f1_test": "Macro F1",
34
+ "auprc_test": "AUPRC",
35
  }
36
 
37
  CATEGORY_DISPLAY_NAMES: dict[str, str] = {
tools/compute_seq_lengths.py CHANGED
@@ -16,7 +16,7 @@ import os
16
  import pathlib
17
  from typing import Any
18
 
19
- from datasets import DatasetDict, load_dataset
20
  from dotenv import load_dotenv
21
 
22
  load_dotenv()
@@ -25,36 +25,37 @@ HF_TOKEN = os.environ.get("HF_TOKEN")
25
  HF_DATASET = "InstaDeepAI/nucleotide_transformer_downstream_tasks_revised"
26
  SAMPLE_SIZE = 100
27
 
 
 
28
  TASKS = [
29
  "H2AFZ", "H3K27ac", "H3K27me3", "H3K36me3",
30
  "H3K4me1", "H3K4me2", "H3K4me3", "H3K9ac", "H3K9me3", "H4K20me1",
31
  "promoter_all", "promoter_tata", "promoter_no_tata",
32
  "enhancers", "enhancers_types",
33
  "splice_sites_all", "splice_sites_donors", "splice_sites_acceptors",
34
- "variant_effect_pathogenic_clinvar", "variant_effect_pathogenic_omim",
35
- "bulk_rna_expression",
36
  ]
37
 
38
- OUTPUT_PATH = pathlib.Path(__file__).parent / "task_seq_lengths.json"
39
-
40
-
41
- def load_dataset_for_task(hf_dataset: str, task_name: str) -> DatasetDict:
42
- """Load HuggingFace dataset for specific task.
43
- Directly from the bdna package
44
- """
45
- kwargs: dict[str, Any] = {}
46
- if HF_TOKEN:
47
- kwargs["token"] = HF_TOKEN
 
48
 
49
- if hf_dataset == "InstaDeepAI/genomics-long-range-benchmark":
50
- return load_dataset(hf_dataset, task_name=task_name, **kwargs)
51
-
52
- return load_dataset(hf_dataset, data_dir=task_name, **kwargs)
53
 
54
 
55
  def compute_mean_length(task_name: str) -> int | None:
56
  try:
57
- ds_dict = load_dataset_for_task(HF_DATASET, task_name)
 
 
 
58
  ds = ds_dict["train"]
59
  # Sample a subset to keep it fast
60
  sample = ds.select(range(min(SAMPLE_SIZE, len(ds))))
@@ -80,7 +81,9 @@ def main():
80
  for task in TASKS:
81
  length = compute_mean_length(task)
82
  if length is not None:
83
- result[task] = length
 
 
84
 
85
  OUTPUT_PATH.write_text(json.dumps(result, indent=2))
86
  print(f"\nWrote {len(result)} entries to {OUTPUT_PATH}")
 
16
  import pathlib
17
  from typing import Any
18
 
19
+ from datasets import load_dataset
20
  from dotenv import load_dotenv
21
 
22
  load_dotenv()
 
25
  HF_DATASET = "InstaDeepAI/nucleotide_transformer_downstream_tasks_revised"
26
  SAMPLE_SIZE = 100
27
 
28
+ # Names match the HF dataset's own data_dir casing (e.g. "H2AFZ"), not the lowercased
29
+ # task_name used elsewhere in the dash — see the .lower() when writing results below.
30
  TASKS = [
31
  "H2AFZ", "H3K27ac", "H3K27me3", "H3K36me3",
32
  "H3K4me1", "H3K4me2", "H3K4me3", "H3K9ac", "H3K9me3", "H4K20me1",
33
  "promoter_all", "promoter_tata", "promoter_no_tata",
34
  "enhancers", "enhancers_types",
35
  "splice_sites_all", "splice_sites_donors", "splice_sites_acceptors",
 
 
36
  ]
37
 
38
+ # variant_effect_causal_eqtl, variant_effect_pathogenic_clinvar, and bulk_rna_expression are
39
+ # long-range tasks (100,000bp anchor-centered windows, see PR #35 in bench-dna). They don't
40
+ # exist in HF_DATASET so they can't be measured the same way as the short-range tasks above,
41
+ # and their raw window length (100,000bp for all of them) wouldn't be a meaningful x-axis value
42
+ # anyway. These are the anchor-centered pooling windows the Genomics LRB paper actually reads
43
+ # from that window -- the portion of the sequence that's relevant to the label.
44
+ LONG_RANGE_SEQ_LENGTHS: dict[str, int] = {
45
+ "variant_effect_causal_eqtl": 1536,
46
+ "variant_effect_pathogenic_clinvar": 1536,
47
+ "bulk_rna_expression": 383 + 256,
48
+ }
49
 
50
+ OUTPUT_PATH = pathlib.Path(__file__).parent / "task_seq_lengths.json"
 
 
 
51
 
52
 
53
  def compute_mean_length(task_name: str) -> int | None:
54
  try:
55
+ kwargs: dict[str, Any] = {}
56
+ if HF_TOKEN:
57
+ kwargs["token"] = HF_TOKEN
58
+ ds_dict = load_dataset(HF_DATASET, data_dir=task_name, **kwargs)
59
  ds = ds_dict["train"]
60
  # Sample a subset to keep it fast
61
  sample = ds.select(range(min(SAMPLE_SIZE, len(ds))))
 
81
  for task in TASKS:
82
  length = compute_mean_length(task)
83
  if length is not None:
84
+ result[task.lower()] = length
85
+
86
+ result.update(LONG_RANGE_SEQ_LENGTHS)
87
 
88
  OUTPUT_PATH.write_text(json.dumps(result, indent=2))
89
  print(f"\nWrote {len(result)} entries to {OUTPUT_PATH}")
tools/task_seq_lengths.json CHANGED
@@ -1,14 +1,14 @@
1
  {
2
- "H2AFZ": 1000,
3
- "H3K27ac": 1000,
4
- "H3K27me3": 1000,
5
- "H3K36me3": 1000,
6
- "H3K4me1": 1000,
7
- "H3K4me2": 1000,
8
- "H3K4me3": 1000,
9
- "H3K9ac": 1000,
10
- "H3K9me3": 1000,
11
- "H4K20me1": 1000,
12
  "promoter_all": 300,
13
  "promoter_tata": 300,
14
  "promoter_no_tata": 300,
@@ -16,5 +16,8 @@
16
  "enhancers_types": 400,
17
  "splice_sites_all": 600,
18
  "splice_sites_donors": 600,
19
- "splice_sites_acceptors": 600
 
 
 
20
  }
 
1
  {
2
+ "h2afz": 1000,
3
+ "h3k27ac": 1000,
4
+ "h3k27me3": 1000,
5
+ "h3k36me3": 1000,
6
+ "h3k4me1": 1000,
7
+ "h3k4me2": 1000,
8
+ "h3k4me3": 1000,
9
+ "h3k9ac": 1000,
10
+ "h3k9me3": 1000,
11
+ "h4k20me1": 1000,
12
  "promoter_all": 300,
13
  "promoter_tata": 300,
14
  "promoter_no_tata": 300,
 
16
  "enhancers_types": 400,
17
  "splice_sites_all": 600,
18
  "splice_sites_donors": 600,
19
+ "splice_sites_acceptors": 600,
20
+ "variant_effect_causal_eqtl": 1536,
21
+ "variant_effect_pathogenic_clinvar": 1536,
22
+ "bulk_rna_expression": 639
23
  }