
    3jy                       U d dl mZ d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ dZddiZded<    G d d      Z G d de      Z	 	 	 d	 	 	 d dZd Zd Zd!dZd!dZ G d de	j8                        Z G d dej<                        Ze dk(  rd dlZ ejB                  e       yy)"    )annotationsN)chord)environment)exceptions21)note)pitch)scale)possibility)realizerScale)
resolution)ruleszfiguredBass.segmentr	   z0dict[str, realizerScale.FiguredBassScale | None]_defaultRealizerScalec                      e Zd ZU g dZdddddddZd	ed
<   	 	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 ddZddZddZddZ	d Z
ddZd Zd Zd Zd Zd Zd Zd Zd Zy)Segment)	allSinglePossibilitiessinglePossibilityRulesallCorrectSinglePossibilitiesconsecutivePossibilityRulesspecialResolutionRules"allCorrectConsecutivePossibilitiesresolveDominantSeventhSegmentresolveDiminishedSeventhSegmentresolveAugmentedSixthSegmentzZA :class:`~music21.note.Note` whose pitch
             forms the bass of each possibility.zThe number of parts (including the bass) that possibilities
             should contain, which
             comes directly from :attr:`~music21.figuredBass.rules.Rules.numParts`
             in the Rules object.zA list of allowable pitch names.
             This is derived from bassNote.pitch and notationString
             using :meth:`~music21.figuredBass.realizerScale.FiguredBassScale.getPitchNames`.a|  A list of allowable pitches in the upper parts of a possibility.
             This is derived using
             :meth:`~music21.figuredBass.segment.getPitches`, providing bassNote.pitch,
             :attr:`~music21.figuredBass.rules.Rules.maxPitch`
             from the Rules object, and
             :attr:`~music21.figuredBass.segment.Segment.pitchNamesInChord` as arguments.z}:attr:`~music21.figuredBass.segment.Segment.allPitchesAboveBass`
             represented as a :class:`~music21.chord.Chord`.zLA deepcopy of the :class:`~music21.figuredBass.rules.Rules` object provided.)bassNotenumPartspitchNamesInChordallPitchesAboveBasssegmentChordfbRuleszdict[str, str]	_DOC_ATTRNc                <   t        |t              rt        j                  |      }t        |t              rt	        j
                  |      }|-t        d   t        j                         t        d<   t        d   }|J |t        j                         | _        nt        j                  |      | _        d| _        d| _        d| _        || _        || _        || _        |
||| _        n+|j+                  | j"                  j                  |      | _        t-        | j(                  | j"                  j                  | j&                        | _        t1        j2                  | j.                  |j4                        | _        t9        j:                  t<              | _        y)aV  
        A Segment corresponds to a 1:1 realization of a bassNote and notationString
        of a :class:`~music21.figuredBass.realizer.FiguredBassLine`.
        It is created by passing six arguments: a
        :class:`~music21.figuredBass.realizerScale.FiguredBassScale`, a bassNote, a notationString,
        a :class:`~music21.figuredBass.rules.Rules` object, a number of parts and a maximum pitch.
        Realizations of a Segment are represented
        as possibility tuples (see :mod:`~music21.figuredBass.possibility` for more details).

        Methods in Python's `itertools`
        module are used extensively. Methods
        which generate possibilities or possibility progressions return iterators,
        which are turned into lists in the examples
        for display purposes only.

        if fbScale is None, a realizerScale.FiguredBassScale() is created

        if fbRules is None, a rules.Rules() instance is created.  Each Segment gets
        its own deepcopy of the one given.

        Here, a Segment is created using the default values: a FiguredBassScale in C,
        a bassNote of C3, an empty notationString, and a default
        Rules object.

        >>> from music21.figuredBass import segment
        >>> s1 = segment.Segment()
        >>> s1.bassNote
        <music21.note.Note C>
        >>> s1.numParts
        4
        >>> s1.pitchNamesInChord
        ['C', 'E', 'G']
        >>> [str(p) for p in s1.allPitchesAboveBass]
        ['C3', 'E3', 'G3', 'C4', 'E4', 'G4', 'C5', 'E5', 'G5']
        >>> s1.segmentChord
        <music21.chord.Chord C3 E3 G3 C4 E4 G4 C5 E5 G5>
        Nr	   )quarterLength) 
