Skip to content

Commit

Permalink
Merge pull request #1326 from StochSS/develop
Browse files Browse the repository at this point in the history
Release v2.4.7
  • Loading branch information
briandrawert authored May 2, 2022
2 parents c6a8f99 + c2c9359 commit d5ccccc
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 102 deletions.
2 changes: 1 addition & 1 deletion __version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# @website https://github.com/stochss/stochss
# =============================================================================

__version__ = '2.4.6'
__version__ = '2.4.7'
__title__ = 'StochSS'
__description__ = 'StochSS is an integrated development environment (IDE) \
for simulation of biochemical networks.'
Expand Down
3 changes: 2 additions & 1 deletion client/models/workflow-groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ var Collection = require('ampersand-collection');
var WorkflowGroup = require('./workflow-group');

module.exports = Collection.extend({
model: WorkflowGroup
model: WorkflowGroup,
comparator: "name"
});
3 changes: 2 additions & 1 deletion client/models/workflows.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ var Collection = require('ampersand-collection');
var Workflow = require('./workflow');

module.exports = Collection.extend({
model: Workflow
model: Workflow,
comparator: "name"
});
11 changes: 11 additions & 0 deletions client/pages/loading-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,23 @@ let LoadingPage = PageView.extend({
let yesBtn = document.querySelector("#uploadFileExistsModal .yes-modal-btn");
let noBtn = document.querySelector("#uploadFileExistsModal .btn-secondary")
yesBtn.addEventListener('click', function (e) {
modal.modal('hide');
self.uploadFileFromLink(filePath, true);
});
noBtn.addEventListener('click', function (e) {
window.location.href = self.homeLink;
});
}
},
error: function(err, response, body) {
if(document.querySelector("#errorModal")) {
document.querySelector("#errorModal").remove();
}
$(self.queryByHook("loading-spinner")).css("display", "none");
let modal = $(modals.errorHtml(body.Reason, body.Message)).modal();
modal.on('hidden.bs.modal', function (e) {
window.location.href = self.homeLink;
});
}
});
},
Expand Down
12 changes: 7 additions & 5 deletions client/pages/model-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,13 @@ let ModelEditor = PageView.extend({
}else if(e.target.dataset.type === "notebook"){
this.notebookWorkflow(e);
}else if(!this.model.is_spatial) {
if(e.target.dataset.type === "ensemble") {
app.newWorkflow(this, this.model.directory, this.model.is_spatial, "Ensemble Simulation");
}else if(e.target.dataset.type === "psweep") {
app.newWorkflow(this, this.model.directory, this.model.is_spatial, "Parameter Sweep");
}
this.saveModel(() => {
if(e.target.dataset.type === "ensemble") {
app.newWorkflow(this, this.model.directory, this.model.is_spatial, "Ensemble Simulation");
}else if(e.target.dataset.type === "psweep") {
app.newWorkflow(this, this.model.directory, this.model.is_spatial, "Parameter Sweep");
}
});
}
}
},
Expand Down
14 changes: 11 additions & 3 deletions client/settings-view/templates/simulationSettingsView.pug
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ div#simulation-settings.card
| Consider the following when selecting an algorithm for your job. If you would like StochSS to choose the algorithm, select <b>Choose for me</b>.

ul.mb-0
li Algorithms <b>ODE</b> and <b>Hybrid ODE/SSA</b> work best to simulate models with a mode of <b>Concentration</b>.
li Algorithms <b>ODE</b>, <b>CLE</b>, and <b>Hybrid ODE/SSA</b> work best to simulate models with a mode of <b>Concentration</b>.
li Algorithns <b>SSA</b>, <b>Tau Leaping</b>, and <b>Hybrid ODE/SSA</b> work best to simulate models with a mode of <b>Population</b>.
li Algorithm <b>Hybrid ODE/SSA</b> is required if the model contains advanced components.

Expand Down Expand Up @@ -58,6 +58,14 @@ div#simulation-settings.card

div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.ssa) <sup><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="info" class="svg-inline--fa fa-info fa-w-6" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M20 424.229h20V279.771H20c-11.046 0-20-8.954-20-20V212c0-11.046 8.954-20 20-20h112c11.046 0 20 8.954 20 20v212.229h20c11.046 0 20 8.954 20 20V492c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20v-47.771c0-11.046 8.954-20 20-20zM96 0C56.235 0 24 32.235 24 72s32.235 72 72 72 72-32.235 72-72S135.764 0 96 0z"></path></svg></sup>

div.col-sm-2

input.mr-2.inline(type="radio", name="simAlgorithm", data-hook="select-cle", data-name="CLE")

span.inline CLE

