def helper_search(mass_min, mass_max, formula_mass, formula, last_index, delta, restrict): """ This function is called when the formula_mass is less than the mass_max It attempts to add a new element and if still in the mass tolerance window and complies with the first rule calls itself recursively :param mass_min: Minimum mass accepted for solution :param mass_max: Maximum mass accepted for solution :param formula_mass: The mass of the formula now :param formula: The formula now :param last_index: The last element added :param delta: Computation error allowed :return: not explicit, it adds to global list of formulas all 7rules complying formulas """ for index, element in enumerate(formula): if index >= last_index: new_formula_mass = formula_mass + element['freqisotope']['mass'] if mass_max - new_formula_mass >= -delta: new_formula = formula.copy() new_formula[element] += 1 if new_formula_mass - mass_min >= -delta: # formula in tolerance interval, add it to solutions if filter_formula(new_formula, restrict): formulas.append(new_formula) else: if rule1(new_formula, restrict): # still some mass left, keep searching helper_search(mass_min, mass_max, new_formula_mass, new_formula, index, delta, restrict)
def search(mass, tolerance, delta, restrict): """ :param mass: the formula mass :param tolerance: tolerance to accommodate equipment errors :param delta: computation error allowed :param restrict: True indicates CHNOPS_restricted :return: a list of candidate formulas """ global formulas formulas = [] if restrict: formula = {element: 0 for element in CHNOPS} # order is important, need to be decreasing element_list = [SULFUR, PHOSPHORUS, OXYGEN, NITROGEN, CARBON, HYDROGEN] else: formula = {element: 0 for element in elements} element_list = elements # scale the input data mass *= scalar tolerance *= scalar # this algorithm work with int masses mass_total = int(math.ceil(mass) + 1) # n is the enumber of decision points # for this unbounded implementation: n <= number_elements * mass # but early termination is implemented n = len(formula) * mass_total # initialise row 0 odd_row = [] even_row = [(0, formula) for i in range(0, mass_total)] i = 0 last_index = -1 repetitions = 0 terminate = False while i < n and not terminate: i += 1 if i % 2 == 0: (even_row, last_index, repetitions, terminate) = helper_search(odd_row, mass_total, element_list, last_index, repetitions, formula, terminate, restrict) (candidate_mass, candidate) = even_row[-1] if candidate_mass - mass > tolerance + delta and len(even_row) > 1: (candidate_mass, candidate) = even_row[-2] candidate_mass = get_formula_mass(candidate) if candidate_mass + tolerance - mass >= -delta and mass + tolerance - candidate_mass >= -delta and not candidate in formulas and the_7rules.filter_formula( candidate, restrict): formulas.append(candidate) else: (odd_row, last_index, repetitions, terminate) = helper_search(even_row, mass_total, element_list, last_index, repetitions, formula, terminate, restrict) (candidate_mass, candidate) = odd_row[-1] if candidate_mass - mass > tolerance + delta and len(odd_row) > 1: (candidate_mass, candidate) = odd_row[-2] if candidate_mass + tolerance - mass >= -delta and mass + tolerance - candidate_mass >= -delta and not candidate in formulas and the_7rules.filter_formula( candidate, restrict): formulas.append(candidate) return formulas