isinstancestrr   Noter   Pitchr   r   FiguredBassScaler   Rulesr   copydeepcopy_specialResolutionRuleChecking_singlePossibilityRuleChecking#_consecutivePossibilityRuleCheckingr   r   	_maxPitchr   getPitchNames
getPitchesr   r   Chordr"   r   r   Environment_MOD_environRules)selfr   notationStringfbScaler   r   maxPitchlistOfPitchess           H/DATA/.local/lib/python3.12/site-packages/music21/figuredBass/segment.py__init__zSegment.__init__B   sT   Z h$yy*Hh${{8,H?$W-51>1O1O1Q%g.+G4G"""? ;;=DL==1DL.2+.2+370  !!m&?%2D" &-%:%:4==;N;NP^%_D"#-d.D.D.2mm.A.A.2nn$>  "KK(@(@6>6L6LN(44T:    c                    |t        j                         }|j                  t        j                  d| j
                  gfdt        j                  d|j                  gf|j                  t        j                  dfg}|S )a  
        A framework for storing single possibility rules and methods to be applied
        in :meth:`~music21.figuredBass.segment.Segment.allCorrectSinglePossibilities`.
        Takes in a :class:`~music21.figuredBass.rules.Rules` object, fbRules.
        If None then a new rules object is created.

        Items are added within this method in the following form:

        (willRunOnlyIfTrue, methodToRun, keepSolutionsWhichReturn, optionalArgs)

        These items are compiled internally when
        :meth:`~music21.figuredBass.segment.Segment.allCorrectSinglePossibilities`
        is called on a Segment. Here, the compilation of rules and
        methods bases on a default fbRules is shown.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment()
        >>> allSingleRules = segmentA.singlePossibilityRules()
        >>> segment.printRules(allSingleRules)
        Will run:  Method:                       Keep solutions which return:  Arguments:
        True       isIncomplete                  False                         ['C', 'E', 'G']
        True       upperPartsWithinLimit         True                          12
        True       voiceCrossing                 False                         None

        Here, a modified fbRules is provided, which allows for incomplete possibilities.

        >>> from music21.figuredBass import rules
        >>> fbRules = rules.Rules()
        >>> fbRules.forbidIncompletePossibilities = False
        >>> allSingleRules = segmentA.singlePossibilityRules(fbRules)
        >>> segment.printRules(allSingleRules)
        Will run:  Method:                       Keep solutions which return:  Arguments:
        False      isIncomplete                  False                         ['C', 'E', 'G']
        True       upperPartsWithinLimit         True                          12
        True       voiceCrossing                 False                         None
        FT)
r   r(   forbidIncompletePossibilitiesr
   isIncompleter   upperPartsWithinLimitupperPartsMaxSemitoneSeparationforbidVoiceCrossingvoiceCrossing)r5   r   singlePossibRuless      r:   r   zSegment.singlePossibilityRules   s    L ?kkmG 22))(()+ 2299:< ((**
 ! r<   c                   |t        j                         }| j                  j                         }dt        j
                  d|j                  gf|j                  t        j                  df|j                  t        j                  dfdt        j                  d|j                  gf|j                  t        j                  df|j                  t        j                   df|j"                  t        j$                  df|j&                  t        j(                  df|j*                  xr |t        j,                  dt/        | j                        |j0                  gfg	}|S )a  
        A framework for storing consecutive possibility rules and methods to be applied
        in :meth:`~music21.figuredBass.segment.Segment.allCorrectConsecutivePossibilities`.
        Takes in a :class:`~music21.figuredBass.rules.Rules` object, fbRules; if None
        then a new rules.Rules() object is created.

        Items are added within this method in the following form:

            (willRunOnlyIfTrue, methodToRun, keepSolutionsWhichReturn, optionalArgs)

        These items are compiled internally when
        :meth:`~music21.figuredBass.segment.Segment.allCorrectConsecutivePossibilities`
        is called on a Segment. Here, the compilation of rules and methods
        bases on a default fbRules is shown.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment()
        >>> allConsecutiveRules = segmentA.consecutivePossibilityRules()

        >>> segment.printRules(allConsecutiveRules)
        Will run:  Method:                       Keep solutions which return:  Arguments:
        True       partsSame                     True                          []
        False      upperPartsSame                True                          None
        True       voiceOverlap                  False                         None
        True       partMovementsWithinLimits     True                          []
        True       parallelFifths                False                         None
        True       parallelOctaves               False                         None
        True       hiddenFifth                   False                         None
        True       hiddenOctave                  False                         None
        False      couldBeItalianA6Resolution    True           [<music21.pitch.Pitch C3>,
                                                                 <music21.pitch.Pitch C3>,
                                                                 <music21.pitch.Pitch E3>,
                                                                 <music21.pitch.Pitch G3>], True

        Now, a modified fbRules is provided, allowing hidden octaves and
        voice overlap, and limiting the soprano line to stepwise motion.

        >>> from music21.figuredBass import rules
        >>> fbRules = rules.Rules()
        >>> fbRules.forbidVoiceOverlap = False
        >>> fbRules.forbidHiddenOctaves = False
        >>> fbRules.partMovementLimits.append((1, 2))
        >>> allConsecutiveRules = segmentA.consecutivePossibilityRules(fbRules)
        >>> segment.printRules(allConsecutiveRules)
        Will run:  Method:                       Keep solutions which return:  Arguments:
        True       partsSame                     True                          []
        False      upperPartsSame                True                          None
        False      voiceOverlap                  False                         None
        True       partMovementsWithinLimits     True                          [(1, 2)]
        True       parallelFifths                False                         None
        True       parallelOctaves               False                         None
        True       hiddenFifth                   False                         None
        False      hiddenOctave                  False                         None
        False      couldBeItalianA6Resolution    True           [<music21.pitch.Pitch C3>,
                                                                 <music21.pitch.Pitch C3>,
                                                                 <music21.pitch.Pitch E3>,
                                                                 <music21.pitch.Pitch G3>], True
        TF)r   r(   r   isItalianAugmentedSixthr
   	partsSame_partsToCheck_upperPartsRemainSameupperPartsSameforbidVoiceOverlapvoiceOverlappartMovementsWithinLimitspartMovementLimitsforbidParallelFifthsparallelFifthsforbidParallelOctavesparallelOctavesforbidHiddenFifthshiddenFifthforbidHiddenOctaveshiddenOctaveresolveAugmentedSixthProperlycouldBeItalianA6Resolution_unpackTriad&restrictDoublingsInItalianA6Resolution)r5   r   rF   consecutivePossibRuless       r:   r   z#Segment.consecutivePossibilityRules   s0   x ?kkmG"&"3"3"K"K"M ;(($1F1F0GH**K,F,FM'')A)A5I;88$A[A[@\]));+E+EuM**K,G,GO'')@)@%H((+*B*BEJ22N7N66d//0'2`2`ac"
 &%r<   c                   |t        j                         }| j                  j                         }| j                  j	                         }| j                  j                         }|j                  xr || j                  f|j                  xr || j                  |j                  gf|j                  xr || j                  fg}|S )a2  
        A framework for storing methods which perform special resolutions
        on Segments. Unlike the methods in
        :meth:`~music21.figuredBass.segment.Segment.singlePossibilityRules` and
        :meth:`~music21.figuredBass.segment.Segment.consecutivePossibilityRules`,
        these methods deal with the Segment itself, and rely on submethods
        to resolve the individual possibilities accordingly depending on what
        the resolution Segment is.

        If fbRules is None, then a new rules.Rules() object is created.

        Items are added within this method in the following form:

        (willRunOnlyIfTrue, methodToRun, optionalArgs)

        These items are compiled internally
        when :meth:`~music21.figuredBass.segment.Segment.allCorrectConsecutivePossibilities`
        is called on a Segment. Here, the compilation of rules and methods
        based on a default fbRules is shown.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment()
        >>> allSpecialResRules = segmentA.specialResolutionRules()
        >>> segment.printRules(allSpecialResRules, maxLength=3)
        Will run:  Method:                          Arguments:
        False      resolveDominantSeventhSegment    None
        False      resolveDiminishedSeventhSegment  False
        False      resolveAugmentedSixthSegment     None

        Dominant Seventh Segment:

        >>> segmentA = segment.Segment(bassNote=note.Note('B2'), notationString='6,5')
        >>> allSpecialResRules = segmentA.specialResolutionRules()
        >>> segment.printRules(allSpecialResRules, maxLength=3)
        Will run:  Method:                          Arguments:
        True       resolveDominantSeventhSegment    None
        False      resolveDiminishedSeventhSegment  False
        False      resolveAugmentedSixthSegment     None

        Fully-Diminished Seventh Segment:

        >>> segmentA = segment.Segment(bassNote=note.Note('B2'), notationString='-7')
        >>> allSpecialResRules = segmentA.specialResolutionRules()
        >>> segment.printRules(allSpecialResRules, maxLength=3)
        Will run:  Method:                          Arguments:
        False      resolveDominantSeventhSegment    None
        True       resolveDiminishedSeventhSegment  False
        False      resolveAugmentedSixthSegment     None

        Augmented Sixth Segment:

        >>> segmentA = segment.Segment(bassNote=note.Note('A-2'), notationString='#6,b5')
        >>> allSpecialResRules = segmentA.specialResolutionRules()
        >>> segment.printRules(allSpecialResRules, maxLength=3)
        Will run:  Method:                          Arguments:
        False      resolveDominantSeventhSegment    None
        False      resolveDiminishedSeventhSegment  False
        True       resolveAugmentedSixthSegment     None
        )r   r(   r   isDominantSeventhisDiminishedSeventhisAugmentedSixthresolveDominantSeventhProperlyr    resolveDiminishedSeventhProperlyr   doubledRootInDim7rW   r   )r5   r   r]   r^   r_   specialResRuless         r:   r   zSegment.specialResolutionRules"  s    x ?kkmG --??A"//CCE,,==? 33I8I//155M:M44**+- 22G7G113
 r<   c                   | j                   }|j                         st        d      t        |      }t	        j
                         j                  |      }|j                         }|j                         }|j                  d      }|j                  d      }|j                  d      }	|j                   }
