def createChildren(self, parents):
        roulette = Roulette(parents)
        children = []
        for _ in range(5):
            parent_1 = roulette.select_parent()
            parent_2 = roulette.select_parent()
            new_children = Crossover(parent_1, parent_2).generate_children()
            Mutation(new_children[0]).mutate()
            Mutation(new_children[1]).mutate()
            children.append(new_children[0])
            children.append(new_children[1])

        return children
def mutate(vcf_info, opts):

    abs_path = opts[util.ABSOLUTE_PATH_OPTION]
    output = opts[util.OUTPUT_OPTION]

    log_not_found = []
    ################################# RefSeq_human_full.fasta ###################################

    util.print_task(util.TASK_LOAD_PROTEIN_FILE)

    refseq_human = read_protein_file(abs_path)

    util.print_status(util.TASK_SUCCESS)

    #############################################################################################

    ############################# Transcripts_refseq.fasta reading ##############################

    util.print_task(util.TASK_LOAD_TRANSCRIPT_FILE)

    refseq_transc, nm_np_conversor = read_transcript_file(abs_path)

    util.print_status(util.TASK_SUCCESS)

    #############################################################################################

    ################################# vcf info file processing ##################################

    mutations = defaultdict(list)
    samples = set()
    curr_sample = 1

    util.print_task(util.TASK_PROCESS_MUTATION)

    with open(vcf_info, "r") as f:

        f.readline()

        for line in f:

            try:
                mutation = Mutation(line, nm_np_conversor, refseq_transc, refseq_human)
            except KeyError:
                log_not_found.append(line.rstrip())
                continue
            
            samples.add(mutation.sample)

            if mutation.mut_protein_sequence:
                if len(samples) == curr_sample:
                    mutations[mutation.transcript].append(mutation)
                else:
                    generate_report.mutation(mutations[mutations.keys()[0]][0].sample, mutations, output)
                    mutations = defaultdict(list)
                    mutations[mutation.transcript].append(mutation)
                    curr_sample += 1
                
    generate_report.mutation(mutations[mutations.keys()[0]][0].sample, mutations, output)

    util.print_status(util.TASK_SUCCESS)
 def createChildren(self, parents):
     # Cria a roleta
     roulette = Roulette(parents)
     children = []
     # Cria 10 filhos
     for _ in range(5):
         parent_1 = roulette.select_parent()
         parent_2 = roulette.select_parent()
         new_children = Crossover(parent_1, parent_2).generate_children()
         # Realiza a mutação nos filhos (respeitando a proporcionalidade)
         Mutation(new_children[0]).mutate()
         Mutation(new_children[1]).mutate()
         children.append(new_children[0])
         children.append(new_children[1])
         
     return children
    def run_mutant(self):
        self.mutation_history = []
        self.mutation_cluster = {}
        self.mutation = Mutation(self.configuration.get_mutation_trace(),
                                 self.databank)
        self.mutation_traces = self.make_mutation_traces()

        # run a default trace for compare
        logging.info(" start run default trace")
        self.executor.start()
        self.executor.goto_url()
        initial_state = self.get_initail_state()
        self.run_mutant_script(initial_state)
        self.close()

        # run all mutation traces
        logging.info(' total %d mutation traces ', len(self.mutation_traces))
        for n in xrange(len(self.mutation_traces)):
            logging.info(" start run number %d mutant trace", n)
            self.executor.start()
            self.executor.goto_url()
            initial_state = self.get_initail_state()
            self.run_mutant_script(initial_state, self.mutation_traces[n])
            self.close()
        self.save_mutation_history()
