Skip to content

Commit 05c3cd0

Browse files
committed
output default annotation
1 parent f92c899 commit 05c3cd0

2 files changed

Lines changed: 172 additions & 57 deletions

File tree

autonima/coordinates/nimads_models.py

Lines changed: 159 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ class PointValue:
1010
"""Represents a value associated with a coordinate point."""
1111
kind: Optional[str] = None
1212
value: Optional[Union[float, str]] = None
13+
14+
def to_dict(self) -> dict:
15+
"""Convert to dictionary representation."""
16+
return {
17+
"kind": self.kind,
18+
"value": self.value
19+
}
1320

1421

1522
@dataclass
@@ -21,6 +28,51 @@ class Point:
2128
label_id: Optional[str] = None
2229
values: List[PointValue] = field(default_factory=list)
2330
analysis_id: Optional[str] = None
31+
32+
def to_dict(self) -> dict:
33+
"""Convert to dictionary representation."""
34+
return {
35+
"coordinates": self.coordinates,
36+
"space": self.space,
37+
"kind": self.kind,
38+
"label_id": self.label_id,
39+
"values": [value.to_dict() for value in self.values],
40+
"analysis_id": self.analysis_id
41+
}
42+
43+
44+
@dataclass
45+
class Condition:
46+
"""A representative term for a psychological, pharmacological, medical, or physical state."""
47+
name: Optional[str] = None
48+
description: Optional[str] = None
49+
50+
def to_dict(self) -> dict:
51+
"""Convert to dictionary representation."""
52+
return {
53+
"name": self.name,
54+
"description": self.description
55+
}
56+
57+
58+
@dataclass
59+
class Image:
60+
"""Statistical image (e.g., beta, t-statistic, and/or z-statistic image)."""
61+
id: Optional[str] = None
62+
filename: Optional[str] = None
63+
space: Optional[str] = None
64+
kind: Optional[str] = None
65+
analysis_id: Optional[str] = None
66+
67+
def to_dict(self) -> dict:
68+
"""Convert to dictionary representation."""
69+
return {
70+
"id": self.id,
71+
"filename": self.filename,
72+
"space": self.space,
73+
"kind": self.kind,
74+
"analysis_id": self.analysis_id
75+
}
2476

2577

2678
@dataclass
@@ -30,8 +82,23 @@ class NimadsAnalysis:
3082
name: Optional[str] = None
3183
description: Optional[str] = None
3284
weights: List[float] = field(default_factory=list)
85+
conditions: List[Condition] = field(default_factory=list)
86+
images: List[Image] = field(default_factory=list)
3387
points: List[Point] = field(default_factory=list)
3488
study_id: Optional[str] = None
89+
90+
def to_dict(self) -> dict:
91+
"""Convert to dictionary representation."""
92+
return {
93+
"id": self.id,
94+
"name": self.name,
95+
"description": self.description,
96+
"weights": self.weights,
97+
"conditions": [condition.to_dict() for condition in self.conditions],
98+
"images": [image.to_dict() for image in self.images],
99+
"points": [point.to_dict() for point in self.points],
100+
"study_id": self.study_id
101+
}
35102

36103

37104
@dataclass
@@ -47,6 +114,21 @@ class Study:
47114
authors: Optional[str] = None
48115
year: Optional[int] = None
49116
analyses: List[NimadsAnalysis] = field(default_factory=list)
117+
118+
def to_dict(self) -> dict:
119+
"""Convert to dictionary representation."""
120+
return {
121+
"id": self.id,
122+
"doi": self.doi,
123+
"name": self.name,
124+
"metadata": self.metadata,
125+
"description": self.description,
126+
"publication": self.publication,
127+
"pmid": self.pmid,
128+
"authors": self.authors,
129+
"year": self.year,
130+
"analyses": [analysis.to_dict() for analysis in self.analyses]
131+
}
50132

51133

52134
@dataclass
@@ -59,6 +141,18 @@ class Studyset:
59141
doi: Optional[str] = None
60142
pmid: Optional[str] = None
61143
studies: List[Study] = field(default_factory=list)
144+
145+
def to_dict(self) -> dict:
146+
"""Convert to dictionary representation."""
147+
return {
148+
"id": self.id,
149+
"name": self.name,
150+
"description": self.description,
151+
"publication": self.publication,
152+
"doi": self.doi,
153+
"pmid": self.pmid,
154+
"studies": [study.to_dict() for study in self.studies]
155+
}
62156

63157