|j                         dk(  }|
j                         }|xr |dk(  }|j                         dk(  rX|
j                         j                  |j                  k(  r1|
j                         s|
j                         rd|j                  _        |
j                         j                  |j                  k(  xr |
j                         t"        j$                  ||gf|
j                         j                  |j                  k(  xr |
j                         t"        j&                  ||gf|
j                         j                  |j                  k(  xr |
j                         xr |dk(  t"        j(                  |gf|
j                         j                  |	j                  k(  xr |
j                         xr |dk(  t"        j*                  |gf|
j                         j                  |j                  k(  xr |
j                         xr |dk(  t"        j,                  |gf|
j                         j                  |j                  k(  xr |
j                         xr |dk(  t"        j.                  |gfg}	 | j1                  ||      S # t        $ r/ | j2                  j5                  d       | j7                  |      cY S w xY w)	aP  
        Can resolve a Segment whose :attr:`~music21.figuredBass.segment.Segment.segmentChord`
        spells out a dominant seventh chord. If no applicable method in
        :mod:`~music21.figuredBass.resolution` can be used, the Segment is resolved
        as an ordinary Segment.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment(bassNote=note.Note('G2'), notationString='7')
        >>> allDomPossib = segmentA.allCorrectSinglePossibilities()
        >>> allDomPossibList = list(allDomPossib)
        >>> len(allDomPossibList)
        8
        >>> allDomPossibList[2]
        (<music21.pitch.Pitch D4>, <music21.pitch.Pitch B3>,
         <music21.pitch.Pitch F3>, <music21.pitch.Pitch G2>)
        >>> allDomPossibList[5]
        (<music21.pitch.Pitch D5>, <music21.pitch.Pitch B4>,
         <music21.pitch.Pitch F4>, <music21.pitch.Pitch G2>)

        Here, the Soprano pitch of resolution (C6) exceeds default maxPitch of B5, so
        it's filtered out.

        >>> [p.nameWithOctave for p in allDomPossibList[7]]
        ['B5', 'F5', 'D5', 'G2']

        >>> segmentB = segment.Segment(bassNote=note.Note('C3'), notationString='')
        >>> domResPairs = segmentA.resolveDominantSeventhSegment(segmentB)
        >>> domResPairsList = list(domResPairs)
        >>> len(domResPairsList)
        7
        >>> domResPairsList[2]
        ((<music21.pitch.Pitch D4>, <...B3>, <...F3>, <...G2>),
         (<...C4>, <...C4>, <...E3>, <...C3>))
        >>> domResPairsList[5]
        ((<...D5>, <...B4>, <...F4>, <...G2>), (<...C5>, <...C5>, <...E4>, <...C3>))
        z<Dominant seventh resolution: Not a dominant seventh Segment.            r   Fz[Dominant seventh resolution: No proper resolution available. Executing ordinary resolution.)r   r]   SegmentException_unpackSeventhChordr	   
MajorScalederivegetParallelMinorgetTonicpitchFromDegree	inversionrootnameisMajorTriadisMinorTriadr   r>   r   dominantSeventhToMajorTonicdominantSeventhToMinorTonic dominantSeventhToMinorSubmediant dominantSeventhToMajorSubmediant!dominantSeventhToMajorSubdominant!dominantSeventhToMinorSubdominant_resolveSpecialSegmentr4   warn_resolveOrdinarySegment)r5   segmentBdomChorddomChordInfodominantScale
minorScaletonicsubdominantmajSubmediantminSubmediantresChorddomInversionresInversionresolveV43toI6dominantResolutionMethodss                  r:   r   z%Segment.resolveDominantSeventhSegmentq  s,   L $$))+"#abb*84((*11(;"335
&&(#33A6%55a8"2215(( **,1 **,%;,!*; A%MMO((EJJ6**,0E0E0G=BH: ]]_!!UZZ/KH4I4I4K33l+- ]]_!!UZZ/KH4I4I4K66.0 mmo""m&8&88 $'')$!#;;	 
 mmo""m&8&88 &))+& A%;;	 
 mmo""k&6&66 &))+& A%<<	 
 mmo""k&6&66 &))+& A%<<	 -%
!:	:..x9RSS 	:##34 //99		:s   )L; ;5M32M3c                   | j                   }|j                         st        d      t        |      }t	        j
                         j                  d|j                               }|j                         }|j                  d      }|j                   }|j                         dk(  r+|j                         dk(  rd}n|j                         dk(  rd}|j                         j                  |j                  k(  xr |j                         t        j                  ||gf|j                         j                  |j                  k(  xr |j                         t        j                   ||gf|j                         j                  |j                  k(  xr |j                         t        j"                  |gf|j                         j                  |j                  k(  xr |j                         t        j$                  |gfg}		 | j'                  ||	      S # t        $ r/ | j(                  j+                  d       | j-                  |      cY S w xY w)	a  
        Can resolve a Segment whose :attr:`~music21.figuredBass.segment.Segment.segmentChord`
        spells out a diminished seventh chord. If no applicable method in
        :mod:`~music21.figuredBass.resolution` can be used, the Segment is resolved
        as an ordinary Segment.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment(bassNote=note.Note('B2'), notationString='b7')
        >>> allDimPossib = segmentA.allCorrectSinglePossibilities()
        >>> allDimPossibList = list(allDimPossib)
        >>> len(allDimPossibList)
        7
        >>> [p.nameWithOctave for p in allDimPossibList[4]]
        ['D5', 'A-4', 'F4', 'B2']
        >>> [p.nameWithOctave for p in allDimPossibList[6]]
        ['A-5', 'F5', 'D5', 'B2']

        >>> segmentB = segment.Segment(bassNote=note.Note('C3'), notationString='')
        >>> dimResPairs = segmentA.resolveDiminishedSeventhSegment(segmentB)
        >>> dimResPairsList = list(dimResPairs)
        >>> len(dimResPairsList)
        7
        >>> dimResPairsList[4]
        ((<...D5>, <...A-4>, <...F4>, <...B2>), (<...E5>, <...G4>, <...E4>, <...C3>))
        >>> dimResPairsList[6]
        ((<...A-5>, <...F5>, <...D5>, <...B2>), (<...G5>, <...E5>, <...E5>, <...C3>))
        z@Diminished seventh resolution: Not a diminished seventh Segment.   re   rh   r   TFz]Diminished seventh resolution: No proper resolution available. Executing ordinary resolution.)r   r^   ri   rj   r	   HarmonicMinorScalederiveByDegreerq   rn   ro   rp   rr   rs   r   diminishedSeventhToMajorTonicrt   diminishedSeventhToMinorTonic#diminishedSeventhToMajorSubdominant#diminishedSeventhToMinorSubdominantr{   r4   r|   r}   )
r5   r~   doubledRootdimChorddimChordInfodimScaler   r   r   diminishedResolutionMethodss
             r:   r   z'Segment.resolveDiminishedSeventhSegment  s   : $$++-"RT T*84++-<<QP !!#..q1((1$!!#q("##%*# ]]_!!UZZ/KH4I4I4K55<(* ]]_!!UZZ/KH4I4I4K88l+- ]]_!![%5%55Q(:O:O:Q>>  ]]_!![%5%55Q(:O:O:Q>> '
#	:..x9TUU 	:##34 //99		:s   =H 5IIc                   | j                   }|j                         st        d      |j                         r| j	                  |      S |j                         rd}nR|j                         rd}n?|j                         rd}n,| j                  j                  d       | j	                  |      S t        j                  |j                         d      }t        j                  |      }|j                   }t        |      }|j!                         dk(  xr9 |j#                         j$                  |j$                  k(  xr |j'                         t        j(                  ||gf|j!                         dk(  xr9 |j#                         j$                  |j$                  k(  xr |j+                         t        j,                  ||gf|j/                  d      j$                  |j                         j$                  k(  xr |j'                         t        j0                  ||gfg}	 | j3                  ||      S # t        $ r/ | j                  j                  d       | j	                  |      cY S w xY w)	a  
        Can resolve a Segment whose :attr:`~music21.figuredBass.segment.Segment.segmentChord`
        spells out a
        French, German, or Swiss augmented sixth chord. Italian augmented sixth Segments
        are solved as an
        ordinary Segment using :meth:`~music21.figuredBass.possibility.couldBeItalianA6Resolution`.
        If no
        applicable method in :mod:`~music21.figuredBass.resolution` can be used, the Segment
        is resolved
        as an ordinary Segment.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment(bassNote=note.Note('A-2'), notationString='#6,b5,3')
        >>> segmentA.pitchNamesInChord  # spell out a Gr+6 chord
        ['A-', 'C', 'E-', 'F#']
        >>> allAugSixthPossib = segmentA.allCorrectSinglePossibilities()
        >>> allAugSixthPossibList = list(allAugSixthPossib)
        >>> len(allAugSixthPossibList)
        7

        >>> allAugSixthPossibList[1]
        (<music21.pitch.Pitch C4>, <music21.pitch.Pitch F#3>, <...E-3>, <...A-2>)
        >>> allAugSixthPossibList[4]
        (<music21.pitch.Pitch C5>, <music21.pitch.Pitch F#4>, <...E-4>, <...A-2>)

        >>> segmentB = segment.Segment(bassNote=note.Note('G2'), notationString='')
        >>> allAugResPossibPairs = segmentA.resolveAugmentedSixthSegment(segmentB)
        >>> allAugResPossibPairsList = list(allAugResPossibPairs)
        >>> len(allAugResPossibPairsList)
        7
        >>> allAugResPossibPairsList[1]
        ((<...C4>, <...F#3>, <...E-3>, <...A-2>), (<...B3>, <...G3>, <...D3>, <...G2>))
        >>> allAugResPossibPairsList[4]
        ((<...C5>, <...F#4>, <...E-4>, <...A-2>), (<...B4>, <...G4>, <...D4>, <...G2>))
        z;Augmented sixth resolution: Not an augmented sixth Segment.rh   rg      z^Augmented sixth resolution: Augmented sixth type not supported. Executing ordinary resolution.M3   zZAugmented sixth resolution: No proper resolution available. Executing ordinary resolution.)r   r_   ri   rF   r}   isFrenchAugmentedSixthisGermanAugmentedSixthisSwissAugmentedSixthr4   r|   r   
_transposebassr	   rk   rj   rp   rq   rr   rs   augmentedSixthToMajorTonicrt   augmentedSixthToMinorTonicro   augmentedSixthToDominantr{   )	r5   r~   augSixthChordaugSixthTyper   
majorScaler   augSixthChordInfoaugmentedSixthResolutionMethodss	            r:   r   z$Segment.resolveAugmentedSixthSegment  sB   J ))--/"#`aa002//99113L113L002L##WX //99%%m&8&8&:DA%%e,
((/>   "a' ,MMO((EJJ6,))+22\CT4UW   "a' ,MMO((EJJ6,))+5501	3
 ((+00HMMO4H4HH ,))+33013+
' 	:..x9XYY 	:##34 //99		:s   H- -5I%$I%c                    | j                   g| j                  dz
  z  }|j                  t        j                  | j
                  j                  j                        g       t        j                  | S )a  
        Returns an iterator through a set of naive possibilities for
        a Segment, using :attr:`~music21.figuredBass.segment.Segment.numParts`,
        the pitch of :attr:`~music21.figuredBass.segment.Segment.bassNote`, and
        :attr:`~music21.figuredBass.segment.Segment.allPitchesAboveBass`.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment()
        >>> allPossib = segmentA.allSinglePossibilities()
        >>> allPossib.__class__
        <... 'itertools.product'>

        The number of naive possibilities is always the length of
        :attr:`~music21.figuredBass.segment.Segment.allPitchesAboveBass`
        raised to the (:attr:`~music21.figuredBass.segment.Segment.numParts` - 1)
        power. The power is 1 less than the number of parts because
        the bass pitch is constant.

        >>> allPossibList = list(allPossib)
        >>> len(segmentA.allPitchesAboveBass)
        9
        >>> segmentA.numParts
        4
        >>> len(segmentA.allPitchesAboveBass) ** (segmentA.numParts-1)
        729
        >>> len(allPossibList)
        729

        >>> for i in (81, 275, 426):
        ...    [str(p) for p in allPossibList[i]]
        ['E3', 'C3', 'C3', 'C3']
        ['C4', 'C4', 'G4', 'C3']
        ['G4', 'G3', 'C4', 'C3']
        rh   )	r   r   appendr   r&   r   nameWithOctave	itertoolsproduct)r5   	iterabless     r:   r   zSegment.allSinglePossibilitiesp  s\    F --.$--!2CD	%++dmm&9&9&H&HIJK  ),,r<   c                    t        | j                  | j                              | _        | j	                         }|D cg c]  }| j                  |      s| c}S c c}w )a  
        Uses :meth:`~music21.figuredBass.segment.Segment.allSinglePossibilities` and
        returns an iterator through a set of correct possibilities for
        a Segment, all possibilities which pass all filters in
        :meth:`~music21.figuredBass.segment.Segment.singlePossibilityRules`.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment()
        >>> allPossib = segmentA.allSinglePossibilities()
        >>> allCorrectPossib = segmentA.allCorrectSinglePossibilities()

        Most of the 729 naive possibilities were filtered out using the default rules set,
        leaving only 21.

        >>> allPossibList = list(allPossib)
        >>> len(allPossibList)
        729
        >>> allCorrectPossibList = list(allCorrectPossib)
        >>> len(allCorrectPossibList)
        21

        >>> for i in (5, 12, 20):
        ...   [str(p) for p in allCorrectPossibList[i]]
        ['E4', 'G3', 'G3', 'C3']
        ['C5', 'G4', 'E4', 'C3']
        ['G5', 'G5', 'E5', 'C3']
        )_compileRulesr   r   r,   r   _isCorrectSinglePossibility)r5   allApossibAs      r:   r   z%Segment.allCorrectSinglePossibilities  sW    8 /<''5/7+**,'+YtGt/O/OPW/XtYYYs   AAc                J   | j                   |j                   k(  st        d      | j                  |j                  k(  st        d      t        | j	                  | j
                        d      | _        | j                  d   D ]  \  }} ||g| c S  | j                  |      S )aK
  
        Returns an iterator through correct (possibA, possibB) pairs.

        * If segmentA (self) is a special Segment, meaning that one of the Segment
          resolution methods in :meth:`~music21.figuredBass.segment.Segment.specialResolutionRules`
          needs to be applied, then this method returns every correct possibility of segmentA
          matched up with exactly one resolution possibility.

        * If segmentA is an ordinary, non-special Segment, then this method returns every
          combination of correct possibilities of segmentA and correct possibilities of segmentB
          which passes all filters
          in :meth:`~music21.figuredBass.segment.Segment.consecutivePossibilityRules`.

        Two notes on segmentA being a special Segment:

        1. By default, resolution possibilities are not filtered
           using :meth:`~music21.figuredBass.segment.Segment.singlePossibilityRules`
           rules of segmentB. Filter by setting
           :attr:`~music21.figuredBass.rules.Rules.applySinglePossibRulesToResolution` to True.

        2. By default, (possibA, possibB) pairs are not filtered
           using :meth:`~music21.figuredBass.segment.Segment.consecutivePossibilityRules`
           rules of segmentA. Filter by setting
           :attr:`~music21.figuredBass.rules.Rules.applyConsecutivePossibRulesToResolution`
           to True.

        >>> from music21.figuredBass import segment
        >>> segmentA = segment.Segment(bassNote=note.Note('C3'), notationString='')
        >>> segmentB = segment.Segment(bassNote=note.Note('D3'), notationString='4,3')

        Here, an ordinary resolution is being executed, because segmentA is an ordinary Segment.

        >>> consecutivePairs1 = segmentA.allCorrectConsecutivePossibilities(segmentB)
        >>> consecutivePairsList1 = list(consecutivePairs1)
        >>> len(consecutivePairsList1)
        31
        >>> consecutivePairsList1[29]
        ((<...G5>, <...G5>, <...E5>, <...C3>), (<...G5>, <...F5>, <...B4>, <...D3>))

        Here, a special resolution is being executed, because segmentA below is a
        special Segment.

        >>> segmentA = segment.Segment(bassNote=note.Note('D3'), notationString='4,3')
        >>> segmentB = segment.Segment(bassNote=note.Note('C3'), notationString='')
        >>> consecutivePairs2 = segmentA.allCorrectConsecutivePossibilities(segmentB)
        >>> consecutivePairsList2 = list(consecutivePairs2)
        >>> len(consecutivePairsList2)
        6
        >>> consecutivePairsList2[5]
        ((<...G5>, <...F5>, <...B4>, <...D3>), (<...G5>, <...E5>, <...C5>, <...C3>))
        z6Two segments with unequal numParts cannot be compared.z6Two segments with unequal maxPitch cannot be compared.r   T)r   ri   r.   r   r   r   r+   r}   )r5   r~   resolutionMethodargss       r:   r   z*Segment.allCorrectConsecutivePossibilities  s    j !2!22"#[\\("4"44"#[\\.;''5/
