Пример #1
0
def find_hits(self, wf_origin, Init, height_cut, rise_time_cut):
    wf = np.array(wf_origin)
    dif = (wf - np.roll(wf, 1))
    dif[0] = dif[1]
    dif_bl = np.median(dif[:Init])
    dif_blw = np.sqrt(np.mean((dif[:Init] - dif_bl)**2))

    while np.amin(wf) < -height_cut:
        maxi = np.argmin(wf)
        if len(
                np.nonzero(
                    np.logical_and(wf[:maxi] > -self.blw,
                                   dif[:maxi] > dif_bl - dif_blw))[0]) > 0:
            left = np.amax(
                np.nonzero(
                    np.logical_and(wf[:maxi] > -self.blw,
                                   dif[:maxi] > dif_bl - dif_blw))[0])
        else:
            left = 0
        if len(
                np.nonzero(
                    np.logical_and(wf[maxi:] > -self.blw,
                                   dif[maxi:] > dif_bl - dif_blw))[0]) > 0:
            right = maxi + np.amin(
                np.nonzero(
                    np.logical_and(wf[maxi:] > -self.blw,
                                   dif[maxi:] > dif_bl - dif_blw))[0])
        else:
            right = len(wf)
        if maxi - left > rise_time_cut:
            hit = Hit(left, right)
            hit.area = -np.sum(wf[left:right])
            self.hits.append(hit)
        wf[left:right] = 0
Пример #2
0
def find_hits(self, wf):
    dif = (wf - np.roll(wf, 1))[1:]
    dif = np.append(dif[0], dif)
    dif_bl, dif_blw, j = find_bl_dif(dif)
    prev_len_out_of_hit = 1e6
    out_of_hit = np.arange(len(wf))
    counter = 0
    while len(out_of_hit)>0 and np.amin(wf[out_of_hit])<-self.blw and np.any(dif[out_of_hit]>dif_bl+dif_blw)\
        and len(out_of_hit)<prev_len_out_of_hit:
        #while len(out_of_hit)>0 and np.amin(wf[out_of_hit])<-self.blw:
        maxi = out_of_hit[np.argmin(wf[out_of_hit])]
        left = 0
        right = len(wf) - 1
        for hit in self.hits:
            if hit.fin > left and hit.init < maxi:
                left = hit.fin
            if hit.init < right and hit.init > maxi:
                right = hit.init

        if len(np.nonzero(wf[left:maxi] > -self.blw)[0]) > 0:
            init_blw = left + np.amax(np.nonzero(wf[left:maxi] > -self.blw)[0])
            if len(np.nonzero(dif[left:maxi] > dif_bl - dif_blw)[0]):
                init_dif = left + np.amax(
                    np.nonzero(dif[left:maxi] > dif_bl - dif_blw)[0])
                init = np.amin([init_blw, init_dif])
            else:
                init = left
        else:
            init = left

        if len(np.nonzero(wf[maxi:right] > -self.blw)[0]) > 0:
            fin_blw = maxi + np.amin(np.nonzero(wf[maxi:right] > -self.blw)[0])
            if len(np.nonzero(dif[maxi:right] < dif_bl + dif_blw)[0]):
                fin_dif = maxi + np.amin(
                    np.nonzero(dif[maxi:right] < dif_bl + dif_blw)[0])
                fin = np.amax([fin_blw, fin_dif])
            else:
                fin = right
        else:
            fin = right

        if np.any(
                dif[init:maxi] < dif_bl - dif_blw
        ) and wf[maxi] < -min_hit_height and maxi - init > min_hit_rise_time:
            hit = Hit(init, fin)
            hit.area = -np.sum(wf[init:fin + 1])
            hit.height = -np.amin(wf[init:fin + 1])
            find_groups(hit, wf, dif, self.blw)
            self.hits.append(hit)
        prev_len_out_of_hit = len(out_of_hit)
        for i in np.arange(init, fin + 1):
            out_of_hit = np.delete(out_of_hit, np.nonzero(out_of_hit == i)[0])

        counter += 1
    self.hits = sorted(self.hits, key=lambda hit: hit.init)
    merge_hits(self, wf, self.blw)
    for hit in self.hits:
        hit.groups = sorted(hit.groups, key=lambda grp: grp.maxi)
