(base_arr, model_arr, same_size_use_model_arr_diff_thresh=None)
return best_arr, diff
Find an array <best_arr> based on <base_arr> that fits best to <model_arr> if their sizes differ.
    <best_arr> will have the same size as <model_arr> and either has surplus elements removed (if <base_arr> is
    bigger than <model_arr>) or missing elements added from <model_arr> (if <base_arr> is smaller than <model_arr>).
    
    Returns the best fitting array and the summed difference of this array and <model_arr>.
    
    It uses a brute force method so this is slow for big arrays.
    
    Example:
        
    values = [
        [0,  10,     30,         40],
        [0,  11,     29,         42],
        [10, 21, 25, 39,         52],
        [0,   9, 15, 29, 32,     41],
        [0,  10,     29, 35, 36, 40],
        [0,   9,                 41],
        [0,          33,           ],
    ]
    
    model = np.array(values[0])  # first row is the "model" -> we know that this is correct
    for row in values[1:]:
        row = np.array(row)
        print(row)
        corrected_row, diffsum = find_best_matching_array(row, model)
        print(corrected_row)
        print(diffsum)
        print()

    Output:
        [ 0 11 29 42]
        [ 0 11 29 42]
        4
        
        [10 21 25 39 52]
        [10 21 39 52]
        4
        
        [ 0  9 15 29 32 41]
        [ 0  9 29 41]
        3
        
        [ 0 10 29 35 36 40]
        [ 0 10 29 40]
        1
        
        [ 0  9 41]
        [ 0  9 30 41]
        2
        
        [ 0 33]
        [ 0 10 33 40]
        3
Find an array <best_arr> based on <base_arr> that fits best to <model_arr> if their sizes differ.
    <best_arr> will have the same size as <model_arr> and either has surplus elements removed (if <base_arr> is
    bigger than <model_arr>) or missing elements added from <model_arr> (if <base_arr> is smaller than <model_arr>).
    
    Returns the best fitting array and the summed difference of this array and <model_arr>.
    
    It uses a brute force method so this is slow for big arrays.
    
    Example:
        
    values = [
        [0,  10,     30,         40],
        [0,  11,     29,         42],
        [10, 21, 25, 39,         52],
        [0,   9, 15, 29, 32,     41],
        [0,  10,     29, 35, 36, 40],
        [0,   9,                 41],
        [0,          33,           ],
    ]
    
    model = np.array(values[0])  # first row is the "model" -> we know that this is correct
    for row in values[1:]:
        row = np.array(row)
        print(row)
        corrected_row, diffsum = find_best_matching_array(row, model)
        print(corrected_row)
        print(diffsum)
        print()