+ )-(K(KD(Q$t#H4t44 )R++H55r<   c                P    | j                   d   D ]  \  }}} ||g| |k(  r y y)z
        Takes in a possibility (possibA) from a segmentA (self) and returns True
        if the possibility is correct given
        :meth:`~music21.figuredBass.segment.Segment.singlePossibilityRules`
        from segmentA.
        TF)r,   )r5   r   method	isCorrectr   s        r:   r   z#Segment._isCorrectSinglePossibility  s;     *.)L)LT)R%VY7*T*i7 *S r<   c                R    | j                   d   D ]  \  }}} |||g| |k(  r y y)z
        Takes in a (possibA, possibB) pair from a segmentA (self) and segmentB,
        and returns True if the pair is correct given
        :meth:`~music21.figuredBass.segment.Segment.consecutivePossibilityRules`
        from segmentA.
        TF)r-   )r5   r   possibBr   r   r   s         r:    _isCorrectConsecutivePossibilityz(Segment._isCorrectConsecutivePossibility  s>     *.)Q)QRV)W%VY7G3d3y@ *X r<   c                     t         j                   j                               _         j	                         }|j	                         }t        j                  ||      }t         fd|      S )am  
        An ordinary segment is defined as a segment which needs no special resolution, where the
        segment does not spell out a special chord, for example, a dominant seventh.

        Finds iterators through all possibA and possibB by calling
        :meth:`~music21.figuredBass.segment.Segment.allCorrectSinglePossibilities`
        on self (segmentA) and segmentB, respectively.
        Returns an iterator through (possibA, possibB) pairs for which
        :meth:`~music21.figuredBass.segment.Segment._isCorrectConsecutivePossibility` returns True.

        >>> from music21.figuredBass import segment
        c                6    j                  | d   | d         S Nr   rh   )r   r   r   possibABr5   s    r:   <lambda>z1Segment._resolveOrdinarySegment.<locals>.<lambda>&  s)    t'L'LU]^_U`V^_`Va (M (cr<   )r   r   r   r-   r   r   r   filter)r5   r~   correctAcorrectB	correctABs   `    r:   r}   zSegment._resolveOrdinarySegment  si     4A,,T\\:4<055799;%%h9	 c " 	"r<   c                    t        |d      }|d   D ]  \  }}g }|D ]&  }|j                  t        j                  |             ( t	        | j                         g| }t         j                         |      }	t        fd|	      }	 j                  j                  rt         fd|	      }	 j                  j                  r8t        j                  j                              _        t        fd|	      }	|	c S  t        d      )Nr   Tc                L    t        j                  | d   j                        S )Nrh   )r   r8   )r
   pitchesWithinLimitr.   r   r~   s    r:   r   z0Segment._resolveSpecialSegment.<locals>.<lambda>2  s     0N0N !++1-r<   c                6    j                  | d   | d         S r   r   r   s    r:   r   z0Segment._resolveSpecialSegment.<locals>.<lambda>7  s$    D4Y4Y$QK$QK 5Z 5)r<   c                .    j                  | d         S )Nrh   )r   )r   r   s    r:   r   z0Segment._resolveSpecialSegment.<locals>.<lambda>>  s    H4X4X$QK 5Y 5)r<   z!No standard resolution available.)r   r   r   repeatmapr   zipr   r   'applyConsecutivePossibRulesToResolution"applySinglePossibRulesToResolutionr   r,   ri   )
r5   r~   specialResolutionMethodsresolutionMethodExecutorr   r   r   argresolutionsr   s
   ``        r:   r{   zSegment._resolveSpecialSegment*  s   #01I1#M (@(F$tI  !1!1#!67 .0R0R0TaW`aKD>>@+NI  - I ||CC" $) 	 ||>>:G33H4D4DE;G7" $)	 + )G. BCCr<   )C3NNNre   B5N)