Exemple #5
0
    def attempt_breeding(self, individual_i, individual_j):

        """
        Attempt to breed the two individuals (several times if necessary)
        If the breeding is successful and the Neural Networks can be built,
        the two offsprings are added into the next generation.

        The breeding process is the following:
            - cross-over between the two lovers
            - mutate the offsprings with probability p
            - create the offsprings neural networks

        """

        successful_breedings = 0
        breeding_attempts = 0

        while(successful_breedings < 2 and breeding_attempts < Settings.MAX_BREEDING_ATTEMPTS):
            
            try:
                # cross over the two individuals
                offspring_1, offspring_2 = Cross_Over(self.population[individual_i], self.population[individual_j]).breed()
            
            except NoBridgeException as e:
                print(e)
                print("Failed to cross-over the individuals")
                return (False)
            except Exception as e:
                print("Failed to cross-over the individuals")
                return (False)
                

            for offspring in [offspring_1, offspring_2]:

                # apply (several if we are stuck in a local optimum) mutations to the offspring  
                for _ in range(self.mutations_per_breeding):
                    offspring = Mutation(offspring).mutate()
                
                mutated_offspring = offspring

                # build and train the crossed-mutated graphs on the spot
                if(successful_breedings < 2):
                        
                    try:
                        mutated_offspring_fitness = self.build_and_train_network(mutated_offspring)

                        self.next_generation_dna.append(mutated_offspring)
                        self.next_generation_fitness.append(mutated_offspring_fitness)
                        successful_breedings += 1

                    except Exception as e:
                        print("Failed to build the NN \n\n" + str(e))
                    
          
        return(successful_breedings)
Exemple #6
0
	def next_generation(self, population):
		selection = Selection(deepcopy(population), strategy=SelectionStrategy.TOURNAMENT.value)
		mating = Mating(selection)
		crossover = Crossover(mating)

		for i, individual in enumerate(crossover.mating.selection.population.individuals):
			mutation = Mutation(individual)
			crossover.mating.selection.population.individuals[i] = mutation.mutate()

		print(f'Individuals: {len(self.individuals)}')
		print(f'New generation: {len(crossover.new_generation)}')
		return crossover.mating.selection.population
Exemple #7
0
def load_mutation_from_dict(d):
    mutation_id = d['id']

    ref_counts = int(d['ref_counts'])
    var_counts = int(d['var_counts'])

    mutation = Mutation(mutation_id, ref_counts, var_counts)

    for state_dict in d['states']:
        state = load_state_from_dict(state_dict)

        mutation.add_state(state)

    return mutation
Exemple #8
0
 def __init__(self,
              population_size,
              sample_genotype,
              crossover_rate=0.6,
              mutation_rate=0.2,
              maximize=True):
     self.population_size = population_size
     self.genotype = sample_genotype
     self.crossover_rate = crossover_rate
     self.mutation_rate = mutation_rate
     self.selector = RankSelector(maximize)
     self.crossover = OnePointCrossover()
     self.mutation = Mutation()
     self.generations = []
     self.maximize = maximize
Exemple #9
0
def main():
    parser = argparse.ArgumentParser(description='Tweak GA parameters')
    parser.add_argument('-size','--populationSize', type=int, required=False, default=100,
                        help = 'Desired population size (int)')
    parser.add_argument('-iter','--maxIter',        type=int, required=False, default=100,
                        help = "Max number of iterations allowed (int)")
    parser.add_argument('-n','--n',                 type=int, required=False, default=10,
                        help = 'Desired number of neural_networks in the hidden layer')
    parser.add_argument('-k','--K',                 type=float, required=False, default=1.1,
                        help = "Chromosome is mutated by adding a number from the normal_distibution(0,K) to it's weights value")
    parser.add_argument('-err','--errThreshold',    type=float, required=False, default=0.1,
                        help = "Algorithm stops search if it has found a chromosome with error less than errThreshold")
    parser.add_argument('-train','--trainSet',      type=str, required=False, default="learningSet/train-set.txt",
                        help = "Path to training_set")
    #parser.add_argument('-test','--testSet',        type=str, required=False, default="learningSet/test-set.txt",
    #                    help = "Path to test_set")

    args = parser.parse_args()
    ERR_THRESHOLD = args.errThreshold
    VEL_POP  = args.populationSize
    MAX_ITER = args.maxIter
    N = args.n
    K = args.K

    train_set = parseLearningSet(args.trainSet)

    ## initialize needed operators
    fitnessOp  = Fitness(train_set)
    mutationOp = Mutation(K, N, VEL_POP)

    ##initialize population
    P = Population(N, VEL_POP)

    ##returns best neural_network (individual)
    best_nn = run_GA(P, fitnessOp, mutationOp, VEL_POP, MAX_ITER, ERR_THRESHOLD)
    test_set  = [] # parseLearningSet(args.testSet)
    test_dict = {} #parseLearningDict(args.testSet)

    writeOut(best_nn, test_set, test_dict)