Find an array <best_arr > based on <base_arr > that fits best to <model_arr > if their sizes differ . <best_arr > will have the same size as <model_arr > and either has surplus elements removed ( if <base_arr > is bigger than <model_arr > ) or missing elements added from <model_arr > ( if <base_arr > is smaller than <model_arr > ) . Returns the best fitting array and the summed difference of this array and <model_arr > . It uses a brute force method so this is slow for big arrays . Example : values = [ [ 0 10 30 40 ] [ 0 11 29 42 ] [ 10 21 25 39 52 ] [ 0 9 15 29 32 41 ] [ 0 10 29 35 36 40 ] [ 0 9 41 ] [ 0 33 ] ] model = np . array ( values [ 0 ] ) # first row is the model - > we know that this is correct for row in values [ 1 : ] : row = np . array ( row ) print ( row ) corrected_row diffsum = find_best_matching_array ( row model ) print ( corrected_row ) print ( diffsum ) print ()
def find_best_matching_array(base_arr, model_arr, same_size_use_model_arr_diff_thresh=None):
    """
    Find an array <best_arr> based on <base_arr> that fits best to <model_arr> if their sizes differ.
    <best_arr> will have the same size as <model_arr> and either has surplus elements removed (if <base_arr> is
    bigger than <model_arr>) or missing elements added from <model_arr> (if <base_arr> is smaller than <model_arr>).
    
    Returns the best fitting array and the summed difference of this array and <model_arr>.
    
    It uses a brute force method so this is slow for big arrays.
    
    Example:
        
    values = [
        [0,  10,     30,         40],
        [0,  11,     29,         42],
        [10, 21, 25, 39,         52],
        [0,   9, 15, 29, 32,     41],
        [0,  10,     29, 35, 36, 40],
        [0,   9,                 41],
        [0,          33,           ],
    ]
    
    model = np.array(values[0])  # first row is the "model" -> we know that this is correct
    for row in values[1:]:
        row = np.array(row)
        print(row)
        corrected_row, diffsum = find_best_matching_array(row, model)
        print(corrected_row)
        print(diffsum)
        print()

    Output:
        [ 0 11 29 42]
        [ 0 11 29 42]
        4
        
        [10 21 25 39 52]
        [10 21 39 52]
        4
        
        [ 0  9 15 29 32 41]
        [ 0  9 29 41]
        3
        
        [ 0 10 29 35 36 40]
        [ 0 10 29 40]
        1
        
        [ 0  9 41]
        [ 0  9 30 41]
        2
        
        [ 0 33]
        [ 0 10 33 40]
        3
    """
    if type(base_arr) is not np.ndarray:
        raise TypeError("base_arr must be NumPy array")
    if type(model_arr) is not np.ndarray:
        raise TypeError("model_arr must be NumPy array")

    if len(base_arr) < 1:
        raise ValueError("base_arr length must be > 0")    
    if len(model_arr) < 1:
        raise ValueError("model_arr length must be > 0")

    amount_diff = len(base_arr)  - len(model_arr)
    
    if amount_diff > 0:    # too many values in base_arr
        # go through all possible combinations of surplus elements in the base_arr and
        # measure the match difference and save it to "candidates"
        del_indices_combi = itertools.combinations(range(len(base_arr)), amount_diff)
        candidates = []
        for del_ind in del_indices_combi:
            candidate_arr = np.delete(base_arr, del_ind)
            # model_arr is normalized -> add first value as offset
            center_medians_w_offset = model_arr + candidate_arr[0]
            diff = array_match_difference_1d(candidate_arr, center_medians_w_offset)
            candidates.append((candidate_arr, diff))
        
        best_arr, diff = sorted(candidates, key=lambda x: x[1])[0]
    elif amount_diff < 0:  # too few values in base_arr
        # this time, reduce the model_arr so that it fits the number of values in base_arr
        # i.e. we find the best candidate of all adjusted model_arr first
        del_indices_combi = itertools.combinations(range(len(model_arr)), -amount_diff)
        candidates = []
        for del_ind in del_indices_combi:
            candidate_arr = np.delete(model_arr, del_ind)
            # model_arr is normalized -> add first value as offset
            diff = array_match_difference_1d(candidate_arr + base_arr[0], base_arr)
            candidates.append((del_ind, diff))
            
        add_ind, _ = sorted(candidates, key=lambda x: x[1])[0]
        model_arr_w_offset = model_arr + base_arr[0]
        
        # take the missing values from best_model_arr
        best_arr = fill_array_a_with_values_from_b(base_arr, model_arr_w_offset, add_ind)
        diff = array_match_difference_1d(best_arr, model_arr_w_offset)
    else:                  # number of values matches
        diff = array_match_difference_1d(base_arr, model_arr + base_arr[0])
        best_arr = base_arr.copy()
        
    if same_size_use_model_arr_diff_thresh is not None and diff > same_size_use_model_arr_diff_thresh:
        best_arr = model_arr + base_arr[0]
        diff = 0  # can only be zero
    
    return best_arr, diff
def find_best_matching_array ( base_arr , model_arr , same_size_use_model_arr_diff_thresh = None ) : if type ( base_arr ) is not np . ndarray : raise TypeError ( "base_arr must be NumPy array" ) if type ( model_arr ) is not np . ndarray : raise TypeError ( "model_arr must be NumPy array" ) if len ( base_arr ) < 1 : raise ValueError ( "base_arr length must be > 0" ) if len ( model_arr ) < 1 : raise ValueError ( "model_arr length must be > 0" ) amount_diff = len ( base_arr ) - len ( model_arr ) if amount_diff > 0 : # too many values in base_arr # go through all possible combinations of surplus elements in the base_arr and # measure the match difference and save it to "candidates" del_indices_combi = itertools . combinations ( range ( len ( base_arr ) ) , amount_diff ) candidates = [ ] for del_ind in del_indices_combi : candidate_arr = np . delete ( base_arr , del_ind ) # model_arr is normalized -> add first value as offset center_medians_w_offset = model_arr + candidate_arr [ 0 ] diff = array_match_difference_1d ( candidate_arr , center_medians_w_offset ) candidates . append ( ( candidate_arr , diff ) ) best_arr , diff = sorted ( candidates , key = lambda x : x [ 1 ] ) [ 0 ] elif amount_diff < 0 : # too few values in base_arr # this time, reduce the model_arr so that it fits the number of values in base_arr # i.e. we find the best candidate of all adjusted model_arr first del_indices_combi = itertools . combinations ( range ( len ( model_arr ) ) , - amount_diff ) candidates = [ ] for del_ind in del_indices_combi : candidate_arr = np . delete ( model_arr , del_ind ) # model_arr is normalized -> add first value as offset diff = array_match_difference_1d ( candidate_arr + base_arr [ 0 ] , base_arr ) candidates . append ( ( del_ind , diff ) ) add_ind , _ = sorted ( candidates , key = lambda x : x [ 1 ] ) [ 0 ] model_arr_w_offset = model_arr + base_arr [ 0 ] # take the missing values from best_model_arr best_arr = fill_array_a_with_values_from_b ( base_arr , model_arr_w_offset , add_ind ) diff = array_match_difference_1d ( best_arr , model_arr_w_offset ) else : # number of values matches diff = array_match_difference_1d ( base_arr , model_arr + base_arr [ 0 ] ) best_arr = base_arr . copy ( ) if same_size_use_model_arr_diff_thresh is not None and diff > same_size_use_model_arr_diff_thresh : best_arr = model_arr + base_arr [ 0 ] diff = 0 # can only be zero return best_arr , diff