r   zstr | note.Noter6   z
str | Noner7   z%realizerScale.FiguredBassScale | Noner   zrules.Rules | Noner8   str | pitch.PitchN)F)__name__
__module____qualname__
_DOC_ORDERr    __annotations__r;   r   r   r   r   r   r   r   r   r   r   r   r}   r{    r<   r:   r   r   #   s    2J4%a ]@a%!I~ , ,0,0@D-1-1#P;(P;!)P; >P; +	P; +P;j7!rP&dM^a:FE:NS:j%-NZB?6H

",Dr<   r   c                      e Zd ZdZd Zy)OverlaidSegmentzF
    Class to allow Segments to be overlaid with non-chord notes.
    c                n   | j                   g| j                  dz
  z  }|j                  t        j                  | j
                  j                  j                        g       | j                  j                  D ]+  \  }}t        j                  |j                        g||dz
  <   - t        j                  | S )Nrh   )r   r   r   r   r&   r   r   r   _partPitchLimitsr   r   )r5   r   
partNumber	partPitchs       r:   r   z&OverlaidSegment.allSinglePossibilitiesK  s    --.$--!2CD	%++dmm&9&9&H&HIJK'+||'D'D#Z).Y5M5M)N(OIj1n% (E  ),,r<   N)r   r   r   __doc__r   r   r<   r:   r   r   F  s    -r<   r   c                   t        t              rt        j                        t        t              rt        j                        j                  t        d      t        j                  | t        j                  dz               }t        d |      }t        j                  fd|      }t        j                  fd|      }t        |      }|j                          |S )a  
    Given a list of pitchNames, a bassPitch, and a maxPitch, returns a sorted list of
    pitches between the two limits (inclusive) which correspond to items in pitchNames.

    >>> from music21.figuredBass import segment
    >>> pitches = segment.getPitches()
    >>> print(', '.join([p.nameWithOctave for p in pitches]))
    C3, E3, G3, C4, E4, G4, C5, E5, G5, C6, E6, G6, C7, E7, G7, C8

    >>> pitches = segment.getPitches(['G', 'B', 'D', 'F'], bassPitch=pitch.Pitch('B2'))
    >>> print(', '.join([p.nameWithOctave for p in pitches]))
    B2, D3, F3, G3, B3, D4, F4, G4, B4, D5, F5, G5, B5, D6, F6, G6, B6, D7, F7, G7, B7

    >>> pitches = segment.getPitches(['F##', 'A#', 'C#'], bassPitch=pitch.Pitch('A#3'))
    >>> print(', '.join([p.nameWithOctave for p in pitches]))
    A#3, C#4, F##4, A#4, C#5, F##5, A#5, C#6, F##6, A#6, C#7, F##7, A#7

    The maxPitch must have an octave:

    >>> segment.getPitches(maxPitch=pitch.Pitch('E'))
    Traceback (most recent call last):
    ValueError: maxPitch must be given an octave
    z maxPitch must be given an octaverh   c                P    t        j                  | d   t        | d         z         S )Nr   rh   )r   r&   r$   )xs    r:   r   zgetPitches.<locals>.<lambda>w  s    %++adS1Y&67r<   c                    | kD  S r   r   )samplePitch	bassPitchs    r:   r   zgetPitches.<locals>.<lambda>x  s
    i+6Mr<   c                    | kD  S r   r   )r   r8   s    r:   r   zgetPitches.<locals>.<lambda>y  s
    kH6Lr<   )r#   r$   r   r&   octave
