public static void process_node(note_node temp_node_, int current_cost_)
        {
            note_node temp_node2 = temp_node_;
            //Add to the stack
            temp_note_stk.Push(temp_node_);

            //Work through the child nodes for the passed parent
            foreach (note_node temp_child_ in DecisionTree.get_Children(temp_node_))
            {

                //When at the last note in the list notes then push current stack out to an arrangemenet
                if (temp_child_.NoteDetails.position == MatchNotes.last_note_position)
                {

                    //Push the current child to the stack to get the last note in the current tree thread
                    temp_note_stk.Push(temp_child_);

                    //Copy the current the stack snapshot to an arrangemenet
                    List<note_node> temp2;

                    //TO DO : Clean up the following as creation of temp array object not great but works for the mo
                    note_node[] tempArray = new note_node[temp_note_stk.Count];
                    temp_note_stk.ToArray().CopyTo(tempArray, 0);
                    temp2 = tempArray.ToList();
                    temp2.Reverse(); // Stack values will be the wrong way round so need to reverse

                    //Generate the Arrangement
                    Arrangement tempArrange = new Arrangement(temp2);

                    tempArrange.number_of_notes = temp2.Count();

                    //Check if the arrangement has all the required notes
                    //If yes then add the arrangment
                    if (temp2.Count() == Arrangemenet_engine.original_note_count)
                    {
                        //Calculate the total costs of the arrangemenet
                        foreach (note_node temp_node in temp2)
                        {
                            tempArrange.total_Cost += temp_node.cost;
                            if (temp_node.cost < 0)
                                tempArrange.total_neg += temp_node.cost;
                            if (temp_node.cost > 0)
                                tempArrange.total_pos += temp_node.cost;

                        };
                        Arrangemenets.add_arrangemenet(tempArrange);
                    };

                    temp_note_stk.Pop();

                }
                else
                {
                    // Call process node again for the next set of children
                    process_node(temp_child_, current_cost_);
                    // Pop the last child off the stack
                    temp_note_stk.Pop();
                }
            };
        }
 public static int compare_Cost(note_node temp_node)
 {
     try
     {
         return temp_node.cost - DicBestNodes[temp_node.NoteDetails.position].cost;
     }
     catch
     {
         return 0;
     }
 }
        public static void add_Node(note_node temp_node)
        {
            //Check if the note exists else not add
            if (DicBestNodes.ContainsKey(temp_node.NoteDetails.position))
            {

                //Find the position in the dictioary and check the paramter note against the current note
                if (DicBestNodes[temp_node.NoteDetails.position].cost > temp_node.cost)
                {
                    DicBestNodes[temp_node.NoteDetails.position] = temp_node;
                }
            }
            else
            {
                DicBestNodes.Add(temp_node.NoteDetails.position, temp_node);
            }
        }
        public static int get_note_cost2(note_node temp_node, note_node parent_node_)
        {
            //New version of the cost engine to support "Best Arrangements" option
            note_node temp_note = new note_node();

            temp_note = temp_node;
            temp_note.cost = 0;

            // Check if the note is an open string and
            if (temp_note.NoteDetails.fret == 0)
            {
                temp_note.cost = -2;
            }

            // Check if it's a route node
            if (temp_node.parent_node_index == null)
            {
                // Currently perform no checks
            }
            else
            {

                //TODO the whole section below needs a bit of a re-write to allow for a gradual costing based on the parent,
                // parent's parent, parents parents parent etc.....

                // Check the last note is the same string as last note
                if (temp_node.NoteDetails.banjoString == parent_node_.NoteDetails.banjoString &&
               temp_node.NoteDetails.notenumber != parent_node_.NoteDetails.notenumber
                   && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                {
                    temp_note.cost += 12;
                }
                // Check distance between last note and current note
                if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.NoteDetails.fret) > 4 &&
                   (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                {
                    temp_note.cost += 10;
                }

                try
                {
                    // Check distance between current note and 2 notes ago
                    if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.parent_node.NoteDetails.fret) > 4 &&
                       (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                    {
                        temp_note.cost += 8;
                    }
                }
                catch
                {
                };
                try
                {
                    //// Check distance between current note and 3 notes ago
                    if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.parent_node.parent_node.NoteDetails.fret) > 4 &&
                       (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                    {
                        temp_note.cost += 6;
                    }
                }
                catch
                {
                };

                try
                {
                    //// Check distance between current note and 3 notes ago
                    if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.parent_node.parent_node.parent_node.NoteDetails.fret) > 4 &&
                       (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                    {
                        temp_note.cost += 4;
                    }
                }
                catch
                {
                };

                try
                {
                    //// Check distance between current note and 3 notes ago
                    if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.parent_node.parent_node.parent_node.parent_node.NoteDetails.fret) > 4 &&
                       (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                    {
                        temp_note.cost += 2;
                    }
                }
                catch
                {
                };
            }
            return temp_note.cost;
        }
        private static note_node get_note_cost(note_node temp_node, List<note_node> DTArray)
        {
            note_node temp_note = new note_node();

            temp_note = temp_node;
            int index = DTArray.IndexOf(temp_node);

            // Check if the note is an open string and
            if (temp_note.NoteDetails.fret == 0)
            {
                temp_note.cost = -2;
            }

            // Check if it's a route node
            if (temp_node.parent_node_index == null)
            {
                // Currently perform no checks
            }
            else
            {
                // Check the last note is the same string as last note
                if (temp_node.NoteDetails.banjoString == DTArray[index - 1].NoteDetails.banjoString &&
               temp_node.NoteDetails.notenumber != DTArray[index - 1].NoteDetails.notenumber
                   && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                {
                    temp_note.cost = 12;
                }
                // Check distance between last note and current note
                if (System.Math.Abs(temp_node.NoteDetails.fret - DTArray[index - 1].NoteDetails.fret) > 4 &&
                   (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                {
                    temp_note.cost = 9;
                }

                try
                {
                    // Check distance between current note and 2 notes ago
                    if (System.Math.Abs(temp_node.NoteDetails.fret - DTArray[index - 2].NoteDetails.fret) > 4 &&
                       (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                    {
                        temp_note.cost = 6;
                    }
                }
                catch
                {
                };
                try
                {
                    //// Check distance between current note and 3 notes ago
                    if (System.Math.Abs(temp_node.NoteDetails.fret - DTArray[index - 3].NoteDetails.fret) > 4 &&
                       (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0))
                    {
                        temp_note.cost = 3;
                    }
                }
                catch
                {
                };

            }
            return temp_note;
        }
        //Accept the parent index as a parameter to allow for recursave calls
        public static void Process_Note_Range(int last_note_index, int? last_DT_index, 
            note_node parent_node_, MatchNote currentMatchNote, 
            int cost_limit, int max_end_notes, CancellationToken cts)
        {
            Logging.Update_note_position(parent_node_.NoteDetails.position);
            //Logging.Update_Status("Processing Notes for parent:" + parent_node_.ToString());

            /* Start the loop at the current index position and work forwards through the
                note results untill the next note position is found
             */

            //try
            //{

            //Get ordered list

            List<MatchNote> MatchLoop = MatchNotes.getNextMatchNotes(currentMatchNote);
            if (MatchLoop == null)
            {
                //No more notes left so finish
                return;
            }

            //First pass of maatching note, calculate cost and add to the BestNodes
            foreach (MatchNote tempMatchNote in MatchLoop)
            {

                int i = 0;
                // Current note note is 'next' in the position then add the current note to the DT

                note_node new_node = new note_node(last_DT_index, last_note_index, i, tempMatchNote, parent_node_);
                new_node.cost = CostCalculator.get_note_cost2(new_node, parent_node_);

                BestNodes.add_Node(new_node);// Need to add the note node to the best nodes incase the position is currently empty
                int costcomp = BestNodes.compare_Cost(new_node);
                if (i <= cost_limit)
                {
                    DecisionTree.add_node(new_node);

                }
            }

            //Get a list of the new DT Nodes order by lowest cost first
            List<note_node> Note_Nodes_list = DecisionTree.get_Children(parent_node_)
                .OrderBy(p => p.cost)
                .ToList();

            // Next loop though the newly created DT Nodes with the parent
            foreach (note_node temp_node in Note_Nodes_list)
            {
                int i;
                //Check the cost comparison is less than or = to the current best node
                //if yes then add to the DT & cotinue to process the notes children
                i = BestNodes.compare_Cost(temp_node);
                if (i <= cost_limit)
                {

                    //If not the last note in
                    if (temp_node.NoteDetails.last_note == false)
                    {

                        if (cts.IsCancellationRequested || currentEndCount_ == max_end_notes)
                        {
                            return;
                        }

                        // DANGER !!!! This is a stab in the dark approach to sort the bigger problem regards
                        // total processing time
                        if (temp_node.NoteDetails.position == MatchNotes.get_last_note_position())
                        {
                            currentEndCount_ += 1;
                            Logging.Update_Status("End note found :" + currentEndCount_.ToString());
                            return;

                        }

                        Process_Note_Range(i, temp_node.tree_index, temp_node, temp_node.NoteDetails,
                            cost_limit, max_end_notes, cts);

                    }
                }

                else
                    temp_node.Excluded = true;

            }
        }
        public static List<note_node> Process_Route_Notes(List<MatchNote> matchingresults, int cost_limit, int max_end_notes, CancellationToken cts)
        {
            BestNodes.Clear();

            //First sort the list by fret & include only the root notes list into
            List<MatchNote> Root_Notes = matchingresults
                .Where(f => f.position == MatchNotes.get_first_note_position())
                .OrderBy(f => f.fret)
                .ToList();

            // get the
            int matchindex = 0;

            //Loop thought root notes
            foreach (MatchNote matchresult in Root_Notes)
            {

                Logging.Update_Status("Starting matching process for :" + matchresult.ToString());
                // Read the route note and check its not the 2nd note in the file
                // If it is then exit the loop as the processing is finished

                if (matchingresults[0].position != matchingresults[matchindex].position)
                {
                    //If the route note is position is different than last route note (I.e. not the first note position then stop)
                    break;
                }

                //Add the note as a route node to the DT

                note_node new_node = new note_node(0, 0, matchresult, null);
                BestNodes.add_Node(new_node); // Need to add the note node to the best nodes incase the position is currently empty

                DecisionTree.add_node(new_node);
                //Run the note through the BestNodes process

                // Note is still the same so process from this point

                if (new_node.NoteDetails.last_note == false)
                {
                    //If the note is not the last note then continue to process i's children
                    //await Task.Run(() =>
                    currentEndCount_ = 0;
                    Process_Note_Range(matchindex, new_node.tree_index, new_node, matchingresults[matchindex],
                        cost_limit, max_end_notes, cts);
                }

                matchindex++; // Track the index of the current matched note in the list of notes

            }
            return DecisionTree.get_all_nodes();

            //    }
            // catch (Exception ex)
            // {
            //     throw new System.ArgumentException("Error processing route notes"+ex.ToString());
            //  }
        }
        //Accept the parent index as a parameter to allow for recursave calls
        public static void Process_Note_Range(int last_note_index, int? last_DT_index, note_node parent_node_, MatchNote currentMatchNote, int cost_limit, CancellationToken cts)
        {
            Logging.Update_note_position(parent_node_.NoteDetails.position);
            //Logging.Update_Status("Processing Notes for parent:" + parent_node_.ToString());

            /* Start the loop at the current index position and work forwards through the
                note results untill the next note position is found
             */

            //try
            //{
            if (parent_node_.NoteDetails.last_note == true)
            {
                //Logging.Update_Status("End note found!");
                return;
            }
            List<MatchNote> MatchLoop = MatchNotes.getNextMatchNotes(currentMatchNote);
            if (MatchLoop == null)
            {
                //No more notes left
                return;
            }

            foreach (MatchNote tempMatchNote in MatchLoop)
            {

                int i = 0;
                // Current note note is 'next' in the position then add the current note to the DT

                //TODO Extract Add note from Decision tree to allow cost evaluation before tree has
                // an added value
                note_node new_node = new note_node(last_DT_index, last_note_index, i, tempMatchNote, parent_node_);
                new_node.cost = CostCalculator.get_note_cost2(new_node, parent_node_);

                i = BestNodes.compare_Cost(new_node);
                BestNodes.add_Node(new_node);// Need to add the note node to the best nodes incase the position is currently empty

                //Check the cost comparison is less than or = to the current best node
                //if yes then add to the DT & cotinue to process the notes children
                if (i <= cost_limit)
                {

                    DecisionTree.add_node(new_node);

                    //If not the last note in
                    if (tempMatchNote.last_note == false)
                    {

                        if (cts.IsCancellationRequested)
                        {
                            return;
                        }

                        // If not the last note position then perform recursive call to generate the next tree node
                        //await Task.Run(() => Process_Note_Range(i, new_node.tree_index, new_node, tempMatchNote, cost_limit, cts), cts);
                        Process_Note_Range(i, new_node.tree_index, new_node, tempMatchNote, cost_limit, cts);
                        // Finished processing of the note to break from the loop
                    }
                }

            }

            //            }
            //          catch (Exception Ex)
            //        {
            //          throw new System.ArgumentException("Some notes cannot be match with this tranposition, Error : " +Ex.ToString());
            //    }
        }