Celine Hernandez
As a model grows to tens and hundreds of nodes, it becomes difficult to monitor its behaviour. In order to be sure that known behaviours are effectively reproduced, a unit testing pipeline can be implemented. This framework allows to automate both local and global analyses of the model.
Steps of analysis:
Load the CoLoMoTo library.
from colomoto_jupyter import tabulate
This notebook has been executed using the docker image colomoto/colomoto-docker:2020-01-24
Load the Unit Test framework.
import unittest
# Re-usable test runner
runner = unittest.TextTestRunner(verbosity=2)
# Container for all test suites
all_suite = unittest.TestSuite()
# Whether test cases should be run independently
debug_test_cases = True
# Whether individual test suites should be run independently
debug_test_suites = True
# Whether all tests should be run at the end
run_all = True
Load the model to be tested.
# Load model to be tested
import biolqm
lqm = biolqm.load("Hernandez_TcellCheckPoints_13april2020.zginml")
Accessory functions
# Transforms a dictionary into a %-joined pattern
# {A:0, D:1} => "A%0 D%1"
def percent_pattern(dict_vals):
return " ".join( [ "%".join((key, str(dict_vals.get(key)))) for key in dict_vals.keys() ]
)
# Transforms a dictionary into a dash-like pattern used for space restrictions.
# If a model has 4 components A, B, C, D in this order,
# {A:0, D:1} => "0--1"
def dash_pattern(model, dict_vals):
specific_comps = dict_vals.keys()
str_pattern = ""
for comp in model.getComponents():
if comp.toString() in specific_comps:
str_pattern += str(dict_vals.get(comp.toString()))
else :
str_pattern += "-"
return(str_pattern)
Following TCR engagement, cytoplasmic Calcium ions is elevated whithin seconds. This paragraph aims at testing the behaviour of the model around this event, and is centered on the Endoplasmic Reticulum (ER), Mitochondria, and the cytoplasmic membrane.
For a general review on Calcium flux during antigen-induced T cell activation, see PMID:23860253. For the specific impact of Mitochondria on sustained signalling, refer to PMID:24117814.
Summary and expected behaviours of the model:
In quiescent cells (absence of IP3):
Following TCR engagement (and increase in IP3 levels):
PMCA with no activation of Mitochondria (translocation): Here, in absence of IP3 signal, activation of PMCA as soon as Calcium_cyt reaches level 2 gives transient oscillations, as ORAI1 increases Calcium_cyt to 2 and PMCA decreases it back to 1. If SERCA gets activated, Calcium_ER can reach level 1, de-activating OARI1. Calcium_cyt:2 is not stable any more. With IP3 signal, there is a cyclic attractor as Calcium_ER is never refilled. Calcium_cyt oscillates between values 1 and 2 due to the combined effects of ORAI1 and PMCA.
Mitochondria are translocated where calcium cytoplasmic increases. There, they act as buffers, absorbing Calcium and releasing it far from ORAI1 and PMCA, thus counter-acting ORAI1 inhibition and PMCA activation caused by a high level of Calcium_cyt.
Note that there is a positive feedback loop on Calcium_ER and Calcium_cyt to avoid any unwanted disappearance of calcium outside of fluxes through the channels.
# Test suite for all calcium-related tests.
calcium_suite = unittest.TestSuite()
class CalciumModuleTestCase(unittest.TestCase):
"""Sub-model to be tested."""
model = biolqm.submodel(lqm, "Calcium_cyt Calcium_ER IP3R1 Mitochondria ORAI1 PMCA SERCA STIM1")
str([component.toString() for component in CalciumModuleTestCase.model.getComponents()])
"['f_CRACR2A', 'f_ROS', 'ZAP70', 'IP3', 'WAVE_cplx', 'IP3R1', 'Calcium_ER', 'Calcium_cyt', 'SERCA', 'STIM1', 'ORAI1', 'PMCA', 'Mitochondria']"
biolqm.to_minibn(CalciumModuleTestCase.model)
Calcium_ER <- (!IP3R1&!Calcium_ER&SERCA)|(!IP3R1&Calcium_ER) Calcium_cyt:1 <- (!IP3R1&Calcium_cyt:1&!Calcium_cyt:2&!SERCA&!ORAI1&!PMCA)|(IP3R1&!Calcium_cyt:2&!SERCA&!ORAI1&!PMCA)|(IP3R1&!Calcium_cyt:2&SERCA&!ORAI1&!PMCA) Calcium_cyt:2 <- (!IP3R1&!Calcium_cyt:1&!SERCA&ORAI1)|(!IP3R1&!Calcium_cyt:1&SERCA&ORAI1&!PMCA)|(!IP3R1&Calcium_cyt:1&!Calcium_cyt:2&!SERCA&ORAI1)|(!IP3R1&Calcium_cyt:1&!Calcium_cyt:2&SERCA&ORAI1&!PMCA)|(!IP3R1&Calcium_cyt:2&!SERCA&!ORAI1&!PMCA)|(!IP3R1&Calcium_cyt:2&!SERCA&ORAI1)|(!IP3R1&Calcium_cyt:2&SERCA&!PMCA)|(IP3R1&!Calcium_cyt:2&!SERCA&ORAI1)|(IP3R1&!Calcium_cyt:2&SERCA&ORAI1&!PMCA)|(IP3R1&Calcium_cyt:2&!SERCA&!ORAI1&!PMCA)|(IP3R1&Calcium_cyt:2&!SERCA&ORAI1)|(IP3R1&Calcium_cyt:2&SERCA&!PMCA) IP3 <- IP3 IP3R1 <- IP3 Mitochondria <- ZAP70&Calcium_cyt:1 ORAI1 <- (f_CRACR2A&!f_ROS&WAVE_cplx&!Calcium_cyt:2&STIM1)|(f_CRACR2A&!f_ROS&WAVE_cplx&Calcium_cyt:2&STIM1&Mitochondria) PMCA <- Calcium_cyt:1&!Mitochondria SERCA <- !Calcium_ER&Calcium_cyt:1 STIM1 <- !Calcium_ER WAVE_cplx <- WAVE_cplx ZAP70 <- ZAP70 f_CRACR2A <- 1 f_ROS <- 0
Typically in naive cells, the ER is full of Calcium ions. As long as there is no IP3 signal that pattern should be stable (whatever the other input values) providing that there was Calcium at some point in any of the compartments (ER or cytoplasm).
class TestCalciumQuiescent(CalciumModuleTestCase):
# Note: changing core_vals was restricting core components values, thus setting up unwanted perturbations.
# To implement this test, I need to find a set up where I can specify that there is calcium either
# in the ER or the cytoplasm in the initial state.
input_vals = {}
core_vals = {}
pattern = None
resting_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.resting_tp = [tp for tp in biolqm.trapspaces(cls.model) if tp["IP3"]==0]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test if all trap spaces correspond to either an absence of Calcium everywhere or presence of Calcium in the ER.
def test_calc_tp_rest_nbtp(self):
no_calcium = len([tp for tp in self.resting_tp if tp["Calcium_ER"]==0 and tp["Calcium_cyt_b1"]==0 and tp["Calcium_cyt_b1"]==0])
calcium_in_er = len([tp for tp in self.resting_tp if tp["Calcium_ER"]==1])
observed = no_calcium+calcium_in_er
expected = len(self.resting_tp)
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:0} then all", str(expected), "TS correspond to no Ca or Ca in ER.")),
observed))
# Test that when there is no Calcium in the ER it means that there is no Calcium anywhere
# This is a biologically incorrect case (see class documentation).
def test_calc_tp_rest_noCalcium(self):
no_calcium_in_ER = len([tp for tp in self.resting_tp if tp["Calcium_ER"]==0])
no_calcium_anywhere = len([tp for tp in self.resting_tp if tp["Calcium_ER"]==0 and tp["Calcium_cyt_b1"]==0 and tp["Calcium_cyt_b1"]==0])
observed = no_calcium_in_ER
expected = no_calcium_anywhere
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:0,Calcium_ER:0} then Calcium_cyt:0, nb cases: ", str(expected))),
observed))
# Test that there exist at least one case where the ER is filled with Calcium.
def test_calc_tp_rest_ER1_present(self):
calcium_in_er = len([tp for tp in self.resting_tp if tp["Calcium_ER"]==1])
observed = calcium_in_er
not_expected = 0
self.assertTrue(observed > not_expected,
self.addcontext("".join(("If {IP3:0,Calcium_ER:1} then there is more than ", str(not_expected), " trap spaces.")),
observed))
# Test that when the ER is filled, SERCA is inactive
def test_calc_tp_rest_ER1_SERCA0(self):
calcium_in_er = [tp for tp in self.resting_tp if tp["Calcium_ER"]==1]
for tp in calcium_in_er:
observed = tp["SERCA"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:0,Calcium_ER:1} then SERCA:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that when there is no input signal and the ER is filled,
# Calcium never reaches a sufficient level to activate downstream signalling.
def test_calc_tp_rest_ER1_cyt1(self):
calcium_in_er = [tp for tp in self.resting_tp if tp["ZAP70"]==0 and tp["WAVE_cplx"]==0 and tp["Calcium_ER"]==1]
for tp in calcium_in_er:
observed = tp["Calcium_cyt_b2"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:0,ZAP70:0,WAVE_cplx:0,Calcium_ER:1} then Calcium_cyt_b2:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Add tests to the current suite
calcium_suite.addTests(unittest.makeSuite(TestCalciumQuiescent, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestCalciumQuiescent, prefix="test_"))
test_calc_tp_rest_ER1_SERCA0 (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_ER1_cyt1 (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_ER1_present (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_nbtp (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_noCalcium (__main__.TestCalciumQuiescent) ... ok ---------------------------------------------------------------------- Ran 5 tests in 0.342s OK
Important analysis for TCR activation as this will determine the calcium signal sent downstream IP3 when all input signals are on. In summary, the ER compartment get emptied while cytoplasm becomes full (level2) thanks to the presence of Mitochondria buffering the calcium influx far from ORAI1 and PMCA.
IP3 | ZAP70 | WAVE_cplx | IP3R1 | Calcium_cyt | Calcium_ER | SERCA | STIM1 | ORAI1 | PMCA | Mitochondria |
---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 1 | * | * | 1 | * | * | * | * | * |
Expected : | ||||||||||
1 | 1 | 1 | 1 | 2 | 0 | 1 | 1 | 1 | 0 | 1 |
More specifically: IP3R1 gets activated by IP3. STIM1 is activated by the drop in Calcium_ER. SERCA gets activated by the drop in Calcium_ER but is not able to refill ER as long as IP3R1 stays active. SERCA alone cannot make Calcium_cyt:2 drop. ORAI1 allows Calcium_cyt to increase to level 2 and is not de-activated by the increase of cytoplasmic Calcium thanks to the translocation of mitochondria acting as a buffer. PMCA is inactive also thanks to mitochondrial translocation.
class TestCalciumActivation(CalciumModuleTestCase):
# Note: changing core_vals was restricting core components values, thus setting up unwanted perturbations.
# To implement this test, I need to find a set up where I can specify that there is calcium either
# in the ER or the cytoplasm in the initial state.
input_vals = {}
core_vals = {}
pattern = None
active_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.active_tp = [tp for tp in biolqm.trapspaces(cls.model) if tp["IP3"]==1]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test that there exist at least one trap space.
def test_calc_tp_act_tppresent(self):
observed = len(self.active_tp)
not_expected = 0
self.assertTrue(observed > not_expected,
self.addcontext("".join(("If {IP3:1} then there is more than ", str(not_expected), " trap spaces.")),
observed))
# Test that when there is no cytoskeletal remodelling there is no Mitochondrial translocation (and cytoplasmic Calcium cannot reach its maximal level).
def test_calc_tp_act_nomitochondria(self):
no_cytoskeleton = [tp for tp in self.active_tp if tp["ZAP70"]==0 and tp["WAVE_cplx"]==1]
for tp in no_cytoskeleton:
observed = tp["Mitochondria"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:1,ZAP70:0,WAVE_cplx:1} then Mitochondria:", str(expected))),
observed))
# Test that when all input signals are present, there exist only one trap space.
def test_calc_tp_act_allinput_tpalone(self):
observed = len([tp for tp in self.active_tp if tp["ZAP70"]==1 and tp["WAVE_cplx"]==1])
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:1,ZAP70:1,WAVE_cplx:1} then there is exactly ", str(expected), " trap spaces.")),
observed))
# Test that when all input signals are present, ER is empty.
def test_calc_tp_act_allinput_ER0(self):
allinput = [tp for tp in self.active_tp if tp["ZAP70"]==1 and tp["WAVE_cplx"]==1]
for tp in allinput:
observed = tp["Calcium_ER"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:1,ZAP70:1,WAVE_cplx:1} then Calcium_ER:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that when all input signals are present,
# SERCA is activated.
def test_calc_tp_act_allinput_SERCA1(self):
allinput = [tp for tp in self.active_tp if tp["ZAP70"]==1 and tp["WAVE_cplx"]==1]
for tp in allinput:
observed = tp["SERCA"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:1,ZAP70:1,WAVE_cplx:1} then SERCA:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that when all input signals are present,
# Calcium cytoplasmic reaches a sufficient level to activate downstream signalling.
def test_calc_tp_act_allinput_Cyt2(self):
allinput = [tp for tp in self.active_tp if tp["ZAP70"]==1 and tp["WAVE_cplx"]==1]
for tp in allinput:
observed = tp["Calcium_cyt_b2"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:1,ZAP70:1,WAVE_cplx:1} then Calcium_cyt_b2:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that when all input signals are present,
# we observe mitochondrial translocation.
def test_calc_tp_act_allinput_Mit1(self):
allinput = [tp for tp in self.active_tp if tp["ZAP70"]==1 and tp["WAVE_cplx"]==1]
for tp in allinput:
observed = tp["Mitochondria"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {IP3:1,ZAP70:1,WAVE_cplx:1} then Mitochondria:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Add tests to the current suite
calcium_suite.addTests(unittest.makeSuite(TestCalciumActivation, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestCalciumActivation, prefix="test_"))
test_calc_tp_act_allinput_Cyt2 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_ER0 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_Mit1 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_SERCA1 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_tpalone (__main__.TestCalciumActivation) ... ok test_calc_tp_act_nomitochondria (__main__.TestCalciumActivation) ... ok test_calc_tp_act_tppresent (__main__.TestCalciumActivation) ... ok ---------------------------------------------------------------------- Ran 7 tests in 0.126s OK
# Add tests to the global suite
all_suite.addTests(calcium_suite)
# Run these tests independently
if debug_test_suites : runner.run(calcium_suite)
test_calc_tp_rest_ER1_SERCA0 (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_ER1_cyt1 (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_ER1_present (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_nbtp (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_noCalcium (__main__.TestCalciumQuiescent) ... ok test_calc_tp_act_allinput_Cyt2 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_ER0 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_Mit1 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_SERCA1 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_tpalone (__main__.TestCalciumActivation) ... ok test_calc_tp_act_nomitochondria (__main__.TestCalciumActivation) ... ok test_calc_tp_act_tppresent (__main__.TestCalciumActivation) ... ok ---------------------------------------------------------------------- Ran 12 tests in 0.370s OK
T Cell Receptors (TCRs) bind antigens, allowins both sensitivity and specificity in the subsequent signal transmission depending on affinity and dosage.
LCK is the major kinase involved in transduction of the TCR signal as it is responsible for the phosphorylation of TCRs and of its main interactor, ZAP70. But its regulation follows complex rules based on its phosphorylation state, constraining its folding and by consequence its activity. In parallel, FYN is subject to a similar regulation, but our knowledge is less detailed.
These two elements, TCR and LCK are at the core of the current module. For a review on the initiation of TCR signalling and the activity of LCK depending on its phosphorylation state, see PMID:25137454.
Additional hypotheses and decisions were needed to build the logical model:
# Test suite for all LCK-related tests.
lck_suite = unittest.TestSuite()
class LCKModuleTestCase(unittest.TestCase):
"""Sub-model to be tested."""
model = biolqm.submodel(lqm,
" ".join(("i_pMHCII_binding i_pMHCII_agonist i_pMHCII_dose i_pMHCII_affinity TCRalphabeta pTCR",
"LCK pY505LCK pY394LCK pS59LCK LCK_activity",
"PTPRC PAG1 CSK PTPN22 CD4 LIME1",
"FYN"
)))
str([component.toString() for component in LCKModuleTestCase.model.getComponents()])
"['i_pMHCII_binding', 'i_pMHCII_agonist', 'i_pMHCII_dose', 'i_pMHCII_affinity', 'TCRalphabeta', 'pTCR', 'CD28', 'PKA', 'CD4', 'f_MAL', 'f_UNC119', 'f_RAB11A', 'LCK', 'pY505LCK', 'pY394LCK', 'pS59LCK', 'LCK_activity', 'CSK', 'PAG1', 'LIME1', 'PTPN6', 'PTPN22', 'PTPRC', 'PTPN11', 'FYN', 'MAPK3', 'MAPK1']"
biolqm.to_minibn(LCKModuleTestCase.model)
CD28 <- CD28 CD4 <- i_pMHCII_binding CSK <- (!PKA&!PAG1&LIME1)|(!PKA&PAG1)|PKA FYN <- LCK_activity LCK <- (!f_MAL&f_UNC119&f_RAB11A)|f_MAL LCK_activity <- (!CD28&CD4&!pY505LCK&pY394LCK)|(!CD28&CD4&pY505LCK&pY394LCK&LIME1)|(CD28&!pY505LCK&pY394LCK)|(CD28&pY505LCK&pY394LCK&LIME1) LIME1 <- CD4 MAPK1 <- MAPK1 MAPK3 <- MAPK3 PAG1 <- !TCRalphabeta PKA <- PKA PTPN11 <- PTPN11 PTPN22 <- CSK&!LIME1 PTPN6 <- PTPN6 PTPRC <- !TCRalphabeta TCRalphabeta <- (i_pMHCII_binding&i_pMHCII_agonist&!i_pMHCII_dose&i_pMHCII_affinity&!PTPN11)|(i_pMHCII_binding&i_pMHCII_agonist&i_pMHCII_dose&!i_pMHCII_affinity&!PTPN11) f_MAL <- 1 f_RAB11A <- 1 f_UNC119 <- 1 i_pMHCII_affinity <- i_pMHCII_affinity i_pMHCII_agonist <- i_pMHCII_agonist i_pMHCII_binding <- i_pMHCII_binding i_pMHCII_dose <- i_pMHCII_dose pS59LCK <- (LCK&!pS59LCK&!MAPK3&MAPK1)|(LCK&!pS59LCK&MAPK3)|(LCK&pS59LCK) pTCR <- (TCRalphabeta&!LCK_activity&!PTPN22&FYN)|(TCRalphabeta&LCK_activity&!PTPN22) pY394LCK <- (LCK&!pS59LCK&!LIME1&!PTPN6&!PTPN22&!PTPRC)|(LCK&!pS59LCK&LIME1&!PTPN6&!PTPN22)|(LCK&pS59LCK&!LIME1&!PTPN22&!PTPRC)|(LCK&pS59LCK&LIME1&!PTPN22) pY505LCK <- (LCK&!pY505LCK&CSK&!LIME1&!PTPRC)|(LCK&!pY505LCK&CSK&LIME1)|(LCK&pY505LCK&!LIME1&!PTPRC)|(LCK&pY505LCK&LIME1)
If the T cell doesn't receive any signal through the TCR, i.e. if there is no antigen whatsoever binding to it, LCK should never be in a configuration that can give rise to sufficient phosphorylation of the neighbouring TCR complexes.
class TestLCKResting(LCKModuleTestCase):
input_vals = {}
core_vals = {}
pattern = None
resting_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.resting_tp = [tp for tp in biolqm.trapspaces(cls.model) if tp["i_pMHCII_binding"]==0]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test that in absence of any binding to the TCR, LCK is inactive
def test_lck_tp_rest_lcknotactive(self):
for tp in self.resting_tp:
observed = tp["LCK_activity"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {i_pMHCII_binding:0} then LCK_activity:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that in absence of any binding to the TCR, LCK is inactive
def test_lck_tp_rest_tcrnotp(self):
for tp in self.resting_tp:
observed = tp["pTCR"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {i_pMHCII_binding:0} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Add tests to the current suite
lck_suite.addTests(unittest.makeSuite(TestLCKResting, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestLCKResting, prefix="test_"))
test_lck_tp_rest_lcknotactive (__main__.TestLCKResting) ... ok test_lck_tp_rest_tcrnotp (__main__.TestLCKResting) ... ok ---------------------------------------------------------------------- Ran 2 tests in 23.624s OK
T Cell receptors can be bound by many antigens, but not all of them are agonist nor have the correct affinity and dose to elicit activation of the T Cell. More precisely, in the model, a productive signal (as measured by the level of phosphorylated TCR) should not be observed in these cases. In parallel, the possible phosphorylation states of LCK change, allowing it to become active. But the global context should prevent it to have an impact on pTCR.
Note that MAPK1 and MAPK3 being only activated by the feedback signal caused by a first activation of the signalling cascade downstream of the TCR, the cases where they are turned on are not considered in the following tests.
class TestLCKNonProd(LCKModuleTestCase):
input_vals = {}
core_vals = {}
pattern = None
nonprod_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.nonprod_tp = [tp for tp in biolqm.trapspaces(cls.model) if tp["i_pMHCII_binding"]==1 and
tp["MAPK1"]==0 and tp["MAPK3"]==0 and
not (tp["i_pMHCII_agonist"]==1 and tp["i_pMHCII_dose"]==0 and tp["i_pMHCII_affinity"]==1 or
tp["i_pMHCII_agonist"]==1 and tp["i_pMHCII_dose"]==1 and tp["i_pMHCII_affinity"]==0)]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test that with an antagonist antigen binding, pTCR is always off
def test_lck_tp_antigenantag_ptcr(self):
antagonist_tp = [tp for tp in self.nonprod_tp if tp["i_pMHCII_agonist"]==0]
for tp in antagonist_tp:
observed = tp["pTCR"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {i_pMHCII_binding:1,i_pMHCII_agonist:0,MAPK1:0,MAPK3:0} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that with an agonist antigen binding, but with dose and affinity too low
def test_lck_tp_antigenaglow_ptcr(self):
antagonist_tp = [tp for tp in self.nonprod_tp if tp["i_pMHCII_agonist"]==1 and
tp["i_pMHCII_dose"]==0 and tp["i_pMHCII_affinity"]==0]
for tp in antagonist_tp:
observed = tp["pTCR"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {i_pMHCII_binding:1,i_pMHCII_agonist:0,MAPK1:0,MAPK3:0,i_pMHCII_dose:0,i_pMHCII_affinity:0} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that with an agonist antigen binding, but with dose and affinity too low
def test_lck_tp_antigenaghigh_ptcr(self):
antagonist_tp = [tp for tp in self.nonprod_tp if tp["i_pMHCII_agonist"]==1 and
tp["i_pMHCII_dose"]==1 and tp["i_pMHCII_affinity"]==1]
for tp in antagonist_tp:
observed = tp["pTCR"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {i_pMHCII_binding:1,i_pMHCII_agonist:0,MAPK1:0,MAPK3:0,i_pMHCII_dose:1,i_pMHCII_affinity:1} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Add tests to the current suite
lck_suite.addTests(unittest.makeSuite(TestLCKNonProd, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestLCKNonProd, prefix="test_"))
test_lck_tp_antigenaghigh_ptcr (__main__.TestLCKNonProd) ... ok test_lck_tp_antigenaglow_ptcr (__main__.TestLCKNonProd) ... ok test_lck_tp_antigenantag_ptcr (__main__.TestLCKNonProd) ... ok ---------------------------------------------------------------------- Ran 3 tests in 23.168s OK
T Cell receptors bound by an agonist antigen with either a low dose and high affinity or high dose and low affinity can elicit a successful signalling downstream of the TCR. Whether this signal will elicit an activation of the cell depends on the activity of the necessary co-activator CD28.
All tests below are performed in the context of a productive agonist (dose:low/affinity:high or dose:high/affinity:low).
We are also interested in the relationship between PTPN6 and MAPK1/MAPK3, activated by a feedback signal (after a first activation of the signalling cascade downstream of the TCR).
class TestLCKProd(LCKModuleTestCase):
input_vals = {}
core_vals = {}
pattern = None
prod_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.prod_tp = [tp for tp in biolqm.trapspaces(cls.model) if tp["i_pMHCII_binding"]==1 and
tp["i_pMHCII_agonist"]==1 and
(tp["i_pMHCII_dose"]==0 and tp["i_pMHCII_affinity"]==1 or
tp["i_pMHCII_dose"]==1 and tp["i_pMHCII_affinity"]==0)]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test that with an agonist antigen binding with good dose/affinity (no feedback, no costimulation),
# pTCR is always on (this doesn't mean that the cell will be activated!)
def test_lck_tp_antigenag_ptcr_nocostim_nofeedback(self):
agonist10_tp = [tp for tp in self.prod_tp if tp["CD28"]==0 and tp["MAPK1"]==0 and tp["MAPK3"]==0 and
tp["PTPN6"]==0 and tp["PTPN11"]==0]
for tp in agonist10_tp:
observed = tp["pTCR"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {CD28:0,MAPK1:0,MAPK3:0,PTPN6:0,PTPN11:0} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that with an agonist antigen binding with good dose/affinity and costimulation through CD28
# but no co-inhibition, pTCR is always on
def test_lck_tp_antigenag_ptcr_costim_nonegcostim(self):
agonist_tp = [tp for tp in self.prod_tp if tp["CD28"]==1 and tp["PTPN6"]==0 and tp["PTPN11"]==0]
for tp in agonist_tp:
observed = tp["pTCR"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {CD28:1,PTPN6:0,PTPN11:0} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test negative co-stimulation by PTPN6 without protective feedback, pTCR is always off
# NB: would fail when pS59LCK is initialized at 1 without MAPK1/MAPK3 being active...
def test_lck_tp_antigenag_ptcr_negcostim_PTPN6_nofeedback(self):
agonist_tp = [tp for tp in self.prod_tp if tp["PTPN6"]==1 and tp["PTPN11"]==0 and
tp["MAPK1"]==0 and tp["MAPK3"]==0 and tp["pS59LCK"]==0]
for tp in agonist_tp:
observed = tp["pTCR"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PTPN6:1,PTPN11:0,MAPK1:0,MAPK3:0,pS59LCK:0} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test negative co-stimulation through PTPN6 with protective feedback, pTCR is always on
def test_lck_tp_antigenag_ptcr_negcostim_PTPN6_feedback(self):
agonist_tp = [tp for tp in self.prod_tp if tp["PTPN6"]==1 and tp["PTPN11"]==0 and
(tp["MAPK1"]==1 or tp["MAPK3"]==1)]
for tp in agonist_tp:
observed = tp["pTCR"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PTPN6:1,PTPN11:0,MAPK1:1/MAPK3:1} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test negative co-stimulation through PTPN11 (whatever the context), pTCR is always off
def test_lck_tp_antigenag_ptcr_negcostim_PTPN11(self):
agonist_tp = [tp for tp in self.prod_tp if tp["PTPN11"]==1]
for tp in agonist_tp:
observed = tp["pTCR"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PTPN11:1} then pTCR:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Add tests to the current suite
lck_suite.addTests(unittest.makeSuite(TestLCKProd, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestLCKProd, prefix="test_"))
test_lck_tp_antigenag_ptcr_costim_nonegcostim (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN11 (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN6_feedback (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN6_nofeedback (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_nocostim_nofeedback (__main__.TestLCKProd) ... ok ---------------------------------------------------------------------- Ran 5 tests in 24.212s OK
# Add tests to the global suite
all_suite.addTests(lck_suite)
# Run these tests independently
if debug_test_suites : runner.run(lck_suite)
test_lck_tp_rest_lcknotactive (__main__.TestLCKResting) ... ok test_lck_tp_rest_tcrnotp (__main__.TestLCKResting) ... ok test_lck_tp_antigenaghigh_ptcr (__main__.TestLCKNonProd) ... ok test_lck_tp_antigenaglow_ptcr (__main__.TestLCKNonProd) ... ok test_lck_tp_antigenantag_ptcr (__main__.TestLCKNonProd) ... ok test_lck_tp_antigenag_ptcr_costim_nonegcostim (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN11 (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN6_feedback (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN6_nofeedback (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_nocostim_nofeedback (__main__.TestLCKProd) ... ok ---------------------------------------------------------------------- Ran 10 tests in 75.744s OK
As seen in the analysis of the Calcium module, activated T cells undergo strong cytoskeleton remodelling which has important consequences downstream of the TCR and for other processes.
# Test suite for all cytoskeleton-related tests.
sk_suite = unittest.TestSuite()
class CytoskeletonModuleTestCase(unittest.TestCase):
"""Sub-model to be tested."""
model = biolqm.submodel(lqm,
" ".join(("WAVE_cplx RAC1 NCK1 RHOA CDC42 PAK1 WAS ARP2_3 LIMK1 CFL1",
"Actin_polymerisation HCLS1 ROCK1 MLCP Actin_contraction_migration"
)))
str([component.toString() for component in CytoskeletonModuleTestCase.model.getComponents()])
"['f_NCKAP1L', 'f_NCKAP1', 'f_BAIAP2', 'f_CYFIP1', 'f_BRK1', 'f_WASF2', 'f_ABI1', 'f_ABI2', 'f_ACTR2', 'f_ACTR3', 'LCP2', 'PIP2', 'PIP3', 'NCK1', 'CDC42', 'WAS', 'RAC1', 'WAVE_cplx', 'ARP2_3', 'PAK1', 'LIMK1', 'CFL1', 'HCLS1', 'VAV1', 'ABL1', 'Actin_polymerisation', 'RHOA', 'ROCK1', 'MLCP', 'Actin_contraction_migration']"
biolqm.to_minibn(CytoskeletonModuleTestCase.model)
ABL1 <- ABL1 ARP2_3 <- (f_ACTR2&f_ACTR3&!WAS&WAVE_cplx)|(f_ACTR2&f_ACTR3&WAS) Actin_contraction_migration <- Actin_polymerisation&!MLCP Actin_polymerisation <- (ARP2_3&!CFL1)|(ARP2_3&CFL1&HCLS1) CDC42 <- VAV1 CFL1 <- !LIMK1 HCLS1 <- ABL1&Actin_polymerisation LCP2 <- LCP2 LIMK1 <- (!PAK1&ROCK1)|PAK1 MLCP <- !ROCK1 NCK1 <- LCP2&VAV1 PAK1 <- (!CDC42&RAC1)|CDC42 PIP2 <- PIP2 PIP3 <- PIP3 RAC1 <- VAV1 RHOA <- VAV1 ROCK1 <- RHOA VAV1 <- VAV1 WAS <- PIP2&NCK1&CDC42 WAVE_cplx <- (!f_NCKAP1L&f_NCKAP1&f_BAIAP2&f_CYFIP1&f_BRK1&f_WASF2&!f_ABI1&f_ABI2&PIP3&RAC1&ABL1)|(!f_NCKAP1L&f_NCKAP1&f_BAIAP2&f_CYFIP1&f_BRK1&f_WASF2&f_ABI1&PIP3&RAC1&ABL1)|(f_NCKAP1L&f_BAIAP2&f_CYFIP1&f_BRK1&f_WASF2&!f_ABI1&f_ABI2&PIP3&RAC1&ABL1)|(f_NCKAP1L&f_BAIAP2&f_CYFIP1&f_BRK1&f_WASF2&f_ABI1&PIP3&RAC1&ABL1) f_ABI1 <- 1 f_ABI2 <- 1 f_ACTR2 <- 1 f_ACTR3 <- 1 f_BAIAP2 <- 1 f_BRK1 <- 1 f_CYFIP1 <- 1 f_NCKAP1 <- 1 f_NCKAP1L <- 1 f_WASF2 <- 1
Complete absence of both PIP2 and PIP3 is not biologically correct. This case should not activate any of the phenotypes. The state of other components cannot be interpreted.
class TestCytoskeletonNonBio(CytoskeletonModuleTestCase):
input_vals = {}
core_vals = {}
pattern = None
nonbio_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.nonbio_tp = [tp for tp in biolqm.trapspaces(cls.model) if tp["PIP2"]==0]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test that in absence of PIP2/PIP3, there is no migration
def test_sk_tp_nopip_nomigration(self):
nopip_tp = [tp for tp in self.nonbio_tp if tp["PIP3"]==0]
for tp in nopip_tp:
observed = tp["Actin_contraction_migration"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PIP2:0,PIP3:0} then Actin_contraction_migration:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that in absence of PIP2/PIP3, there is no actin polymerisation
def test_sk_tp_nopip_nopolymerisation(self):
nopip_tp = [tp for tp in self.nonbio_tp if tp["PIP3"]==0]
for tp in nopip_tp:
observed = tp["Actin_polymerisation"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PIP2:0,PIP3:0} then Actin_polymerisation:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Add tests to the current suite
sk_suite.addTests(unittest.makeSuite(TestCytoskeletonNonBio, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestCytoskeletonNonBio, prefix="test_"))
test_sk_tp_nopip_nomigration (__main__.TestCytoskeletonNonBio) ... ok test_sk_tp_nopip_nopolymerisation (__main__.TestCytoskeletonNonBio) ... ok ---------------------------------------------------------------------- Ran 2 tests in 0.791s OK
In the absence of any received signal (through LCK/LCP2 or CD28), VAV1 being inactive, T cells don't go through any cytoskeleton remodelling. WAS cannot be activated. Cofilin (CFL1) and Protein phosphatase 1 regulatory subunit 12A (MLCP) are active, inhibiting the processes.
class TestCytoskeletonResting(CytoskeletonModuleTestCase):
input_vals = {}
core_vals = {}
pattern = None
resting_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.resting_tp = [tp for tp in biolqm.trapspaces(cls.model) if not(tp["PIP2"]==0 and tp["PIP3"]==0)]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test that in absence of kinase, there is no migration
def test_sk_tp_rest_nomigration(self):
inactive_tp = [tp for tp in self.resting_tp if tp["VAV1"]==0]
for tp in inactive_tp:
observed = tp["MLCP"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {VAV1:0} then MLCP:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
for tp in inactive_tp:
observed = tp["Actin_contraction_migration"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {VAV1:0} then Actin_contraction_migration:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that in absence of kinase, there is no polymerisation
def test_sk_tp_rest_nopolymerisation(self):
inactive_tp = [tp for tp in self.resting_tp if tp["VAV1"]==0]
for tp in inactive_tp:
observed = tp["CFL1"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {VAV1:0} then CFL1:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
for tp in inactive_tp:
observed = tp["Actin_polymerisation"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {VAV1:0} then Actin_polymerisation:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that with PIP2 but no signal from VAV1 or from LCP2, the WAS complex cannot be activated
def test_sk_tp_rest_pip2novav1ornolcp2(self):
inactive_tp = [tp for tp in self.resting_tp if tp["PIP2"]==1 and (tp["VAV1"]==0 or tp["LCP2"]==0)]
for tp in inactive_tp:
observed = tp["WAS"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PIP2:1,VAV1:0/LCP2:0} then WAS:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Add tests to the current suite
sk_suite.addTests(unittest.makeSuite(TestCytoskeletonResting, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestCytoskeletonResting, prefix="test_"))
test_sk_tp_rest_nomigration (__main__.TestCytoskeletonResting) ... ok test_sk_tp_rest_nopolymerisation (__main__.TestCytoskeletonResting) ... ok test_sk_tp_rest_pip2novav1ornolcp2 (__main__.TestCytoskeletonResting) ... ok ---------------------------------------------------------------------- Ran 3 tests in 0.720s OK
During activation, T cells undergo cytoskeleton remodelling. In a first step, using PIP2, activated WAS induces actin polymerisation. Secondly, if a co-activating signal is also present, PIP3 production allows the WAVE complex to take over WAS activity.
class TestCytoskeletonActivated(CytoskeletonModuleTestCase):
input_vals = {}
core_vals = {}
pattern = None
activ_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.activ_tp = [tp for tp in biolqm.trapspaces(cls.model) if not(tp["PIP2"]==0 and tp["PIP3"]==0)]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test that in absence of PIP2, WAS cannot be activated
def test_sk_tp_nopip2_nowas(self):
nopip2_tp = [tp for tp in self.activ_tp if tp["PIP2"]==0]
for tp in nopip2_tp:
observed = tp["WAS"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PIP2:0} then WAS:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that in absence of PIP3, the WAVE complex cannot be activated
def test_sk_tp_nopip3_nowave(self):
nopip3_tp = [tp for tp in self.activ_tp if tp["PIP3"]==0]
for tp in nopip3_tp:
observed = tp["WAVE_cplx"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PIP3:0} then WAVE_cplx:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that with PIP2 and VAV1 and LCP2, the WAS complex is activated
def test_sk_tp_activ_pip2vav1lcp2(self):
signal_tp = [tp for tp in self.activ_tp if tp["PIP2"]==1 and tp["VAV1"]==1 and tp["LCP2"]==1]
for tp in signal_tp:
observed = tp["WAS"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PIP2:1,VAV1:1,LCP2:1} then WAS:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that with PIP3 and VAV1 and ABL1, the WAVE complex is activated
def test_sk_tp_activ_pip3vav1abl1(self):
signal_tp = [tp for tp in self.activ_tp if tp["PIP3"]==1 and tp["VAV1"]==1 and tp["ABL1"]==1]
for tp in signal_tp:
observed = tp["WAVE_cplx"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {PIP3:1,VAV1:1,ABL1:1} then WAVE_cplx:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that with WAS active, there is actin polymerisation
def test_sk_tp_activ_was(self):
signal_tp = [tp for tp in self.activ_tp if tp["WAS"]==1]
for tp in signal_tp:
observed = tp["Actin_polymerisation"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {WAS:1} then Actin_polymerisation:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that with WAVE_cplx active, there is actin polymerisation
def test_sk_tp_activ_wave(self):
signal_tp = [tp for tp in self.activ_tp if tp["WAVE_cplx"]==1]
for tp in signal_tp:
observed = tp["Actin_polymerisation"]
expected = 1
self.assertEqual(observed, expected,
self.addcontext("".join(("If {WAVE_cplx:1} then Actin_polymerisation:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Test that in absence of VAV1, there is no actin contraction/migration
def test_sk_tp_activ_novav1_nomigration(self):
nopip3_tp = [tp for tp in self.activ_tp if tp["VAV1"]==0]
for tp in nopip3_tp:
observed = tp["Actin_contraction_migration"]
expected = 0
self.assertEqual(observed, expected,
self.addcontext("".join(("If {VAV1:0} then Actin_contraction_migration:", str(expected))),
" ".join((str(observed), "in", str(tp))) ))
# Add tests to the current suite
sk_suite.addTests(unittest.makeSuite(TestCytoskeletonActivated, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestCytoskeletonActivated, prefix="test_"))
test_sk_tp_activ_novav1_nomigration (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_pip2vav1lcp2 (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_pip3vav1abl1 (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_was (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_wave (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_nopip2_nowas (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_nopip3_nowave (__main__.TestCytoskeletonActivated) ... ok ---------------------------------------------------------------------- Ran 7 tests in 0.394s OK
# Add tests to the global suite
all_suite.addTests(sk_suite)
# Run these tests independently
if debug_test_suites : runner.run(sk_suite)
test_sk_tp_nopip_nomigration (__main__.TestCytoskeletonNonBio) ... ok test_sk_tp_nopip_nopolymerisation (__main__.TestCytoskeletonNonBio) ... ok test_sk_tp_rest_nomigration (__main__.TestCytoskeletonResting) ... ok test_sk_tp_rest_nopolymerisation (__main__.TestCytoskeletonResting) ... ok test_sk_tp_rest_pip2novav1ornolcp2 (__main__.TestCytoskeletonResting) ... ok test_sk_tp_activ_novav1_nomigration (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_pip2vav1lcp2 (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_pip3vav1abl1 (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_was (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_wave (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_nopip2_nowas (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_nopip3_nowave (__main__.TestCytoskeletonActivated) ... ok ---------------------------------------------------------------------- Ran 12 tests in 2.234s OK
The model adresses two main events related to T cell stimulation. First, after the TCR receives a sufficient stimulation, it shifts from Quiescence to Proliferation. Second, an insufficient stimulation doesn't lead to IL2 production but to a different program called Anergy, where cells enter an iresponsive state (PMID:15928679).
# Test suite for this sub-model's related tests.
aad_suite = unittest.TestSuite()
class ActivationModuleTestCase(unittest.TestCase):
"""Sub-model to be tested."""
model = biolqm.submodel(lqm,
" ".join(("Anergy Differentiation Treg IL2 NFAT_nuc DGKA FOXP3 CREBBP CTLA4_out PDCD1_out",
"GSK3B FOXO1 TP53 CDKN1A CDKN1B CTNNB1 MYC PCNA CCND1 Quiescence Proliferation"
)))
str([component.toString() for component in ActivationModuleTestCase.model.getComponents()])
"['f_14_3_3', 'f_MDM2', 'f_Axin1', 'f_SMAD3', 'AKT1', 'FOXO1', 'GSK3B', 'TP53', 'CDKN1A', 'CDKN1B', 'Quiescence', 'PCNA', 'CTNNB1', 'CCND1', 'MYC', 'Proliferation', 'NF_KB', 'CREBBP', 'FOXP3', 'CTLA4_out', 'Treg', 'RPS6KA1', 'Calcineurin', 'NFAT_nuc', 'PDCD1_out', 'DGKA', 'Anergy', 'FOS', 'JUN', 'p38', 'RPS6KA5', 'CREB1', 'IL2', 'Differentiation']"
biolqm.to_minibn(ActivationModuleTestCase.model)
AKT1 <- AKT1 Anergy <- NFAT_nuc&DGKA&!FOS&!JUN CCND1 <- CTNNB1 CDKN1A <- !AKT1&TP53 CDKN1B <- f_SMAD3&!AKT1&FOXO1&!RPS6KA1 CREB1 <- CREB1 CREBBP <- !NF_KB CTLA4_out <- FOXP3 CTNNB1 <- !f_Axin1&!GSK3B Calcineurin <- Calcineurin DGKA <- FOXO1&NFAT_nuc Differentiation <- IL2 FOS <- FOS FOXO1 <- !f_14_3_3&!AKT1 FOXP3 <- f_SMAD3&FOXO1&NF_KB&CREBBP&NFAT_nuc&CREB1 GSK3B <- !AKT1&!RPS6KA1 IL2 <- NF_KB&NFAT_nuc&FOS&JUN JUN <- JUN MYC <- CTNNB1&RPS6KA5 NFAT_nuc <- !GSK3B&Calcineurin NF_KB <- NF_KB PCNA <- !CDKN1A PDCD1_out <- NFAT_nuc Proliferation <- PCNA&CCND1&MYC&IL2 Quiescence <- (FOXO1&!CDKN1A&CDKN1B)|(FOXO1&CDKN1A) RPS6KA1 <- RPS6KA1 RPS6KA5 <- RPS6KA5 TP53 <- !f_MDM2|(f_MDM2&p38) Treg <- FOXP3 f_14_3_3 <- 0 f_Axin1 <- 0 f_MDM2 <- 0 f_SMAD3 <- 0 p38 <- p38
class TestActivationModule(ActivationModuleTestCase):
input_vals = {}
core_vals = {}
pattern = None
all_tp = None
@classmethod
def setUpClass(cls):
cls.pattern = dash_pattern(cls.model, {**cls.input_vals, **cls.core_vals})
cls.all_tp = [tp for tp in biolqm.trapspaces(cls.model)]
def addcontext(self, message, observed):
return(" ".join(("Pattern:", self.pattern, "\n",
"Context:", str(self.input_vals), str(self.core_vals), "\n",
"Tested:", message, "\n",
"Observed:", str(observed), ".\n")))
# Test that Proliferation and Quiescence cannot be activated together
def test_aad_tp_quiescence_prolif(self):
for tp in self.all_tp:
observed = tp["Quiescence"]
observed2 = tp["Proliferation"]
not_expected = 1
self.assertFalse((observed==observed2 and observed==not_expected),
self.addcontext("".join(("Quiescence:", str(observed),
" and Proliferation:", str(observed2),
" should be different ")),
" ".join((str(observed!=observed2), "in", str(tp))) ))
# Test that if Anergy is activated, IL2 is not
def test_aad_tp_anergy_il2(self):
for tp in self.all_tp:
observed = tp["Anergy"]
observed2 = tp["IL2"]
not_expected = 1
self.assertFalse((observed==observed2 and observed==not_expected),
self.addcontext("".join(("Anergy:", str(observed),
" and IL2:", str(observed2),
" should be different ")),
" ".join((str(observed!=observed2), "in", str(tp))) ))
# Add tests to the current suite
aad_suite.addTests(unittest.makeSuite(TestActivationModule, prefix="test_"))
# Run these tests independently
if debug_test_cases : runner.run(unittest.makeSuite(TestActivationModule, prefix="test_"))
test_aad_tp_anergy_il2 (__main__.TestActivationModule) ... ok test_aad_tp_quiescence_prolif (__main__.TestActivationModule) ... ok ---------------------------------------------------------------------- Ran 2 tests in 11.738s OK
# Add tests to the global suite
all_suite.addTests(aad_suite)
# Run these tests independently
if debug_test_suites : runner.run(aad_suite)
test_aad_tp_anergy_il2 (__main__.TestActivationModule) ... ok test_aad_tp_quiescence_prolif (__main__.TestActivationModule) ... ok ---------------------------------------------------------------------- Ran 2 tests in 13.485s OK
# Run global suite
if run_all: result = runner.run(all_suite)
test_calc_tp_rest_ER1_SERCA0 (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_ER1_cyt1 (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_ER1_present (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_nbtp (__main__.TestCalciumQuiescent) ... ok test_calc_tp_rest_noCalcium (__main__.TestCalciumQuiescent) ... ok test_calc_tp_act_allinput_Cyt2 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_ER0 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_Mit1 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_SERCA1 (__main__.TestCalciumActivation) ... ok test_calc_tp_act_allinput_tpalone (__main__.TestCalciumActivation) ... ok test_calc_tp_act_nomitochondria (__main__.TestCalciumActivation) ... ok test_calc_tp_act_tppresent (__main__.TestCalciumActivation) ... ok test_lck_tp_rest_lcknotactive (__main__.TestLCKResting) ... ok test_lck_tp_rest_tcrnotp (__main__.TestLCKResting) ... ok test_lck_tp_antigenaghigh_ptcr (__main__.TestLCKNonProd) ... ok test_lck_tp_antigenaglow_ptcr (__main__.TestLCKNonProd) ... ok test_lck_tp_antigenantag_ptcr (__main__.TestLCKNonProd) ... ok test_lck_tp_antigenag_ptcr_costim_nonegcostim (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN11 (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN6_feedback (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_negcostim_PTPN6_nofeedback (__main__.TestLCKProd) ... ok test_lck_tp_antigenag_ptcr_nocostim_nofeedback (__main__.TestLCKProd) ... ok test_sk_tp_nopip_nomigration (__main__.TestCytoskeletonNonBio) ... ok test_sk_tp_nopip_nopolymerisation (__main__.TestCytoskeletonNonBio) ... ok test_sk_tp_rest_nomigration (__main__.TestCytoskeletonResting) ... ok test_sk_tp_rest_nopolymerisation (__main__.TestCytoskeletonResting) ... ok test_sk_tp_rest_pip2novav1ornolcp2 (__main__.TestCytoskeletonResting) ... ok test_sk_tp_activ_novav1_nomigration (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_pip2vav1lcp2 (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_pip3vav1abl1 (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_was (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_activ_wave (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_nopip2_nowas (__main__.TestCytoskeletonActivated) ... ok test_sk_tp_nopip3_nowave (__main__.TestCytoskeletonActivated) ... ok test_aad_tp_anergy_il2 (__main__.TestActivationModule) ... ok test_aad_tp_quiescence_prolif (__main__.TestActivationModule) ... ok ---------------------------------------------------------------------- Ran 36 tests in 87.404s OK