Exemple #10
0
    def __init__(self, algorithm_config):
        start = time.time()
        variable_config = algorithm_config
        tab_epoch = []
        tab_mean = []
        tab_std = []
        tab_mean2 = []
        tab_std2 = []
        tab_epoch2 = []
        tab_elitary = []
        tab_epoch3 = []
        tab_epoch4 = []
        tab_elitary2 = []
        # chrom = Chromosome(variable_config)
        # chrom = chrom.initialChromosome(variable_config)
        # print(chrom)

        # generujemy populację
        pop = Population(variable_config)
        popul = pop.initialPopulation(variable_config)
        # print(popul)

        randomBinSol = evaluateFitness(variable_config)
        # pojedyncze x
        decision_variables = randomBinSol.decVariables(variable_config, popul)
        # print(decision_variables)

        # dekodujemy na odpowiedniki dziesietne
        decimal = randomBinSol.decoding(decision_variables, variable_config)
        # print(decimal)

        # zamieniamy na zmienne rzeczywiste
        real = randomBinSol.realVariables(variable_config, decimal)
        # print(real)

        # obliczamy wartosc funkcji dla kazdej kolumny

        func_solution = randomBinSol.funcSolution(variable_config, real)
        # print(func_solution)
        tab_mean.append(np.mean(func_solution))
        tab_std.append(np.std(func_solution))
        tab_epoch.append(0)

        counter = 1
        countEp = 0
        selType = SelectionType(variable_config)
        while (counter < variable_config.T):
            selection = selType.selType(variable_config, func_solution, popul)

            # KRZYŻOWANIE
            # print("KRZYŻOWANIE")
            crosov = CrossingOver(variable_config)
            crosingover = crosov.crosingOver(variable_config, selection)
            # print(crosingover)

            # MUTACJA
            # print("MUTACJA")
            mutat = Mutation(variable_config)
            mutation = mutat.mutation(variable_config, crosingover)
            # print(mutation)

            # INWERSJA
            # print("INWERSJA")
            inver = Inversion(variable_config)
            inversion = inver.inversion(variable_config, mutation)
            # print(inversion)

            offspring = np.asarray(inversion)
            # print(offspring)

            decision_variables2 = randomBinSol.decVariables(
                variable_config, offspring)
            # print(decision_variables2)

            # dekodujemy na odpowiedniki dziesietne
            decimal2 = randomBinSol.decoding(decision_variables2,
                                             variable_config)
            # print(decimal2)

            # zamieniamy na zmienne rzeczywiste
            real2 = randomBinSol.realVariables(variable_config, decimal2)
            # print(real2)

            # obliczamy wartosc funkcji dla kazdej kolumny

            func_solution2 = randomBinSol.funcSolution(variable_config, real2)

            combin = Combinate()
            combination = combin.newPopulation(popul, offspring, func_solution,
                                               func_solution2, variable_config)
            popul = combination[0]
            func_solution = combination[1]
            best = combination[2]

            tab_mean.append(np.mean(func_solution))
            tab_std.append(np.std(func_solution))
            tab_epoch.append(counter)
            tab_elitary.append(best)
            tab_epoch3.append(countEp)
            print(tab_elitary)
            if counter != 1:
                tab_mean2.append(np.mean(func_solution))
                tab_std2.append(np.std(func_solution))
                tab_epoch2.append(counter)

            if countEp != 0:
                tab_epoch4.append(countEp)
                tab_elitary2.append(best)

            counter += 1
            countEp += 1

        end = time.time()
        print("wynik czasu")
        el_time = (end - start)

        self.__el_time = el_time
        self.__tab_mean = tab_mean
        self.__tab_std = tab_std
        self.__tab_epoch = tab_epoch
        self.__tab_mean2 = tab_mean2
        self.__tab_std2 = tab_std2
        self.__tab_epoch2 = tab_epoch2
        self.__tab_elitary = tab_elitary
        self.__tab_epoch3 = tab_epoch3
        self.__tab_elitary2 = tab_elitary2
        self.__tab_epoch4 = tab_epoch4