ValueErrorr   r   ranger   filterfalselistsort)
pitchNamesr   r8   iter1iter2iter3iter4
allPitchess    ``     r:   r0   r0   U  s    4 )S!KK	*	(C ;;x(;<<j%!0C*DEE7?E!!"MuUE!!"LeTEeJOOr<   c                    | j                         }| j                         }| j                  d      }| j                  d      }| j                  d      }|||||g}|S )Nr   r   r   r   rq   getChordStep)seventhChordr   rq   thirdfifthseventhseventhChordInfos          r:   rj   rj     se    DD%%a(E%%a(E''*GdE5':r<   c                    | j                         }| j                         }| j                  d      }| j                  d      }||||g}|S )Nr   r   r   )threePartChordr   rq   r   r  threePartChordInfos         r:   rY   rY     sS     D D''*E''*EeU3r<   c                @   t        j                  t              }t        t	        |             D ]m  }g }t	        | |         |k(  r| |   d   }|dk(  r$| |   dd \  }}}||   j                  |||f       G|dk(  sM| |   dd \  }}||   j                  ||f       o |S )Nre   r   r   rg   )collectionsdefaultdictr   r   lenr   )	rulesList	maxLengthruleChecking	ruleIndexr   shouldRunMethodr   r   s           r:   r   r     s    **40L3y>*	y#$	1Y'+D>3<Y3G!3L0_fi)00&)T1JK!^(1)(<Qq(A%_f)00&$@ + r<   c                   d| D ]9  }t        |d   j                        k\  st        |d   j                        dz   ; fd}dddz
  z  z   }|dk(  rt        d	| d
       n|dk(  rt        d	| d       t        t        |             D ]  }d}g }t        | |         |k(  r| |   d   }|sd}nCd}t        t        |            D ]*  }	|t	        ||	         z  }|	t        |      dz
  k(  r&|dz  }, |dk(  r3| |   dd \  }
}} ||      }t	        |
      d| t	        |      d| }n*|dk(  r%| |   dd \  }
} ||      }t	        |
      d| | }t        |        y)a  
    Method which can print to the console rules inputted into
    :meth:`~music21.figuredBass.segment.Segment.singlePossibilityRules`,
    :meth:`~music21.figuredBass.segment.Segment.consecutivePossibilityRules`, and
    :meth:`~music21.figuredBass.segment.Segment.specialResolutionRules`.
    For the first two methods, maxLength is 4. For the third method, maxLength is 3.

    OMIT_FROM_DOCS
    maxLength is the maximum length of a rule, a rule which includes arguments,
    because arguments are optional.
       rh   rg   c                j    | j                   d }t        |      k  r|dt        |      z
  z  z  }|S )Nr    )r   r  )m
