def valid_sequence(sequences):
    """
    Function that iterates through all protein sequences and validates that
    each sequence is made up of valid canonical amino acid letters. If no
    invalid values are found then None will be returned. If invalid letters
    are found in the sequence, the sequence index and the index of the value
    in the sequence will be appened to a dict.

    Parameters
    ----------
    sequences : list/np.ndarray
        list or array of protein sequences.

    Returns
    -------
    None or invalid_indices : None/list
        if no invalid values found in the protein sequences, None returned. if
        invalid values found, list of dicts returned in the form
        {sequence index: invalid value in sequence index}.
    """
    #if input is string, cast to a list so it is iterable
    if isinstance(sequences,str):
        sequences = [sequences]

    # sequences = np.array(sequences).reshape((-1,1))
    #valid canonical amino acid letters
    valid_amino_acids = ['A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M',\
        'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y','-']
    invalid_indices = []

    #iterate through all sequences, validating that there are no invalid values
    #   present in the sequences, if there are then append to list of invalid indices
    try:
        for seq in range(0,len(sequences)):
            for aa in range(0,len(sequences[seq])):
                if (sequences[seq][aa] not in valid_amino_acids):
                    invalid_indices.append({'Sequence #'+str(seq) : 'Index #'+str(aa)})
    except:
        print('Error parsing sequences in datasets.')

    #if no invalid values found in sequences return None, else return list of
    #   dicts containing invalid index and invalid values
    if invalid_indices == []:
        return None
    else:
        return invalid_indices