DiODeProject / MuMoT

Multiscale Modelling Tool - mathematical modelling without the maths
https://mumot.readthedocs.io/
GNU General Public License v3.0
21 stars 4 forks source link

Add getter for simulation data #288

Closed jarmarshall closed 5 years ago

jarmarshall commented 5 years ago

Suggest a method saveSimulationData(<filename>) - need to figure out how to access local filespace, and what to do if no argument is provided (open a dialog?)

joefresna commented 5 years ago

Duplicate of #9

joefresna commented 5 years ago

@jarmarshall, I thought you were looking into this

jarmarshall commented 5 years ago

I have started something and will hand over to you shortly...

jarmarshall commented 5 years ago

@joefresna please switch to branch export-data where I have modified downloadTimeEvolution() in MuMoTmultiagentController to use a Qt file dialog - due to an apparent bug in PyQt5, at least on OS X, I have had to use the non-native version of the dialog. The selected file is then written into with a test message. It remains to be seen how this works on MyBinder - hopefully the user's local filesystem will be accessible.

I think now you should be able to write your simulation data into this file in an appropriate format. As I assume MuMoTSSAView also uses the same data structure I think the relevant methods should be moved up to MuMoTstochasticSimulationView from where they will be inherited by all child classes. Then we just need to add this to the documentation (issue #139 already updated).

joefresna commented 5 years ago

The branch export-data does not work for me...

---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-4d2bf7b6699e> in <module>
----> 1 import mumot
      2 mumot.about()
      3 mumot.setVerboseExceptions(True)

~/MuMoT/mumot/__init__.py in <module>
     34     matplotlib.use('TkAgg')
     35 
---> 36 from PyQt5 import QtGui
     37 from PyQt5 import QtGui, QtWidgets
     38 import ipywidgets.widgets as widgets

ModuleNotFoundError: No module named 'PyQt5'
joefresna commented 5 years ago

about the formatting, you can try this (should work):

        f = open(fname[0], 'w')
        line = 'runID' + '\t' + 'time'
        for state in sorted(self._view._initialState.keys(), key=str):
            line += '\t' + str(state)
        line += '\n'
        f.write(line)
        for runID,runData in enumerate(self._view._latestResults):
            line = str(runID) + '\t' + runData['time'] 
            for state in sorted(self._view._initialState.keys(), key=str):
                if state in self._mumotModel._constantReactants: continue
                line += '\t' + str(runData[state])
            line +=  '\n'
            f.write(line) 
        f.close()

and also I would move the function downloadTimeEvolution() into the MuMoTstochasticSimulationController() parent class.

willfurnass commented 5 years ago

I recommend using a context manager (the 'with' keyword) when reading/writing files.

jarmarshall commented 5 years ago

I updated setup.py to include the requirement for pyqt in branch export-data - for now I pinned this to 5.6.0, which works for me, in case of any dependency side-effects by going for any other version; but probably this can be relaxed later. @joefresna can you see if this works for you? I suggest you follow @willfurnass suggestion to use a context manager in your implementation; these are used elsewhere in the code.

joefresna commented 5 years ago

I pulled the new setup.py, generated a new environment and followed the installation steps. The pip installation does not work, I get this error:

$$ python -m pip install /Users/joefresna/MuMoT

Processing /Users/joefresna/MuMoT
Collecting antlr4-python3-runtime==4.5.3 (from mumot==0.1.0.dev0)
Collecting graphviz (from mumot==0.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/1f/e2/ef2581b5b86625657afd32030f90cf2717456c1d2b711ba074bf007c0f1a/graphviz-0.10.1-py2.py3-none-any.whl
Collecting ipykernel<4.7 (from mumot==0.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/18/c3/76775a650cae2e3d9c033b26153583e61282692d9a3af12a3022d8f0cefa/ipykernel-4.6.1-py3-none-any.whl
Collecting ipython (from mumot==0.1.0.dev0)
  Downloading https://files.pythonhosted.org/packages/14/3b/3fcf422a99a04ee493e6a4fc3014e3c8ff484a7feed238fef68bdc285085/ipython-7.3.0-py3-none-any.whl (768kB)
    100% |████████████████████████████████| 778kB 1.9MB/s 
Collecting ipywidgets (from mumot==0.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/30/9a/a008c7b1183fac9e52066d80a379b3c64eab535bd9d86cdc29a0b766fd82/ipywidgets-7.4.2-py2.py3-none-any.whl
Collecting matplotlib<3.0 (from mumot==0.1.0.dev0)
  Downloading https://files.pythonhosted.org/packages/55/bf/cb625a3050c444da570541d33f51c3640d34a34a6f593bc7780deb97b4ec/matplotlib-2.2.4-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (14.0MB)
    100% |████████████████████████████████| 14.0MB 1.8MB/s 
Collecting networkx (from mumot==0.1.0.dev0)
Collecting notebook<5.5 (from mumot==0.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/96/1f/e113875e6b8c8ee0e8c5748bf6fc942a109874adc9ca25248e95cf069803/notebook-5.4.1-py2.py3-none-any.whl
Collecting pydstool (from mumot==0.1.0.dev0)
Collecting pyqt==5.6.0 (from mumot==0.1.0.dev0)
  Could not find a version that satisfies the requirement pyqt==5.6.0 (from mumot==0.1.0.dev0) (from versions: )
No matching distribution found for pyqt==5.6.0 (from mumot==0.1.0.dev0)

@jarmarshall , did the installation work for you?

joefresna commented 5 years ago

just tried also with pyqt5==5.6.0 but it says:

Could not find a version that satisfies the requirement pyqt5==5.6.0 (from mumot==0.1.0.dev0) (from versions: 5.7.1, 5.8, 5.8.1.1, 5.8.2, 5.9, 5.9.1, 5.9.2, 5.10, 5.10.1, 5.11.2, 5.11.3, 5.12)

jarmarshall commented 5 years ago

Didn’t have time to try it (and I am a bit lost with the installation process now - this seemed the only place to put this). Maybe @willfurnass can advise... I believe I had version 5.6.0 installed though...

willfurnass commented 5 years ago

Why is Qt needed? To provide a file download dialog? Could you eliminate this dependency if you use tkinter instead of PyQt5?

willfurnass commented 5 years ago

Might be useful: https://pythonspot.com/tk-file-dialogs/

jarmarshall commented 5 years ago

Thanks @willfurnass - that looked promising, but just trying the code snippet at the link you shared reliably caused my kernel to die on OS X. This was a problem I also had with Qt, and had to tweak the code for that, so maybe it could be made to work. But it may be more straightforward to fix the qt dependency. Is there a reason to prefer tk over qt?

willfurnass commented 5 years ago

tkinter is bundled with Python:

>>> import tkinter
>>> tkinter.__file__
'/usr/lib64/python3.7/tkinter/__init__.py'
jarmarshall commented 5 years ago

Unfortunately if it doesn't work, being bundled doesn't help...

willfurnass commented 5 years ago

Do you have a minimal failing example with tkinter?

jarmarshall commented 5 years ago

The one you linked to ;)

from tkinter import filedialog
from tkinter import *

root = Tk()
root.filename =  filedialog.asksaveasfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
print (root.filename)
willfurnass commented 5 years ago

Ah, yes, this won't work if using a remote server. How about the following?

from IPython.display import HTML
import base64

def create_download_link(text, title="Download file", filename="file.txt"):  
    b64 = base64.b64encode(text.encode())
    payload = b64.decode()
    html = '<a download="{filename}" href="data:text/text;base64,{payload}" target="_blank">{title}</a>'
    html = html.format(payload=payload,title=title,filename=filename)
    return HTML(html)

create_download_link("some text here")

(inspired by https://medium.com/ibm-data-science-experience/how-to-upload-download-files-to-from-notebook-in-my-local-machine-6a4e65a15767)

jarmarshall commented 5 years ago

Actually I was running the tkinter example on a localhost, on OS X.

I'd seen the display alternative, and it works, but I think it is quite ugly... I would rather get the Qt example working I think...

willfurnass commented 5 years ago

But tkinter or Qt will only work for local Jupyter servers for which $DISPLAY references a local display.

jarmarshall commented 5 years ago

Thanks @willfurnass

@joefresna I've reverted on branch export-data to remove the additional, now unnecessary, requirement. Please can you pull that and try Will's proposed solution for downloading your log files?

jarmarshall commented 5 years ago

@joefresna N.B it might be simplest to start a completely new branch, since the beginning of the export-data branch simply introduced the now redundant Qt approach, and that branch is now behind master by some way...

joefresna commented 5 years ago

Thanks, @willfurnass , your solution worked great. The pending pull request #303 will implement this functionality