diff --git a/exp/annotations.py b/exp/annotations.py
new file mode 100644
--- /dev/null
+++ b/exp/annotations.py
@@ -0,0 +1,46 @@
+import sys
+sys.path.append("../src")
+
+import gzip
+import json
+from typing import MutableMapping
+
+from analyzer.epoint import EPoint
+
+
+class DataFile(MutableMapping):
+	"""self._data: {filename: [EPoint,EPoint,EPoint,EPoint]}"""
+	def __init__(self,filename):
+		self.filename=filename
+		try:
+			with gzip.open(filename,mode="rt",encoding="utf8") as f:
+				self._data=json.load(f,object_hook=self.deserialize)
+		except OSError:
+			self._data=dict()
+
+	def save(self):
+		with gzip.open(self.filename,mode="wt",encoding="utf8") as f:
+			json.dump(self._data,f,default=self.serialize,indent="\t")
+
+	def serialize(self,obj):
+		if isinstance(obj,EPoint):
+			return {"type": "EPoint", "val": [obj.x,obj.y]}
+		raise TypeError(obj)
+
+	def deserialize(self,obj):
+		if obj.get("type")!="EPoint": return obj
+		return EPoint(*obj["val"])
+
+	def __getitem__(self, key): return self._data[key]
+	def __setitem__(self, key, val): self._data[key]=val
+	def __delitem__(self, key): del self._data[key]
+	def __iter__(self): return iter(self._data)
+	def __len__(self): return len(self._data)
+
+
+def computeBoundingBox(corners):
+	x1=min(p.x for p in corners)
+	x2=max(p.x for p in corners)
+	y1=min(p.y for p in corners)
+	y2=max(p.y for p in corners)
+	return (x1,y1,x2,y2)