Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9762716
update default parameter files, including comments
murrayrm Nov 25, 2025
4402cf1
use mechanisms/, mixtures/ for default parameters in most places
murrayrm Nov 26, 2025
17eb058
RNAse, RNAase --> RNase
murrayrm Nov 26, 2025
b33d216
update extract parameters and mechanism to give reasonable expression…
murrayrm Nov 28, 2025
ff32483
update PURE parameters and mechanisms to give reasonable expression l…
murrayrm Nov 28, 2025
e730f69
Add missing PURE parameters + comments for TetR
murrayrm Nov 30, 2025
77206f9
fix issue with multiple toctrees
murrayrm Dec 22, 2025
ba8bc5b
add default parameters to mechanisms
murrayrm Dec 22, 2025
a89efb1
add unit alaiases + checks, tests
murrayrm Dec 22, 2025
831798d
add default parameter files for mechanisms
murrayrm Dec 25, 2025
9e48299
allow part_id to be a list; add binding subtypes
murrayrm Dec 26, 2025
79f6cfc
change 'cooperative_binding' mechanism type to 'binding'
murrayrm Dec 26, 2025
c1c77c1
add missing reverse energy reaction for energy translation
murrayrm Dec 26, 2025
e18e71b
add documentation + code cleanup
murrayrm Dec 27, 2025
469ec28
add (default) parameter files for txtl mechanisms
murrayrm Dec 28, 2025
fbf03d9
add default parameter_file for transport mechanisms
murrayrm Dec 28, 2025
714d5ec
consistent capitalization of BioCRNpyler
murrayrm Dec 28, 2025
32b4302
add default parameter_file for enzyme mechanisms
murrayrm Dec 28, 2025
8869b5d
convert parameter files to pure ASCII
murrayrm Dec 29, 2025
b84d850
fix sbml unit management with the new unit updates in pr320, add othe…
ayush9pandey Apr 26, 2026
22e2ce9
remove unnecessary test in unit params
ayush9pandey Apr 26, 2026
2d9fee8
typo in workflow and add aliases for nL, mL so tests pass
ayush9pandey Apr 27, 2026
2f14b63
ruff format
murrayrm May 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Tests/Combinatorial/test_construct_combinatorially.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ def test_combinatorial_DNAconstruct_in_Mixtures():
for mclass, args in mixture_classes:
# create the Mixture with parameters
args['parameters'] = dict(parameters)
args['parameter_file'] = None
m = mclass(**args)

# Promoters and terminators are instances
Expand Down Expand Up @@ -221,6 +222,7 @@ def test_combinatorial_RNAconstruct_in_Mixtures():
for mclass, args in mixture_classes:
# create the Mixture with parameters
args['parameters'] = dict(parameters)
args['parameter_file'] = None
m = mclass(**args)

# RBSs and CDSs are instances
Expand Down Expand Up @@ -252,6 +254,7 @@ def test_combinatorial_DNAconstruct_RNAconstruct_in_Mixtures():
for mclass, args in mixture_classes:
# create the Mixture with parameters
args['parameters'] = dict(parameters)
args['parameter_file'] = None
m = mclass(**args)

# Promoters and terminators are instances
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,12 @@ def setUp(self) -> None:
self.parameters = {
'kb': 1.0,
'ku': 1.0,
'kb_ntps': 1.0,
'ku_ntps': 1.0,
'ktx': 1.0,
'ktl': 1.0,
'kb_fuel': 1.0,
'ku_fuel': 1.0,
'kdeg': 1.0,
'kdil': 1.0,
'kexpress': 1.0,
Expand Down
2 changes: 1 addition & 1 deletion Tests/Unit/test_compartment.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def test_compartment_in_special_mixtures(self):
)
E = EnergyTxTlExtract(
components=[activatable_assembly],
parameter_file='examples/Specialized Tutorials/txtl_toolbox_parameters.txt',
parameter_file='mixtures/extract_parameters.tsv',
)
CRN_1 = E.compile_crn() # compile CRN

Expand Down
152 changes: 150 additions & 2 deletions Tests/Unit/test_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def test_parameter_entry(self):
parameter_value=1.0,
parameter_key={'part_id': 'id'},
parameter_info={'comment': 'comment', 'unit': 'M'},
unit='m',
unit='uM',
)

# Invalid keys
Expand Down Expand Up @@ -527,7 +527,7 @@ def test_findpath():

# Make sure that files in package can be found
assert os.path.exists(
bcp.find_file_in_bcp_path('components/tetr_parameters.tsv')
bcp.find_file_in_bcp_path('mechanisms/txtl_parameters.tsv')
)

# Make sure we can find files in current directory
Expand All @@ -545,3 +545,151 @@ def test_findpath():
os.environ['BCP_PATH'] = '/tmp:.:..'
assert os.path.exists(bcp.find_file_in_bcp_path('__testfile__.tsv'))
os.remove('../__testfile__.tsv')


