this all looks like its the same code as in ``analysis.py``. argues for a common base class