div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.cle) <sup><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="info" class="svg-inline--fa fa-info fa-w-6" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M20 424.229h20V279.771H20c-11.046 0-20-8.954-20-20V212c0-11.046 8.954-20 20-20h112c11.046 0 20 8.954 20 20v212.229h20c11.046 0 20 8.954 20 20V492c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20v-47.771c0-11.046 8.954-20 20-20zM96 0C56.235 0 24 32.235 24 72s32.235 72 72 72 72-32.235 72-72S135.764 0 96 0z"></path></svg></sup>

div.col-sm-2

input.mr-2.inline(type="radio", name="simAlgorithm", data-hook="select-tau-leaping", data-name="Tau-Leaping")
Expand All @@ -66,15 +74,15 @@ div#simulation-settings.card

div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.tauLeaping) <sup><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="info" class="svg-inline--fa fa-info fa-w-6" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M20 424.229h20V279.771H20c-11.046 0-20-8.954-20-20V212c0-11.046 8.954-20 20-20h112c11.046 0 20 8.954 20 20v212.229h20c11.046 0 20 8.954 20 20V492c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20v-47.771c0-11.046 8.954-20 20-20zM96 0C56.235 0 24 32.235 24 72s32.235 72 72 72 72-32.235 72-72S135.764 0 96 0z"></path></svg></sup>

div.col-sm-3
div.col-sm-2

input.mr-2.inline(type="radio", name="simAlgorithm", data-hook="select-hybrid-tau", data-name="Hybrid-Tau-Leaping")

span.inline Hybrid ODE/SSA

div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.hybrid) <sup><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="info" class="svg-inline--fa fa-info fa-w-6" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M20 424.229h20V279.771H20c-11.046 0-20-8.954-20-20V212c0-11.046 8.954-20 20-20h112c11.046 0 20 8.954 20 20v212.229h20c11.046 0 20 8.954 20 20V492c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20v-47.771c0-11.046 8.954-20 20-20zM96 0C56.235 0 24 32.235 24 72s32.235 72 72 72 72-32.235 72-72S135.764 0 96 0z"></path></svg></sup>

div.col-sm-3
div.col-sm-2

input.mr-2.inline(type="radio", name="simAlgorithm", data-hook="select-automatic", data-name="Automatic")