Exemple #11
0
#from autots import Molecule
#from autots import Mutation
#from autots import connect

from molecule import Molecule
from mutation import Mutation
from utils import connect

import random

if __name__ == "__main__":

    mol = Molecule("examples/diels-alder.xyz")

    muts1 = [
        Mutation("mutations/8.xyz"),
        #Mutation("mutations/cn.xyz"),
        #Mutation("mutations/cooh.xyz"),
        #Mutation("mutations/nh2.xyz"),
        #Mutation("mutations/oh.xyz")
    ]

    unique_structures = []

    for i in range(100):
        print('Generating', i, '...')
        # How many mutations?
        #n = random.randint(1, 3)
        n = 6

        # Which n bonds?
            pop_fsum = pop_fsum + fitness_function.sum_all_fitness()
            population[i] = fitness_function.chromosome

        parents = []
        for i in range(2):  #select 2 chromosomes for crossover
            parent = RouletteSelection(population).do_selection()
            parents.append(parent)

        point = choice(range(0, len(parents[0]), 2))

        children = OnePoint().exe(parents[0], parents[1], point)

        probability = 100
        mutated_children = []
        for i in range(2):
            mutated_children.append(Mutation(
                children[i], probability).exe())  #mutate offspring

        i = 0
        for chromosome in population:  #replace current population with new one
            if str(chromosome) == str(parents[0]):
                population[i] = mutated_children[0]
                i = i + 1
            elif str(chromosome) == str(parents[1]):
                population[i] = mutated_children[1]
                i = i + 1
            else:
                i = i + 1

        #get list of fitness for each individual
        fsums = []
        for i in range(p):