def test_parameter_ordering():
import biocrnpyler as bcp

# Create the components for testing
TetR = bcp.Protein('TetR')
aTc = bcp.Species('aTc')
TetR_inactive=bcp.ChemicalComplex([TetR.species, aTc])
ptet = bcp.RegulatedPromoter('ptet', TetR)
dna_GFP = bcp.DNAassembly(
'GFP', promoter=ptet, rbs='RBS', protein='GFP')

# Default case: make sure we can compile with no additional paramters
default_mixture = bcp.BasicPURE(
'default', components=[dna_GFP, TetR_inactive])
default_crn = default_mixture.compile_crn()

# Find the binding reactions of TetR to DNA and aTc
aTc_TetR_index = dna_TetR_index = -1
for i, reaction in enumerate(default_crn.reactions):
if not isinstance(reaction.propensity_type, bcp.MassAction):
continue

inputs = [input.species for input in reaction.inputs]

# Find the binding of aTc to TetR
if aTc in inputs and TetR.species in inputs:
aTc_TetR_index = i

# Find the binding of TetR to DNA
if dna_GFP.species in inputs and TetR.species in inputs:
dna_TetR_index = i

assert aTc_TetR_index != -1 and dna_TetR_index != -1
assert default_crn.reactions[
dna_TetR_index].propensity_type.k_forward != 1
assert default_crn.reactions[
aTc_TetR_index].propensity_type.k_forward != 1

# Rebuild using given parameters
baseline_parameters = {
('binding', None, 'kb'): 1,
('binding', None, 'ku'): 0.1,
('binding', None, 'cooperativity'): 2,
}
TetR_inactive=bcp.ChemicalComplex(
[TetR.species, aTc], parameters=baseline_parameters)
dna_GFP = bcp.DNAassembly(
'GFP', promoter=ptet, rbs='RBS', protein='GFP',
parameters=baseline_parameters)
baseline_mixture = bcp.BasicPURE(
'baseline', components=[dna_GFP, TetR_inactive])
baseline_crn = baseline_mixture.compile_crn()
assert baseline_crn.reactions[
dna_TetR_index].propensity_type.k_forward == 1
assert baseline_crn.reactions[
aTc_TetR_index].propensity_type.k_forward == 1

# Override using mechanism subtypes
mechtype_parameters = baseline_parameters | {
('binding', 'dna_protein', 'kb'): 2,
('binding', 'chemical_complex', 'kb'): 3,
}
TetR_inactive=bcp.ChemicalComplex(
[TetR.species, aTc], parameters=mechtype_parameters)
dna_GFP = bcp.DNAassembly(
'GFP', promoter=ptet, rbs='RBS', protein='GFP',
parameters=mechtype_parameters)
mechtype_mixture = bcp.BasicPURE(
'mechtype', components=[dna_GFP, TetR_inactive])
mechtype_crn = mechtype_mixture.compile_crn()
assert mechtype_crn.reactions[
dna_TetR_index].propensity_type.k_forward == 2
assert mechtype_crn.reactions[
aTc_TetR_index].propensity_type.k_forward == 3

# Override using part IDs
partid_parameters = mechtype_parameters | {
('binding', 'ptet_TetR', 'kb'): 4,
('binding', 'aTc_protein_TetR', 'kb'): 5,
}
TetR_inactive=bcp.ChemicalComplex(
[TetR.species, aTc], parameters=partid_parameters)
dna_GFP = bcp.DNAassembly(
'GFP', promoter=ptet, rbs='RBS', protein='GFP',
parameters=partid_parameters)
partid_mixture = bcp.BasicPURE(
'partid', components=[dna_GFP, TetR_inactive])
partid_crn = partid_mixture.compile_crn()
assert partid_crn.reactions[
dna_TetR_index].propensity_type.k_forward == 4
assert partid_crn.reactions[
aTc_TetR_index].propensity_type.k_forward == 5

# Override using mechanism name
mechname_parameters = baseline_parameters | {
('one_step_cooperative_binding', None, 'kb'): 6,
('binding', 'chemical_complex', 'kb'): 7,
}
TetR_inactive=bcp.ChemicalComplex(
[TetR.species, aTc], parameters=mechname_parameters)
dna_GFP = bcp.DNAassembly(
'GFP', promoter=ptet, rbs='RBS', protein='GFP',
parameters=mechname_parameters)
mechname_mixture = bcp.BasicPURE(
'mechname', components=[dna_GFP, TetR_inactive])
mechname_crn = mechname_mixture.compile_crn()
assert mechname_crn.reactions[
dna_TetR_index].propensity_type.k_forward == 6
assert mechname_crn.reactions[
aTc_TetR_index].propensity_type.k_forward == 7

