.. _examine: ********************************************* Examining MDLs Generated by CellBlender ********************************************* In this tutorial, we will examine some MDL (Model Description Language) files generated by CellBlender. These MDLs are what MCell actually parses. It is possible to use CellBlender without ever having to edit or even look at an MDL. However, this section may be useful if you ever decide to hand-edit your MDL files for any reason. .. contents:: :local: .. _examine_mdl: Examining the Main MDL --------------------------------------------- For every CellBlender project, you will have a blend file and corresponding directory (note: the directory will only appear once you run a simulation). For instance, if you have a blend file called **intro.blend**, then you will also have a folder called **intro_files**. All of the input and output files generated by CellBlender and MCell are stored within this directory (including MDLs, reaction data, and visualization data). To be more specific, they are actually inside a sub-directory called **mcell**. In this example, they would be in **./intro_files/mcell**. Every project will have a file called **Scene.main.mdl**, which will look something like this: .. code-block:: mdl :linenos: ITERATIONS = 1000 TIME_STEP = 1e-05 INCLUDE_FILE = "Scene.initialization.mdl" INCLUDE_FILE = "Scene.molecules.mdl" INCLUDE_FILE = "Scene.reactions.mdl" INCLUDE_FILE = "Scene.geometry.mdl" INSTANTIATE Scene OBJECT { Cube OBJECT Cube {} vol1_rel RELEASE_SITE { SHAPE = Scene.Cube MOLECULE = vol1 NUMBER_TO_RELEASE = 2000 RELEASE_PROBABILITY = 1 } surf1_rel RELEASE_SITE { SHAPE = Scene.Cube[top] MOLECULE = surf1' NUMBER_TO_RELEASE = 2000 RELEASE_PROBABILITY = 1 } } sprintf(seed,"%05g",SEED) INCLUDE_FILE = "Scene.viz_output.mdl" INCLUDE_FILE = "Scene.rxn_output.mdl" The first two lines are :ref:`init_commands` that we'll cover in the next section. :index:`\ ` **INCLUDE_FILE** commands let you break up MDLs into multiple sections. Examples of this can be seen on lines 4-10 and 33-35. **Scene.initialization.mdl** contains advanced initialization commands, **Scene.molecules.mdl** contains molecule definitions, **Scene.reactions.mdl** contains reaction definitions, **Scene.geometry.mdl** contains the the vertices and faces that make up our **Cube**, **Scene.viz_output.mdl** contains the MCell visualization data output (i.e. what molecule species should be visualized and at what iterations), and **Scene.rxn_output.mdl** contains the MCell reaction data output (i.e. what molecule species should be counted and where). In addition to simply *including* meshes, you also have to :index:`\ ` **INSTANTIATE** meshes to make them exist and interact in the simulation, starting on line 12. You can see we're also instantiating another type of object called a **RELEASE_SITE**, which we'll discuss later in the :ref:`rel_sites` section. .. _init_commands: Initialization Commands --------------------------------------------- :index:`\ ` :index:`\ ` At the beginning of the file are the initialization commands, **TIME_STEP** and **ITERATIONS**. As the names imply, these commands control how many **ITERATIONS** the simulation runs for, with each iteration lasting one **TIME_STEP** (units are seconds). Notice that **ITERATIONS** is set to **1000** and **TIME_STEP** to **1e-5**. This means that the simulation will run for 1000 iterations at a time step of **1e-5** seconds (total time: 1000*1e-5=0.01 seconds). .. _molec_def: Geometry Files --------------------------------------------- Your geometry will be stored in **Scene.geometry.mdl**: .. code-block:: mdl Cube POLYGON_LIST { VERTEX_LIST { [ 1, 0.999999940395355, -1 ] [ 1, -1, -1 ] [ -1.00000011920929, -0.999999821186066, -1 ] [ -0.999999642372131, 1.00000035762787, -1 ] [ 1.00000047683716, 0.999999463558197, 1 ] [ 0.999999344348907, -1.00000059604645, 1 ] [ -1.00000035762787, -0.999999642372131, 1 ] [ -0.999999940395355, 1, 1 ] } ELEMENT_CONNECTIONS { [ 0, 1, 2 ] [ 4, 7, 5 ] [ 0, 4, 1 ] [ 1, 5, 2 ] [ 2, 6, 7 ] [ 4, 0, 3 ] [ 3, 0, 2 ] [ 4, 5, 1 ] [ 5, 6, 2 ] [ 3, 2, 7 ] [ 7, 4, 3 ] [ 7, 6, 5 ] } DEFINE_SURFACE_REGIONS { top { ELEMENT_LIST = [8, 9] } } } Mesh objects made in Blender become a **POLYGON_LIST** object in MCell. A **POLYGON_LIST** object consists of two to three sections in MCell: a **VERTEX_LIST**, an **ELEMENT_CONNECTIONS** list, and optionally a **DEFINE_SURFACE_REGIONS** section. A **VERTEX_LIST** is exactly what it sounds like, a list of vertices. The **ELEMENT_CONNECTIONS** list defines the faces of the triangles. Each number in the list is an index to a single vertex defined in the **VERTEX_LIST**. Each set of three numbers (e.g. **[ 0, 1, 2 ]**) tells which vertices are connected together to form a single face. **DEFINE_SURFACE_REGIONS** is optional, unless you want to specify specify surface regions. Each number in the **ELEMENT_LIST** is an index to a triangle in **ELEMENT_CONNECTIONS**. Molecule Definitions --------------------------------------------- Molecules need to be defined before they are used (as a release site or a reaction) in the MDL. :index:`\ ` Open the **Scene.molecules.mdl** file, and you'll see the following: .. code-block:: mdl DEFINE_MOLECULES { vol1 { DIFFUSION_CONSTANT_3D = 1e-06 } vol2 { DIFFUSION_CONSTANT_3D = 1e-06 } surf1 { DIFFUSION_CONSTANT_2D = 1e-07 } } :index:`\ ` :index:`\ ` Molecules that use **DIFFUSION_CONSTANT_3D** command, like **vol1** and **vol2**, will be volume molecules, meaning that they will exist in solution. Molecules that use **DIFFUSION_CONSTANT_2D**, like **surf1**, will be surface molecules, meaning that they exist on a surface. The units of the values assigned to this command (**1E-6** and **1E-7** in this instance) are in cm\ :sup:`2`\ /s. .. _reactions: Reactions --------------------------------------------- Molecules that were defined in the previous section can be created and destroyed in a number of different ways using reactions. A reaction is defined in the following manner: **reactant(s) -> product(s) [rate]** This means that **reactant(s)** are converted into **product(s)** at a given **rate**. There must be one or more molecules on the left hand **reactants** side. On the right hand **products** side, you must have zero (:index:`\ ` **NULL**) or more molecules. The units of the **rate** depend on the type of reaction. [s\ :sup:`-1`\ ] for unimolecular reactions and [M\ :sup:`-1`\ s\ :sup:`-1`\ ] for bimolecular reactions between two volume molecules or a volume molecule and a surface molecule. .. _rxn_dir: Reaction Directionality --------------------------------------------- :index:`\ ` Surface molecules have a :index:`\ ` **TOP** and a :index:`\ ` **BOTTOM**, so we need a way to differentiate between reactions that happen on one side versus the other. Commas (**,**), ticks (**'**), and semi-colons (**;**) serve this purpose. For detailed information on this reaction syntax, please refer to this pdf_. Let's look at the relatively simple example we have created in **Scene.reactions.mdl**: .. code-block:: mdl DEFINE_REACTIONS { vol1' + surf1, -> surf1, + vol2, [1e+08] } .. _pdf: http://mcell.psc.edu/download/files/MCell3_rxns_06_18_2007.pdf Read this next section carefully, as some people find this syntax confusing at first. If a volume molecule and a surface molecule have their orientations *opposed* (i.e. a tick and a comma), then the volume molecule interacts with the **BOTTOM** of the surface molecule. If a volume molecule and a surface molecule have their orientations *aligned* (i.e. two ticks *or* two commas), then the volume molecule interacts with the **TOP** of the surface molecule. For this reaction, **vol1** and **surf1** are opposed (a comma and a tick), and **vol2** and **surf1** are aligned (two commas). This means that **vol1** will react with the **BOTTOM** of **surf1**, creating **vol2** at the **TOP** of **surf1**. Since **vol1** is not on the products side, it is destroyed when it reacts with **surf1**. Conversely, **surf1** is on both the **reactant** and **product** side, so it will not be destroyed from the reaction. The directionality of these ticks and commas are relative, which means that we could flip the signs and get the same result, like this: .. code-block:: mdl DEFINE_REACTIONS { vol1, + surf1' -> surf1' + vol2' [1e+08] } .. index:: single: RELEASE_SITES .. _rel_sites: Release Sites --------------------------------------------- Let's examine the **INSTANTIATE** section of **Scene.main.mdl** more closely: .. code-block:: mdl INSTANTIATE Scene OBJECT { Cube OBJECT Cube {} vol1_rel RELEASE_SITE { SHAPE = Scene.Cube MOLECULE = vol1 NUMBER_TO_RELEASE = 2000 RELEASE_PROBABILITY = 1 } surf1_rel RELEASE_SITE { SHAPE = Scene.Cube[top] MOLECULE = surf1' NUMBER_TO_RELEASE = 2000 RELEASE_PROBABILITY = 1 } } This section creates two release sites, one called **vol1_rel** and the other **surf1_rel**. Each release site can take a number of different commands. The **SHAPE** of the release determines what object (or region of an object) that molecules are released onto or into. You can also use some predefined shapes, like **CUBIC** or **SPHERICAL**, but we won't cover that here. **MOLECULE** determines what molecule is released. If it is a surface molecule, an orientation is also specified This is similar to what's described in :ref:`rxn_dir`, but it is not relative. A tick means that the **TOP** of the molecule is aligned with the **FRONT** of the surface, and a comma means that the **TOP** is aligned with the **BACK** of the surface. **NUMBER_TO_RELEASE** gives an absolute number of molecules to be released. Alternatively, one could define a **CONCENTRATION** (for volume molecules) or **DENSITY** (for surface molecules). These two release sites together will release 2000 **vol1** molecules randomly throughout the inside of **Scene.Cube** and also 2000 **surf1** molecules randomly on the **top** surface region of **Scene.Cube**. Also, the **TOP** of **surf1** will be aligned with the **FRONT** of the surface. .. index:: single: REACTION_DATA_OUTPUT .. _rxn_data: Visualization Data --------------------------------------------- Open the file called **Scene.viz_output.mdl** with the following text in it: .. code-block:: mdl VIZ_OUTPUT { MODE = CELLBLENDER FILENAME = "./viz_data/seed_" & seed & "/Scene" MOLECULES { NAME_LIST {vol1 vol2 surf1} ITERATION_NUMBERS {ALL_DATA @ ALL_ITERATIONS} } } The :index:`\ ` **VIZ_OUTPUT** section specifies what visualization data to export and at what time values. Right now, it is set to export everything at all iterations. Reaction Data --------------------------------------------- Now, create a file called **Scene.rxn_output.mdl**: .. code-block:: mdl REACTION_DATA_OUTPUT { STEP=1e-05 {COUNT[surf1,WORLD]}=> "./react_data/seed_" & seed & "/surf1.World.dat" {COUNT[vol1,WORLD]}=> "./react_data/seed_" & seed & "/vol1.World.dat" {COUNT[vol2,WORLD]}=> "./react_data/seed_" & seed & "/vol2.World.dat" } The **STEP** command tells MCell how often it should write out reaction data. The brackets after the **COUNT** command tell MCell what molecule to count and where to count it. For instance the first **COUNT** statement tells it to count all of the **vol1** molecules in the **WORLD** (the entire simulation). Alternatively, you could specify that it only count those found in/on an object/region (e.g. **[vol1,Scene.Cube]**) The file listed after the arrow symbol (**=>**) tells it where to save it. Examine the Log Data --------------------------------------------- CellBlender should have created two log files with names similar to this:: log.2013-05-07_16:29_1.txt. log.2013-05-07_16:29_2.txt. If you do not see these files, it means an error was encountered. By default, errors are printed to the command line, but they can also be saved just like the log files (e.g. **error.2013-05-07_16:29_2.txt.**) in the **Run Simulation** panel. Note that this includes the date, time, and seed value. If you open the file, you will see the following:: MCell 3.1 (revision 998/2012-08-29 16:46:46 -0700) Running on jacob-PRO114978 at Wed May 8 12:19:26 2013 Copyright (C) 2006 - 2010 by Pittsburgh Supercomputing Center, Carnegie Mellon University and The Salk Institute for Biological Studies MCell initializing simulation... MCell[0]: random sequence 1 Defining molecules with the following theoretical average diffusion distances: l_r_bar=0.0713649646 um for vol1 l_r_bar=0.0713649646 um for vol2 l_r_bar=0.0560499122 um for surf1 Reaction probabilities generated for the following reactions: Probability 9.3073e-01 set for surf1{-1} + vol1{1} -> surf1{-1} vol2{-1} Creating geometry (this may take some time) MCell: world bounding box in microns = [ -1.00000036 -1.0000006 -1 ] [ 1.00000048 1.00000036 1 ] Creating 125 subvolumes (5,5,5 per axis). Creating 1 memory partitions (1,1,1 per axis). Instantiating objects... Creating walls... Creating edges... Running simulation. Releasing 2000 molecules vol1 ... Released 2000 vol1 from "Scene.vol1_rel" at iteration 0. Releasing 2000 molecules surf1 ... Released 2000 surf1 from "Scene.surf1_rel" at iteration 0. Iterations: 0 of 1000 Iterations: 100 of 1000 (459.781 iter/sec) Iterations: 200 of 1000 (459.844 iter/sec) Iterations: 300 of 1000 (461.076 iter/sec) Iterations: 400 of 1000 (446.614 iter/sec) Iterations: 500 of 1000 (318.155 iter/sec) Iterations: 600 of 1000 (462.592 iter/sec) Iterations: 700 of 1000 (463.891 iter/sec) Iterations: 800 of 1000 (439.014 iter/sec) Iterations: 900 of 1000 (457.831 iter/sec) Iterations: 1000 of 1000 (454.612 iter/sec) Exiting run loop. iterations = 1000 ; elapsed time = 0.01 seconds Average diffusion jump was 1.00 timesteps Total number of random number use: 8850744 Total number of ray-subvolume intersection tests: 2319051 Total number of ray-polygon intersection tests: 6016068 Total number of ray-polygon intersections: 97381 Initialization CPU time = 0.048000 (user) and 0.004000 (system) Simulation CPU time = 2.064000 (user) and 0.120000 (system) Total wall clock time = 2 seconds Done running. This file contains potentially useful information, such as reaction probabilities, the number of molecules released, and how many iterations are completed per second.