|
1 |
| -""" |
2 |
| -This app takes in a mmif which has been annotated with bounding boxes. |
3 |
| -For each timepoint that has a bounding box, the app produces a larger bounding box |
4 |
| -using the outermost coordinates of the initial set. This produces a "concatenation" |
5 |
| -effect, wherein the box is guaranteed to contain every other bounding box. This |
6 |
| -is a useful bit of processing for downstream tasks. |
7 |
| -""" |
8 |
| -# ====================================| |
9 |
| -# Import Statements |
10 |
| -import argparse |
11 |
| -import logging |
12 | 1 | from collections import defaultdict
|
13 |
| -from typing import Dict, List, Tuple, Union |
| 2 | +from typing import Dict, List |
14 | 3 |
|
15 |
| -# Imports needed for Clams and MMIF. |
16 |
| -# Non-NLP Clams applications will require AnnotationTypes |
| 4 | +from mmif import AnnotationTypes |
17 | 5 |
|
18 |
| -from clams import ClamsApp, Restifier |
19 |
| -from mmif import Mmif, View, Annotation, Document, AnnotationTypes, DocumentTypes |
20 |
| - |
21 |
| -# For an NLP tool we need to import the LAPPS vocabulary items |
22 |
| -from lapps.discriminators import Uri |
23 |
| -# ====================================| |
24 |
| - |
25 |
| -class BoundingboxConcatenation(ClamsApp): |
26 |
| - def __init__(self): |
27 |
| - super().__init__() |
28 |
| - |
29 |
| - def _appmetadata(self): |
30 |
| - # see `metadata.py` |
31 |
| - pass |
32 |
| - |
33 |
| - def _annotate(self, mmif: Union[str, dict, Mmif], **parameters) -> Mmif: |
34 |
| - |
35 |
| - # see https://sdk.clams.ai/autodoc/clams.app.html#clams.app.ClamsApp._annotate |
36 |
| - |
37 |
| - # initialize mmif view |
38 |
| - if not isinstance(mmif, Mmif): |
39 |
| - mmif_obj = Mmif(mmif) |
40 |
| - else: |
41 |
| - mmif_obj = mmif |
42 |
| - new_view = mmif_obj.new_view() |
43 |
| - self.sign_view(new_view, parameters) |
44 |
| - new_view.new_contain( |
45 |
| - AnnotationTypes.BoundingBox |
46 |
| - ) |
47 |
| - |
48 |
| - # get bounding-box alignment |
| 6 | +if __name__ == '__main__': |
| 7 | + |
| 8 | + def read_small_boxes(mmif_obj, **parameters): |
49 | 9 | alignment_annotations = mmif_obj.get_alignments(
|
50 | 10 | at_type1=AnnotationTypes.TimePoint, at_type2=AnnotationTypes.BoundingBox
|
51 | 11 | )
|
@@ -85,14 +45,13 @@ def _annotate(self, mmif: Union[str, dict, Mmif], **parameters) -> Mmif:
|
85 | 45 | box_dict[timepoint_anno].append(box_anno)
|
86 | 46 |
|
87 | 47 | # concatenate bounding boxes and add to mmif
|
88 |
| - out_coords = self.make_boxes(box_dict) |
89 |
| - mmif_obj = self.annotate_boxes(mmif_obj, new_view, out_coords, **parameters) |
90 |
| - |
| 48 | + out_coords = make_big_boxes(box_dict) |
91 | 49 |
|
92 | 50 | return mmif_obj
|
93 | 51 |
|
| 52 | + |
94 | 53 | @staticmethod
|
95 |
| - def make_boxes(boundingbox_dictionary) -> Dict[float, List[List[float]]]: |
| 54 | + def make_big_boxes(boundingbox_dictionary) -> Dict[float, List[List[float]]]: |
96 | 55 | """Perform bounding-box concatenation
|
97 | 56 |
|
98 | 57 | ### params
|
@@ -138,63 +97,3 @@ def make_boxes(boundingbox_dictionary) -> Dict[float, List[List[float]]]:
|
138 | 97 | c, d = current_max_x, current_max_y
|
139 | 98 | out[timepoint] = [[a, b], [c, b], [a, d], [c, d]]
|
140 | 99 | return out
|
141 |
| - |
142 |
| - @staticmethod |
143 |
| - def annotate_boxes(mmif: Mmif, |
144 |
| - view: View, |
145 |
| - coords: Dict, |
146 |
| - **config) -> Mmif: |
147 |
| - """Perform mmif annotation with new coordinates. |
148 |
| - |
149 |
| - ### params |
150 |
| - + mmif => Mmif object we are annotating |
151 |
| - + view => View to which we are adding annotations |
152 |
| - + coords => Dict of individual bounding boxes for each timepoint |
153 |
| -
|
154 |
| - ### returns |
155 |
| - + Mmif object with new view annotations |
156 |
| - """ |
157 |
| - for time_point, box_coords in coords.items(): |
158 |
| - bb_annotation = view.new_annotation(AnnotationTypes.BoundingBox) |
159 |
| - tp_annotation = view.new_annotation(AnnotationTypes.TimePoint) |
160 |
| - tp_annotation.add_property("timeUnit", config["timeUnit"]) |
161 |
| - tp_annotation.add_property("timePoint", time_point) |
162 |
| - |
163 |
| - bb_annotation.add_property("label", config["label"]) |
164 |
| - |
165 |
| - bb_annotation.add_property("coordinates", box_coords) |
166 |
| - |
167 |
| - alignment_annotation = view.new_annotation(AnnotationTypes.Alignment) |
168 |
| - alignment_annotation.add_property("source", tp_annotation.id) |
169 |
| - alignment_annotation.add_property("target", bb_annotation.id) |
170 |
| - |
171 |
| - return mmif |
172 |
| - |
173 |
| - |
174 |
| -def get_app(): |
175 |
| - """ |
176 |
| - This function effectively creates an instance of the app class, without any arguments passed in, meaning, any |
177 |
| - external information such as initial app configuration should be set without using function arguments. The easiest |
178 |
| - way to do this is to set global variables before calling this. |
179 |
| - """ |
180 |
| - return BoundingboxConcatenation() |
181 |
| - |
182 |
| - |
183 |
| -if __name__ == "__main__": |
184 |
| - parser = argparse.ArgumentParser() |
185 |
| - parser.add_argument("--port", action="store", default="5000", help="set port to listen") |
186 |
| - parser.add_argument("--production", action="store_true", help="run gunicorn server") |
187 |
| - |
188 |
| - parsed_args = parser.parse_args() |
189 |
| - |
190 |
| - # create the app instance |
191 |
| - app = get_app() |
192 |
| - |
193 |
| - http_app = Restifier(app, port=int(parsed_args.port)) |
194 |
| - # for running the application in production mode |
195 |
| - if parsed_args.production: |
196 |
| - http_app.serve_production() |
197 |
| - # development mode |
198 |
| - else: |
199 |
| - app.logger.setLevel(logging.DEBUG) |
200 |
| - http_app.run() |
0 commit comments