Пример #3
0
def main():
    def _dump_data():
        try:
            obj = dict(
                params=dict(
                    allowed_rhythm_deviation=allowed_rhythm_deviation,
                    allowed_tempo_deviation=allowed_tempo_deviation,
                    current_level=current_level,
                    experiment_type=experiment_type,
                    trial_on_path=trial_on_path,
                    truth_on_path=truth_on_path,
                ),
                processing=dict(
                    hits=[h.to_dict() for h in hits],
                    messages=[m.to_dict() for m in msgs],
                    messages_tempo_transformed=[
                        tmsg.to_dict() for tmsg in tempoed_msgs
                    ],
                    tempo_estimation=tempo_estimation,
                    tempo_str=tempo_str,
                ),
                results=dict(
                    passed=passed,
                    mistakes=mistakes,
                    played_enough_notes=played_enough_notes,
                ),
            )
            if check_rhythm:
                obj['processing'].update(
                    tempo_ceil=tempo_ceil,
                    tempo_floor=tempo_floor,
                )
            if not passed:  # only time when passed is True (all_hits_correct), advance_trial isn't referenced
                obj['results'].update(advance_trial=advance_trial)

            with open(data_dump_path, mode='w') as f:
                json.dump(obj, f, indent=4, sort_keys=True)
        except:
            pass

    if len(sys.argv) > 1:
        allowed_rhythm_deviation = int(sys.argv[1][:-1])
        allowed_tempo_deviation = int(sys.argv[2][:-1])
        trial_on_path = sys.argv[3]
        truth_on_path = sys.argv[4]
        current_level = json.loads(sys.argv[5])
        experiment_type = sys.argv[6]
    else:
        allowed_rhythm_deviation = 20
        allowed_tempo_deviation = 30
        trial_on_path = r'c:\Sync\Code\Python\Pyano-release\src\experiments\subjects\tests\ORIN\level_1_trial_0_on.txt'
        truth_on_path = r'c:\Sync\Code\Python\Pyano-release\src\experiments\truths\fur_elise_B_on.txt'
        current_level = dict(notes=10, trials=1, rhythm=True, tempo=50)
        experiment_type = 'exam'

    data_dump_path = trial_on_path.rpartition('_on.txt')[0] + '_data.json'
    truths: List[Message] = Message.normalize_chords_in_file(truth_on_path)
    msgs: List[Message] = Message.normalize_chords_in_file(trial_on_path)

    check_rhythm = current_level['rhythm']
    current_level_notes = current_level['notes']
    tempo_estimation = estimate_tempo_percentage(msgs, truths,
                                                 current_level_notes)
    tempoed_msgs: List[Message] = Message.transform_to_tempo(
        msgs, tempo_estimation)

    mistakes = []
    hits = []  # for data dumping
    truth_chords = Message.get_chords(truths[:current_level_notes])
    try:
        Message.normalize_chords(
            tempoed_msgs,
            truth_chords)  # of tempoed_msgs, according to truth_chords
    except Exception as e:
        entry = logger.log(
            dict(tempoed_msgs=tempoed_msgs,
                 truth_chords=truth_chords,
                 msg=msgs,
                 current_level_notes=current_level_notes,
                 check_rhythm=check_rhythm,
                 tempo_estimation=tempo_estimation,
                 truths=truths,
                 e=e),
            title=
            f"Exception at Message.normalize_chords(tempoed_msgs, truth_chords)"
        )
        raise Exception(
            f"check done trial normalize chords exception. see log check_done_trial, entry: {entry}"
        )
    for i in range(min(current_level_notes, len(msgs))):
        hit = Hit(tempoed_msgs[i], truths[i], allowed_rhythm_deviation)
        hits.append(hit)
        mistakes.append(hit.get_mistake_kind())

    played_enough_notes = len(msgs) >= current_level_notes
    if not played_enough_notes:
        # needed to play 4 notes but playeed 3: [ null, null, null, "accuracy" ]
        # if also made a mistake: [ null, "rhythm", null, "accuracy" ]
        # Failed feedback msg could be "[ null, 'rhythm', null, 'accuracy' ], not enough notes and too fast"
        mistakes += ["accuracy"] * (current_level_notes - len(msgs))
    tempo_str = "ok"
    if check_rhythm:
        # Failed feedback msg could be "[ null, 'rhythm', null, 'accuracy' ] and too fast"

        if not (0 <= allowed_tempo_deviation <= 100):
            entry = logger.log(
                dict(trial_on_path=trial_on_path,
                     truth_on_path=truth_on_path,
                     current_level=current_level,
                     allowed_tempo_deviation=allowed_tempo_deviation),
                title="check_done_trial ValueError bad allowed_tempo_deviation"
            )
            raise ValueError(
                f"check_done_trial inside rhythm checking got bad allowed_tempo_deviation, got: {allowed_tempo_deviation}. see classes.log, entry: {entry}"
            )

        level_tempo = current_level['tempo']  # 75
        extra = level_tempo * allowed_tempo_deviation / 100  # 75*0.1 = 7.5
        tempo_floor = level_tempo - extra  # 67.5
        tempo_ceil = max(100, level_tempo + extra)  # max(100, 82.5) = 100
        if tempo_estimation < tempo_floor:
            tempo_str = "slow"
        elif tempo_estimation > tempo_ceil:
            tempo_str = "fast"
        else:
            tempo_str = "ok"

        if tempo_str != 'ok':
            # acc mistake when checking rhythm. if experiemnt is exam, advance anyway
            if experiment_type == 'exam':
                advance_trial = True
            else:
                advance_trial = 'accuracy' not in mistakes
            passed = False
            _dump_data()
            prfl(
                dict(
                    advance_trial=advance_trial,
                    mistakes=mistakes,
                    passed=passed,
                    played_enough_notes=played_enough_notes,
                    tempo_str=tempo_str,
                ))
            return
    else:  # delete rhythm mistakes if not checking rhythm. ["rhythm", null, "accuracy"] => [null, null, "accuracy"]
        mistakes = [None if m == "rhythm" else m for m in mistakes]

    if not played_enough_notes:
        # not enough notes == accuracy mistakes. dont adv if check rhythm. if experiemnt is exam, advance anyway
        if experiment_type == 'exam':
            advance_trial = True
        else:
            advance_trial = not check_rhythm

        passed = False
        played_enough_notes = False
        _dump_data()
        prfl(
            dict(passed=passed,
                 mistakes=mistakes,
                 advance_trial=advance_trial,
                 played_enough_notes=played_enough_notes,
                 tempo_str=tempo_str))
        return

    # Played all notes or too many notes
    all_hits_correct = all([mistake is None for mistake in mistakes])
    if all_hits_correct:
        passed = True
        played_too_many_notes = len(msgs) > current_level_notes
        _dump_data()
        prfl(dict(passed=passed, played_too_many_notes=played_too_many_notes))
        return
    else:
        # Had mistakes
        # Tempo ok, played all required notes
        # if not check rhythm: has accuracy mistakes
        # if check rhythm: has accuracy and/or rhythm mistakes
        # ['accuracy', 'rhythm', None, ...]
        if experiment_type == 'exam':
            advance_trial = True
        else:
            advance_trial = not (check_rhythm and 'accuracy' in mistakes)
        passed = False
        _dump_data()
        prfl(
            dict(passed=passed, advance_trial=advance_trial,
                 mistakes=mistakes))