methodNameMAX_SIZEs     r:   	padMethodzprintRules.<locals>.padMethod  s=    ZZ(+
z?X%#C
O!;<<Jr<   zMethod:r  r   re   zWill run:  z(Keep solutions which return:  Arguments:r   z
Arguments:Nr  None z, r   1130)r  r   printr   r$   )r  r  ruler  	methodStrr  ruleToPrintr   
argsString	itemIndexr  r   r   r  s                @r:   
printRulesr#    s    HtAw H,47++,q0H  C8a<00IA~I;&NOP	aI;j123y>*	y#$	1Y'+DJJ"3t9-	c$y/22
 CIM1$&J . >3<Y3G!3L0_fiv&F 1"5fXc)nR=PQ[P\]K!^(1)(<Qq(A%_fv&F 1"5fXj\JKk+ +r<   c                      e Zd Zy)ri   Nr   r   r   r   r<   r:   ri   ri         r<   ri   c                      e Zd Zy)TestNr%  r   r<   r:   r(  r(    r&  r<   r(  __main__))CEGr   C8)r   r   r8   r   )re   )"
__future__r   r	  r)   r   unittestmusic21r   r   r   r   r   r	   music21.figuredBassr
   r   r   r   r3   r   r   r   r   r0   rj   rY   r   r#  Music21Exceptionri   TestCaser(  r   mainTestr   r<   r:   <module>r5     s    #            + - * %  TI E 
`D `DF
-g 
- *,0+/')'('T 2j	|44 		8 	 zGT r<   