Index: /framspy/evolalg/base/frams_step.py
===================================================================
--- /framspy/evolalg/base/frams_step.py	(revision 1138)
+++ /framspy/evolalg/base/frams_step.py	(revision 1139)
@@ -3,5 +3,6 @@
 
 class FramsStep(Step):
-    def __init__(self, frams_lib, commands=None):
+    def __init__(self, frams_lib, commands=None, *args, **kwargs):
+        super(FramsStep, self).__init__(*args, **kwargs)
         if commands is None:
             commands = []
Index: /framspy/evolalg/base/lambda_step.py
===================================================================
--- /framspy/evolalg/base/lambda_step.py	(revision 1138)
+++ /framspy/evolalg/base/lambda_step.py	(revision 1139)
@@ -18,4 +18,5 @@
 
     def call(self, population):
+        super(LambdaStep, self).call(population)
         if self.in_place:
             [self.fun(_) for _ in population]
Index: /framspy/evolalg/base/step.py
===================================================================
--- /framspy/evolalg/base/step.py	(revision 1138)
+++ /framspy/evolalg/base/step.py	(revision 1139)
@@ -1,2 +1,3 @@
+import logging
 from abc import abstractmethod
 
@@ -7,10 +8,17 @@
 
     """
+
+    def __init__(self, name=None):
+        self.name = name
+        if name is None:
+            self.name = type(self).__name__
+
+
     def pre(self):
         pass
 
     @abstractmethod
-    def call(self, *args, **kwargs):
-        pass
+    def call(self, population, *args, **kwargs):
+        logging.getLogger(self.name).debug(f"Population size {len(population)}")
 
     def post(self):
Index: /framspy/evolalg/base/union_step.py
===================================================================
--- /framspy/evolalg/base/union_step.py	(revision 1138)
+++ /framspy/evolalg/base/union_step.py	(revision 1139)
@@ -5,5 +5,6 @@
 
 class UnionStep(Step):
-    def __init__(self, steps):
+    def __init__(self, steps, *args, **kwargs):
+        super(UnionStep, self).__init__(*args, **kwargs)
         if isinstance(steps, Iterable):
             self.steps = steps
@@ -12,5 +13,12 @@
 
     def call(self, population):
+        super(UnionStep, self).call(population)
         for s in self.steps:
             population = s(population)
         return population
+
+    def __len__(self):
+        return len(self.steps)
+
+    def __iter__(self):
+        return iter(self.steps)
Index: /framspy/evolalg/dissimilarity/frams_dissimilarity.py
===================================================================
--- /framspy/evolalg/dissimilarity/frams_dissimilarity.py	(revision 1138)
+++ /framspy/evolalg/dissimilarity/frams_dissimilarity.py	(revision 1139)
@@ -33,4 +33,5 @@
 
     def call(self, population):
+        super(FramsDissimilarity, self).call(population)
         if len(population) == 0:
             return []
Index: /framspy/evolalg/dissimilarity/levenshtein.py
===================================================================
--- /framspy/evolalg/dissimilarity/levenshtein.py	(revision 1138)
+++ /framspy/evolalg/dissimilarity/levenshtein.py	(revision 1139)
@@ -9,4 +9,5 @@
 
     def call(self, population):
+        super(LevenshteinDissimilarity, self).call(population)
         if len(population) == 0:
             return []
Index: /framspy/evolalg/examples/niching_novelty.py
===================================================================
--- /framspy/evolalg/examples/niching_novelty.py	(revision 1138)
+++ /framspy/evolalg/examples/niching_novelty.py	(revision 1139)
@@ -1,3 +1,4 @@
 import argparse
+import logging
 import os
 import pickle
@@ -22,4 +23,5 @@
 from evolalg.statistics.statistics_deap import StatisticsDeap
 from evolalg.base.union_step import UnionStep
+from evolalg.utils.name_propagation import propagate_names
 from evolalg.utils.population_save import PopulationSave
 import time
@@ -58,14 +60,15 @@
                         help='optimization criteria : vertpos, velocity, distance, vertvel, lifespan, numjoints, numparts, numneurons, numconnections (or other as long as it is provided by the .sim file and its .expdef). Single or multiple criteria.')
     parser.add_argument('-lib', required=False, help="Filename of .so or .dll with the Framsticks library")
+
     parser.add_argument('-genformat', required=False, default="1",
                         help='Genetic format for the demo run, for example 4, 9, or B. If not given, f1 is assumed.')
     parser.add_argument('-sim', required=False, default="eval-allcriteria.sim", help="Name of the .sim file with all parameter values")
+    parser.add_argument('-fit', required=False, default=Fitness.raw, type=Fitness,
+                        help=' Fitness criteria, default: raw', choices=list(Fitness))
     parser.add_argument('-dissim', required=False, type=Dissim, default=Dissim.frams,
-                        help='Dissimilarity measure, default = frams', choices=list(Dissim))
-    parser.add_argument('-fit', required=False, default=Fitness.raw, type=Fitness,
-                        help=' Fitness criteria, default = raw', choices=list(Fitness))
-    parser.add_argument('-popsize', type=int, default=50, help="Population size, default 50.")
-    parser.add_argument('-generations', type=int, default=5, help="Number of generations, default 5.")
-    parser.add_argument('-tournament', type=int, default=5, help="Tournament size, default 5.")
+                        help='Dissimilarity measure, default: frams', choices=list(Dissim))
+    parser.add_argument('-popsize', type=int, default=50, help="Population size, default: 50.")
+    parser.add_argument('-generations', type=int, default=5, help="Number of generations, default: 5.")
+    parser.add_argument('-tournament', type=int, default=5, help="Tournament size, default: 5.")
 
     parser.add_argument('-max_numparts', type=int, default=None, help="Maximum number of Parts. Default: no limit")
@@ -74,6 +77,9 @@
     parser.add_argument('-max_numconnections', type=int, default=None, help="Maximum number of Neural connections. Default: no limit")
 
+    parser.add_argument('-hof_evaluations', type=int, default=20, help="Number of final evaluations of each genotype in Hall of Fame to obtain reliable (averaged) fitness. Default: 20.")
     parser.add_argument('-checkpoint_path', required=False, default=None, help="Path to the checkpoint file")
     parser.add_argument('-checkpoint_interval', required=False, type=int, default=100, help="Checkpoint interval")
+    parser.add_argument('--debug', dest='debug', action='store_true', help="Prints names of steps as they are executed")
+    parser.set_defaults(debug=False)
     return parser.parse_args()
 
@@ -123,4 +129,11 @@
         return individual.numconnections > self.max_number
 
+class ReplaceWithHallOfFame(Step):
+    def __init__(self, hof, *args, **kwargs):
+        super(ReplaceWithHallOfFame, self).__init__(*args, **kwargs)
+        self.hof = hof
+    def call(self, population, *args, **kwargs):
+        super(ReplaceWithHallOfFame, self).call(population)
+        return list(self.hof.halloffame)
 
 def func_niching(ind): setattr(ind, "fitness", ind.fitness_raw * (1 + ind.dissim))
@@ -173,7 +186,8 @@
                               evaluation_count=1)
 
+
     fitness_end = FitnessStep(frams_lib, fields={parsed_args.opt: "fitness_raw"},
                               fields_defaults={parsed_args.opt: None},
-                              evaluation_count=100)  # evaluate the contents of the last population 100 times (TODO replace this approach and evaluate HOF instead of the last population)
+                              evaluation_count=parsed_args.hof_evaluations)
     # Remove
     remove = []
@@ -230,4 +244,5 @@
     # Statistics
     hall_of_fame = HallOfFameStatistics(100, "fitness_raw")  # Wrapper for halloffamae
+    replace_with_hof = ReplaceWithHallOfFame(hall_of_fame)
     statistics_deap = StatisticsDeap([
         ("avg", np.mean),
@@ -248,4 +263,5 @@
     # End stages: this will execute exacly once after all generations.
     end_stages = [
+        replace_with_hof,
         fitness_end,
         PopulationSave("halloffame.gen", provider=hall_of_fame.halloffame, fields={"genotype": "genotype",
@@ -254,5 +270,9 @@
 
     # -------------------------------------------------
+
+
+
     # Experiment creation
+
 
     experiment = Experiment(init_population=init_stages,
@@ -271,4 +291,6 @@
     print("Running experiment with", sys.argv)
     parsed_args = parseArguments()
+    if parsed_args.debug:
+        logging.basicConfig(level=logging.DEBUG)
 
     if parsed_args.checkpoint_path is not None and os.path.exists(parsed_args.checkpoint_path):
@@ -301,3 +323,4 @@
 
 if __name__ == '__main__':
+
     main()
Index: /framspy/evolalg/experiment.py
===================================================================
--- /framspy/evolalg/experiment.py	(revision 1138)
+++ /framspy/evolalg/experiment.py	(revision 1139)
@@ -9,5 +9,5 @@
 from evolalg.selection.selection import Selection
 from evolalg.utils.stable_generation import StableGeneration
-
+import logging
 
 class Experiment:
@@ -44,5 +44,5 @@
         self.generation_modification.init()
         self.end_steps.init()
-
+        self.population = []
         for s in self.init_population:
             self.population = s(self.population)
Index: /framspy/evolalg/fitness/fitness_step.py
===================================================================
--- /framspy/evolalg/fitness/fitness_step.py	(revision 1138)
+++ /framspy/evolalg/fitness/fitness_step.py	(revision 1139)
@@ -8,7 +8,7 @@
 class FitnessStep(FramsStep):
     def __init__(self, frams_lib, fields: Dict, fields_defaults: Dict, commands: List[str] = None,
-                 vectorized: bool = True, evaluation_count=None):
+                 vectorized: bool = True, evaluation_count=None, *args, **kwargs):
 
-        super().__init__(frams_lib, commands)
+        super().__init__(frams_lib, commands, *args, **kwargs)
         self.fields = fields
         self.fields_defaults = fields_defaults
@@ -28,4 +28,5 @@
 
     def call(self, population: List[Individual]):
+        super(FitnessStep, self).call(population)
         if self.vectorized:
             data = self.frams.evaluate([_.genotype for _ in population])
Index: /framspy/evolalg/fitness/multiple_evaluations.py
===================================================================
--- /framspy/evolalg/fitness/multiple_evaluations.py	(revision 1138)
+++ /framspy/evolalg/fitness/multiple_evaluations.py	(revision 1139)
@@ -7,10 +7,11 @@
 class MultipleEvaluationFitness(FitnessStep):
     def __init__(self, frams_lib, fields: Dict, fields_defaults: Dict, commands: List[str] = None,
-                 vectorized: bool = True, number_evaluations = 10):
-        super().__init__(frams_lib, fields, fields_defaults, commands, vectorized)
+                 vectorized: bool = True, number_evaluations = 10, *args, **kwargs):
+        super().__init__(frams_lib, fields, fields_defaults, commands, vectorized, *args, **kwargs)
         self.number_evaluations = number_evaluations
 
 
     def call(self, population: List[Individual]):
+        super(MultipleEvaluationFitness, self).call(population)
         pop = copy.deepcopy(population)
         statistics = [{} for _ in range(len(population))]
Index: /framspy/evolalg/mutation_cross/frams_cross.py
===================================================================
--- /framspy/evolalg/mutation_cross/frams_cross.py	(revision 1138)
+++ /framspy/evolalg/mutation_cross/frams_cross.py	(revision 1139)
@@ -6,9 +6,10 @@
 
 class FramsCross(FramsStep):
-    def __init__(self, frams_lib, commands, cross_prob):
-        super().__init__(frams_lib, commands)
+    def __init__(self, frams_lib, commands, cross_prob, *args, **kwargs):
+        super().__init__(frams_lib, commands, *args, **kwargs)
         self.cross_prob = cross_prob
 
     def call(self, population):
+        super(FramsCross, self).call(population)
         for i in range(1, len(population), 2):
             if random.random() < self.cross_prob:
Index: /framspy/evolalg/mutation_cross/frams_cross_and_mutate.py
===================================================================
--- /framspy/evolalg/mutation_cross/frams_cross_and_mutate.py	(revision 1138)
+++ /framspy/evolalg/mutation_cross/frams_cross_and_mutate.py	(revision 1139)
@@ -5,6 +5,6 @@
 
 class FramsCrossAndMutate(FramsStep):
-    def __init__(self, frams_lib, cross_prob, mutate_prob, mutate_commands=None, cross_commands=None):
-        super().__init__(frams_lib)
+    def __init__(self, frams_lib, cross_prob, mutate_prob, mutate_commands=None, cross_commands=None, *args, **kwargs):
+        super().__init__(frams_lib, *args, **kwargs)
 
         self.cross_prob = cross_prob
@@ -15,4 +15,5 @@
 
     def call(self, population):
+        super(FramsCrossAndMutate, self).call(population)
         population = self.frams_cross(population)
         population = self.frams_mutate(population)
Index: /framspy/evolalg/mutation_cross/frams_cross_or_mutate.py
===================================================================
--- /framspy/evolalg/mutation_cross/frams_cross_or_mutate.py	(revision 1138)
+++ /framspy/evolalg/mutation_cross/frams_cross_or_mutate.py	(revision 1139)
@@ -4,7 +4,9 @@
 import random
 
+
 class FramsCrossOrMutate(FramsStep):
-    def __init__(self, frams_lib, commands, cross_prob, mutate_prob, mutate_commands=None, cross_commands=None):
-        super().__init__(frams_lib, commands)
+    def __init__(self, frams_lib, commands, cross_prob, mutate_prob, mutate_commands=None, cross_commands=None, *args,
+                 **kwargs):
+        super().__init__(frams_lib, commands, *args, **kwargs)
 
         self.cross_prob = cross_prob
@@ -15,4 +17,5 @@
 
     def call(self, population):
+        super(FramsCrossOrMutate, self).call(population)
         mutate_idx = []
         cross_idx = []
@@ -21,5 +24,5 @@
             if rng < self.cross_prob:
                 cross_idx.append(i)
-            elif rng < self.cross_prob+self.mutate_prob:
+            elif rng < self.cross_prob + self.mutate_prob:
                 mutate_idx.append(i)
 
@@ -32,8 +35,8 @@
             self.frams_cross(cross_idx)
 
-        for i,ind in zip(mutate_idx, mutate_ind):
+        for i, ind in zip(mutate_idx, mutate_ind):
             population[i] = ind
 
-        for i,ind in zip(cross_idx, cross_ind):
+        for i, ind in zip(cross_idx, cross_ind):
             population[i] = ind
 
Index: /framspy/evolalg/mutation_cross/frams_mutation.py
===================================================================
--- /framspy/evolalg/mutation_cross/frams_mutation.py	(revision 1138)
+++ /framspy/evolalg/mutation_cross/frams_mutation.py	(revision 1139)
@@ -6,9 +6,10 @@
 
 class FramsMutation(FramsStep):
-    def __init__(self, frams_lib, commands, mutate_prob):
-        super().__init__(frams_lib, commands)
+    def __init__(self, frams_lib, commands, mutate_prob, *args, **kwargs):
+        super().__init__(frams_lib, commands, *args, **kwargs)
         self.mutate_prob = mutate_prob
 
     def call(self, population):
+        super(FramsMutation, self).call(population)
         idx = []
         for i in range(len(population)):
Index: /framspy/evolalg/population/frams_population.py
===================================================================
--- /framspy/evolalg/population/frams_population.py	(revision 1138)
+++ /framspy/evolalg/population/frams_population.py	(revision 1139)
@@ -4,13 +4,15 @@
 
 class FramsPopulation(FramsStep):
-    def __init__(self, frams_lib, genetic_format, pop_size, commands=None):
+    def __init__(self, frams_lib, genetic_format, pop_size, commands=None, *args, **kwargs):
+
         if commands is None:
             commands = []
-        super().__init__(frams_lib, commands)
+        super().__init__(frams_lib, commands,*args, **kwargs)
 
         self.pop_size = pop_size
         self.genetic_format = genetic_format
 
-    def call(self, *args, **kwargs):
+    def call(self, population, *args, **kwargs):
+        super(FramsPopulation, self).call(population)
         return [Individual(self.frams.getSimplest(self.genetic_format)) for _ in range(self.pop_size)]
 
Index: /framspy/evolalg/repair/const.py
===================================================================
--- /framspy/evolalg/repair/const.py	(revision 1138)
+++ /framspy/evolalg/repair/const.py	(revision 1139)
@@ -5,6 +5,6 @@
 
 class ConstRepair(Repair):
-    def __init__(self, value, excepted_size):
-        super(ConstRepair, self).__init__(excepted_size)
+    def __init__(self, value, excepted_size, *args, **kwargs):
+        super(ConstRepair, self).__init__(excepted_size, *args, **kwargs)
         self.value = value
 
Index: /framspy/evolalg/repair/halloffame_repair.py
===================================================================
--- /framspy/evolalg/repair/halloffame_repair.py	(revision 1138)
+++ /framspy/evolalg/repair/halloffame_repair.py	(revision 1139)
@@ -6,6 +6,6 @@
 
 class HallOfFameRepair(Repair):
-    def __init__(self, excepted_size, halloffame, top):
-        super(HallOfFameRepair, self).__init__(excepted_size)
+    def __init__(self, excepted_size, halloffame, top, *args, **kwargs):
+        super(HallOfFameRepair, self).__init__(excepted_size, *args, **kwargs)
         self.halloffame = halloffame
         self.top = top
Index: /framspy/evolalg/repair/multistep.py
===================================================================
--- /framspy/evolalg/repair/multistep.py	(revision 1138)
+++ /framspy/evolalg/repair/multistep.py	(revision 1139)
@@ -3,6 +3,6 @@
 
 class MultistepRepair(Repair):
-    def __init__(self, selection, steps, excepted_size):
-        super(MultistepRepair, self).__init__(excepted_size)
+    def __init__(self, selection, steps, excepted_size, *args, **kwargs):
+        super(MultistepRepair, self).__init__(excepted_size, *args, **kwargs)
         self.selection = selection
         self.steps = steps
Index: /framspy/evolalg/repair/mutate.py
===================================================================
--- /framspy/evolalg/repair/mutate.py	(revision 1138)
+++ /framspy/evolalg/repair/mutate.py	(revision 1139)
@@ -6,6 +6,6 @@
 
 class MutateRepair(Repair):
-    def __init__(self, mutate_step, excepted_size, iterations=1):
-        super(MutateRepair, self).__init__(excepted_size)
+    def __init__(self, mutate_step, excepted_size, iterations=1, *args, **kwargs):
+        super(MutateRepair, self).__init__(excepted_size, *args, **kwargs)
         self.mutate_step = mutate_step
         self.iterations = iterations
Index: /framspy/evolalg/repair/remove/field.py
===================================================================
--- /framspy/evolalg/repair/remove/field.py	(revision 1138)
+++ /framspy/evolalg/repair/remove/field.py	(revision 1139)
@@ -3,6 +3,6 @@
 
 class FieldRemove(Remove):
-    def __init__(self, field_name, field_value):
-        super(FieldRemove, self).__init__()
+    def __init__(self, field_name, field_value, *args, **kwargs):
+        super(FieldRemove, self).__init__(*args, **kwargs)
         self.field_name = field_name
         self.field_value = field_value
Index: /framspy/evolalg/repair/remove/function.py
===================================================================
--- /framspy/evolalg/repair/remove/function.py	(revision 1138)
+++ /framspy/evolalg/repair/remove/function.py	(revision 1139)
@@ -3,6 +3,6 @@
 from evolalg.repair.remove.remove import Remove
 class LambdaRemove(Remove):
-    def __init__(self, func):
-        super(LambdaRemove, self).__init__()
+    def __init__(self, func, *args, **kwargs):
+        super(LambdaRemove, self).__init__(*args, **kwargs)
         self.func = func
 
Index: /framspy/evolalg/repair/remove/remove.py
===================================================================
--- /framspy/evolalg/repair/remove/remove.py	(revision 1138)
+++ /framspy/evolalg/repair/remove/remove.py	(revision 1139)
@@ -5,5 +5,6 @@
 
 class Remove(Step):
-    def __init__(self):
+    def __init__(self, *args, **kwargs):
+        super(Remove, self).__init__(*args , **kwargs)
         pass
 
@@ -13,3 +14,4 @@
 
     def call(self, population):
+        super(Remove, self).call(population)
         return [_ for _ in population if not self.remove(_)]
Index: /framspy/evolalg/repair/repair.py
===================================================================
--- /framspy/evolalg/repair/repair.py	(revision 1138)
+++ /framspy/evolalg/repair/repair.py	(revision 1139)
@@ -6,5 +6,6 @@
 
 class Repair(Step):
-    def __init__(self, excepted_size):
+    def __init__(self, excepted_size, *args, **kwargs):
+        super(Repair, self).__init__(*args, **kwargs)
         self.excepted_size = excepted_size
 
@@ -14,4 +15,5 @@
 
     def call(self, population):
+        super(Repair, self).call(population)
         generated = []
         while len(generated) + len(population) < self.excepted_size:
Index: /framspy/evolalg/selection/identity.py
===================================================================
--- /framspy/evolalg/selection/identity.py	(revision 1138)
+++ /framspy/evolalg/selection/identity.py	(revision 1139)
@@ -6,8 +6,9 @@
 
 class IdentitySelection(Selection):
-    def __init__(self, copy=False):
-        super(IdentitySelection, self).__init__(copy)
+    def __init__(self, copy=False, *args, **kwargs):
+        super(IdentitySelection, self).__init__(copy, *args, **kwargs)
 
     def call(self, population, selection_size=None):
+        super(IdentitySelection, self).call(population)
         res = population
         if selection_size is not None:
Index: /framspy/evolalg/selection/selection.py
===================================================================
--- /framspy/evolalg/selection/selection.py	(revision 1138)
+++ /framspy/evolalg/selection/selection.py	(revision 1139)
@@ -6,5 +6,6 @@
 
 class Selection(Step):
-    def __init__(self, copy=False):
+    def __init__(self, copy=False, *args, **kwargs):
+        super(Selection, self).__init__(*args, **kwargs)
         self.copy = copy
 
@@ -14,4 +15,5 @@
 
     def call(self, population, count=None):
+        super(Selection, self).call(population)
         res = []
         if count is None:
Index: /framspy/evolalg/selection/tournament.py
===================================================================
--- /framspy/evolalg/selection/tournament.py	(revision 1138)
+++ /framspy/evolalg/selection/tournament.py	(revision 1139)
@@ -8,6 +8,6 @@
 
 class TournamentSelection(Selection):
-    def __init__(self, tournament_size: int, fit_attr="fitness", copy=False):
-        super(TournamentSelection, self).__init__(copy)
+    def __init__(self, tournament_size: int, fit_attr="fitness", copy=False, *args, **kwargs):
+        super(TournamentSelection, self).__init__(copy, *args, **kwargs)
         self.tournament_size = tournament_size
         self.fit_attr = fit_attr
Index: /framspy/evolalg/statistics/halloffame_custom.py
===================================================================
--- /framspy/evolalg/statistics/halloffame_custom.py	(revision 1138)
+++ /framspy/evolalg/statistics/halloffame_custom.py	(revision 1139)
@@ -5,6 +5,6 @@
 
 class HallOfFameCustom(HallOfFame):
-    def __init__(self,  maxsize, similar=operator.eq, fitness_field="fitness"):
-        super(HallOfFameCustom, self).__init__(maxsize, similar)
+    def __init__(self,  maxsize, similar=operator.eq, fitness_field="fitness", *args, **kwargs):
+        super(HallOfFameCustom, self).__init__(maxsize, similar, *args, **kwargs)
         print("HOF_size =",self.maxsize)
         self._fitness_field = fitness_field
Index: /framspy/evolalg/statistics/halloffame_stats.py
===================================================================
--- /framspy/evolalg/statistics/halloffame_stats.py	(revision 1138)
+++ /framspy/evolalg/statistics/halloffame_stats.py	(revision 1139)
@@ -4,5 +4,6 @@
 
 class HallOfFameStatistics(Statistics):
-    def __init__(self, size, fields="fitness"):
+    def __init__(self, size, fields="fitness", *args, **kwargs):
+        super(HallOfFameStatistics, self).__init__(*args, **kwargs)
         self.halloffame = HallOfFameCustom(size, fitness_field=fields)
 
Index: /framspy/evolalg/statistics/statistics.py
===================================================================
--- /framspy/evolalg/statistics/statistics.py	(revision 1138)
+++ /framspy/evolalg/statistics/statistics.py	(revision 1139)
@@ -11,4 +11,5 @@
 
     def call(self, population):
+        super(Statistics, self).call(population)
         self.collect(population)
         return population
Index: /framspy/evolalg/statistics/statistics_deap.py
===================================================================
--- /framspy/evolalg/statistics/statistics_deap.py	(revision 1138)
+++ /framspy/evolalg/statistics/statistics_deap.py	(revision 1139)
@@ -5,5 +5,6 @@
 
 class StatisticsDeap(Statistics):
-    def __init__(self, stats, extract_fn=lambda ind: ind.fitness, verbose=True):
+    def __init__(self, stats, extract_fn=lambda ind: ind.fitness, verbose=True, *args, **kwargs):
+        super(StatisticsDeap, self).__init__(*args, **kwargs)
         self.stats = tools.Statistics(extract_fn)
         for name, fn in stats:
Index: /framspy/evolalg/utils/name_propagation.py
===================================================================
--- /framspy/evolalg/utils/name_propagation.py	(revision 1139)
+++ /framspy/evolalg/utils/name_propagation.py	(revision 1139)
@@ -0,0 +1,15 @@
+from typing import Iterable, Union, List
+
+from evolalg.base.step import Step
+import copy
+
+def propagate_names(step: Step, prefix=""):
+
+    if isinstance(step, Iterable):
+        for s in step:
+            if hasattr(step, "name"):
+                propagate_names(s, prefix=prefix + "." + step.name)
+            else:
+                propagate_names(s, prefix=prefix)
+    if hasattr(step, "name"):
+        step.name = f"{prefix}.{step.name}"
Index: /framspy/evolalg/utils/population_save.py
===================================================================
--- /framspy/evolalg/utils/population_save.py	(revision 1138)
+++ /framspy/evolalg/utils/population_save.py	(revision 1139)
@@ -5,5 +5,6 @@
 
 class PopulationSave(Step):
-    def __init__(self, path, fields, provider=None):
+    def __init__(self, path, fields, provider=None, *args, **kwargs):
+        super(PopulationSave, self).__init__(*args, **kwargs)
         self.path = path
         self.provider = provider
@@ -19,4 +20,5 @@
 
     def call(self, population):
+        super(PopulationSave, self).call(population)
         PopulationSave.ensure_dir(self.path)
         provider = self.provider