Expand Down
10 changes: 6 additions & 4 deletions client/settings-view/views/simulation-settings-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module.exports = View.extend({
events: {
'change [data-hook=select-ode]' : 'handleSelectSimulationAlgorithmClick',
'change [data-hook=select-ssa]' : 'handleSelectSimulationAlgorithmClick',
'change [data-hook=select-cle]' : 'handleSelectSimulationAlgorithmClick',
'change [data-hook=select-tau-leaping]' : 'handleSelectSimulationAlgorithmClick',
'change [data-hook=select-hybrid-tau]' : 'handleSelectSimulationAlgorithmClick',
'change [data-hook=select-automatic]' : 'handleSelectSimulationAlgorithmClick',
Expand Down Expand Up @@ -81,13 +82,14 @@ module.exports = View.extend({
let isAutomatic = this.model.isAutomatic;
let isODE = this.model.algorithm === "ODE";
let isSSA = this.model.algorithm === "SSA";
let isCLE = this.model.algorithm === "CLE";
let isLeaping = this.model.algorithm === "Tau-Leaping";
let isHybrid = this.model.algorithm === "Hybrid-Tau-Leaping";
$(this.queryByHook("relative-tolerance")).find('input').prop('disabled', !(isODE || isHybrid || isAutomatic));
$(this.queryByHook("absolute-tolerance")).find('input').prop('disabled', !(isODE || isHybrid || isAutomatic));
$(this.queryByHook("trajectories")).find('input').prop('disabled', !(isSSA || isLeaping || isHybrid || isAutomatic));
$(this.queryByHook("seed")).find('input').prop('disabled', !(isSSA || isLeaping || isHybrid || isAutomatic));
$(this.queryByHook("tau-tolerance")).find('input').prop('disabled', !(isHybrid || isLeaping || isAutomatic));
$(this.queryByHook("trajectories")).find('input').prop('disabled', !(isSSA || isCLE || isLeaping || isHybrid || isAutomatic));
$(this.queryByHook("seed")).find('input').prop('disabled', !(isSSA || isCLE || isLeaping || isHybrid || isAutomatic));
$(this.queryByHook("tau-tolerance")).find('input').prop('disabled', !(isHybrid || isCLE || isLeaping || isAutomatic));
},
handleSelectSimulationAlgorithmClick: function (e) {
let value = e.target.dataset.name;
Expand Down Expand Up @@ -128,7 +130,7 @@ module.exports = View.extend({
updateValid: function (e) {},
updateViewer: function () {
$(this.queryByHook("view-algorithm")).html(this.algorithm);
let hideDeterministic = this.model.isAutomatic || this.model.algorithm === "SSA" || this.model.algorithm === "Tau-Leaping";
let hideDeterministic = this.model.isAutomatic || this.model.algorithm === "SSA" || this.model.algorithm === "CLE" || this.model.algorithm === "Tau-Leaping";
let hideStochastic = this.model.isAutomatic || this.model.algorithm === "ODE" ;
if(hideDeterministic) {
$(this.queryByHook("view-deterministic-settings")).css("display", "none");
Expand Down
11 changes: 7 additions & 4 deletions stochss/handlers/file_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,10 +685,13 @@ async def get(self):
log.debug(f"The command for the upload script: {cmd}")
script = '/stochss/stochss/handlers/util/scripts/upload_remote_file.py'
if cmd == "validate":
folder = StochSSFolder(path="")
resp = {'exists': folder.validate_upload_link(remote_path=path)}
log.debug(f"Response: {resp}")
self.write(resp)
try:
folder = StochSSFolder(path="")
resp = {'exists': folder.validate_upload_link(remote_path=path)}
log.debug(f"Response: {resp}")
self.write(resp)
except StochSSAPIError as err:
report_error(self, log, err)
elif cmd is None:
overwrite = self.get_query_argument(name='overwrite', default=False)
outfile = f"{str(uuid.uuid4()).replace('-', '_')}.tmp"
Expand Down
3 changes: 2 additions & 1 deletion stochss/handlers/util/ensemble_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@


import os
import numpy
import pickle
import logging
import traceback
Expand Down Expand Up @@ -88,7 +89,7 @@ def __update_timespan(self):
end = self.settings['timespanSettings']['endSim']
step_size = self.settings['timespanSettings']['timeStep']
self.g_model.timespan(
TimeSpan.arange(t=end + step_size, increment=step_size)
TimeSpan(numpy.arange(0, end + step_size, step_size))
)


Expand Down
3 changes: 2 additions & 1 deletion stochss/handlers/util/parameter_sweep.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import os
import json
import numpy
import pickle
import logging
import traceback
Expand Down Expand Up @@ -120,7 +121,7 @@ def configure(self):
end = self.settings['timespanSettings']['endSim']
step_size = self.settings['timespanSettings']['timeStep']
self.g_model.timespan(
TimeSpan.arange(t=end + step_size, increment=step_size)
TimeSpan(numpy(0, end + step_size, step_size))
)
kwargs = {"model":self.g_model, "settings":run_settings}
parameters = []
Expand Down
145 changes: 81 additions & 64 deletions stochss/handlers/util/stochss_folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import shutil
import string
import zipfile
import tempfile
import datetime
import traceback

Expand All @@ -33,7 +34,7 @@
from .stochss_model import StochSSModel
from .stochss_sbml import StochSSSBMLModel
from .stochss_errors import StochSSFileExistsError, StochSSFileNotFoundError, \
StochSSPermissionsError
StochSSPermissionsError, StochSSUnzipError


class StochSSFolder(StochSSBase):
Expand Down Expand Up @@ -66,6 +67,38 @@ def __init__(self, path, new=False):
raise StochSSFileExistsError(message, traceback.format_exc()) from err


def __get_file_from_link(self, remote_path):
ext = remote_path.split('.').pop().split('?')[0]
if os.path.exists("/stochss/.proxies.txt"):
with open("/stochss/.proxies.txt", "r") as proxy_file:
proxy_ip = proxy_file.read().strip()
proxies = {
"https": f"https://{proxy_ip}",
"http": f"http://{proxy_ip}"
}
else:
proxies = None
response = requests.get(remote_path, allow_redirects=True, proxies=proxies)
body = response.content
if "download_presentation" in remote_path:
if ext in ("mdl", "smdl"):
file = f"{json.loads(body)['name']}.{ext}"
elif ext == "ipynb":
file = json.loads(body)['file']
body = json.dumps(json.loads(body)['notebook'])
elif ext == "job":
file = self.get_file(path=remote_path)
elif "?" in remote_path:
file = self.get_file(path=remote_path.split("?")[0])
else:
file = self.get_file(path=remote_path)
if response.status_code == 404:
message = f"Could not upload this file as {file} was not found."
if "?token=" in remote_path:
message += " The token for this file may be out of date."
raise StochSSFileNotFoundError(message, traceback.format_exc())
return ext, file, body

def __get_rmt_upld_path(self, file):
if not file.endswith(".zip"):
return file
Expand Down Expand Up @@ -150,18 +183,30 @@ def __get_presentation_notebook_name(cls, file_path):
return name


@classmethod
def __overwrite(cls, path, ext):
if ext == "zip":
with zipfile.ZipFile(path, "r") as zip_file:
members = zip_file.namelist()
for name in members:
if os.path.isdir(name):
shutil.rmtree(name)
elif os.path.exists(name):
os.remove(name)
elif os.path.exists(path):
def __overwrite(self, path, ext, body):
if ext != "zip":
os.remove(path)
else:
if os.path.exists(path):
os.remove(path)
file = self.get_file(path=path)
with tempfile.TemporaryDirectory() as tmp_dir:
ext_path = os.path.join(tmp_dir, file)
with open(ext_path, "wb") as zip_file:
zip_file.write(body)
try:
with zipfile.ZipFile(ext_path, 'r') as zip_file:
members = set([name.split('/')[0] for name in zip_file.namelist()])
for name in members:
m_path = self.get_new_path(dst_path=name)
if os.path.exists(m_path):
if os.path.isdir(m_path):
shutil.rmtree(m_path)
else:
os.remove(m_path)
except zipfile.BadZipFile as err:
message = "File is not a zip file"
raise StochSSFileNotFoundError(message, traceback.format_exc()) from err


def __upload_file(self, file, body, new_name=None):
Expand Down Expand Up @@ -529,38 +574,13 @@ def upload_from_link(self, remote_path, overwrite=False):
overwrite : bool
Overwrite the existing files.
'''
ext = remote_path.split('.').pop()
if os.path.exists("/stochss/.proxies.txt"):
with open("/stochss/.proxies.txt", "r") as proxy_file:
proxy_ip = proxy_file.read().strip()
proxies = {
"https": f"https://{proxy_ip}",
"http": f"http://{proxy_ip}"
}
else:
proxies = None
body = requests.get(remote_path, allow_redirects=True, proxies=proxies).content
if "download_presentation" in remote_path:
if ext in ("mdl", "smdl"):
file = f"{json.loads(body)['name']}.{ext}"
elif ext == "ipynb":
file = json.loads(body)['file']
body = json.dumps(json.loads(body)['notebook'])
else:
file = self.get_file(path=remote_path)
if "404: Not Found" in body.decode():
message = f"Could not upload this file as {file} was not found."
if "?token=" in file:
message += " The token for this file may be out of date."
return {"message": message, "reason":"File Not Found"}
if "?token=" in file:
file = file.split("?token=")[0]
ext, file, body = self.__get_file_from_link(remote_path)
path = self.get_new_path(dst_path=file)
if os.path.exists(path):
if not overwrite:
message = f"Could not upload this file as {file} already exists"
return {"message":message, "reason":"File Already Exists"}
self.__overwrite(path=path, ext=ext)
if overwrite:
self.__overwrite(path=path, ext=ext, body=body)
elif os.path.exists(path):
message = f"Could not upload this file as {file} already exists"
return {"message":message, "reason":"File Already Exists"}
try:
file_types = {"mdl":"model", "smdl":"model", "sbml":"sbml"}
file_type = file_types[ext] if ext in file_types.keys() else "file"
Expand All @@ -581,25 +601,22 @@ def validate_upload_link(self, remote_path):
remote_path : str
Path to the remote file
'''
ext = remote_path.split('.').pop()
body = requests.get(remote_path, allow_redirects=True).content
if "download_presentation" in remote_path:
if ext in ("mdl", "smdl"):
file = f"{json.loads(body)['name']}.{ext}"
elif ext == "ipynb":
file = json.loads(body)['file']
body = json.dumps(json.loads(body)['notebook'])
elif ext == "job":
file = self.get_file(path=remote_path)
else:
file = self.get_file(path=remote_path)
if "?token=" in file:
file = file.split("?token=")[0]
ext, file, body = self.__get_file_from_link(remote_path)
path = self.get_new_path(dst_path=file)
if ext == "zip":
with zipfile.ZipFile(path, "r") as zip_file:
members = zip_file.namelist()
for name in members:
if os.path.exists(name):
return True
return os.path.exists(path)
exists = os.path.exists(path)
if ext != "zip" or exists:
return exists
with tempfile.TemporaryDirectory() as tmp_dir:
ext_path = os.path.join(tmp_dir, file)
with open(ext_path, "wb") as zip_file:
zip_file.write(body)
try:
with zipfile.ZipFile(ext_path, 'r') as zip_file:
members = set([name.split('/')[0] for name in zip_file.namelist()])
for name in members:
if os.path.exists(self.get_new_path(dst_path=name)):
return True
except zipfile.BadZipFile as err:
message = "File is not a zip file"
raise StochSSFileNotFoundError(message, traceback.format_exc()) from err
return False
Loading

0 comments on commit d5ccccc

Please sign in to comment.