'Returns the input vector for the given position in the melody.
Returns a self.input_size length list of floats. Assuming
self._min_note = 48, self._note_range = 36, two lookback distances, and
seven binary counters, then self.input_size = 74. Each index represents a
different input signal to the model.
Indices [0, 73]:
[0, 35]: A note is playing at that pitch [48, 84).
36: Any note is playing.
37: Silence is playing.
38: The current event is the note-on event of the currently playing note.
39: Whether the melody is currently ascending or descending.
40: The last event is repeating (first lookback distance).
41: The last event is repeating (second lookback distance).
[42, 48]: Time keeping toggles.
49: The next event is the start of a bar.
[50, 61]: The keys the current melody is in.
[62, 73]: The keys the last 3 notes are in.
Args:
events: A magenta.music.Melody object.
position: An integer event position in the melody.
Returns:
An input vector, an self.input_size length list of floats.'

def events_to_input(self, events, position):

    current_note = None
    is_attack = False
    is_ascending = None
    last_3_notes = collections.deque(maxlen=3)
    sub_melody = melodies_lib.Melody(events[:(position + 1)])
    for note in sub_melody:
        if (note == MELODY_NO_EVENT):
            is_attack = False
        elif (note == MELODY_NOTE_OFF):
            current_note = None
        else:
            is_attack = True
            current_note = note
            if last_3_notes:
                if (note > last_3_notes[(-1)]):
                    is_ascending = True
                if (note < last_3_notes[(-1)]):
                    is_ascending = False
            if (note in last_3_notes):
                last_3_notes.remove(note)
            last_3_notes.append(note)
    input_ = ([0.0] * self.input_size)
    offset = 0
    if current_note:
        input_[((offset + current_note) - self._min_note)] = 1.0
        input_[(offset + self._note_range)] = 1.0
    else:
        input_[((offset + self._note_range) + 1)] = 1.0
    offset += (self._note_range + 2)
    if is_attack:
        input_[offset] = 1.0
    offset += 1
    if (is_ascending is not None):
        input_[offset] = (1.0 if is_ascending else (-1.0))
    offset += 1
    for (i, lookback_distance) in enumerate(self._lookback_distances):
        lookback_position = (position - lookback_distance)
        if ((lookback_position >= 0) and (events[position] == events[lookback_position])):
            input_[offset] = 1.0
        offset += 1
    n = len(sub_melody)
    for i in range(self._binary_counter_bits):
        input_[offset] = (1.0 if ((n / (2 ** i)) % 2) else (-1.0))
        offset += 1
    if ((len(sub_melody) % DEFAULT_STEPS_PER_BAR) == 0):
        input_[offset] = 1.0
    offset += 1
    key_histogram = sub_melody.get_major_key_histogram()
    max_val = max(key_histogram)
    for (i, key_val) in enumerate(key_histogram):
        if (key_val == max_val):
            input_[offset] = 1.0
        offset += 1
    last_3_note_melody = melodies_lib.Melody(list(last_3_notes))
    key_histogram = last_3_note_melody.get_major_key_histogram()
    max_val = max(key_histogram)
    for (i, key_val) in enumerate(key_histogram):
        if (key_val == max_val):
            input_[offset] = 1.0
        offset += 1
    assert (offset == self.input_size)
    return input_