# Override in mixture instead of components
mixture_parameters = baseline_parameters | {
('one_step_cooperative_binding', None, 'kb'): 8,
('binding', 'chemical_complex', 'kb'): 9,
}
TetR_inactive=bcp.ChemicalComplex([TetR.species, aTc])
dna_GFP = bcp.DNAassembly(
'GFP', promoter=ptet, rbs='RBS', protein='GFP')
mixture_mixture = bcp.BasicPURE(
'mixture', components=[dna_GFP, TetR_inactive],
parameters=mixture_parameters)
mixture_crn = mixture_mixture.compile_crn()
assert mixture_crn.reactions[
dna_TetR_index].propensity_type.k_forward == 8
assert mixture_crn.reactions[
aTc_TetR_index].propensity_type.k_forward == 9

# Override in components and not mixture
component_parameters = baseline_parameters | {
('one_step_cooperative_binding', None, 'kb'): 10,
('binding', 'chemical_complex', 'kb'): 11,
}
TetR_inactive=bcp.ChemicalComplex(
[TetR.species, aTc], parameters=component_parameters)
dna_GFP = bcp.DNAassembly(
'GFP', promoter=ptet, rbs='RBS', protein='GFP',
parameters=component_parameters)
mixture_mixture = bcp.BasicPURE(
'mixture', components=[dna_GFP, TetR_inactive],
parameters=mixture_parameters)
mixture_crn = mixture_mixture.compile_crn()
assert mixture_crn.reactions[
dna_TetR_index].propensity_type.k_forward == 10
assert mixture_crn.reactions[
aTc_TetR_index].propensity_type.k_forward == 11
3 changes: 2 additions & 1 deletion Tests/Unit/test_plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ def test_render_network_bokeh():
('rna_degradation_mm', None, 'kdeg'): 0.001,
(None, None, 'cooperativity'): 2,
}
txtl = bcp.TxTlExtract('mixture1', parameters=parameters)
txtl = bcp.TxTlExtract(
'mixture1', parameters=parameters, overwrite_parameters=True)
dna = bcp.DNAassembly(
'mydna',
promoter=bcp.RegulatedPromoter('plac', ['laci']),
Expand Down
60 changes: 58 additions & 2 deletions Tests/Unit/test_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@


def check(value, message):
"""If 'value' is None, prints an error message constructed using
'message' and then exits with status code 1 (for libsbml). If 'value' is an integer,
"""Utility function for printing SBML error messages.

If `value` is None, prints an error message constructed using 'message'
and then exits with status code 1 (for libsbml). If 'value' is an integer,
it assumes it is a libSBML return status code. If the code value is
LIBSBML_OPERATION_SUCCESS, returns without further action; if it is not,
prints an error message constructed using 'message' along with text from
libSBML explaining the meaning of the code, and exits with status code 1.

"""
if value == None:
raise SystemExit(
Expand Down Expand Up @@ -52,3 +55,56 @@ def test_units_initialization(self):
'Arguments are not of expected type. unit_id must be a string.',
):
create_new_unit_definition(sbml_model, 24)


def test_supported_units():
supported_units = biocrnpyler_supported_units()
for key in [
'nM',
'uM',
'mM',
'M',
'nL',
'uL',
'mL',
'L',
'sec',
'min',
'hrs',
]:
assert key in supported_units

for base, aliases in [
('second', ['s', 'sec', 'secs', 'seconds']),
('minute', ['min', 'mins', 'minutes']),
('hour', ['hr', 'hrs', 'hours']),
]:
for alias in aliases:
assert supported_units[alias] == supported_units[base]


def test_unit_conversion_variables():
from biocrnpyler.utils.units import (
nM,
uM,
mM,
M,
nL,
uL,
mL,
L,
sec,
min,
hrs,
)

assert nM == uM * 1e-3
assert mM == uM * 1e3
assert M == uM * 1e6

assert nL == uL * 1e-3
assert mL == uL * 1e3
assert L == uL * 1e6

assert min == sec * 60
assert hrs == min * 60
6 changes: 5 additions & 1 deletion biocrnpyler/components/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,8 @@ class ChemicalComplex(Component):
attributes : list of str, optional
List of attribute tags to associate with the complex species. The
complex also inherits attributes from its constituent species.
binding_type : str, default='chemical_complex'
Part type for binding reaction parameters.
**kwargs
Additional keyword arguments passed to the `Component` base class
constructor.
Expand Down Expand Up @@ -574,6 +576,7 @@ def __init__(
name: str = None,
material_type='complex',
attributes=None,
binding_type='chemical_complex',
**kwargs,
):
if not isinstance(species, list) or len(species) < 2:
Expand All @@ -582,6 +585,7 @@ def __init__(
"Species, strings, or Component objects."
)

self.binding_type = binding_type
self.internal_species = [] # a list of species inside the complex

for s in species:
Expand Down Expand Up @@ -659,7 +663,7 @@ def update_reactions(self) -> List[Reaction]:
bindee,
complex_species=self.get_species(),
component=self,
part_id=self.name,
part_id=[self.name, self.binding_type],
)
return reactions

Expand Down
Loading
Loading