Last active
January 24, 2017 14:02
-
-
Save danyx23/deba145d2e769863b59c to your computer and use it in GitHub Desktop.
A very simple model to show how long it would take for a population of wild type mosquitos to be taken over by mutants carrying a CRISPR/CAS9 modification in their genome. This is not a proper way to model this problem :).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Html exposing (text, div) | |
import String exposing (padLeft) | |
-- You can paste this code into http://elm-lang.org/try to have it evaluated | |
gen0WildTypeFemales = 2000000000.0 | |
gen0WildTypeMales = 2000000000.0 | |
gen0MutantFemals = 100.0 | |
gen0MutantMales = 100.0 | |
femaleMatingSuccessFactor = 0.2 | |
survivalFactorToMatingAge = 0.1 | |
eggsPerMating = 100.0 | |
geneDriveSuccessFactor = 0.97 | |
generationsToCalculate = 26 | |
type alias GenerationData = | |
{ wildTypeFemales : Float | |
, wildTypeMales : Float | |
, mutantFemales : Float | |
, mutantMales : Float | |
} | |
-- This is the definition for the function calculateMutantEggs. It takes a GenerationData and returns the number of mutant eggs | |
calculateMutantEggs generationData = | |
let -- calculate intermediate results | |
mutantMaleRatio = generationData.mutantMales / (generationData.mutantMales + generationData.wildTypeMales) | |
wildTypeMaleRatio = 1.0 - mutantMaleRatio | |
mutantFemaleMutantMalePairings = toFloat ( floor (generationData.mutantFemales * mutantMaleRatio * femaleMatingSuccessFactor) ) | |
mutantFemaleWildTypeMalePairings = toFloat ( floor (generationData.mutantFemales * wildTypeMaleRatio * geneDriveSuccessFactor * femaleMatingSuccessFactor) ) | |
wildTypeFemaleMutantMalePairings = toFloat ( floor (generationData.wildTypeFemales * mutantMaleRatio * geneDriveSuccessFactor * femaleMatingSuccessFactor) ) | |
mutantEggs = (mutantFemaleMutantMalePairings + mutantFemaleWildTypeMalePairings + wildTypeFemaleMutantMalePairings) * eggsPerMating | |
in -- return the number of eggs | |
mutantEggs | |
-- This is the definition for the function calculateMutantEggs. It takes a GenerationData and returns the number of Wild Type eggs | |
calculateWildTypeEggs generationData = | |
let -- calculate intermediate results | |
mutantMaleRatio = generationData.mutantMales / (generationData.mutantMales + generationData.wildTypeMales) | |
wildTypeMaleRatio = 1.0 - mutantMaleRatio | |
wildTypeFemaleMutantMalePairings = toFloat ( floor (generationData.wildTypeFemales * mutantMaleRatio * (1.0 - geneDriveSuccessFactor) * femaleMatingSuccessFactor) ) | |
wildTypeFemaleWildTypeMalePairings = toFloat ( floor (generationData.wildTypeFemales * wildTypeMaleRatio * femaleMatingSuccessFactor) ) | |
wildTypeEggs = (wildTypeFemaleMutantMalePairings + wildTypeFemaleWildTypeMalePairings) * eggsPerMating | |
in -- return the number of eggs | |
wildTypeEggs | |
-- calculateGeneration takes the previous generation, calculates the number of wild type and mutant eggs, and returns a new generation from it | |
calculateGeneration previousGeneration = | |
let -- calculate the number of mutant and wild type eggs | |
mutantEggs = calculateMutantEggs previousGeneration | |
wildTypeEggs = calculateWildTypeEggs previousGeneration | |
in -- return a new GenerationData | |
{ wildTypeFemales = survivalFactorToMatingAge * wildTypeEggs / 2.0 | |
, wildTypeMales = survivalFactorToMatingAge * wildTypeEggs / 2.0 | |
, mutantFemales = survivalFactorToMatingAge * mutantEggs / 2.0 | |
, mutantMales = survivalFactorToMatingAge * mutantEggs / 2.0 | |
} | |
type alias GenerationStep = | |
{ currentGenerationData : GenerationData | |
, formattedOutput : List String | |
} | |
-- calculateGenerationAndOutput takes the last GenerationStep and the generationCounter, | |
-- runs calculateGeneration and returns a new GenerationStep with the formatted output | |
-- for the current Generation added | |
calculateGenerationAndOutput generationCounter generationOutput = | |
let | |
nextGeneration = calculateGeneration generationOutput.currentGenerationData | |
formattedOutputForGeneration = ("Generation: " ++ (padLeft 2 '0' (toString generationCounter)) | |
++ " Mutant females: " ++ (padLeft 10 '0' (toString nextGeneration.mutantFemales)) | |
++ " Wild Type females: " ++ (padLeft 10 '0' (toString nextGeneration.wildTypeFemales)) | |
++ " Ratio m/wt: 1:" ++ toString (round (nextGeneration.wildTypeFemales / nextGeneration.mutantFemales))) | |
formattedOutput = formattedOutputForGeneration :: generationOutput.formattedOutput | |
in | |
GenerationStep nextGeneration formattedOutput | |
-- create the initial generation0 GenerationData record | |
generation0 = GenerationData gen0WildTypeFemales gen0WildTypeMales gen0MutantFemals gen0MutantMales | |
-- prepare the initial GenerationStep with generation0 and an empty list of formatted outputs | |
initialGenerationStep = GenerationStep generation0 [] | |
-- prepare a list from 1 to the number of generations to calculate | |
generations = [1..generationsToCalculate] | |
-- Use a fold (=reduce) function to map the GenerationSteps over the list of generations. | |
-- This will accumulate a final GenerationStep containing a list of Strings, one | |
-- line of formatted string data for each generation | |
allGenerations = generations | |
|> List.foldl calculateGenerationAndOutput initialGenerationStep | |
-- Helper function to turn the list of strings into one with with contained text each | |
transformGenerationOuputIntoTexts generationStep = | |
List.map (\line -> div [] [text line]) generationStep.formattedOutput | |
main = | |
div [] (List.reverse (transformGenerationOuputIntoTexts allGenerations)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment