Skip to content

Commit

Permalink
Merge pull request #217 from sysbio-curie/update/physiboss
Browse files Browse the repository at this point in the history
PhysiBoSS 2.2.3 update
MathCancer authored Jun 3, 2024
2 parents d61aa79 + 98cc80e commit 36153c0
Showing 8 changed files with 112 additions and 58 deletions.
18 changes: 16 additions & 2 deletions CITATION.txt
Original file line number Diff line number Diff line change
@@ -23,13 +23,27 @@ with BioFVM [2] to solve the transport equations.
llelized diffusive transport solver for 3-D biological simulations,
Bioinformatics 32(8): 1256-8, 2016. DOI: 10.1093/bioinformatics/btv730

If you use PhysiBoSS, please cite:
If you use PhysiBoSS, please cite as below:

G. Letort, A. Montagud, G. Stoll, R. Heiland, E. Barillot, P. Macklin,
We implemented and solved the model using PhysiCell (Version 1.11.0) [1],
with PhysiBoSS[2,3] to simulate the intracellular mechanisms.

[1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin,
PhysiCell: an Open Source Physics-Based Cell Simulator for Multicellu-
lar Systems, PLoS Comput. Biol. 14(2): e1005991, 2018
DOI: 10.1371/journal.pcbi.1005991

[2] G. Letort, A. Montagud, G. Stoll, R. Heiland, E. Barillot, P. Macklin,
A. Zinovyev, and L. Calzone. PhysiBoSS: a multi-scale agent based
modelling framework integrating physical dimension and cell signalling.
Bioinformatics 35(7):1188-96, 2019. DOI: 10.1093/bioinformatics/bty766.

[3] M. Ponce-de-Leon, A. Montagud, V. Noël, A. Meert, G. Pradas, E. Barillot,
L. Calzone, and A. Valencia. PhysiBoSS 2.0: a sustainable integration of
stochastic Boolean and agent-based modelling frameworks. NPJ Systems
Biology and Applications 9(1):54, 2023.
DOI: 10.1038/s41540-023-00314-4

If you use libRoadrunner, please cite:

Endre T. Somogyi, Jean-Marie Bouteiller, James A. Glazier, Matthias
28 changes: 6 additions & 22 deletions beta/setup_libmaboss.py → addons/PhysiBoSS/setup_libmaboss.py
Original file line number Diff line number Diff line change
@@ -9,9 +9,8 @@
import os
import sys
import tarfile
import zipfile

if os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "addons", "PhysiBoSS", "MaBoSS-env-2.0")):
if os.path.exists(os.path.join(os.path.dirname(__file__), "MaBoSS-env-2.0")):
print('libMaBoSS already installed')

else:
@@ -21,35 +20,26 @@
# Assume Windows
mb_file = ""
url = ""
maboss_version = "v2.5.2"
maboss_version = "v2.5.4"
if os_type.lower() == 'darwin':
if "ARM64" in platform.uname().version:
mb_file = "libMaBoSS-macos-arm64.tar.gz"
url = "https://github.com/PhysiCell-Tools/intracellular_libs/raw/main/boolean/libMaBoSS-macos-arm64.tar.gz"
else:
mb_file = "libMaBoSS-osx64.tar.gz"
url = "https://github.com/sysbio-curie/MaBoSS-env-2.0/releases/download/" + maboss_version + "/" + mb_file
elif os_type.lower().startswith("win") or os_type.lower().startswith("msys_nt") or os_type.lower().startswith("mingw64_nt"):
mb_file = "libMaBoSS-win64.tar.gz"
url = "https://github.com/sysbio-curie/MaBoSS-env-2.0/releases/download/" + maboss_version + "/" + mb_file
elif os_type.lower().startswith("linux"):
mb_file = "libMaBoSS-linux64.tar.gz"
url = "https://github.com/sysbio-curie/MaBoSS-env-2.0/releases/download/" + maboss_version + "/" + mb_file
else:
print("Your operating system seems to be unsupported. Please submit a ticket at https://sourceforge.net/p/physicell/tickets/ ")
sys.exit(1)

# url = "https://github.com/sysbio-curie/MaBoSS-env-2.0/releases/download/v2.4.1/" + mb_file
url = "https://github.com/sysbio-curie/MaBoSS-env-2.0/releases/download/" + maboss_version + "/" + mb_file

fname = mb_file

home = os.path.expanduser("~")
print('libMaBoSS will now be installed into the addon PhysiBoSS addon folder:')
dir_name = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons', 'PhysiBoSS')
dir_name = os.path.dirname(__file__)
print(dir_name + '\n')
# print(' - Press ENTER to confirm the installation')
# print(' - Press CTL-C to abort the installation')


if not os.path.exists(dir_name):
try:
os.makedirs(dir_name)
@@ -59,15 +49,9 @@
print('Beginning download of libMaBoSS into ' + dir_name + ' ...')
print(url)

my_file = os.path.join(dir_name, fname)
my_file = os.path.join(dir_name, mb_file)
print('my_file = ',my_file)

# if os_type.lower().startswith("win"):
# rrlib_dir = my_file[:-4]
# else: # darwin or linux
# rrlib_dir = my_file[:-7]
# print('rrlib_dir = ',rrlib_dir)

def download_cb(blocknum, blocksize, totalsize):
readsofar = blocknum * blocksize
if totalsize > 0:
51 changes: 32 additions & 19 deletions addons/PhysiBoSS/src/maboss_intracellular.cpp
Original file line number Diff line number Diff line change
@@ -69,32 +69,38 @@ void MaBoSSIntracellular::update_inputs(PhysiCell::Cell* cell, PhysiCell::Phenot
int i=0;
for (auto& input: listOfInputs)
{
if (input.second.isNode()) {
maboss.set_node_value(
input.first,
input.second.updateNode(maboss.get_node_value(input.second.intracellular_name), signals[i])
);
} else if (input.second.isParameter()) {
maboss.set_parameter_value(
input.first,
input.second.updateParameter(signals[i])
);
if (cell->phenotype.death.dead == false || input.second.use_for_dead == true) {

if (input.second.isNode()) {
maboss.set_node_value(
input.first,
input.second.updateNode(maboss.get_node_value(input.second.intracellular_name), signals[i])
);
} else if (input.second.isParameter()) {
maboss.set_parameter_value(
input.first,
input.second.updateParameter(signals[i])
);
}
}
i++;
}
}

void MaBoSSIntracellular::update_outputs(PhysiCell::Cell* cell, PhysiCell::Phenotype& phenotype, double dt)
{
std::vector<double> signals = std::vector<double>(listOfOutputs.size(), 0.0);

int i=0;

for (auto& output: listOfOutputs)
{
signals[i] = output.second.update(maboss.get_node_value(output.second.intracellular_name));
if (cell->phenotype.death.dead == false || output.second.use_for_dead == true) {
PhysiCell::set_single_behavior(
cell, indicesOfOutputs[i],
output.second.update(maboss.get_node_value(output.second.intracellular_name))
);
}
i++;
}
PhysiCell::set_selected_behaviors(cell, indicesOfOutputs, signals);
}


@@ -366,7 +372,8 @@ void MaBoSSIntracellular::initialize_intracellular_from_pugixml(pugi::xml_node&
node_input.attribute( "physicell_name" ).value(),
intracellular_name,
(settings && settings.child( "scaling" ) ? PhysiCell::xml_get_my_double_value( settings.child( "scaling" )) : 1.0),
(settings && settings.child( "smoothing" ) ? PhysiCell::xml_get_my_int_value( settings.child( "smoothing" )) : 0)
(settings && settings.child( "smoothing" ) ? PhysiCell::xml_get_my_int_value( settings.child( "smoothing" )) : 0),
(settings && settings.child( "use_for_dead" ) ? PhysiCell::xml_get_my_bool_value( settings.child( "use_for_dead" )) : false)
);

// This construct is a trick to avoid making inputs and outputs constructible and assignable, or using c++17 insert_or_assign
@@ -382,7 +389,8 @@ void MaBoSSIntracellular::initialize_intracellular_from_pugixml(pugi::xml_node&
PhysiCell::xml_get_my_string_value(settings.child("action")),
PhysiCell::xml_get_my_double_value(settings.child("threshold")),
(settings && settings.child( "inact_threshold" ) ? PhysiCell::xml_get_my_double_value( settings.child( "inact_threshold" )) : PhysiCell::xml_get_my_double_value(settings.child("threshold"))),
(settings && settings.child( "smoothing" ) ? PhysiCell::xml_get_my_int_value( settings.child( "smoothing" )) : 0)
(settings && settings.child( "smoothing" ) ? PhysiCell::xml_get_my_int_value( settings.child( "smoothing" )) : 0),
(settings && settings.child( "use_for_dead" ) ? PhysiCell::xml_get_my_bool_value( settings.child( "use_for_dead" )) : false)
);

auto const res = listOfInputs.insert(std::pair<std::string, MaBoSSInput>(intracellular_name, input));
@@ -403,7 +411,9 @@ void MaBoSSIntracellular::initialize_intracellular_from_pugixml(pugi::xml_node&
PhysiCell::xml_get_my_string_value(settings.child("action")),
PhysiCell::xml_get_my_double_value(settings.child("value")),
(settings && settings.child( "base_value" ) ? PhysiCell::xml_get_my_double_value( settings.child( "base_value" )) : PhysiCell::xml_get_my_double_value(settings.child("value"))),
(settings && settings.child( "smoothing" ) ? PhysiCell::xml_get_my_int_value( settings.child( "smoothing" )) : 0)
(settings && settings.child( "smoothing" ) ? PhysiCell::xml_get_my_int_value( settings.child( "smoothing" )) : 0),
(settings && settings.child( "steepness" ) ? PhysiCell::xml_get_my_int_value( settings.child( "steepness" )) : 10),
(settings && settings.child( "use_for_dead" ) ? PhysiCell::xml_get_my_bool_value( settings.child( "use_for_dead" )) : false)
);

auto const res = listOfOutputs.insert(std::pair<std::string, MaBoSSOutput>(physicell_name, output));
@@ -442,13 +452,16 @@ void MaBoSSIntracellular::display(std::ostream& os)
os << "\t\t " << listOfInputs.size() << " input mapping defined" << std::endl;
for (const auto& input : listOfInputs)
os << "\t\t\t" << input.second.physicell_name << " = " << input.first
<< "(" << input.second.threshold << ", " << input.second.inact_threshold << ", " << input.second.smoothing << ")"
<< "(" << input.second.threshold << ", " << input.second.inact_threshold
<< ", " << input.second.smoothing << ", " << input.second.use_for_dead << ")"
<< std::endl;

os << "\t\t " << listOfOutputs.size() << " output mapping defined" << std::endl;
for (const auto& output : listOfOutputs)
os << "\t\t\t" << output.first << " = " << output.second.intracellular_name
<< "(" << output.second.value << ", " << output.second.base_value << ", " << output.second.smoothing << ")"
<< "(" << output.second.value << ", " << output.second.base_value
<< ", " << output.second.smoothing << ", " << output.second.steepness
<< ", " << output.second.use_for_dead << ")"
<< std::endl;

os << "\t\t global inheritance = " << inherit_state << std::endl;
14 changes: 7 additions & 7 deletions addons/PhysiBoSS/src/maboss_intracellular.h
Original file line number Diff line number Diff line change
@@ -10,7 +10,9 @@
#include "maboss_network.h"
#include "utils.h"

static std::string PhysiBoSS_Version = "2.2.2";
static std::string PhysiBoSS_Version = "2.2.3";
static std::string PhysiBoSS_DOI = "10.1038/s41540-023-00314-4";
static std::string PhysiBoSS_URL = "https://github.com/PhysiBoSS/PhysiBoSS";

class MaBoSSIntracellular : public PhysiCell::Intracellular {
private:
@@ -68,12 +70,10 @@ class MaBoSSIntracellular : public PhysiCell::Intracellular {
}

void update(PhysiCell::Cell * cell, PhysiCell::Phenotype& phenotype, double dt) {
if (!cell->phenotype.death.dead) {
this->update_inputs(cell, phenotype, dt);
this->maboss.run_simulation();
this->update_outputs(cell, phenotype, dt);
this->next_physiboss_run += this->maboss.get_time_to_update();
}
this->update_inputs(cell, phenotype, dt);
this->maboss.run_simulation();
this->update_outputs(cell, phenotype, dt);
this->next_physiboss_run += this->maboss.get_time_to_update();
}

bool need_update() {
13 changes: 13 additions & 0 deletions addons/PhysiBoSS/src/maboss_network.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "maboss_network.h"
#include <fstream>

/* Default constructor */
void MaBoSSNetwork::init_maboss( std::string networkFile, std::string configFile)
@@ -19,6 +20,18 @@ void MaBoSSNetwork::init_maboss( std::string networkFile, std::string configFile

#pragma omp critical
{
std::ifstream f_bnd(networkFile.c_str());
if (!f_bnd.good()) {
std::cerr << "PhysiBoSS ERROR : Could not open the BND file " << networkFile.c_str() << std::endl;
exit(1);
}

std::ifstream f_cfg(configFile.c_str());
if (!f_cfg.good()) {
std::cerr << "PhysiBoSS ERROR : Could not open the CFG file " << configFile.c_str() << std::endl;
exit(1);
}

// Initialize MaBoSS Objects for a model
this->network = new Network();
this->network->parse(networkFile.c_str());
16 changes: 10 additions & 6 deletions addons/PhysiBoSS/src/utils.h
Original file line number Diff line number Diff line change
@@ -17,12 +17,14 @@ class MaBoSSInput
double scaling;
int smoothing;
double smoothed_value;
MaBoSSInput(std::string physicell_name, std::string intracellular_name, std::string action, double threshold, double inact_threshold, int smoothing) : physicell_name(physicell_name), intracellular_name(intracellular_name), action(action), threshold(threshold), inact_threshold(inact_threshold), smoothing(smoothing) {
bool use_for_dead;

MaBoSSInput(std::string physicell_name, std::string intracellular_name, std::string action, double threshold, double inact_threshold, int smoothing, bool use_for_dead) : physicell_name(physicell_name), intracellular_name(intracellular_name), action(action), threshold(threshold), inact_threshold(inact_threshold), smoothing(smoothing), use_for_dead(use_for_dead){
type = NODE;
smoothed_value = 0;
}

MaBoSSInput(std::string physicell_name, std::string intracellular_parameter, double scaling, int smoothing) : physicell_name(physicell_name), intracellular_parameter(intracellular_parameter), scaling(scaling), smoothing(smoothing) {
MaBoSSInput(std::string physicell_name, std::string intracellular_parameter, double scaling, int smoothing, bool use_for_dead) : physicell_name(physicell_name), intracellular_parameter(intracellular_parameter), scaling(scaling), smoothing(smoothing), use_for_dead(use_for_dead) {
type = PARAMETER;
smoothed_value = 0;
}
@@ -83,13 +85,15 @@ class MaBoSSOutput
int smoothing;
double probability;
bool initialized = false;
int steepness;
bool use_for_dead;

MaBoSSOutput(std::string physicell_name, std::string intracellular_name,
std::string action, double value, double base_value,
int smoothing)
int smoothing, int steepness, bool use_for_dead)
: physicell_name(physicell_name), intracellular_name(intracellular_name),
action(action), value(value), base_value(base_value),
smoothing(smoothing) {
smoothing(smoothing), steepness(steepness), use_for_dead(use_for_dead) {
probability = 0.5;
}

@@ -115,10 +119,10 @@ class MaBoSSOutput
}

if (action == "activation") {
double hill = PhysiCell::Hill_response_function(hill_input * 2, 1, 10);
double hill = PhysiCell::Hill_response_function(hill_input * 2, 1, steepness);
return (value - base_value) * hill + base_value;
} else if (action == "inhibition") {
double hill = PhysiCell::Hill_response_function(hill_input * 2, 1, 10);
double hill = PhysiCell::Hill_response_function(hill_input * 2, 1, steepness);
return ((value - base_value) * (1 - hill)) + base_value;
}

26 changes: 26 additions & 0 deletions licenses/MaBoSS.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
BSD 3-Clause License (see https://opensource.org/licenses/BSD-3-Clause)

Copyright (c) 2011-2023 Institut Curie, 26 rue d'Ulm, Paris, France
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Original file line number Diff line number Diff line change
@@ -202,9 +202,9 @@ Compile_MaBoSS: ./addons/PhysiBoSS/MaBoSS-env-2.0/engine/src/BooleanNetwork.h

$(MaBoSS):
ifeq ($(OS), Windows_NT)
python beta/setup_libmaboss.py
python addons/PhysiBoSS/setup_libmaboss.py
else
python3 beta/setup_libmaboss.py
python3 addons/PhysiBoSS/setup_libmaboss.py
endif

maboss_network.o: ./addons/PhysiBoSS/src/maboss_network.cpp $(MaBoSS)

0 comments on commit 36153c0

Please sign in to comment.