Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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 :).
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