<commit_before>"""
scale.py:

Handle all scale-related data and methods.

* Author:       <NAME> <<EMAIL>>
* License:      MIT License: http://creativecommons.org/licenses/MIT/
"""

from copy import deepcopy
import globals
from note import Note

step_patterns = {
  'major':[1,1,0.5,1,1,1,0.5],
  'natural_minor':[1,0.5,1,1,0.5,1,1],
  'harmonic_minor':[1,0.5,1,1,0.5,1.5,0.5],
  'melodic_minor_up':[1,0.5,1,1,1,1,0.5],
  'melodic_minor_down':[1,1,0.5,1,1,0.5,1],
  'dorian':[1,0.5,1,1,1,0.5,1],
  'minor_pentatonic_blues':[1.5,1,1,1.5,1]
}

# direction: 1=up, -1=down, None=none-specified
def get_scale(notes, scale, direction=None):
  if scale not in step_patterns.keys():
    return None

  if len(notes) < 2:
    return None

  scale_pattern = step_patterns[scale]
  
  if not direction or abs(direction) != 1:
    direction = 1

  root = deepcopy(notes[0])

  # move away from min/max octave levels
  if notes[0].octave >= globals.max_octave:
    direction = -1
  if notes[0].octave <= globals.min_octave:
    direction = 1

  allowable_notes = []

  prev = deepcopy(root)
  root.octave = 0
  root.duration = 0.0
  allowable_notes.append(root)
  for p in scale_pattern:
    times = int(p/0.5)
    new_note = prev
    for n in range(times):
      if direction == -1:
        new_note.dec(True)
      else:
        new_note.inc(True)
    # if pitch is same as previous, inc pitch and set accidental
    prev_note = prev.note
    prev = deepcopy(new_note)
    new_note.octave = 0
    new_note.duration = 0.0
    if None and new_note.note == prev_note:
      if direction == -1:
        new_note.decNote()
        new_note.accidental = 'sharp'
      else:
        new_note.incNote()
        new_note.accidental = 'flat'
    allowable_notes.append(new_note)

  print "Allowed: " 
  for a in allowable_notes:
    print "  " + a.to_str()
  return allowable_notes<commit_msg>improved get_scale to properly select sharps or flats to ensure correct pitch representation in a scale<commit_after>"""
scale.py:

Handle all scale-related data and methods.

* Author:       <NAME> <<EMAIL>>
* License:      MIT License: http://creativecommons.org/licenses/MIT/
"""

from copy import deepcopy
import globals
from note import Note

step_patterns = {
  'major':[1,1,0.5,1,1,1,0.5],
  'natural_minor':[1,0.5,1,1,0.5,1,1],
  'harmonic_minor':[1,0.5,1,1,0.5,1.5,0.5],
  'melodic_minor_up':[1,0.5,1,1,1,1,0.5],
  'melodic_minor_down':[1,1,0.5,1,1,0.5,1],
  'dorian':[1,0.5,1,1,1,0.5,1],
  'minor_pentatonic_blues':[1.5,1,1,1.5,1]
}

# direction: 1=up, -1=down, None=none-specified
def get_scale(notes, scale, direction=None):
  if scale not in step_patterns.keys():
    return None

  if len(notes) < 2:
    return None

  scale_pattern = step_patterns[scale]
  
  if not direction or abs(direction) != 1:
    direction = 1

  root = deepcopy(notes[0])

  # move away from min/max octave levels
  if notes[0].octave >= globals.MAX_OCTAVE:
    direction = -1
  if notes[0].octave <= globals.MIN_OCTAVE:
    direction = 1

  allowable_notes = []
  added_notes = []

  prev = deepcopy(root)
  root.octave = 0
  root.duration = 0.0
  allowable_notes.append(root)
  for p in scale_pattern:
    times = int(p/0.5)
    new_note = prev
    for n in range(times):
      if direction == -1:
        new_note.dec(True)
      else:
        new_note.inc(True)

    prev_note = prev.note
    prev = deepcopy(new_note)
    new_note.octave = 0
    new_note.duration = 0.0

    # when incrementing up the scale, it is possible to reach a stage where there is:
    # g-n...a-n...a-#...c-n
    # when what is needed is one note instance for all notes in scale, i.e. it's missing the b
    # use alternate notation to turn that a-# into b-flat so that b is represented in scale
    if new_note.note in added_notes:
      new_note = new_note.getAlternateNotation()

    allowable_notes.append(new_note)
    added_notes.append(new_note.note)

  return allowable_notes
{'fraction_non_alphanumeric': 0.13874745417515275, 'fraction_numerical': 0.0420061099796334, 'mean_word_length': 3.193169690501601, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5723022', 'n_tokens_mistral': 1574, 'n_tokens_neox': 1508, 'n_words': 342}