Skip to content

Instantly share code, notes, and snippets.

@drdozer
Last active December 17, 2015 19:39
Show Gist options
  • Save drdozer/5661935 to your computer and use it in GitHub Desktop.
Save drdozer/5661935 to your computer and use it in GitHub Desktop.
Simple genetic parts simulator
import javafx.scene.paint.Color
import uk.co.turingatemyhamster.gyo._
object Designs {
def main(args: Array[String]) {
val gfp = Reporter("GFP", Color.GREEN)
val gfpCDS = CDS("gfp", gfp)
val rfp = Reporter("RFP", Color.RED)
val rfpCDS = CDS("fgp", rfp)
val yfp = Reporter("YFP", Color.YELLOW)
val yfpCDS = CDS("yfp", yfp)
val glucose = SmallMolecule("glucose")
val co2 = SmallMolecule("CO<sub>2</sub>")
val o2 = SmallMolecule("O<sub>2</sub>")
val contP = Promoter("always-on", None)
val graTF = TranscriptionFactor("glucose-required activator tf", Activator, Some(Presence(glucose)))
val graCDS = CDS("glucose-required activator", graTF)
val graP = Promoter("glucose-required promoter", Some(graTF))
val t1 = Terminator("t1")
val t2 = Terminator("t2")
val design1 = GeneticDesign(contP :: graCDS :: gfpCDS :: t1 :: graP :: rfpCDS :: t2 :: Nil)
Simulator.simulate(design1, StateVector()).take(5) foreach (s => println(s.pretty))
Simulator.simulate(design1, StateVector(Set(glucose))).take(5) foreach (s => println(s.pretty))
}
}
package uk.co.turingatemyhamster.gyo
import javafx.scene.paint.Color
/** All the things we're working with have human-readable labels */
trait Entity {
def label: String
}
/** Genetic parts are bits of our design. */
trait GeneticPart extends Entity
// there are tree types of parts
/** Promoters are optionally modulated by a transcription factor. */
case class Promoter(label: String, tf: Option[TranscriptionFactor]) extends GeneticPart
/** CDSs produce a protein product. */
case class CDS(label: String, product: Protein) extends GeneticPart
/** Terminators don't carry any extra information around. */
case class Terminator(label: String) extends GeneticPart
/** A genetic design is a list of parts. */
case class GeneticDesign(parts: List[GeneticPart])
/** Free molecules are floatign around in the cell. They are the basis for keeping state. */
trait FreeMolecule extends Entity
/** Small molecules are free molecules that are simple and small. For example, metabolites. */
case class SmallMolecule(label: String) extends FreeMolecule
/** Proteins are free molecules. */
sealed trait Protein extends FreeMolecule
/** Enzymes are proteins that catalyse a reaction. */
case class Enzyme(label: String, consumes: Set[SmallMolecule], produces: Set[SmallMolecule]) extends Protein
/** Transcription factors modulate promoter activity, possibly dependent upon a modifier molecule. */
case class TranscriptionFactor(label: String,
activity: TranscriptionFactorEffect,
modifier: Option[Modifier]) extends Protein
/** Reporter proteins are colored so that we can see them. */
case class Reporter(label: String, color: Color) extends Protein
/** Transcription factors can have different effects. (affects?) */
sealed trait TranscriptionFactorEffect
/** Activators turn on transcription from a promoter when bound. */
object Activator extends TranscriptionFactorEffect
/** Repressors turn off transcription from a promoter when bound. */
object Repressor extends TranscriptionFactorEffect
/** Modifiers enable or disable a transcription factor from binding promoters. */
sealed trait Modifier {
def required: SmallMolecule
}
/** The small molecule must be present for binding. */
case class Presence(required: SmallMolecule) extends Modifier
/** The small molecule must be absent for binding. */
case class Absence(required: SmallMolecule) extends Modifier
/** A state vector at a time-step in our simulation. */
case class StateVector(ms: Set[SmallMolecule], ps: Set[Protein]) {
def add(p: Protein) = this.copy(ps = ps + p)
def pretty: String = "StateVector\n\tmolecules: " + (ms map (_.label) mkString(", ")) + "\n\tproteins: " + (ps map (_.label) mkString(", "))
}
object StateVector {
def apply(): StateVector = StateVector(Set(), Set())
def apply(ms: Set[SmallMolecule]): StateVector = StateVector(ms, Set())
}
object Simulator {
/** Run a simulation for a design from an initial state. */
def simulate(design: GeneticDesign, state: StateVector): Stream[StateVector] = {
def step(transcribe_? : Boolean, parts: List[GeneticPart]): StateVector = parts match {
case Nil => StateVector(state.ms)
case head :: tail => head match {
case Terminator(_) => step(false, tail)
case CDS(_, p) => if(transcribe_?) step(transcribe_?, tail).add(p) else step(transcribe_?, tail)
case Promoter(_, None) => step(true, tail)
case Promoter(_, Some(tf)) => tf match {
case TranscriptionFactor(_, Activator, None) =>
step(transcribe_? || state.ps.contains(tf), tail)
case TranscriptionFactor(_, Repressor, None) =>
step(transcribe_? && !state.ps.contains(tf), tail)
case TranscriptionFactor(_, Activator, Some(Presence(sm))) =>
step(transcribe_? || (state.ps.contains(tf) && state.ms.contains(sm)), tail)
case TranscriptionFactor(_, Activator, Some(Absence(sm))) =>
step(transcribe_? || (state.ps.contains(tf) && !state.ms.contains(sm)), tail)
case TranscriptionFactor(_, Repressor, Some(Presence(sm))) =>
step(transcribe_? && !(state.ps.contains(tf) && state.ms.contains(sm)), tail)
case TranscriptionFactor(_, Repressor, Some(Absence(sm))) =>
step(transcribe_? && !(state.ps.contains(tf) && !state.ms.contains(sm)), tail)
}
}
}
val s = step(false, design.parts)
s #:: simulate(design, s)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment