/// <summary>
        /// Move a sliding window and apply the filter by using its BottomUp() method.
        /// </summary>
        protected override void bottomUp()
        {
            System.Collections.Concurrent.ConcurrentStack <IONode> filterClones = new ConcurrentStack <IONode>();
            int stepsWidth  = (int)(input.Width / stepSize.X);
            int stepsHeight = (int)(input.Height / stepSize.Y);

            int totalIterations = stepsWidth * stepsHeight;

            for (int i = 0; i < totalIterations; i++)
            {
                IONode clone = ObjectCopier.Clone(filter);
                filterClones.Push(clone);
            }

            System.Collections.Concurrent.ConcurrentStack <IONode> filterClonesUsed = new ConcurrentStack <IONode>();

            //We pass all components of the input signal
            Parallel.For(0, stepsWidth, stepX =>
            {
                int xI = stepX * (int)stepSize.X;
                Parallel.For(0, stepsHeight, stepY =>
                {
                    int yI = stepY * (int)stepSize.Y;

                    //Clone the filter
                    IONode clone;
                    while (!filterClones.TryPop(out clone))
                    {
                        ;
                    }

                    //We construct the filter input based on its dimensions
                    for (int xF = 0; xF < clone.input.Width; xF++)
                    {
                        for (int yF = 0; yF < clone.input.Height; yF++)
                        {
                            int x = xI - clone.input.Width / 2 + xF;
                            int y = yI - clone.input.Height / 2 + yF;
                            x     = Math.Min(input.Width - 1, Math.Max(x, 0));
                            y     = Math.Min(input.Height - 1, Math.Max(y, 0));
                            clone.input.reality[xF, yF] = input.reality[x, y];
                        }
                    }

                    //We apply the clone
                    clone.BottomUp();

                    //We copy the result of the clone to the output
                    for (int xF = 0; xF < clone.output.Width; xF++)
                    {
                        for (int yF = 0; yF < clone.output.Height; yF++)
                        {
                            output.prediction[(int)(xI / stepSize.X) * clone.output.Width + xF, (int)(yI / stepSize.Y) * clone.output.Height + yF] = clone.output.prediction[xF, yF];
                        }
                    }
                    filterClonesUsed.Push(clone);
                });
            });

            if (filter is IONodeAdaptive)
            {
                IEnumerable <IONodeAdaptive> casted = filterClonesUsed.Cast <IONodeAdaptive>();
                (filter as IONodeAdaptive).fuse(casted);
            }
        }