64158
def convert_to_nimads_point(analysis_id: str, point: CoordinatePoint) -> Point:
@@ -131,6 +225,46 @@ def convert_to_nimads_study(study_id: str, autonima_study: 'autonima.models.type
131225
return nimads_study
132226

133227

228+
@dataclass
229+
class NoteCollection:
230+
"""The storage object for all notes within an annotation for a single analysis."""
231+
note: Optional[dict] = None
232+
analysis_id: Optional[str] = None
233+
annotation_id: Optional[str] = None
234+
235+
def to_dict(self) -> dict:
236+
"""Convert to dictionary representation."""
237+
return {
238+
"note": self.note,
239+
"analysis": self.analysis_id,
240+
"annotation": self.annotation_id
241+
}
242+
243+
244+
@dataclass
245+
class Annotation:
246+
"""An annotation describes each analysis within a studyset with typically subjective information."""
247+
id: str
248+
name: Optional[str] = None
249+
description: Optional[str] = None
250+
metadata: Optional[dict] = None
251+
note_keys: Optional[dict] = None
252+
studyset_id: Optional[str] = None
253+
notes: List[NoteCollection] = field(default_factory=list)
254+
255+
def to_dict(self) -> dict:
256+
"""Convert to dictionary representation."""
257+
return {
258+
"id": self.id,
259+
"name": self.name,
260+
"description": self.description,
261+
"metadata": self.metadata,
262+
"note_keys": self.note_keys,
263+
"studyset": self.studyset_id,
264+
"notes": [note.to_dict() for note in self.notes]
265+
}
266+
267+
134268
def convert_to_nimads_studyset(studyset_id: str, studies: List['autonima.models.types.Study'], name: Optional[str] = None) -> Studyset:
135269
"""Convert a list of autonima studies to a NiMADS studyset."""
136270
studyset = Studyset(
@@ -144,4 +278,28 @@ def convert_to_nimads_studyset(studyset_id: str, studies: List['autonima.models.
144278
nimads_study = convert_to_nimads_study(study_id, study)
145279
studyset.studies.append(nimads_study)
146280

147-
return studyset
281+
return studyset
282+
283+
284+
def create_default_annotation(studyset_id: str, studyset: Studyset) -> Annotation:
285+
"""Create a default annotation with include=True for all analyses in the studyset."""
286+
annotation_id = f"annotation_{studyset_id}"
287+
annotation = Annotation(
288+
id=annotation_id,
289+
name="replication_annotations",
290+
description="",
291+
note_keys={"include": "boolean"},
292+
studyset_id=studyset_id
293+
)
294+
295+
# Create notes for each analysis
296+
for study in studyset.studies:
297+
for analysis in study.analyses:
298+
note = NoteCollection(
299+
note={"include": True},
300+
analysis_id=analysis.id,
301+
annotation_id=annotation_id
302+
)
303+
annotation.notes.append(note)
304+
305+
return annotation

autonima/pipeline.py

Lines changed: 13 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import logging
44
import csv
5+
import json
56
from datetime import datetime
67
from pathlib import Path
78
from typing import Dict, Any
@@ -16,6 +17,7 @@
1617
from .screening import LLMScreener
1718
from .retrieval import PubGetRetriever
1819
from .utils import log_error_with_debug
20+
from .coordinates.nimads_models import convert_to_nimads_studyset
1921

2022
logger = logging.getLogger(__name__)
2123

@@ -705,8 +707,7 @@ async def _generate_nimads_output(self):
705707

706708
try:
707709
# Import NiMADS models
708-
from .coordinates.nimads_models import convert_to_nimads_studyset
709-
import json
710+
from .coordinates.nimads_models import convert_to_nimads_studyset, create_default_annotation
710711

711712
# Create a studyset from the included studies
712713
studyset_id = f"autonima_studyset_{self.results.started_at.strftime('%Y%m%d_%H%M%S')}"
@@ -716,63 +717,19 @@ async def _generate_nimads_output(self):
716717
name="Autonima Generated Studyset"
717718
)
718719

719-
# Convert to dictionary for JSON serialization
720-
def studyset_to_dict(studyset):
721-
return {
722-
"id": studyset.id,
723-
"name": studyset.name,
724-
"description": studyset.description,
725-
"publication": studyset.publication,
726-
"doi": studyset.doi,
727-
"pmid": studyset.pmid,
728-
"studies": [study_to_dict(study) for study in studyset.studies]
729-
}
730-
731-
def study_to_dict(study):
732-
return {
733-
"id": study.id,
734-
"doi": study.doi,
735-
"name": study.name,
736-
"metadata": study.metadata,
737-
"description": study.description,
738-
"publication": study.publication,
739-
"pmid": study.pmid,
740-
"authors": study.authors,
741-
"year": study.year,
742-
"analyses": [analysis_to_dict(analysis) for analysis in study.analyses]
743-
}
744-
745-
def analysis_to_dict(analysis):
746-
return {
747-
"id": analysis.id,
748-
"name": analysis.name,
749-
"description": analysis.description,
750-
"weights": analysis.weights,
751-
"points": [point_to_dict(point) for point in analysis.points],
752-
"study_id": analysis.study_id
753-
}
754-
755-
def point_to_dict(point):
756-
return {
757-
"coordinates": point.coordinates,
758-
"space": point.space,
759-
"kind": point.kind,
760-
"label_id": point.label_id,
761-
"values": [point_value_to_dict(value) for value in point.values],
762-
"analysis_id": point.analysis_id
763-
}
720+
# Create a default annotation
721+
annotation = create_default_annotation(studyset_id, studyset)
764722

765-
def point_value_to_dict(point_value):
766-
return {
767-
"kind": point_value.kind,
768-
"value": point_value.value
769-
}
770-
771-
# Save NiMADS output
723+
# Save NiMADS studyset output using the to_dict method
772724
output_dir = Path(self.config.output.directory)
773-
nimads_output_file = output_dir / "outputs" / "nimads_output.json"
725+
nimads_output_file = output_dir / "outputs" / "nimads_studyset.json"
774726
with open(nimads_output_file, 'w') as f:
775-
json.dump(studyset_to_dict(studyset), f, indent=2)
727+
json.dump(studyset.to_dict(), f, indent=2)
728+
729+
# Save NiMADS annotation output using the to_dict method
730+
nimads_annotation_file = output_dir / "outputs" / "nimads_annotation.json"
731+
with open(nimads_annotation_file, 'w') as f:
732+
json.dump(annotation.to_dict(), f, indent=2)
776733

777734
logger.info(
778735
f"NiMADS output generated: {len(included_studies_with_analyses)} studies "

0 commit comments

Comments
 (0)