Exemple #13
0
def main():
    parser = argparse.ArgumentParser(
        description="Simple toolkit to test changes in RBP/TF binding affinity"
        "caused by genetic variants.")
    parser.add_argument(dest='vcf', help='Path to the VCF file')
    parser.add_argument(dest='bed', help='Path to the bed file')
    parser.add_argument(dest='fasta', help='Path to the fasta file.')
    parser.add_argument(
        '--list',
        action='store_true',
        help='If bed argument represents a list of bed file to process'
        ' (one per line)')
    parser.add_argument(
        '--chr',
        action='store_true',
        help='Input files should contain chr string. If not found,'
        ' a fix is tried.')
    parser.add_argument(
        '--gtf',
        help=
        'gtf file to further take into account intron/exon boundaries. Canonical transcripts'
        'will be retrieved.')
    parser.add_argument(
        '--gtf_is_processed',
        action='store_true',
        help='If set \'--gtf\' argument represents the processed'
        'daraframe from an original gtf file.')
    parser.add_argument('-o',
                        '--output',
                        default=os.getcwd(),
                        help='Output directory. Default: current directory')
    parser.add_argument(
        '-p',
        '--fromPickle',
        help="If given, analysis should start from previously serialized object."
        "Input file will be ignored")
    args = parser.parse_args()

    osutils = OSutils()
    is_pickle = False
    if args.fromPickle:
        osutils.is_pickled(args.fromPickle)
        with open(args.fromPickle, 'rb') as file_object:
            raw_data = file_object.read()
        deserialized = pickle.loads(raw_data)
        is_pickle = True

    else:
        Logger.print_advances('Validating input data')
        if args.gtf:
            gtf = GTF(args.gtf, args.gtf_is_processed, args.output)
        else:
            gtf = None

        mutation = Mutation(args.vcf, args.bed, args.fasta, gtf, args.list,
                            args.chr, args.output)
        deserialized = {}
        Logger.print_advances('Starting analysis')
        for name, bedobj in mutation.beds.items():
            Logger.print_advances("Processing {} peak file.".format(name))
            Logger.log("Intercepting variants")
            fn = mutation.vcf_intersect(mutation.vcf_bed, bedobj, name)

            Logger.log('Extracting peaks fasta sequences')
            bed_seq = mutation.get_peak_sequence(bedobj, mutation.fasta)
            bed_peak_fasta = mutation.save_fasta_sequence(
                bed_seq, osutils.set_out_fn(mutation.outdir, name + ".fasta"))

            Logger.log("Mutating fasta sequences")
            isec = Isec(fn)
            seqs_mut = mutation.mutate_fasta(bed_peak_fasta, isec)
            deserialized[name] = seqs_mut
            Logger.log("Done")

        Logger.log("Dumping data structure to {}".format("data.pickle"))
        serialized = pickle.dumps(deserialized)
        with open(osutils.set_out_fn(mutation.outdir, "data.pickle"),
                  'wb') as file_object:
            file_object.write(serialized)

    motdisrupt = PeaksMutated(deserialized, is_pickle, args.output)
    motdisrupt.list_beds()
    motdisrupt.write_object()
    pwm = PWMs()
    pwm.parse_cisBP_pwm()
Exemple #14
0
    creator.create("FitnessMax", base.Fitness, weights=(-1.0,))
creator.create("Individual", Individual, fitness=creator.FitnessMax)

toolbox = base.Toolbox()

# Structure initializers
toolbox.register("individual", initIndividual, creator.Individual)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

# use multiple processors 
pool = multiprocessing.Pool(5)
toolbox.register("map", pool.map)

# register operators 
fit = Fitness("data/"+trainset_name)
mut = Mutation()
cross = Crossover()

toolbox.register("evaluate", fit.evaluate)
toolbox.register("mate", cross.cxOnePoint)
toolbox.register("mutate", mut.mutate)
toolbox.register("select", tools.selTournament, tournsize=3)

def main(id, checkpoint_name=None):
    # random.seed(64)

    if checkpoint_name:
        # A file name has been given, then load the data from the file
        cp = pickle.load(open(checkpoint_name, "rb"))
        pop = cp["population"]
        start_gen = cp["generation"] + 1
Exemple #15
0
import random
import numpy as np

from math import sin, cos, pi

from population import Population
from selection import Selection
from crossover import Crossover
from mutation import Mutation
from toolkits import GAEngine

f = lambda x, y: y * sin(2 * pi * x) + x * cos(2 * pi * y)

population = Population(100, [-2, 2], [-2, 2]).init()
selection = Selection(f, 100)
crossover = Crossover(pe=0.5)
mutation = Mutation([-2, 2], [-2, 2], pm=0.5)

engine = GAEngine(population, selection, crossover, mutation)

if '__main__' == __name__:
    engine.run(200)
Exemple #16
0
# Structure initializers
toolbox.register("individual", initIndividual, creator.Individual)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

# use multiple processors or GPU
if config.global_config["device"]["device_type"] == "CPU":
    n_cpus = config.global_config["device"]["n_cpus"]
    pool = multiprocessing.Pool(n_cpus)
    toolbox.register("map", pool.map)
    logging.info(f"Running on {n_cpus} CPUs")
else:
    logging.info(f"Running on GPU.")

