
    rh              
         % S r SSKJr  SSKrSSKrSSKrSSKJr  SSKrSSK	r	SSK
Jr  SSKJr  SSKJr  SSK
Jr  SS	K
Jr  SS
K
Jr  SSK
Jr  SSK
Jr  SSK
Jr  SSK
Jr  \R.                  " S5      r\R2                  " SSS9r\R2                  " SSS9r\\-  \R<                  -  \R>                  -  r 0 r!S\"S'   S r#S r$Sr%SSSSSSSSSS .	r& S-   S.S! jjr' " S" S#\RP                  5      r) " S$ S%\RP                  5      r* " S& S'\+5      r, " S( S\RZ                  5      r. " S) S\.\R^                  5      r0 " S* S+\Rb                  5      r2\.\0/r3\4S,:X  a  SSK
r
\
Rj                  " \25        gg)/aQ  
This module defines objects for representing key signatures as well as key
areas. The :class:`~music21.key.KeySignature` is used in
:class:`~music21.stream.Measure` objects for defining notated key signatures.

The :class:`~music21.key.Key` object is a fuller representation not just of
a key signature but also of the key of a region.
    )annotationsN)overload)base)cacheMethod)StepName)environment)exceptions21)interval)note)pitch)scale)stylekeyKeySignatureTypeKeySignature)boundKeyTypeKeyzdict[int, pitch.Pitch]_sharpsToPitchCachec                   U R                  S5      (       a  U S:X  a   U $ U S:X  a  Sn U $ U S:X  a  Sn U $ [        U 5      S:X  a  U S   S:X  a
  U S   S	-   n U $ [        U S
S 5      S1:X  a  U S   S	[        U 5      S
-
  -  -   n U $ )a  
Utility function to change strings in the form of "Eb" to
"E-" (for E-flat major) and leaves alone proper music21 strings
(like "E-" or "f#").  A little bit complex because of parsing
bb as B-flat minor and Bb as B-flat major.

>>> key.convertKeyStringToMusic21KeyString('Eb')
'E-'
>>> key.convertKeyStringToMusic21KeyString('f#')
'f#'
>>> key.convertKeyStringToMusic21KeyString('bb')
'b-'
>>> key.convertKeyStringToMusic21KeyString('Bb')
'B-'
>>> key.convertKeyStringToMusic21KeyString('b#')
'b#'
>>> key.convertKeyStringToMusic21KeyString('c')
'c'
>>> key.convertKeyStringToMusic21KeyString('Bbb')
'B--'
>>> key.convertKeyStringToMusic21KeyString('bbb')
'b--'
>>> key.convertKeyStringToMusic21KeyString('Ebb')
'E--'
bbbzb-BbB-   r   -   N)endswithlenset)
textStrings    E/home/james-whalen/.local/lib/python3.13/site-packages/music21/key.py"convertKeyStringToMusic21KeyStringr$   4   s    4 $$s):  
t	
  
t	

 	 
ZA	*R.C"7]S(
  
Z^		%]SC
Oa,?%@@
    c                d   U c  Sn U [         ;   a  [        R                  " [         U    5      $ [        R                  " S5      nSUl        U S:  a  SnOU S:  a  SnOU$ [        R                  " U5      n[        [        U 5      5       H  nUR                  U5      nM     SUl        U[         U '   U$ )a/  
Given a positive/negative number of sharps, return a Pitch
object set to the appropriate major key value.

>>> key.sharpsToPitch(1)
<music21.pitch.Pitch G>
>>> key.sharpsToPitch(2)
<music21.pitch.Pitch D>
>>> key.sharpsToPitch(-2)
<music21.pitch.Pitch B->
>>> key.sharpsToPitch(-6)
<music21.pitch.Pitch G->

Note that these are :class:`music21.pitch.Pitch` objects not just names:

>>> k1 = key.sharpsToPitch(6)
>>> k1
<music21.pitch.Pitch F#>
>>> k1.step
'F'
>>> k1.accidental
<music21.pitch.Accidental sharp>

OMIT_FROM_DOCS

The second time we do something it should be in the cache, so let's make sure it still works:

>>> key.sharpsToPitch(1)
<music21.pitch.Pitch G>
>>> key.sharpsToPitch(1)
<music21.pitch.Pitch G>
>>> 1 in key._sharpsToPitchCache
True
>>> key._sharpsToPitchCache[1]
<music21.pitch.Pitch G>
Nr   CP5zP-5)r   copydeepcopyr   Pitchoctaver
   IntervalrangeabstransposePitch)
sharpCount	pitchInitintervalStrintervalObjis        r#   sharpsToPitchr6   [   s    J 
((}}0<==C IIA~	a##K0K3z?#..y9	 $I&/
#r%   )Fr'   GDAEBr   r   )	majorionianminoraeoliandorianphrygianlydian
mixolydianlocrianc                D   [        U [        5      (       a  [        R                  " U 5      nO\[        U [        R                  5      (       a  U nO:[        U [        R
                  5      (       a  U R                  nO[        SU  35      e[        R                  UR                  5      S-
  nUR                  bO  UR                  R                  5       SL a  [        S5      e[        UR                  R                  5      nUSU-  -   nUb  U[        ;   a  U[        U   -  nU$ )a#  
Given a pitch string or :class:`music21.pitch.Pitch` or
:class:`music21.note.Note` object,
return the number of sharps found in that mode.

The `mode` parameter can be 'major', 'minor', or most
of the common church/jazz modes ('dorian', 'mixolydian', etc.)
including Locrian.

If `mode` is omitted or not found, the default mode is major.

(extra points to anyone who can find the earliest reference to
the Locrian mode in print.  David Cohen and I (MSAC) have been
looking for this for years).

>>> key.pitchToSharps('c')
0
>>> key.pitchToSharps('c', 'minor')
-3
>>> key.pitchToSharps('a', 'minor')
0
>>> key.pitchToSharps('d')
2
>>> key.pitchToSharps('e-')
-3
>>> key.pitchToSharps('a')
3
>>> key.pitchToSharps('e', 'minor')
1
>>> key.pitchToSharps('f#', 'major')
6
>>> key.pitchToSharps('g-', 'major')
-6
>>> key.pitchToSharps('c#')
7
>>> key.pitchToSharps('g#')
8
>>> key.pitchToSharps('e', 'dorian')
2
>>> key.pitchToSharps('d', 'dorian')
0
>>> key.pitchToSharps('g', 'mixolydian')
0
>>> key.pitchToSharps('e-', 'lydian')
-2
>>> key.pitchToSharps('e-', 'lydian')
-2
>>> key.pitchToSharps('a', 'phrygian')
-1
>>> key.pitchToSharps('e', 'phrygian')
0
>>> key.pitchToSharps('f#')
6
>>> key.pitchToSharps(note.Note('f-'))
-8
>>> key.pitchToSharps(pitch.Pitch('f--'))
-15
>>> key.pitchToSharps('f--', 'locrian')
-20
>>> key.pitchToSharps('a', 'ionian')
3
>>> key.pitchToSharps('a', 'aeolian')
0

But quarter tones don't work:

>>> key.pitchToSharps('C~')
Traceback (most recent call last):
music21.key.KeyException: Cannot determine sharps for quarter-tone keys! silly!
z&Cannot get a sharp number from value: r   Fz5Cannot determine sharps for quarter-tone keys! silly!   )
isinstancestrr   r+   r   NoteKeyExceptionfifthsOrderindexstep
accidentalisTwelveToneintaltermodeSharpsAlter)valuemode
pitchValuesharpsvaas        r#   pitchToSharpsr]      s    R %[['
	E5;;	'	'
	E499	%	%[[
CE7KLL z/!3F(  --/58VWW*''--.!c'!DO3/$''Mr%   c                      \ rS rSrSrg)KeySignatureExceptioni
   N__name__
__module____qualname____firstlineno____static_attributes__r`   r%   r#   r_   r_   
      r%   r_   c                      \ rS rSrSrg)rO   i  r`   Nra   r`   r%   r#   rO   rO     rg   r%   rO   c                      \ rS rSrSrg)
KeyWarningi  r`   Nra   r`   r%   r#   rj   rj     rg   r%   rj   c                  x  ^  \ rS rSrSr\R                  rSrSr	SSU 4S jjjr
S rS rSSS jjr\\SS	 j5       5       r\R"                    SS
 j5       r\SS j5       rS S jr\SS.     S!S jj5       r\      S"S j5       rSS.     S#S jjrSS.S$S jjrS%S jrS&S jrS'S jr\" \\SS9rSrU =r$ )(r   i  aR  
A KeySignature object specifies the signature to be used for a piece; it normally
takes one argument: an `int` giving the number of sharps,
or, if negative, the number of flats.

If you are starting with the name of a key, see the :class:`~music21.key.Key` object.

>>> A = key.KeySignature(3)
>>> A
<music21.key.KeySignature of 3 sharps>

>>> Eflat = key.KeySignature(-3)
>>> Eflat
<music21.key.KeySignature of 3 flats>

If you want to get a real Key, then use the :class:`~music21.key.Key` object instead:

>>> illegal = key.KeySignature('c#')
Traceback (most recent call last):
music21.key.KeySignatureException: Cannot get a KeySignature from this
    "number" of sharps: 'c#'; did you mean to use a key.Key() object instead?

>>> legal = key.Key('c#')
>>> legal.sharps
4
>>> legal
<music21.key.Key of c# minor>

To set a non-traditional Key Signature, create a KeySignature object
with `sharps=None`, and then set the `alteredPitches` list:

>>> unusual = key.KeySignature(sharps=None)
>>> unusual.alteredPitches = ['E-', 'G#']
>>> unusual
<music21.key.KeySignature of pitches: [E-, G#]>
>>> unusual.isNonTraditional
True

To set a pitch as displayed in a particular octave, create a non-traditional
KeySignature and then set pitches with octaves:

>>> unusual = key.KeySignature(sharps=None)
>>> unusual.alteredPitches = ['F#4']
>>> unusual
<music21.key.KeySignature of pitches: [F#4]>

If the accidental applies to all octaves but is being displayed differently
then you are done, but if you want them to apply only to the octave displayed
in then set `.accidentalsApplyOnlyToOctave` to `True`:

>>> unusual.accidentalsApplyOnlyToOctave
False
>>> unusual.accidentalsApplyOnlyToOctave = True

**Equality**

Two KeySignatures are equal if they pass all `super().__eq__` checks and
their sharps are equal.  Currently, non-standard key signatures are not
checked (this may change).

>>> sharp2 = key.KeySignature(2)
>>> flat4 = key.KeySignature(-4)
>>> sharp2 == flat4
False
>>> sharp2 == key.KeySignature(2)
True

* Changed in v7: `sharps` defaults to 0 (key of no flats/sharps)
  rather than `None` for nontraditional keys.
)r[   r   c                   > [         TU ]  " S0 UD6   Ub"  U[        U5      :w  a  [        SU< S3S-   5      eXl        S U l        SU l        g ! [         a  n[        SU< S3S-   5      UeS nAff = f)Nz8Cannot get a KeySignature from this "number" of sharps: z; z/did you mean to use a key.Key() object instead?Fr`   )super__init__rU   r_   
ValueError_sharps_alteredPitchesaccidentalsApplyOnlyToOctave)selfr[   keywordsve	__class__s       r#   rn   KeySignature.__init__g  s    $8$		!vV'<+NvjXZ[GHI I  8<,1)  	'J6*TVWCD 	s   %A 
A0A++A0c           	        SnU R                   nUc=  SSR                  U R                   Vs/ s H  n[        U5      PM     sn5      -   S-   nU$ US:  a  U S3nU$ US:X  a  SnU$ US:X  a  S	nU$ US
:X  a  SnU$ [	        U5       S3nU$ s  snf )N z
pitches: [z, ]r   z sharpsz1 sharpr   zno sharps or flatsr   z1 flatz flats)r[   joinalteredPitchesrM   r/   )rs   outputnsps       r#   _strDescriptionKeySignature._strDescription~  s    [[:!DIIt?R?R.S?R!s1v?R.S$TTWZZF  !Vt7^F  1WF  1W)F
 	 2XF  By'F /Ts   B

c                (    SU R                  5       -   $ Nzof )r   rs   s    r#   _reprInternalKeySignature._reprInternal  s    t++---r%   c                N   U R                   =(       d    SnUb!  Ub  [        R                  " SU 3[        5        Uc  Uc  SnUc>  Ub;  [        R                  5        VVs0 s H  u  pEXT_M	     nnn[        U5      n XcU-
     n[        R                  " [        U5      nUR                  5       nU[        ;  a  [        SU S35      e[        U   n	[        X9-
  5      n
[        U
R                  U5      $ s  snnf ! [         a!  n[        SU R                    SU 35      UeSnAff = f)	a  
Return a `key.Key` object representing this KeySignature object as a key in the
given mode or in the given tonic. If `mode` is None, and `tonic` is not provided,
major is assumed. If both mode and tonic are provided, the tonic is ignored.

>>> ks = key.KeySignature(2)
>>> ks.asKey()
<music21.key.Key of D major>
>>> ks.asKey(mode='minor')
<music21.key.Key of b minor>

If `mode` is None, an attempt is made to solve for the mode:

>>> ks.asKey(tonic='A')
<music21.key.Key of A mixolydian>

But will raise `KeyException` if an impossible solution is requested:

>>> ks.asKey(tonic='D#')
Traceback (most recent call last):
music21.key.KeyException: Could not solve for mode from sharps=2, tonic=D#

Ionian and Aeolian are supplied instead of major or minor when deriving mode in this way:

>>> ks2 = key.KeySignature()
>>> ks2.asKey()
<music21.key.Key of C major>
>>> ks2.asKey(tonic='C')
<music21.key.Key of C ionian>

* New in v7: `tonic` argument to solve for mode.
r   Nzignoring provided tonic: rA   z%Could not solve for mode from sharps=z, tonic=zMode z is unknown)r[   warningswarnrj   rW   itemsr]   KeyErrorrO   tcastrM   lowerr6   r   name)rs   rY   tonic
our_sharpskvmajorSharpsToModemajorSharpskesharpAlterationFromMajorpitchObjs              r#   asKeyKeySignature.asKey  s1   B [[%A
 1MM5eW=zJ<EMD<E-2A2G2G2I J2I$!2I J'.Kb(k)AB vvc4 zz|&tfK899#24#8  !FG8==$'' !K  b";DKK=QVPWXZ_abbs   C3<C9 9
D$DD$c                   U R                   b  U R                   $ / nU R                  c  U$ U R                  S:  a  [        R                  " S5      nU R                  S:  a   [	        U R                  5       HA  nUR                  SSS9  [        R                  " U5      nSUl        UR                  U5        MC     U$ U R                  S:  ay  [        R                  " S5      n[	        [        U R                  5      5       HA  nUR                  S	SS9  [        R                  " U5      nSUl        UR                  U5        MC     U$ )
a  
Return or set a list of music21.pitch.Pitch objects that are altered by this
KeySignature. That is, all Pitch objects that will receive an accidental.

>>> a = key.KeySignature(3)
>>> a.alteredPitches
[<music21.pitch.Pitch F#>, <music21.pitch.Pitch C#>, <music21.pitch.Pitch G#>]
>>> b = key.KeySignature(1)
>>> b.alteredPitches
[<music21.pitch.Pitch F#>]

>>> c = key.KeySignature(9)
>>> [str(p) for p in c.alteredPitches]
['F#', 'C#', 'G#', 'D#', 'A#', 'E#', 'B#', 'F##', 'C##']

>>> d = key.KeySignature(-3)
>>> d.alteredPitches
[<music21.pitch.Pitch B->, <music21.pitch.Pitch E->, <music21.pitch.Pitch A->]

>>> e = key.KeySignature(-1)
>>> e.alteredPitches
[<music21.pitch.Pitch B->]

>>> f = key.KeySignature(-6)
>>> [str(p) for p in f.alteredPitches]
['B-', 'E-', 'A-', 'D-', 'G-', 'C-']

>>> g = key.KeySignature(-8)
>>> [str(p) for p in g.alteredPitches]
['B-', 'E-', 'A-', 'D-', 'G-', 'C-', 'F-', 'B--']


Non-standard, non-traditional key signatures can set their own
altered pitches cache.

>>> nonTrad = key.KeySignature(sharps=None)
>>> nonTrad.alteredPitches = ['B-', 'F#', 'E-', 'G#']
>>> nonTrad.alteredPitches
[<music21.pitch.Pitch B->,
 <music21.pitch.Pitch F#>,
 <music21.pitch.Pitch E->,
 <music21.pitch.Pitch G#>]

OMIT_FROM_DOCS

Ensure at least something is provided when the user hasn't provided enough info:

>>> nonTrad2 = key.KeySignature(sharps=None)
>>> nonTrad2.alteredPitches
[]

Nr   r<      r(   TinPlacer7   P4)rq   r[   r   r+   r.   	transposer)   r*   r,   appendr/   )rs   postpKeepr5   r   s        r#   r|   KeySignature.alteredPitches  s   r +'''"$;;K;;?KK$E{{Q4;;'d3MM%(A	 (  [[1_KK$E3t{{+,d3MM%(A	 - r%   c                   U R                  5         / nU H  n[        U[        5      (       a'  UR                  [        R
                  " U5      5        M?  [        U[        R
                  5      (       a  UR                  U5        Mq  [        U[        R                  5      (       d  M  UR                  [        R                  " UR                  5      5        M     X l
        g N)
clearCacherL   rM   r   r   r+   r   rN   r)   r*   rq   )rs   newAlteredPitchesnewListr   s       r#   r|   r     s     	%'"A!S!!u{{1~.Au{{++q!Atyy))t}}QWW56 #  'r%   c                B    U R                   c  U R                  (       a  gg)aV  
Returns bool if this is a non-traditional KeySignature:

>>> g = key.KeySignature(3)
>>> g.isNonTraditional
False

>>> g = key.KeySignature(sharps=None)
>>> g.alteredPitches = [pitch.Pitch('E`')]
>>> g.isNonTraditional
True

>>> g
<music21.key.KeySignature of pitches: [E`]>

>>> g.accidentalByStep('E')
<music21.pitch.Accidental half-flat>
TF)r[   r|   r   s    r#   isNonTraditionalKeySignature.isNonTraditional,  s    ( ;;4#6#6r%   c                    [        U R                  5       HQ  nUR                  R                  5       UR                  5       :X  d  M1  [        R
                  " UR                  5      s  $    g)a  
Given a step (C, D, E, F, etc.) return the accidental
for that note in this key (using the natural minor for minor)
or None if there is none.

>>> g = key.KeySignature(1)
>>> g.accidentalByStep('F')
<music21.pitch.Accidental sharp>
>>> g.accidentalByStep('G') is None
True

>>> f = key.KeySignature(-1)
>>> bbNote = note.Note('B-5')
>>> f.accidentalByStep(bbNote.step)
<music21.pitch.Accidental flat>

Fix a wrong note in F-major:

>>> wrongBNote = note.Note('B#4')
>>> if f.accidentalByStep(wrongBNote.step) != wrongBNote.pitch.accidental:
...    wrongBNote.pitch.accidental = f.accidentalByStep(wrongBNote.step)
>>> wrongBNote
<music21.note.Note B->

Set all notes to the correct notes for a key using the
note's Key Context.  Before:

>>> s1 = stream.Stream()
>>> s1.append(key.KeySignature(4))  # E-major or C-sharp-minor
>>> s1.append(note.Note('C', type='half'))
>>> s1.append(note.Note('E-', type='half'))
>>> s1.append(key.KeySignature(-4))  # A-flat-major or F-minor
>>> s1.append(note.Note('A', type='whole'))
>>> s1.append(note.Note('F#', type='whole'))
>>> #_DOCS_SHOW s1.show()

.. image:: images/keyAccidentalByStep_Before.*
    :width: 400

After:

>>> for n in s1.notes:
...    n.pitch.accidental = n.getContextByClass(key.KeySignature).accidentalByStep(n.step)
>>> #_DOCS_SHOW s1.show()

.. image:: images/keyAccidentalByStep.*
    :width: 400

OMIT_FROM_DOCS
>>> s1.show('text')
{0.0} <music21.key.KeySignature of 4 sharps>
{0.0} <music21.note.Note C#>
{2.0} <music21.note.Note E>
{4.0} <music21.key.KeySignature of 4 flats>
{4.0} <music21.note.Note A->
{8.0} <music21.note.Note F>

Test to make sure there are not linked accidentals (fixed bug 22 Nov. 2010)

>>> nB1 = note.Note('B', type='whole')
>>> nB2 = note.Note('B', type='whole')
>>> s1.append(nB1)
>>> s1.append(nB2)
>>> for n in s1.notes:
...    n.pitch.accidental = n.getContextByClass(key.KeySignature).accidentalByStep(n.step)
>>> (nB1.pitch.accidental, nB2.pitch.accidental)
(<music21.pitch.Accidental flat>, <music21.pitch.Accidental flat>)
>>> nB1.pitch.accidental.name = 'sharp'
>>> (nB1.pitch.accidental, nB2.pitch.accidental)
(<music21.pitch.Accidental sharp>, <music21.pitch.Accidental flat>)
N)reversedr|   rR   r   r)   r*   rS   )rs   rR   thisAlterations      r#   accidentalByStepKeySignature.accidentalByStepE  sQ    R 't':':;N""((*djjl:}}^%>%>?? <
 r%   Fr   c                   g r   r`   rs   rX   r   s      r#   r   KeySignature.transpose      
 	r%   c                   g r   r`   r   s      r#   r   r     r   r%   c                   [        U[        R                  5      (       a  UnO8[        U[        R                  5      (       a  UnO[        R                  " U5      nU(       d  [        R
                  " U 5      nOU nUR                  S5      nUR                  nUR                  U5      n[        U[        5      (       a(  [        [        U5      5      S:  a  UR                  5       n[        U5      Ul        UR                  5         U(       d  U$ g)a  
Transpose the KeySignature by the user-provided value.
If the value is an integer, the transposition is treated
in half steps. If the value is a string, any Interval string
specification can be provided. Alternatively, a
:class:`music21.interval.Interval` object can be supplied.

>>> a = key.KeySignature(2)
>>> a
<music21.key.KeySignature of 2 sharps>
>>> a.asKey('major')
<music21.key.Key of D major>

>>> b = a.transpose('p5')
>>> b
<music21.key.KeySignature of 3 sharps>
>>> b.asKey('major')
<music21.key.Key of A major>
>>> b.sharps
3

>>> c = b.transpose('-m2')
>>> c.asKey('major')
<music21.key.Key of G# major>
>>> c.sharps
8

>>> d = c.transpose('-a3')
>>> d.asKey('major')
<music21.key.Key of E- major>
>>> d.sharps
-3

Transposition by semitone (or other chromatic interval)

>>> c = key.KeySignature(0)
>>> dFlat = c.transpose(1)
>>> dFlat
<music21.key.KeySignature of 5 flats>
>>> d = dFlat.transpose(1)
>>> d
<music21.key.KeySignature of 2 sharps>
>>> eFlat = d.transpose(1)
>>> eFlat
<music21.key.KeySignature of 3 flats>
rA      N)rL   r
   r-   GenericIntervalr)   r*   r   r   r0   rU   r/   r]   getEnharmonicr[   r   )rs   rX   r   r4   r   k1p1p2s           r#   r   r     s    f eX..//Kx7788K"++E2K==&DDZZ XX''+eS!!c-*;&<q&@!!#B#B' Kr%   c                  SnSnUR                   nU(       d  [        R                  " U5      nU R                  S:X  a
  U(       a  gU$ U R                  S:  a,  [	        U R                  5      n[
        R                  " S5      nO"U R                  n[
        R                  " S5      n[        U5       H  nUR                  USS9  M     Ub  XQl         U(       d  U$ g)aQ  
Takes a pitch in C major and transposes it so that it has
the same step position in the current key signature.

Example: B is the leading tone in C major, so given
a key signature of 3 flats, get the leading tone in E-flat major:

>>> ks = key.KeySignature(-3)
>>> p1 = pitch.Pitch('B')
>>> p2 = ks.transposePitchFromC(p1)
>>> p2.name
'D'

Original pitch is unchanged:

>>> p1.name
'B'

>>> ks2 = key.KeySignature(2)
>>> p2 = ks2.transposePitchFromC(p1)
>>> p2.name
'C#'

For out of scale pitches the relationship still works; note also that
original octave is preserved.

>>> p3 = pitch.Pitch('G-4')
>>> p4 = ks.transposePitchFromC(p3)
>>> p4.nameWithOctave
'B--4'

If inPlace is True then the original pitch is
modified and nothing is returned.

>>> p5 = pitch.Pitch('C5')
>>> ks.transposePitchFromC(p5, inPlace=True)
>>> p5.nameWithOctave
'E-5'
Nr   r   r(   Tr   )	r,   r)   r*   r[   r/   r
   r-   r.   r0   )rs   r   r   transInterval
transTimesoriginalOctaver5   s          r#   transposePitchFromC KeySignature.transposePitchFromC  s    P 
a A;;!H[[1_T[[)J$--d3MJ$--d3Mz"A((D(9 # %%HHr%   c                    U R                  U5      R                  nUS;   a  [        R                  " U5      $ US:X  a  [        R                  " U5      $ [        SU 35      e)a  
Return a :class:`music21.scale.Scale` object (or, actually, a subclass such as
:class:`~music21.scale.MajorScale` or :class:`~music21.scale.MinorScale`) that is
representative of this key signature and mode.

Raises KeySignatureException if mode is not in [None, 'major', 'minor'].

>>> ks = key.KeySignature(3)
>>> ks
<music21.key.KeySignature of 3 sharps>
>>> ks.getScale('major')
<music21.scale.MajorScale A major>
>>> ks.getScale('minor')
<music21.scale.MinorScale F# minor>
)NrA   rC   z0No mapping to a scale exists for this mode yet: )r   r   r   
MajorScale
MinorScaler_   )rs   rY   r   s      r#   getScaleKeySignature.getScale8  s^      ::d#))?"##H--W_##H--'*Z[_Z`(abbr%   c                    U R                   $ r   )rp   r   s    r#   
_getSharpsKeySignature._getSharpsS  s    ||r%   c                P    XR                   :w  a  Xl         U R                  5         g g r   )rp   r   )rs   rX   s     r#   
_setSharpsKeySignature._setSharpsV  s     LL  LOO !r%   a  
        Get or set the number of sharps.  If the number is negative
        then it sets the number of flats.  Equivalent to musicxml's 'fifths'
        attribute.

        >>> ks1 = key.KeySignature(2)
        >>> ks1.sharps
        2
        >>> ks1.sharps = -4
        >>> ks1
        <music21.key.KeySignature of 4 flats>

        Can be set to None for a non-traditional key signature
        )doc)rq   rp   rr   )r   )r[   
int | None)NN)rY   
str | Noner   r   )returnzlist[pitch.Pitch])r   z#list[str | pitch.Pitch | note.Note]r   None)r   bool)rR   r   r   zpitch.Accidental | None)rs   r   rX   TransposeTypesr   t.Literal[False]r   r   )rs   r   rX   r   r   t.Literal[True]r   r   )rs   r   rX   r   r   r   r   zKeySignatureType | None)r   pitch.Pitchr   zpitch.Pitch | None)rA   )r   r   )rX   r   )rb   rc   rd   re   __doc__r   	TextStyle_styleClassequalityAttributesclassSortOrderrn   r   r   r   propertyr   r|   setterr   r   r   r   r   r   r   r   r[   rf   __classcell__rv   s   @r#   r   r     s\   EL //K$ N2 2.".6(p P  Pd ' ' '  0Nd  /4' , 9I  ' + 04  #(L'L  L -BL\ >C CJc6
 j*Fr%   c                  .  ^  \ rS rSr% SrSrSrS\S'   S\S'     S SS	 jjrS
 r	S r
S rS r\SS j5       r\SS j5       r\SS j5       rU 4S jrS rSSS jjr\SS.     S S jj5       r\      S!S j5       rSS.     S"U 4S jjjrSrU =r$ )#r   il  a  
Note that a key is a sort of hypothetical/conceptual object.
It probably has a scale (or scales) associated with it and a :class:`~music21.key.KeySignature`,
but not necessarily.

A Key object has all the attributes of a KeySignature and all the attributes of a
:class:`~music21.scale.DiatonicScale`.

>>> cm = key.Key('c')  # lowercase = c minor.
>>> cm
<music21.key.Key of c minor>
>>> cm.mode
'minor'
>>> cm.tonic
<music21.pitch.Pitch C>

>>> cm.sharps
-3
>>> cm.pitchFromDegree(3)
<music21.pitch.Pitch E-4>
>>> cm.pitchFromDegree(7)
<music21.pitch.Pitch B-4>

>>> cSharpMaj = key.Key('C#')  # uppercase = C# major
>>> cSharpMaj
<music21.key.Key of C# major>
>>> cSharpMaj.sharps
7

>>> fFlatMaj = key.Key('F-')
>>> fFlatMaj
<music21.key.Key of F- major>
>>> fFlatMaj.sharps
-8
>>> fFlatMaj.accidentalByStep('B')
<music21.pitch.Accidental double-flat>


>>> eDor = key.Key('E', 'dorian')
>>> eDor
<music21.key.Key of E dorian>
>>> eDor.sharps
2
>>> eDor.pitches
[<music21.pitch.Pitch E4>,
 <music21.pitch.Pitch F#4>,
 <music21.pitch.Pitch G4>,
 <music21.pitch.Pitch A4>,
 <music21.pitch.Pitch B4>,
 <music21.pitch.Pitch C#5>,
 <music21.pitch.Pitch D5>,
 <music21.pitch.Pitch E5>]

If you prefer not to use uppercase and lowercase to distinguish major and minor,
the shorthand of CM or Cm can also be used:

>>> key.Key('EM')
<music21.key.Key of E major>
>>> key.Key('F#m')
<music21.key.Key of f# minor>

**Equality**

Two Keys are equal if their tonics' names are equal, their sharps are equal,
and their modes are equal (and they pass all superclass tests)

>>> k = key.Key(pitch.Pitch('C4'))
>>> k2 = key.Key(pitch.Pitch('C5'))
>>> k == k2
True
>>> k.mode = 'minor'
>>> k == k2
False

* Changed in v8: keys now compare equal regardless of the octave of their tonics.
r   Nr   _moder   r   c                T   [        U[        R                  [        R                  45      (       a  UR
                  nOUnUc\  SU;   a  Sn[        R                  " SSU5      nOKSU;   a  Sn[        R                  " SSU5      nO*UR                  5       U:X  a  SnOSnOUR                  5       n[        XB5      n[        U[        R                  5      (       a  UnOB[        U[        R                  5      (       a  UR                  nO[        R                  " U5      n[        R                  " X40 UD6  [        R                  R                  " U 4SU0UD6  X`l        X l        X l        U R"                  b%  U R"                  R%                  U R                  5        S U l        / U l        g )NmrC   ry   MrA   r   )rL   r   rN   r   r+   r   resubr   r]   r   rn   r   DiatonicScaler   typerY   	_abstractbuildNetworkcorrelationCoefficientalternateInterpretations)rs   r   rY   rt   tonicStrr[   
tonicPitchs          r#   rn   Key.__init__  sQ    edii566zzHH <h66#r8466#r84!X-::<Dx.eU[[))Jtyy))JX.Jd7h7$$THHxH
		 >>%NN''		2
 '+# 46%r%   c                    S[        U 5      -   $ r   )rM   r   s    r#   r   Key._reprInternal  s    s4y  r%   c                <    U R                   nU SU R                   3$ )N )tonicPitchNameWithCaserY   )rs   r   s     r#   __str__Key.__str__  s$     ++$))%%r%   c                    [         R                  X5      (       d  gU R                  R                  UR                  R                  :H  =(       a    U R                  UR                  :H  $ )NF)r   __eq__r   r   rY   )rs   others     r#   r   
Key.__eq__  sE    ""4//zz%++"2"22NtyyEJJ7NNr%   c                    [        U 5      S-	  $ )N   )idr   s    r#   __hash__Key.__hash__   s    $x1}r%   c                    U R                   S;  a  U $ U R                   S:X  a$  [        U R                  5      R                  S5      $ [        U R                  5      R                  S5      $ )a  
if the Key is major or minor, return the relative minor or major.

Otherwise, just returns self -- this is the best way to not have random crashes
in the middle of large datasets.

Note that this uses .sharps as a speedup, so if that has been changed, there
will be a problem:

>>> k = key.Key('E-')
>>> k
<music21.key.Key of E- major>
>>> k.relative
<music21.key.Key of c minor>
>>> k.relative.relative
<music21.key.Key of E- major>

>>> key.Key('D', 'dorian').relative
<music21.key.Key of D dorian>
rC   rA   rA   rC   )rY   r   r[   r   r   s    r#   relativeKey.relative  sV    , 99..K99,227;;,227;;r%   c                    U R                   S;  a  U $ U R                   S:X  a  [        U R                  S5      $ [        U R                  S5      $ )a  
if the Key is major or minor, return the parallel minor or major.

Otherwise, just returns self -- this is the best way to not have random crashes
in the middle of large datasets.

>>> k = key.Key('D')
>>> k
<music21.key.Key of D major>
>>> k.parallel
<music21.key.Key of d minor>
>>> k.parallel.parallel
<music21.key.Key of D major>

>>> key.Key('D', 'dorian').parallel
<music21.key.Key of D dorian>
r  rA   rC   )rY   r   r   r   s    r#   parallelKey.parallel!  sD    & 99..K99tzz7++tzz7++r%   c                    U R                   R                  nU R                  S:X  a  UR                  5       nU$ U R                  S:X  a  UR	                  5       nU$ )az  
Return the pitch name as a string with the proper case (upper = major; lower = minor)

Useful, but simple:

>>> k = key.Key('c#')
>>> k.tonicPitchNameWithCase
'c#'
>>> k = key.Key('B')
>>> k.tonicPitchNameWithCase
'B'
>>> k.mode = 'minor'
>>> k.tonicPitchNameWithCase
'b'

Anything else will return the default (capital)

>>> k.mode = 'dorian'
>>> k.tonicPitchNameWithCase
'B'
rA   rC   )r   r   rY   upperr   )rs   r   s     r#   r   Key.tonicPitchNameWithCase<  sO    . ::??99~~'H  YY'!~~'Hr%   c                d   > [         TU ]  X5      nU R                  Ul        SUl        / Ul        U$ )a  
Given a degree and pitchReference derive a new
Key object that has the same mode but a different tonic

Example: What minor key has scale degree 3 as B-flat?

>>> minorKey = key.Key(mode='minor')
>>> newMinor = minorKey.deriveByDegree(3, 'B-')
>>> newMinor
<music21.key.Key of g minor>

Note that in minor, the natural form is used:

>>> minorKey.deriveByDegree(7, 'E')
<music21.key.Key of f# minor>
>>> minorKey.deriveByDegree(6, 'G')
<music21.key.Key of b minor>

To use the harmonic form, change `.abstract` on the key to
another abstract scale:

>>> minorKey.abstract = scale.AbstractHarmonicMinorScale()
>>> minorKey.deriveByDegree(7, 'E')
<music21.key.Key of f minor>
>>> minorKey.deriveByDegree(6, 'G')
<music21.key.Key of b minor>

Currently because of a limitation in bidirectional scale
searching, melodic minor scales cannot be used as abstracts
for deriving by degree.

* New in v6: preserve mode in key.Key.deriveByDegree
N)rm   deriveByDegreerY   r   r   )rs   degreepitchRefretrv   s       r#   r  Key.deriveByDegreeZ  s7    D g$V699 &*"')$
r%   c                r   U R                   (       d  [        S5      e/ nUR                  U R                  5        U R                    H(  nUR                  nUS:  d  M  UR                  U5        M*     [	        U5      S:  a  U R                  S::  a  gU R                  $ US   nUS   US   -
  nUS-  US-  -   $ )NzDcannot process ambiguity without a list of .alternateInterpretationsr   r   g        r   )r   r_   r   r   r    )rs   focussubKeyccabsMagnitude
leaderSpans         r#   %_tonalCertaintyCorrelationCoefficient)Key._tonalCertaintyCorrelationCoefficient  s    ,,'VX XT00133F..BAvR  4 u:>**a/222 Qx 1Xa(
 q Z!^44r%   c                J    US:X  a  U R                  5       $ [        SU 35      e)au  
Provide a measure of tonal ambiguity for Key
determined with one of many methods.

The `correlationCoefficient` assumes that the
alternateInterpretations list has
been filled from the use of a KeyWeightKeyAnalysis subclass.

>>> littlePiece = converter.parse("tinyNotation: 4/4 c4 d e f g a b c' e' g' e' c'")
>>> k = littlePiece.analyze('key')
>>> k
<music21.key.Key of C major>
>>> k.tonalCertainty()
1.1648...

Three most likely alternateInterpretations:

>>> k.alternateInterpretations[0:3]
[<music21.key.Key of a minor>, <music21.key.Key of F major>, <music21.key.Key of d minor>]
>>> k.correlationCoefficient
0.9068...
>>> k.alternateInterpretations[0].correlationCoefficient
0.7778...

least likely interpretation:

>>> k.alternateInterpretations[-1]
<music21.key.Key of F# major>


Note that this method only exists if the key has come from an analysis method. Otherwise
it raises a KeySignatureException

>>> k2 = key.Key('b-')
>>> k2.tonalCertainty()
Traceback (most recent call last):
music21.key.KeySignatureException: cannot process ambiguity without a
    list of .alternateInterpretations

>>> k2.alternateInterpretations
[]
r   zUnknown method: )r  ro   )rs   methods     r#   tonalCertaintyKey.tonalCertainty  s0    V --==??/x899r%   Fr   c                   g r   r`   r   s      r#   r   Key.transpose       	r%   c                   g r   r`   r   s      r#   r   r    r   r%   c                  > USL a  [         TU ]  XS9  U nO[         TU ]  XS9nUR                  U R                  5      nUR                  Ul        UR                  5         U(       d  U$ g)a  
Transpose the Key by the user-provided value.
If the value is an integer, the transposition is treated
in half steps. If the value is a string, any Interval string
specification can be provided. Alternatively, a
:class:`music21.interval.Interval` object can be supplied.

>>> dMajor = key.Key('D')
>>> dMajor
<music21.key.Key of D major>

>>> aMaj = dMajor.transpose('p5')
>>> aMaj
<music21.key.Key of A major>
>>> aMaj.sharps
3
>>> aMaj.tonic
<music21.pitch.Pitch A>
>>> aMaj.mode
'major'

`inPlace=True` works here and returns None while changing the Key itself.

>>> changingKey = key.Key('g')
>>> changingKey
<music21.key.Key of g minor>
>>> changingKey.sharps
-2
>>> changingKey.transpose('m-3', inPlace=True)
>>> changingKey
<music21.key.Key of e minor>
>>> changingKey.sharps
1

>>> changingKey.transpose(1, inPlace=True)
>>> changingKey
<music21.key.Key of f minor>
>>> changingKey.sharps
-4
>>> changingKey.transpose(1, inPlace=True)
>>> changingKey
<music21.key.Key of f# minor>
>>> changingKey.transpose(1, inPlace=True)
>>> changingKey
<music21.key.Key of g minor>
>>> changingKey.transpose(1, inPlace=True)
>>> changingKey
<music21.key.Key of g# minor>
Tr   N)rm   r   r   rY   r   r   )rs   rX   r   r   postKeyrv   s        r#   r   r    sh    l d?Ge5D7$U$<D**TYY']]
 Kr%   )r   r   rY   r   r   )r'   N)r   str | pitch.Pitch | note.Note)r   r   )r   rM   )r   )r   float)rs   r   rX   r   r   r   r   r   )rs   r   rX   r   r   r   r   r   )rs   r   rX   r   r   r   r   zKeyType | None)rb   rc   rd   re   r   rp   r   __annotations__rn   r   r   r   r   r   r  r  r   r  r  r  r   r   rf   r   r   s   @r#   r   r   l  s.   KX GE8 5826126h!&O < <: , ,4  :)X58.:`  /4' , 	  ' + 	  #(C'C  C $	C Cr%   c                  2    \ rS rSrS rS rS rS rS rSr	g)	Testi)  c                2    SSK Jn  U" U [        5       5        g )Nr   )testCopyAll)music21.test.commonTestr*  globals)rs   r*  s     r#   testCopyAndDeepcopyTest.testCopyAndDeepcopy+  s    7D')$r%   c                P    [        5       nU R                  UR                  S5        g )Nr   )r   assertEqualr[   )rs   as     r#   	testBasicTest.testBasic/  s    N1%r%   c                0   SSK Jn  [        5       n[        R                  " S5      nX2l        U R                  UR
                  U5        UR                  S5      R                  5       n[        US9nU R                  UR
                  R                  S5        g )Nr   )chordr<   z	Bb4 D5 F5r   r   )music21r5  r   r   r+   r   assertIsChordrootr0  r   )rs   r5  r   r   
b_flat_majs        r#   testSetTonicTest.testSetTonic3  sn    !E KKaggq! [[-224
j!t,r%   c                   SSK Jn  SSK Jn  UR                  S5      nUR	                  S5      nUR                  SS9nU R                  SUs=:  =(       a    S	:  Os  5        UR                  S
S5      nUR	                  S5      nUR                  SS9nU R                  SUs=:  =(       a    S	:  Os  5        [        R                  " S5      n[        R                  " S5      n[        R                  " S5      n[        R                  " S5      n	UR                  5       nUR                   H(  n
UR                  [        R                  " U
5      5        M*     UR	                  S5      nUR                  SS9nU R                  SUs=:  =(       a    S	:  Os  5        UR                  5       nUR                  UR                  -   UR                  -   UR                  -    H(  n
UR                  [        R                  " U
5      5        M*     UR	                  S5      nUR                  SS9nU R                  SUs=:  =(       a    S	:  Os  5        UR                  5       nUR                  U	R                  -    H(  n
UR                  [        R                  " U
5      5        M*     UR	                  S5      nUR                  SS9nU R                  SUs=:  =(       a    S	:  Os  5        UR                  5       nS H(  n
UR                  [        R                  " U
5      5        M*     UR	                  S5      nUR                  SS9nU R                  SUs=:  =(       a
    S	:  5        g s  5        g )Nr   )corpus)streamzbwv66.6KrumhanslSchmucklerr   )r  r   g?zschoenberg/opus19r   gdr1  zf#)crB  rD  rD  e)r7  r?  r@  parseanalyzer  
assertTruer   r   Streampitchesr   r   rN   )rs   r?  r@  sr   tasc1sc2sc3sc5r   s              r#   testTonalAmbiguityATest.testTonalAmbiguityAB  s   ""
 LL#II+,%=>B%LL,a0II+,%=>B%s#s#s#t$MMOAHHTYYq\" II+,%=>B%MMOs{{*S[[83;;FAHHTYYq\" GII+,%=>B%MMOs{{*AHHTYYq\" +II+,%=>B%MMO*AHHTYYq\" +II+,%=>B%%r%   c                   [        S5      nUR                  S S S9nU R                  UR                  S5        U R                  UR                  S5        UR                  SS9nU R                  UR                  S5        U R                  UR                  S5        SnU R                  [        U5       nUR                  S	SS9nS S S 5        U R                  UR                  S	5        U R                  UR                  S
5        SnU R                  [        U5       nUR                  S SS9nS S S 5        U R                  WR                  R                  [        5        g ! , (       d  f       N= f! , (       d  f       NJ= f)Nr   )rY   r   rA   r9   r;   r6  rE   zignoring provided tonic: ErC   r   z0Could not solve for mode from sharps=2, tonic=A-zA-)r   r   r0  rY   r   assertWarnsRegexrj   assertRaisesRegexrO   assertIsInstance	exception	__cause__r   )rs   ksr   expectedcms        r#   	testAsKeyTest.testAsKeyy  s7   !_HH$dH+)1137HH3H*1137/"":x8BgS1A 9 	)1137E##L(;rd$/A < 	bll44h? 98 <;s   3E E1 
E.1
E?r`   N)
rb   rc   rd   re   r-  r2  r<  rQ  r\  rf   r`   r%   r#   r(  r(  )  s    %&-0&n@r%   r(  __main__r   )rX   r$  rY   r   r   rU   )6r   
__future__r   r)   r   typingr   r   unittestr   r7  r   music21.common.decoratorsr   music21.common.typesr   r   r	   r
   r   r   r   r   EnvironmentenvironLocalTypeVarr   r   rU   rM   r-   r   r   r   r&  r$   r6   rP   rW   r]   Music21Exceptionr_   rO   Warningrj   Music21Objectr   r   r   TestCaser(  
_DOC_ORDERrb   mainTestr`   r%   r#   <module>rm     s   #  	      1 )        &&u-99/~F 
))IU
+S***8+C+CC
 /1 + 0$N<D 2 !!# 	 $(] ],/]@	L99 		<00 		 	
R	4%% R	jy,++ yzf@8 f@V C 
 zT r%   