# register operators
fit = Fitness(**config.global_config["dataset"])
mut = MutationConv() if use_conv_layers else Mutation()
cross = CrossoverConv() if use_conv_layers else Crossover()

toolbox.register("eval_batch", fit.evaluate_batch)
toolbox.register("evaluate", fit.evaluate)
toolbox.register("mate", cross.cxOnePoint)
toolbox.register("mutate", mut.mutate)
if nsga_number == 3:
    ref_points = tools.uniform_reference_points(2, 12)
    toolbox.register("select", tools.selNSGA3, ref_points=ref_points)
elif nsga_number == 2:
    # nsgaII - deap implementation
    toolbox.register("select", tools.selNSGA2)
elif nsga_number == 1:
    # stepan's version of nsga
    toolbox.register("select", selectNSGA)
Exemple #17
0
        # Select parents for offspring generation
        for ch in range(0, scored_population.__len__(), 1):
            # perform parent selection from scored population
            selection = Selection(population=scored_population)
            parents = selection.select()

            # perform crossover based on 50% probability
            crossover_prob = random.choice([True, False])
            crossover = Crossover(parents,
                                  crossover_probability=crossover_prob)
            offspring = crossover.perform_crossover()

            # perform mutation based on 50% probability
            mutation_prob = random.choice([True, False])
            mutation = Mutation(offspring, mutation_probability=mutation_prob)
            final_offspring = mutation.mutate()

            # add offspring to next generation
            next_gen_population.append(final_offspring)

        # Score next gen population
        scored_next_gen_population = []
        for chromosome in next_gen_population:
            fitness = Fitness(chromosome=chromosome, fitness_goal=fitness_goal)
            scored_next_gen_chromosome = fitness.calculate_fitness()
            scored_next_gen_population.append(scored_next_gen_chromosome)

        # Get generation best
        scored_next_gen_population.sort(key=lambda x: x[1])
        last_index = scored_next_gen_population.__len__() - 1
Exemple #18
0
from molecule import Molecule
from mutation import Mutation
from utils import connect

import random
import os

if __name__ == "__main__":

    mol = Molecule("examples/DA.xyz")

    ewg_dir = "mutations/EWG/"
    edg_dir = "mutations/EDG/"

    ewg_files = [Mutation(ewg_dir + f) for f in os.listdir(ewg_dir)]
    edg_files = [Mutation(edg_dir + f) for f in os.listdir(edg_dir)]

    print(ewg_files)
    print(edg_files)

    mol.bonds = [(1, 7), (2, 8)]
    #mol.bonds = [(6,12),(3,9)]

    unique_structures = []

    for i in range(50):
        print('Generating', i, '...')
        # Which n mutations?

        # Which n mutations?
Exemple #19
0
#    num = random.randint(0, numOfLuckyFew)
#    isInList(which_lucky_few, num, numOfLuckyFew)
#    which_lucky_few.append(num)
#
#for x in range(numOfLuckyFew):
#    lucky_few.append(temp_population[which_lucky_few[x]])
#
#print("The lucky few that will survive are: " + str(lucky_few))

Breeders = Breeders(population, password, best_sample, lucky_few)

print("The next generation is: ")
print(Breeders.selectFromPopulation(Breeders.computePerfPopulation(population, password), best_sample, lucky_few))

print("Time for reproduction...")

Reproduction = Reproduction()  /// TODO
print("What chance of mutation?")
chance_of_mutation = int(input())

Mutation = Mutation(population, chance_of_mutation)

population = Mutation.mutatePopulation(population, chance_of_mutation)

print("The new population is: ")
print(population)


#Fitness = Fitness()
#Reproduction = Reproduction()
Exemple #20
0
        print("roullette")
        roulet = Roulette_wheel(variable_config)
        roulette = roulet.roulette(variable_config, func_solution, popul)
        selection = roulette
        #print(roulette)
    '''

    #KRZYŻOWANIE
    #print("KRZYŻOWANIE")
    crosov = CrossingOver(variable_config)
    crosingover = crosov.crosingOver(variable_config, selection)
    #print(crosingover)

    #MUTACJA
    #print("MUTACJA")
    mutat = Mutation(variable_config)
    mutation = mutat.mutation(variable_config, crosingover)
    #print(mutation)

    #INWERSJA
    #print("INWERSJA")
    inver = Inversion(variable_config)
    inversion = inver.inversion(variable_config, mutation)
    #print(inversion)

    offspring = np.asarray(inversion)
    #print(offspring)

    decision_variables2 = randomBinSol.decVariables(variable_config, offspring)
    #print(decision_variables2)
Exemple #21
0
 def __mutation(self):
     mutator = Mutation(self.__childs, self.mutation_probability)
     mutator.perform()
Exemple #22
0
    def update(self, opt, select_pressure, mutagenic_pressure, t_curr,
               prolif_adj, all_muts):
        """Update this clone and its children for one time step."""
        if self.is_dead_end():
            return (
                0,
                0,
                0,
                0,
            )

        new_pop_size = new_sub_count = new_mut_agg = new_pro_agg = 0

        if not self.is_dead():
            if self.is_resistant:
                # warning: as currently implemented, the value of
                # resist_strength is not actually guaranteed to be
                # in the interval [0,1]
                eff_pressure = select_pressure * (1.0 - self.resist_strength)
                effective_prolif = self.prolif_rate - prolif_adj - eff_pressure
                effective_mut = self.mut_rate
            else:
                effective_prolif = self.prolif_rate - prolif_adj - select_pressure
                if mutagenic_pressure:
                    effective_mut = self.mut_rate * mutagenic_pressure
                else:
                    effective_mut = self.mut_rate
            # sample for cell death, division and mutation
            # note that we sample for both division AND death before
            # updating the clone size. This means that a 'cell'
            # can reproduce and die in the same cycle
            # (i.e. if cells_dead + cells_new > initial_size)
            cells_new = safe_binomial_sample(self.size, effective_prolif)
            cells_dead = safe_binomial_sample(self.size, self.death_rate)
            self.size = self.size + cells_new - cells_dead
            # this is the total number of mutations this cycle,
            # not necessarily number of new subclones to spawn
            new_mutns = safe_binomial_sample(cells_new, effective_mut)
        else:
            # clone is dead - update its attributes
            # if it died on the previous cycle
            if self.size < 0:
                self.size = 0
            if not self.d_time:
                self.d_time = t_curr

        # update child nodes - whether or not clone is alive
        for node in self.nodes:
            node_results = node.update(opt, select_pressure,
                                       mutagenic_pressure, t_curr, prolif_adj,
                                       all_muts)
            node_pop, node_sub_count, node_mut_agg, node_pro_agg = node_results
            new_pop_size += node_pop
            new_sub_count += node_sub_count
            new_mut_agg += node_mut_agg
            new_pro_agg += node_pro_agg
        # check again whether clone is alive;
        # clones which have died in this update
        # will now register as dead
        if not self.is_dead():
            for _i in xrange(new_mutns):
                new_mutn = Mutation(opt, t_curr, all_muts)
                if self.is_neutral_mutn(new_mutn):
                    new_mutn.classify_neutral(all_muts)
                    new_mutn.original_clone = self
                    self.num_neutral_mutns += 1
                else:
                    self.new_child(t_curr, opt, new_mutn)
                    self.size -= 1
                    new_sub_count += 1
                    new_pop_size += 1

        # finally, add this clone's stats to the return values
        new_pop_size += self.size
        new_sub_count += 1
        # return aggregate prolif and mut rates, ignoring
        # selective and mutagenic pressure
        new_mut_agg += self.mut_rate * self.size
        new_pro_agg += (self.prolif_rate - prolif_adj) * self.size

        return new_pop_size, new_sub_count, new_mut_agg, new_pro_agg