
    3js0                       d Z ddlmZ ddlZddl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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m Z   ejB                  d      Z" G d dejF                        Z$ G d dejJ                  e$      Z& G d dejN                  e$      Z( G d de(      Z) G d d e)      Z* G d! d"e(      Z+ G d# d$e(      Z, G d% d&ejZ                  e$      Z. G d' d(e.      Z/ G d) d*e.      Z0 G d+ d,e.      Z1 G d- d.ejd                  e$      Z3 G d/ d0e3      Z4 G d1 d2e3      Z5 G d3 d4e3      Z6 G d5 d6ejn                  e$      Z8 G d7 d8e8      Z9 G d9 d:e8      Z: G d; d<ejv                  e$      Z< G d= d>e<      Z= G d? d@e<      Z> G dA dBej~                  e$      Z@ G dC dDe@      ZA G dE dFej                  e$      ZC G dG dHeC      ZD G dI dJej                  e$      ZF G dK dLeF      ZG G dM dNe	j                        ZI G dO dPe	j                        ZJe/e0e1e9e:e)e*e+e,e>e=eAe4e5e6eDgZKeLdQk(  rddlZ ej                  eJ       yy)Ra!  
Object definitions for plotting :class:`~music21.stream.Stream` objects.

The :class:`~music21.graph.plot.PlotStream`
object subclasses combine a Graph object with the PlotStreamMixin to give
reusable approaches to graphing data and structures in
:class:`~music21.stream.Stream` objects.
    )annotationsN)	correlate)discrete)	reduction)windowed)base)chord)common)corpus)	converter)dynamics)environment)features)note)prebase)stream)axis)
primitives)GraphExceptionPlotStreamExceptionz
graph.plotc                      e Zd ZU dZej
                  ej
                  dZded<   ddZddZ	e
d	        Zdd
ddZd Zd ZddZ	 	 	 	 	 	 	 	 ddZd Zed        Zd Zedd       Ze
d        Zy)PlotStreamMixinzj
    This Mixin adds Stream extracting and Axis holding features to any
    class derived from Graph.
    xydict[str, type[axis.Axis]]axesClassesNTc                ,   |t        |d      st        d|       || _        || _        ddg| _        d| _        d | _        | j                  j                         D ]/  \  }}|	 || |      }t        | d|j                         z   |       1 || _        y )Nelementsz!non-stream provided as argument: NoteChordTr   )hasattrr   	streamObjrecurseclassFilterListmatchPitchCountForChordsdatar   itemssetattruppersavedKeywords)selfr#   r$   keywordsaxisName	axisClassaxisObjs          ?/DATA/.local/lib/python3.12/site-packages/music21/graph/plot.py__init__zPlotStreamMixin.__init__C   s     J)G%(I)&UVV" &0(,%	#'#3#3#9#9#;Hi$#D(3fx~~'77A $<
 &    c                D    | j                   }|t        |      }nd}d| S )av  
        The representation of the Plot shows the stream repr
        in addition to the class name.

        >>> st = stream.Stream()
        >>> st.id = 'empty'
        >>> plot = graph.plot.ScatterPitchClassQuarterLength(st)
        >>> plot
        <music21.graph.plot.ScatterPitchClassQuarterLength for <music21.stream.Stream empty>>

        >>> plot = graph.plot.ScatterPitchClassQuarterLength(None)
        >>> plot
        <music21.graph.plot.ScatterPitchClassQuarterLength for (no stream)>

        >>> plot.axisX
        <music21.graph.axis.QuarterLengthAxis: x axis for ScatterPitchClassQuarterLength>

        >>> plot.axisY
        <music21.graph.axis.PitchClassAxis: y axis for ScatterPitchClassQuarterLength>

        >>> axIsolated = graph.axis.DynamicsAxis(axisName='z')
        >>> axIsolated
        <music21.graph.axis.DynamicsAxis: z axis for (no client)>
        z(no stream)zfor )r#   repr)r,   s
streamNames      r1   _reprInternalzPlotStreamMixin._reprInternalU   s-    4 NN=aJ&Jj\""r3   c                h    g }dD ]*  }t        | |      s|j                  t        | |             , |S )a  
        return a list of axisX, axisY, axisZ if any are defined in the class.

        Some might be None.

        >>> s = stream.Stream()
        >>> p = graph.plot.ScatterPitchClassOffset(s)
        >>> p.allAxes
        [<music21.graph.axis.OffsetAxis: x axis for ScatterPitchClassOffset>,
         <music21.graph.axis.PitchClassAxis: y axis for ScatterPitchClassOffset>]
        )axisXaxisYaxisZ)r"   appendgetattr)r,   allAxesListr.   s      r1   allAxeszPlotStreamMixin.allAxesw   s:     3HtX&""74#:; 4 r3   callProcessc               r   t         j                  r$ddlm} t	        | |      rt	        | t
              sJ | j                          | j                          t        | d      r\| j                  rP| j                  d| j                  j                                | j                  d| j                  j                         t        | d      r\| j                  rP| j                  d| j                  j                                | j                  d| j                  j                         |r| j                          yy)z
        main routine to extract data, set axis labels, run process() on the underlying
        Graph object, and if self.doneAction is not None, either write or show the graph.
        r   )Graphr;   r   r:   r   N)tTYPE_CHECKINGmusic21.graph.primitivesrD   
isinstancer   setAxisKeywordsextractDatar"   r;   setTickstickssetAxisLabellabelr:   process)r,   rB   r-   rD   s       r1   runzPlotStreamMixin.run   s    
 ??6dE*z$/PPP4!djjMM#tzz//12c4::#3#344!djjMM#tzz//12c4::#3#34LLN r3   c                (   | j                   D ]  }||j                  }| j                  D ]c  }|j                  |      st	        |      dk  r$|d   j                         |dd z   }t        ||      sJt        ||| j                  |          e  y)a  
        Configure axis parameters based on keywords given when creating the Plot.

        Looks in self.savedKeywords, in case any post creation manipulation needs
        to happen.

        Finds keywords that begin with x, y, z and sets the remainder of the
        keyword (lowercasing the first letter) as an attribute.  Does not
        set any new attributes, only existing ones.

        >>> b = corpus.parse('bwv66.6')
        >>> hist = graph.plot.HistogramPitchSpace(b, xHideUnused=False)
        >>> hist.axisX.hideUnused
        True
        >>> hist.setAxisKeywords()
        >>> hist.axisX.hideUnused
        False
        N         )r@   r.   r+   
startswithlenlowerr"   r)   )r,   thisAxisthisAxisLetterkwshortKws        r1   rI   zPlotStreamMixin.setAxisKeywords   s    & H%..N((}}^4r7Q;Q%++-"QR&0x1'4+=+=b+AB )	 %r3   c                <   d | j                   v rt        d      | j                  r| j                  j                         }n| j                  j	                         }| j
                  r|j                  | j
                        }g | _        |D ]1  }| j                  |      }|| j                  j                  |       3 | j                          t        | j                         D ]1  \  }}|j                  | j                  D cg c]  }||   	 c}       3 y c c}w )Nz3Set all axes before calling extractData() via run())r@   r   r$   r#   iterr%   getElementsByClassr'   processOneElementextendpostProcessData	enumeratesetBoundariesFromData)r,   sItereldataListirX   ds          r1   rJ   zPlotStreamMixin.extractData   s    4<<%&[\\<<NN**,ENN'')E,,T-A-ABE	B--b1H#		  * 
 	$T\\2KAx**$))+D)QAaD)+DE 3+Ds   D
c                p   t        t        | j                              D cg c]  }g  }}i }t        |t        j
                        sJt        | j                        D ]1  \  }}|j                  ||      }t        |t              s||g}|||<   3 n| j                  ||      } | j                  ||g|  d|v ryt        |D cg c]  }t        |       c}      }	t        |	      D cg c]  }|j                          }
}|j                  |
       t        t        |       }|S c c}w c c}w c c}w )a  
        Get a list of data from a single element (generally a Note or chord):

        >>> n = note.Note('C#4')
        >>> n.offset = 10.25
        >>> s = stream.Stream([n])
        >>> pl = graph.plot.ScatterPitchClassOffset(s)
        >>> pl.processOneElement(n)
        [(10.25, 1, {})]

        >>> c = chord.Chord(['D4', 'E5'])
        >>> s.insert(5.0, c)
        >>> pl.processOneElement(c)
        [(5.0, 2, {}), (5.0, 4, {})]
        N)rangerV   r@   rH   r	   r!   rb   extractOneElementlistextractChordDataMultiAxispostProcessElementmaxcopyr=   zip)r,   re   _elementValues
formatDictrg   rX   	axisValueevelementValueLengthformatDictList
returnLists               r1   r_   z!PlotStreamMixin.processOneElement   s1     9>c$,,>O8P+Q8P1B8P+Q)+
 "ekk*(68$66r:F	
 ")T2y7L!*I#,a   7 !::2zJMJ??=  M!BMb#b'M!BC5:;M5NO5N*//+5NO^,#}-.
3 ,R* "COs   	D)D.,D3c                     y)z
        Any processing that needs to take place for each element, independent
        of what the axis is finding can go here.  For chords, a single
        formatDict applies to all pitches/notes in the chord.
        N )r,   re   rt   valuess       r1   rn   z"PlotStreamMixin.postProcessElement  s     	r3   c                F    | j                   D ]  }|j                           y)N
        Call any post data processing routines here and on any axes.
        N)r@   ra   )r,   rX   s     r1   ra   zPlotStreamMixin.postProcessData  s     H$$& %r3   c                    g }d}	 | j                  ||      }||j                  |       |s0|D ]+  }d}	 | j                  ||      }||j                  |       - |S # t        $ r Y Rw xY w# t        $ r Y  |S w xY w)z
        Look for Note-like attributes in a Chord. This is done by first
        looking at the Chord, and then, if attributes are not found, looking at each pitch.

        Returns a list of values.
        N)rk   AttributeErrorr=   )axcrt   r|   valuens         r1   extractChordDataOneAxisz'PlotStreamMixin.extractChordDataOneAxis  s     	((J7E MM% 00J?E $MM%(  #  		 &  s"   A A.	A+*A+.	A<;A<c                   | j                   D cg c]  }| j                  |||       }}g }t        | j                   |      D ]  \  }}|r	|j                  ||f        |D ]3  \  }}|D ])  }		 |j	                  |	|      }
|
|j                  |
       + 5 | j                  r| j                  |       |S c c}w # t
        $ r Y ]w xY w)zB
        Returns a list of lists of values for each axis.
        )r@   r   rq   r=   rk   r   r&   fillValueLists)r,   r   rt   r   rs   lookIntoChordForNotesGroupsrX   r|   
destValuesr   targets              r1   rm   z)PlotStreamMixin.extractChordDataMultiAxis9  s     TXS_S_`S_R55b!ZHS_`&(# #DLL- @Hf+22Hf3EF !A %@ Hj%77:FF %%%f-  %@ ((.1 a & s   B8/B==	C	C	c                    t        | D cg c]  }t        |       c}      }| D ]&  }|t        |      z
  }|r|d   }n|}|s||g|z  z  }( yc c}w )a2  
        pads a list of lists so that each list has the same length.
        Pads with the first element of the list or nullFillValue if
        the list has no elements.   Modifies in place so returns None

        Used by extractChordDataMultiAxis

        >>> l0 = [2, 3, 4]
        >>> l1 = [10, 20, 30, 40, 50]
        >>> l2 = []
        >>> listOfLists = [l0, l1, l2]
        >>> graph.plot.PlotStream.fillValueLists(listOfLists)
        >>> listOfLists
        [[2,   3,  4,  2,  2],
         [10, 20, 30, 40, 50],
         [0,   0,  0,  0,  0]]
        r   N)ro   rV   )rs   nullFillValueval	maxLengthshortAmountfillVals         r1   r   zPlotStreamMixin.fillValueListsW  sc    & ];]cS];<	 C#c#h.Ka&'y;.. ! <s   Ac                t    | j                   }| j                  D ]  }||j                  d   }|d|z   z  } |S )a"  
        Each PlotStream has a unique id that consists of its class name and
        the class names of the axes:

        >>> s = stream.Stream()
        >>> pScatter = graph.plot.ScatterPitchClassQuarterLength(s)
        >>> pScatter.id
        'scatter-quarterLength-pitchClass'
        r   -)	graphTyper@   
quantities)r,   idNamer0   r.   s       r1   idzPlotStreamMixin.idu  sH     ||G))!,HcHn$F	 $ r3   )NT)returnstrrB   bool)re   base.Music21Object)re   r   rt   dict[t.Any, t.Any]r|   list[numbers.Real]r   None)r   )__name__
__module____qualname____doc__r   Axisr   __annotations__r2   r8   propertyr@   rP   rI   rJ   r_   rn   ra   staticmethodr   rm   r   r   r{   r3   r1   r   r   <   s     59IIDII.NK+N&$ #D  $ *. , CHF0)V	1	'9	 %7	 <@	'  << / /:  r3   r   c                      e Zd ZdZddZy)
PlotStreamz#
    A generic stream plotter.
    Nc                    t        j                  j                  | fi | t        j                  | |fi | t	        j
                  | d      | _        y )Nr   )r   rD   r2   r   r   
OffsetAxisr:   r,   r#   r-   s      r1   r2   zPlotStream.__init__  sB    !!$3(3  y=H=__T3/
r3   Nr   r   r   r   r2   r{   r3   r1   r   r     s    0r3   r   c                      e Zd ZdZddZy)Scatterz*
    Base class for 2D scatter plots.
    Nc                r    t        j                  j                  | fi | t        j                  | |fi | y r   )r   GraphScatterr2   r   r   s      r1   r2   zScatter.__init__  s0    ((::  y=H=r3   r   r   r{   r3   r1   r   r     s    >r3   r   c                  b     e Zd ZU dZej
                  ej                  dZded<   d fd	Z	 xZ
S )ScatterPitchSpaceQuarterLengthaX  
    A scatter plot of pitch space and quarter length

    >>> s = corpus.parse('bach/bwv324.xml')
    >>> p = graph.plot.ScatterPitchSpaceQuarterLength(s)
    >>> p.doneAction = None #_DOCS_HIDE
    >>> p.id
    'scatter-quarterLength-pitchSpace'
    >>> p.run()

    .. image:: images/ScatterPitchSpaceQuarterLength.*
        :width: 600
    r   r   r   c                v    t        |   |fi | d| j                  _        d|vrd| _        d|vrd| _        y y )NT
figureSize   r   titlezPitch by Quarter Length Scatter)superr2   r:   useLogScaler   r   r,   r#   r-   	__class__s      r1   r2   z'ScatterPitchSpaceQuarterLength.__init__  sD    /h/!%

x'$DO(":DJ #r3   r   )r   r   r   r   r   QuarterLengthAxisPitchSpaceAxisr   r   r2   __classcell__r   s   @r1   r   r     s5     ##  /K+ 
; ;r3   r   c                  b     e Zd ZU dZej
                  ej                  dZded<   d fd	Z	 xZ
S )ScatterPitchClassQuarterLengtha  
    A scatter plot of pitch class and quarter length

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.ScatterPitchClassQuarterLength(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.ScatterPitchClassQuarterLength(s)
    >>> p.id
    'scatter-quarterLength-pitchClass'
    >>> p.run()

    .. image:: images/ScatterPitchClassQuarterLength.*
        :width: 600
    r   r   r   c                >    t        |   |fi | d|vrd| _        y y )Nr   z%Pitch Class by Quarter Length Scatter)r   r2   r   r   s      r1   r2   z'ScatterPitchClassQuarterLength.__init__  s)    /h/("@DJ #r3   r   )r   r   r   r   r   r   PitchClassAxisr   r   r2   r   r   s   @r1   r   r     s7     ##  /K+ 
A Ar3   r   c                  b     e Zd ZU dZej
                  ej                  dZded<   d fd	Z	 xZ
S )ScatterPitchClassOffseta  
    A scatter plot of pitch class and offset

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.ScatterPitchClassOffset(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.ScatterPitchClassOffset(s)
    >>> p.id
    'scatter-offset-pitchClass'
    >>> p.run()

    .. image:: images/ScatterPitchClassOffset.*
        :width: 600
    r   r   r   c                j    t        |   |fi | d|vrd| _        d|vrd| _        d|vrd| _        y y )Nr   )
      r   zPitch Class by Offset Scatteralphaffffff?r   r2   r   r   r   r   s      r1   r2   z ScatterPitchClassOffset.__init__  sI    /h/ x'%DO("8DJ("DJ #r3   r   )r   r   r   r   r   r   r   r   r   r2   r   r   s   @r1   r   r     s3     __  /K+ 
	 	r3   r   c                  l     e Zd ZU dZdZej                  ej                  dZde	d<   d fd	Z
d Z xZS )	ScatterPitchSpaceDynamicSymbolaH  
    A graph of dynamics used by pitch space.

    >>> s = converter.parse('tinynotation: 4/4 C4 d E f', makeNotation=False) #_DOCS_HIDE
    >>> s.insert(0.0, dynamics.Dynamic('pp')) #_DOCS_HIDE
    >>> s.insert(2.0, dynamics.Dynamic('ff')) #_DOCS_HIDE
    >>> p = graph.plot.ScatterPitchSpaceDynamicSymbol(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('schumann_robert/opus41no1/movement2.xml')
    >>> #_DOCS_SHOW p = graph.plot.ScatterPitchSpaceDynamicSymbol(s)
    >>> p.run()

    .. image:: images/ScatterPitchSpaceDynamicSymbol.*
        :width: 600
    )   r   r   r   r   c                    t        |   |fi | d| j                  _        d|vr| j                  | _        d|vrd| _        d|vrd| _        y y )NFr   r   zDynamics by Pitch Scatterr   r   )r   r2   r:   showEnharmonicfigureSizeDefaultr   r   r   r   s      r1   r2   z'ScatterPitchSpaceDynamicSymbol.__init__  sY    /h/$)

!x'"44DO("4DJ("DJ #r3   c                   t        j                  | j                        }|j                  d      }g | _        |D ]#  \  }}| j                  j                  ||i f       % | j                  D cg c]  }|d   	 }}| j                  D cg c]  }|d   	 }}| j                  j                  |       | j                  j                  |       | j                          y c c}w c c}w )NT
dataPointsr   rS   )
r   ActivityMatchr#   pitchToDynamicr'   r=   r:   rc   r;   ra   )r,   amamDatar   r   rh   xValsyValss           r1   rJ   z*ScatterPitchSpaceDynamicSymbol.extractData  s    $$T^^4""d"3	DAqIIaBZ(   $yy)y!1y)#yy)y!1y)

((/

((/ *)s   /C C%r   )r   r   r   r   r   r   r   DynamicsAxisr   r   r2   rJ   r   r   s   @r1   r   r     s;        /K+ 

r3   r   c                  j    e Zd ZU dZej
                  ej                  dZded<   ddZ	dddd	Z
d
 Zy)	HistogramzH
    Base class for histograms that plot one axis against its count
    r   r   r   Nc                    t        j                  j                  | fi | t        j                  | |fi | d|vrd| _        y y )Nr         ?)r   GraphHistogramr2   r   r   r   s      r1   r2   zHistogram.__init__:  sD    !!**4<8<  y=H=("DJ #r3   TrA   c                  t         j                  rt        | d      rt        | d      sJ | j                          | j	                          | j                  d| j                  j                                | j                         }| j                  d|       | j                  d| j                  j                         | j                  d| j                  j                         |r| j                          yy)zK
        Override run method to remap X data into individual bins.
        r:   r;   r   r   N)rE   rF   r"   rI   rJ   rK   r;   rL   remapXTicksDatarM   rN   r:   rO   )r,   rB   r-   	xTicksNews       r1   rP   zHistogram.runA  s     ??4)gdG.DDDc4::++-.((*	c9%#tzz//0#tzz//0LLN r3   c                   | j                   j                         }|D ci c]  }|d   |d    }}g }t        | j                   d      rD| j                   j                  du s,| j                   j                  | j                   j
                  rt        t        | j                              D ]O  }| j                  |   }|d   }|dz   f|dd z   | j                  |<   ||v s5|dz   ||   f}|j                  |       Q |S ddl
m}	 t        t        | j                   j                        t        | j                   j
                        dz         D ]k  }||v r||   }
nJt        | j                   d      r2| j                   j                  s|	j                  |      j                  }
nd}
||
f}|j                  |       m |S c c}w )	z[
        Changes the ticks and data so that they both run
        1, 2, 3, 4, etc.
        r   rS   
hideUnusedTN)pitchblankLabelUnused )r:   rL   r"   r   minValuemaxValuerj   rV   r'   r=   music21r   intr   Pitchname)r,   
xTicksOrigv	xTickDictr   rg   dataValxDataValnewTickr   rN   s              r1   r   zHistogram.remapXTicksDataS  s    ZZ%%'
)34AQqT1Q4Z	4	\2djj6K6Kt6S::&&.::&&.3tyy>*))A,"1: !Ax'!"+5		!y( 1ui&9:G$$W- +&  &3tzz223S9L9L5MPQ5QR	>%aLETZZ);<TZZE`E`!KKN//EEe*  ) S 3 5s   F>r   r   )r   r   r   r   r   r   CountingAxisr   r   r2   rP   r   r{   r3   r1   r   r   1  s<     YY/K+ 
 *. $ r3   r   c                  h     e Zd ZU dZi ej
                  dej                  iZded<   d fd	Z	 xZ
S )HistogramPitchSpacea  
    A histogram of pitch space.

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.HistogramPitchSpace(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.HistogramPitchSpace(s)
    >>> p.id
    'histogram-pitchSpace-count'
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/HistogramPitchSpace.*
        :width: 600
    r   r   r   c                v    t        |   |fi | d| j                  _        d|vrd| _        d|vrd| _        y y )NFr   r   r   r   zPitch Histogram)r   r2   r:   r   r   r   r   s      r1   r2   zHistogramPitchSpace.__init__  sD    /h/$)

!x'%DO("*DJ #r3   r   )r   r   r   r   r   r   r   r   r   r2   r   r   s   @r1   r   r   v  s?    /


/T  /K+ 
+ +r3   r   c                  h     e Zd ZU dZi ej
                  dej                  iZded<   d fd	Z	 xZ
S )HistogramPitchClassa  
    A histogram of pitch class

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.HistogramPitchClass(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.HistogramPitchClass(s)
    >>> p.id
    'histogram-pitchClass-count'
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/HistogramPitchClass.*
        :width: 600

    r   r   r   c                `    t        |   |fi | d| j                  _        d|vrd| _        y y )NFr   zPitch Class Histogram)r   r2   r:   r   r   r   s      r1   r2   zHistogramPitchClass.__init__  s5    /h/$)

!("0DJ #r3   r   )r   r   r   r   r   r   r   r   r   r2   r   r   s   @r1   r   r     s?    /


/T  /K+ 
1 1r3   r   c                  h     e Zd ZU dZi ej
                  dej                  iZded<   d fd	Z	 xZ
S )HistogramQuarterLengtha  
    A histogram of pitch class.

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.HistogramQuarterLength(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.HistogramQuarterLength(s)
    >>> p.id
    'histogram-quarterLength-count'
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/HistogramQuarterLength.*
        :width: 600

    r   r   r   c                    t        |   |fi | t        j                  | d      | _        d| j                  _        d|vrd| _        y y )Nr   Fr   zQuarter Length Histogram)r   r2   r   r   r:   r   r   r   s      r1   r2   zHistogramQuarterLength.__init__  sI    /h/++D#6
!&

("3DJ #r3   r   )r   r   r   r   r   r   r   r   r   r2   r   r   s   @r1   r   r     s?    /


/T##/K+ 
4 4r3   r   c                  l    e Zd ZU dZej
                  ej
                  ej                  dZded<   ddZ	y)ScatterWeightedz
    Base class for histograms that plot one axis against its count.

    The count is stored as the Z axis, though it is represented as size.
    r   r   zr   r   Nc                    t        j                  j                  | fi | t        j                  | |fi | d| j                  _        y Nr   )r   GraphScatterWeightedr2   r   r<   	countAxesr   s      r1   r2   zScatterWeighted.__init__  s<    ''00BB  y=H=)

r3   r   )
r   r   r   r   r   r   r   r   r   r2   r{   r3   r1   r  r    s4     YYYY/K+ *r3   r  c                  ~     e Zd ZU dZi ej
                  ej                  ej                  dZde	d<   d fd	Z
 xZS )&ScatterWeightedPitchSpaceQuarterLengtha  
    A graph of event, sorted by pitch, over time.

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.ScatterWeightedPitchSpaceQuarterLength(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.ScatterWeightedPitchSpaceQuarterLength(s)
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/ScatterWeightedPitchSpaceQuarterLength.*
        :width: 600
    r   r   r   c                j    t        |   |fi | d|vrd| _        d|vrd| _        d|vrd| _        y y )Nr      r  r   z!Count of Pitch and Quarter Lengthr   皙?r   r   s      r1   r2   z/ScatterWeightedPitchSpaceQuarterLength.__init__  sO    	#!	# x'$DO("<DJ("DJ #r3   r   )r   r   r   r   r  r   r   r   r   r   r2   r   r   s   @r1   r
  r
    sF    /

%
%/##  /K+ 	 	r3   r
  c                  ~     e Zd ZU dZi ej
                  ej                  ej                  dZde	d<   d fd	Z
 xZS )&ScatterWeightedPitchClassQuarterLengtha  
    A graph of event, sorted by pitch class, over time.

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.ScatterWeightedPitchClassQuarterLength(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.ScatterWeightedPitchClassQuarterLength(s)
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/ScatterWeightedPitchClassQuarterLength.*
        :width: 600

    r   r   r   c                j    t        |   |fi | d|vrd| _        d|vrd| _        d|vrd| _        y y )Nr   r  r   'Count of Pitch Class and Quarter Lengthr   r  r   r   s      r1   r2   z/ScatterWeightedPitchClassQuarterLength.__init__  sO    	#!	# x'$DO("BDJ("DJ #r3   r   )r   r   r   r   r  r   r   r   r   r   r2   r   r   s   @r1   r  r    sF    /

%
%/##  /K+ 
 
r3   r  c                       e Zd ZU dZi ej
                  ej                  ej                  dZde	d<   d fd	Z
d Z xZS )&ScatterWeightedPitchSpaceDynamicSymbola  
    A graph of dynamics used by pitch space.

    >>> #_DOCS_SHOW s = corpus.parse('schumann_robert/opus41no1/movement2.xml')
    >>> s = converter.parse('tinynotation: 4/4 C4 d E f', makeNotation=False) #_DOCS_HIDE
    >>> s.insert(0.0, dynamics.Dynamic('pp')) #_DOCS_HIDE
    >>> s.insert(2.0, dynamics.Dynamic('ff')) #_DOCS_HIDE
    >>> p = graph.plot.ScatterWeightedPitchSpaceDynamicSymbol(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW p = graph.plot.ScatterWeightedPitchSpaceDynamicSymbol(s)
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/ScatterWeightedPitchSpaceDynamicSymbol.*
        :width: 600

    r   r   r   c                    t        |   |fi | d| j                  _        d|vrd| _        d|vrd| _        d|vrd| _        d|vrd	| _        y y )
NFr   )r   r   r   r  r   r  tickFontSizer  )r   r2   r:   r   r   r   r   r  r   s      r1   r2   z/ScatterWeightedPitchSpaceDynamicSymbol.__init__9  sm    	#!	# %*

! x'&DO("BDJ("DJ) !D *r3   c                   t        j                  | j                        }|j                  d      | _        | j                  D cg c]  \  }}|	 }}}| j                  D cg c]  \  }}|	 }}}| j                  D cg c]
  \  }}||dg c}}| _        | j
                  j                  |       | j                  j                  |       | j                          y c c}}w c c}}w c c}}w )NTr   rS   )	r   r   r#   r   r'   r:   rc   r;   ra   )r,   r   r   unused_yr   unused_xr   r   s           r1   rJ   z2ScatterWeightedPitchSpaceDynamicSymbol.extractDataJ  s    $$T^^4%%%6	&*ii0i{q(i0&*ii0i{xi0+/995941aaAY95	

((/

((/ 105s   C!$C'C-r   )r   r   r   r   r  r   r   r   r   r   r2   rJ   r   r   s   @r1   r  r  #  sF    /

%
%/  /K+ ""
r3   r  c                       e Zd ZU dZdZej                  j                  dz   Zdej                  iZ
ded<   ej                  Zded<   dd	Zed
        ZddddZd Zd Zd fd	Z xZS )WindowedAnalysiszS
    Base Plot for windowed analysis routines such as Key Analysis or Ambitus.
    	colorGrid)	minWindow	maxWindow
windowStep
windowTypecompressLegendprocessorClassgraphLegendr   r   r   ztype[discrete.DiscreteAnalysis]processorClassDefaultc                ,   | j                   | _        d | _        d | _        d| _        d | _        d| _        d| _        d| _        t        j                  j                  | fi | t        j                  | |fi | t        j                  | d      | _        y )NrS   pow2overlapTr   )r$  r"  
_processorr#  r  r  r  r   r!  r   GraphColorGridr2   r   r   r   r:   r   s      r1   r2   zWindowedAnalysis.__init__h  s    "88 #"!!**4<8<  y=H=__T3/
r3   c                    | j                   sy | j                  s | j                  | j                        | _        | j                  S r   )r"  r(  r#   )r,   s    r1   	processorzWindowedAnalysis.processorx  s5    """11$..ADOr3   TrA   c                  | j                   dk(  rF| j                  r:| j                  j                  d| j                  j                          dz   | _         | j	                         \  }}|| _        | j                  d|       | j                  j                          | j                  j                         }t        |      dk\  rd|d   d   fd|d   d   fg}t        j                  d	|g       | j                  d
|       | j                  dd       | j                  d
d| j                  j                   d       | j                         | _        |r| j#                          yy)z-
        Actually creates the graph.
        zMusic21 Graphz ()r   rT   r   rS   xTicksr   zWindow Size
(Quarter Lengths)z	Windows (z Span)N)r   r+  r   solutionUnitStringrJ   r'   rK   r:   rc   rL   rV   environLocal
printDebugrM   rN   
_getLegendr#  rO   )r,   rB   r-   r'   yTicksr/  s         r1   rP   zWindowedAnalysis.run  s8    ::(T^^..-- !B!B!D EQGHDJ '')f	c6"

((*!!#v;!&)A,'!VBZ]);<F6 23c6"#?@#4::+;+;*<FCD??,LLN r3   c                X   t        j                  | j                  | j                        }|j	                  | j
                  | j                  | j                  | j                        \  }}}t        |      dkD  r#t        dt        |      t        |      dz        }nt        t        |            }t        j                  d|g       d}g }|D ]W  }||   d   }	|j                  |dg       |j                  |dz   t        |	      g       |j                  |dz   dg       |d	z  }Y ||fS )
z
        Extract data actually calls the processing routine.

        Returns two element tuple of the data (colorMatrix) and the yTicks list
        )r   r   r   	tickRange
windowSizer   rS   rT   rR   )r   r  r#   r+  rO   r  r  r  r   rV   rj   r1  r2  r=   r   )
r,   waunused_solutionMatrixcolorMatrix
metaMatrixr6  posr4  r   thisWindowSizes
             r1   rJ   zWindowedAnalysis.extractData  s    &&t~~t~~F9;DNNDHNNDHOOOS :D :`6{J z?RaZ#j/R2GHIc*o.Ii 89 A']<8NMM3)$MM37C$789MM37B-(1HC  F""r3   c                    t        j                  d| j                        }| j                  j	                  | j
                        }||_        |S )zB
        Returns a solution legend for a WindowedAnalysis
        N
doneActionr   )compress)r   GraphColorGridLegendr   r+  solutionLegendr!  r'   )r,   r#  	graphDatas      r1   r3  zWindowedAnalysis._getLegend  sI     !55<@JJHNN114;N;N1O	$r3   c                z   t         |   |       |t        j                  dd      }nt	        j
                  |d      }t        j                  j                  |      \  }}t        j                  j                  |d|z         }| j                  j                          | j                  j                  |       y)zI
        Overrides the normal write method here to add a legend.
        N.pngT)returnPathlibzlegend-)r   writer1  getTempFiler
   	cleanpathospathsplitjoinr#  rO   )r,   fp	directoryfnfpLegendr   s        r1   rH  zWindowedAnalysis.write  s    
 	b:))&)EB!!"D9Bb)	277<<	9r>:  "x(r3   r   r   )r   r   r   r   formatr   r)  keywordConfigurablesr   r   r   r   r   KrumhanslSchmucklerr$  r2   r   r+  rP   rJ   r3  rH  r   r   s   @r1   r  r  [  s     F%44II M) ) 03DOO.DK+D=E=Y=Y:Y0    *. 8!#F) )r3   r  c                  (    e Zd ZdZej
                  Zy)WindowedKeya  
    Stream plotting of windowed version of Krumhansl-Schmuckler analysis routine.
    See :class:`~music21.analysis.discrete.KrumhanslSchmuckler` for more details.

    >>> s = corpus.parse('bach/bwv66.6')
    >>> p = graph.plot.WindowedKey(s.parts[0])
    >>> p.doneAction = None #_DOCS_HIDE
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/WindowedKrumhanslSchmuckler.*
        :width: 600

    .. image:: images/legend-WindowedKrumhanslSchmuckler.*

    Set the processor class to one of the following for different uses:

    >>> p = graph.plot.WindowedKey(s.parts.first())
    >>> p.processorClass = analysis.discrete.AardenEssen
    >>> p.processorClass = analysis.discrete.SimpleWeights
    >>> p.processorClass = analysis.discrete.BellmanBudge
    >>> p.processorClass = analysis.discrete.TemperleyKostkaPayne
    >>> p.doneAction = None #_DOCS_HIDE
    >>> p.run()

    N)r   r   r   r   r   rU  r$  r{   r3   r1   rW  rW    s    2 %88r3   rW  c                  (    e Zd ZdZej
                  Zy)WindowedAmbitusaq  
    Stream plotting of basic pitch span.

    >>> s = corpus.parse('bach/bwv66.6')
    >>> p = graph.plot.WindowedAmbitus(s.parts.first())
    >>> p.doneAction = None #_DOCS_HIDE
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/WindowedAmbitus.*
        :width: 600

    .. image:: images/legend-WindowedAmbitus.*

    N)r   r   r   r   r   Ambitusr$  r{   r3   r1   rY  rY    s     %,,r3   rY  c                       e Zd ZU dZej
                  ej                  dZded<   	 ddd	 	 	 ddZ	dd	d fd
Z
ddZ	 	 	 	 	 	 d fdZ fdZ xZS )HorizontalBarz
    A graph of events, sorted by pitch, over time.

    If colorByPart is True, then each part will get its own color from
    `self.colors` (unless there are more parts than colors).
    r   r   r   FcolorByPartc                   || _         i | _        |  t        j                  j                  | fi | t        j                  | |fi | d| j                  _        y )NF)r^  _partsToColorr   GraphHorizontalBarr2   r   r;   r   )r,   r#   r^  r-   s       r1   r2   zHorizontalBar.__init__  sQ     '57%%..t@x@  y=H= %

r3   TrA   c               `    | j                   r| j                          t        |   dd|i| y)zV
        Optionally assign colors to Part objects and then do the normal run.
        rB   Nr{   )r^  assignColorsToPartsr   rP   )r,   rB   r-   r   s      r1   rP   zHorizontalBar.run+  s.     $$&88x8r3   c                    | j                   }t        | j                        }t        |t        j
                           D ]$  \  }}| j                  ||z     | j                  |<   & | j                  S )a;  
        Give a different color for each part, if self.colorByPart is True.

        Returns the assignment for any further manipulation.

        Currently, two piano hands (PartStaff objects) get different colors.

        >>> bach = corpus.parse('bwv66.6')
        >>> plot = graph.plot.HorizontalBar(bach, colorByPart=True)
        >>> plot.assignColorsToParts()
        {<music21.stream.Part Soprano>: '#605c7f',
         <music21.stream.Part Alto>: '#5c7f60',
         <music21.stream.Part Tenor>: '#988969',
         <music21.stream.Part Bass>: '#628297'}
        )r#   rV   colorsrb   r   Partr`  )r,   r6   	numColorsrg   ps        r1   rc  z!HorizontalBar.assignColorsToParts3  s_      NN$	an-DAq$(KKI$>Dq! .!!!r3   c                    t        |   ||g|  | j                  rO|j                  t        j
                        }|-| j                  j                  || j                  d         |d<   yyy)zG
        Assign colors to each element if colorByPart is True.
        Nr   color)	r   rn   r^  getContextByClassr   rf  r`  getre  )r,   re   rt   r|   partr   s        r1   rn   z HorizontalBar.postProcessElementJ  so     	"2z;F;''4D&*&8&8&<&<T=A[[^'M
7#   r3   c                2   t         |           | j                  j                  | j                  D cg c]  }|d   	 c}       | j                  j                         }i }g }i }| j                  D ]/  \  }}}||vr
g ||<   i ||<   g ||}	||   j                  |	       1 |j                         D ]  \  }
}|j                  d         |D ]8  \  }}||v r|j                  |||   ||   g       %|j                  |g i g       : || _        yc c}w )r~   rS   c                    | d   | d   fS )Nr   rS   r{   )points    r1   <lambda>z/HorizontalBar.postProcessData.<locals>.<lambda>q  s    eAha%9r3   )keyN)	r   ra   r;   rc   r'   rL   r=   r(   sort)r,   rh   r4  pitchSpanDictnewDatadictOfFormatDictspositionData	pitchDatart   positionDataWithFormatDictunused_kr   numericValuerN   r   s                 r1   ra   zHorizontalBar.postProcessDataX  s=    	!

((		)B	1!A$	)BC!!#3799/L)Z-+-i(/1!),)D<)D)D&)$++,FG 4= )..0KHaFF9F: 1 $*L% }, -l ; 1, ? A B r2/ $** 	[ *Cs   Dr   )r#   zstream.Stream | Noner   r   r   )r   zdict[stream.Part, str])re   r   rt   r   r|   r   )r   r   r   r   r   OffsetEndAxisr   r   r   r2   rP   rc  rn   ra   r   r   s   @r1   r\  r\    s       /K+  )-& 	&%& 
&" *. 9".M1M'9M %7M2 2r3   r\  c                  n     e Zd ZU dZi ej
                  dej                  iZded<   ddd fdZ	 xZ
S )	HorizontalBarPitchClassOffseta  
    A graph of events, sorted by pitch class, over time.

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.HorizontalBarPitchClassOffset(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.HorizontalBarPitchClassOffset(s)
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/HorizontalBarPitchClassOffset.*
        :width: 600

    r   r   r   Fr]  c                   t        |   |fd|i| t        j                  | d      | _        d| j                  _        d|vrd| _        d|vrd| _        y y )Nr^  r   Fr   r      r   z-Note Quarter Length and Offset by Pitch Class)r   r2   r   r   r;   r   r   r   r,   r#   r^  r-   r   s       r1   r2   z&HorizontalBarPitchClassOffset.__init__  s_    HHxH((s3
 %

 x'%DO("HDJ #r3   r   )r   r   r   r   r\  r   r   r   r   r2   r   r   s   @r1   r~  r~    sI    /

#
#/T  /K+ 
	Ie 	I 	Ir3   r~  c                  *     e Zd ZdZddd fdZ xZS )HorizontalBarPitchSpaceOffseta   
    A graph of events, sorted by pitch space, over time, generally called
    a "piano roll".

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.HorizontalBarPitchSpaceOffset(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW s = corpus.parse('bach/bwv57.8')
    >>> #_DOCS_SHOW p = graph.plot.HorizontalBarPitchSpaceOffset(s)
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/HorizontalBarPitchSpaceOffset.*
        :width: 600
    Fr]  c               X    t        |   |fd|i| d|vrd| _        d|vrd| _        y y )Nr^  r   r   r   zNote Quarter Length by Pitchr   r2   r   r   r  s       r1   r2   z&HorizontalBarPitchSpaceOffset.__init__  s=    HHxHx'%DO("7DJ #r3   r   )r   r   r   r   r2   r   r   s   @r1   r  r    s    8e 8 8r3   r  c                  x    e Zd ZU dZdej
                  iZded<   ej                  j                  dz   Z
d	dZd Zy)
HorizontalBarWeightedz
    A base class for plots of Scores with weighted (by height) horizontal bars.
    Many weighted segments represent a dynamic parameter of a Part.
    r   r   r   )fillByMeasurenormalizeByPart
partGroupssegmentByTargetNc                    d| _         d| _        d| _        d | _        t	        j
                  j                  | fi | t        j                  | |fi | y )NFT)r  r  r  r  r   GraphHorizontalBarWeightedr2   r   r   s      r1   r2   zHorizontalBarWeighted.__init__  sO    "#$--66tHxH  y=H=r3   c                L   t        | j                  t        j                        st	        d      t        j                  | j                  | j                  | j                  | j                  | j                        }|j                          |j                         }g }|D ]G  \  }}|D ]=  }|d   }|d   }||vr|j                  |       ||z   |vs*|j                  ||z          ? I t        |      | j                  _        t#        |      | j                  _        || _        y)z3
        Extract the data from the Stream.
        zprovided Stream must be Score)r  r  r  r  r   rS   N)rH   r#   r   Scorer   r   PartReductionr  r  r  r  rO   !getGraphHorizontalBarWeightedDatar=   minr:   r   ro   r   r'   )	r,   prr'   uniqueOffsets
unused_keyr   rf   startdurs	            r1   rJ   z!HorizontalBarWeighted.extractData  s    $..&,,7 !@AA$$NN,, 00 002 	

335!%J! qk-!((/3;m3!((5 " "& "-0

!-0

	r3   r   )r   r   r   r   r   r   r   r   r   r  rT  r2   rJ   r{   r3   r1   r  r    sD     03DOO.DK+D%@@UU Y >r3   r  c                  *     e Zd ZdZd fd	Zd Z xZS )Dolana  
    A graph of the activity of a parameter of a part (or a group of parts) over time.
    The default parameter graphed is Dynamics. Dynamics are assumed to extend activity
    to the next change in dynamics.

    Numerous parameters can be configured based on functionality encoded in
    the :class:`~music21.analysis.reduction.PartReduction` object.

    If the `fillByMeasure` parameter is True, and if measures are available, each part
    will segment by Measure divisions, and look for the target activity only once per
    Measure. If more than one target is found in the Measure, values will be averaged.
    If `fillByMeasure` is False, the part will be segmented by each Note.

    The `segmentByTarget` parameter is True, segments, which may be Notes or Measures,
    will be divided if necessary to show changes that occur over the duration of the
    segment by a target object.

    If the `normalizeByPart` parameter is True, each part will be normalized within the
    range only of that part. If False, all parts will be normalized by the max of all parts.
    The default is True.

    >>> s = corpus.parse('bwv66.6')
    >>> dyn = ['p', 'mf', 'f', 'ff', 'mp', 'fff', 'ppp']
    >>> i = 0
    >>> for p in s.parts:
    ...     for m in p.getElementsByClass(stream.Measure):
    ...         m.insert(0, dynamics.Dynamic(dyn[i % len(dyn)]))
    ...         i += 1
    ...
    >>> #_DOCS_SHOW s.plot('dolan', fillByMeasure=True, segmentByTarget=True)

    .. image:: images/Dolan.*
        :width: 600

    c                \   t        |   |fi | || j                          d|vrd| _        d|vrnd| _        | j
                  r[| j
                  j                  E| j
                  j                  j                  %| j
                  j                  j                  | _        d|vrd| _        y y )Nr   r  r   Instrumentation	hideYGridT)r   r2   _getPartGroupsr   r   r#   metadatar  r   s      r1   r2   zDolan.__init__  s    /h/
  !x'%DO("*DJ~~$.."9"9"E>>**00<!%!8!8!>!>DJh&!DN 'r3   c                   ddl m} | j                  ry| j                  ry| j                  j	                         j                  |j                        }|syt        |      dk(  r?| j                  j                  d      $ddddgd	d
dddgd	dddgd	dddgd	g}|| _        yt        |      dk(  r@| j                  j                  d      %ddg dd	ddg dd	dddgd	ddg dd	g}|| _        yt        |      dkD  rYdddd gd	d!d"d#d$gd	d%dd&d'gd	d(dd)d*gd	d+dd,d-gd	d.d/g d0d	d1d/d2gd	d3d4dd	d5dd6d7gd	d8d9d:d;gd	dd<dd	d=d>d?d@gd	g}|| _        yy)Az
        Examine the instruments in the Score and determine if there
        is a good match for a default configuration of parts.
        r   )
instrumentNr  Sopranopurplesoprano0)r   rj  matchAltoorangealto1Tenor
lightgreentenorBass
mediumbluebassViolaz
1st Violin)z
1st violinr  zviolin 1violin iz
2nd Violin)z
2nd violinr  zviolin 2	violin iiviolaCello)cellovioloncelloz'cellor   Flutez#C154C1flautozflute \dOboeblueoboezoboe \dClarinet
clarinettozclarinet in \w* \dBassoonfagottoz
bassoon \dHornscornozhorn in \w* \dTrumpetred)trombaz
trumpet \dztrumpet in \w* \dTromboneztrombone \dTimpaniz#5C3317zViolin Iz	violino ir  z	Violin IIgreenz
violino iir  forestgreenzVioloncello & CBz
dark greenr  contrabasso)	r   r  r  r#   flattenr^   
InstrumentrV   getElementById)r,   r  
instStreampgOrcs       r1   r  zDolan._getPartGroups3  s   
 	'??>>^^++-@@AVAVW
z?aDNN$A$A)$L$X"XC@PQ(fc]K <7)L,&J	E $DO_!dnn&C&CG&L&X%HJ%IK <7)L <?AE $DO_r! 9+?VW&FJ;OP#l')>?A"XM@Z[ 8wHY>Z["UIK#e~>NO"YF $lkS]E^_$w,P[A\] =4H+l(-8:#E* $DO- "r3   r   )r   r   r   r   r2   r  r   r   s   @r1   r  r    s    "H"(:$r3   r  c                  l    e Zd ZU dZej
                  ej                  ej                  dZde	d<   ddZ
y)
Plot3DBarsz1
    Base class for Stream plotting classes.
    r  r   r   Nc                    t        j                  j                  | fi | t        j                  | |fi | d| j                  _        y r  )r   Graph3DBarsr2   r   r<   r  r   s      r1   r2   zPlot3DBars.__init__}  s<    ''99  y=H=)

r3   r   )r   r   r   r   r   r   r   r   r   r   r2   r{   r3   r1   r  r  s  s8     ##  /K+ *r3   r  c                  h     e Zd ZU dZi ej
                  dej                  iZded<   d fd	Z	 xZ
S )!Plot3DBarsPitchSpaceQuarterLengthae  
    A scatter plot of pitch and quarter length

    >>> s = corpus.parse('bach/bwv324.xml') #_DOCS_HIDE
    >>> p = graph.plot.Plot3DBarsPitchSpaceQuarterLength(s, doneAction=None) #_DOCS_HIDE
    >>> #_DOCS_SHOW from music21.musicxml import testFiles
    >>> #_DOCS_SHOW s = converter.parse(testFiles.mozartTrioK581Excerpt)
    >>> #_DOCS_SHOW p = graph.plot.Plot3DBarsPitchSpaceQuarterLength(s)
    >>> p.id
    '3DBars-quarterLength-pitchSpace-count'
    >>> p.run()  # with defaults and proper configuration, will open graph

    .. image:: images/Plot3DBarsPitchSpaceQuarterLength.*
        :width: 600
    r   r   r   c                T    t        |   |fi | d|vrd| _        d|vrd| _        y y )Nr   r   r   zPitch by Quarter Length Countr  r   s      r1   r2   z*Plot3DBarsPitchSpaceQuarterLength.__init__  s:    /h/ x'$DO("8DJ #r3   r   )r   r   r   r   r  r   r   r   r   r2   r   r   s   @r1   r  r    s?    /

 
 /T  /K+ 
9 9r3   r  c                  .    e Zd ZU dZi Zded<   ddZd Zy)MultiStreama+  
    Approaches to plotting and graphing multiple Streams.
    A base class from which Stream plotting Classes inherit.

    Not yet integrated into the 2017 system, unfortunately.

    Provide a list of Streams as an argument. Optionally
    provide an additional list of labels for each list.
    r   r   Nc                   t        j                  j                  | fi | t        j                  | d        |g }d | _        | j                  |      }|s&t        |      t        |      k(  r|| _        d | _        y || _        d | _        y r   )	r   GraphGroupedVerticalBarr2   r   
streamListparseStreamsrV   	labelListr'   )r,   r  r  r-   
foundPathss        r1   r2   zMultiStream.__init__  s    **33DEHE  t,I&&z2
 S_J?'DN 	 'DN	r3   c                R   g | _         g }|D ]  }t        |t              ry|j                  t        j
                  j                  |             t        j
                  j                  |      rt        j                  |      }nt        j                  |      }npt        |t        j                        rV|j                  |j                         |j                         rt        j                  |      }nt        j                  |      }| j                   j                  |        |S r   )r  rH   r   r=   rK  rL  basenameexistsr   parser   pathlibPathr   )r,   r  r  r6   s       r1   r  zMultiStream.parseStreams  s    
A!S!!!"''"2"21"5677>>!$!*AQAAw||,!!!&&)88:!*AQAOO""1%   r3   r   )r   r   r   r   r   r   r2   r  r{   r3   r1   r  r    s     /1K+0"r3   r  c                  <     e Zd ZdZdZd fd	Zddd	dZd Z xZS )
Featureszh
    Plots the output of a set of feature extractors.

    FeatureExtractors can be ids or classes.
    r   c                    |g }t        |   ||fi | || _        d| _        d| _        d| _        d|vrd| _        d|vrd | _        y y )NZ   lefttopr   r   r   )r   r2   featureExtractorsxTickLabelRotationxTickLabelHorizontalAlignmentxTickLabelVerticalAlignmentr   r   )r,   r  r  r  r-   r   s        r1   r2   zFeatures.__init__  sg    IY;(;!2"$-3*+0( x'%DO("DJ #r3   TrA   c                   | j                          | j                         \  | _        }}d| _        | j	                  d|       | j	                  d|       |r| j                          y y )NFr   r   )rI   rJ   r'   gridrK   rO   )r,   rB   r-   r/  r4  s        r1   rP   zFeatures.run  sY    $($4$4$6!	66	c6"c6"LLN r3   c                   t        | j                        t        | j                        k7  r/t        t        | j                              D cg c]  }|dz   	 }}n| j                  }g }| j                  D ][  }t        |t              r3t        j                  |      }|D ]  }|j                   |               F|j                   |              ] g }| j                  D ](  }t        j                  |      }	|j                  |	       * g }
t        |      D ]  \  }}	t        j                         }|D ]h  }|	|_        |j                         j                   }t        |      dk(  r|d   ||j"                  <   Et%        |      t        |      z  ||j"                  <   j ||   |g}|
j                  |        g }t        |      D ]  \  }}|j                  |dz   | g        g }|
||fS c c}w )NrS   r         ?)rV   r  r  rj   r  rH   r   r   extractorsByIdr=   DataInstancerb   collectionsOrderedDictr'   extractvectorr   sum)r,   r   r  feListfepostsubdiListr6   dir'   rg   r   	dataPointr/  rN   r4  s                    r1   rJ   zFeatures.extractData  s   t~~#doo"66(-c$//.B(CD(C1Q(CIDI((B"c"..r2CMM#%(   bd# ) A&&q)BMM" ! v&EAr))+CJJL''q6Q;#$Q4CL $'q6CF?CL  #1s+IKK	" ' !),HAu MM1s7ug/0 -
 VV##U Es   G-r   r   )	r   r   r   r   rS  r2   rP   rJ   r   r   s   @r1   r  r    s#    
 F* *. ,$r3   r  c                  N    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zy)TestExternalManualc                    t        j                  d      }t        |j                  d   d      }|j	                          t        |d      }|j	                          y )Nbach/bwv57.8r   Bach (soprano voice)r   zBach (all parts))r   r  r  partsrP   r,   abs      r1   !testHorizontalBarPitchSpaceOffsetz4TestExternalManual.testHorizontalBarPitchSpaceOffset7  sD    LL()!''!*<RS	)!3EF	r3   c                    t        j                  d      }t        |j                  d   d      }|j	                          t        j                  d      }t        |j                  d   j                  dd      d      }|j	                          y )Nr  r   r  r  rR   r   zBach (soprano voice, mm 3-6))r   r  r~  r  rP   measuresr  s      r1   !testHorizontalBarPitchClassOffsetz4TestExternalManual.testHorizontalBarPitchClassOffset@  sj    LL()!''!*<RS	LL()!''!**=*=a*C4RT	r3   c                *   t        j                  d      j                  d   j                         }dD ]^  }t	        |d      }||j
                  _        |j                          t        |d      }||j
                  _        |j                          ` y )Nr  r   TFz Pitch Space Bach (soprano voice)r  z Pitch Class Bach (soprano voice))	r   r  r  r  r
  r:   r   rP   r  )r,   r	  xLogr
  s       r1   *testScatterWeightedPitchSpaceQuarterLengthz=TestExternalManual.testScatterWeightedPitchSpaceQuarterLengthJ  s|    LL(..q199;!D6;A #'AGGEEG6;A #'AGGEEG "r3   c                    t        j                  d      }t        |j                  d   j	                         d      }|j                          y Nr  r   r  r  r   r  r   r  r  rP   r  s      r1   testPitchSpacez!TestExternalManual.testPitchSpaceY  7    LL(
 2 2 4<RS	r3   c                    t        j                  d      }t        |j                  d   j	                         d      }|j                          y r  r   r  r   r  r  rP   r  s      r1   testPitchClassz!TestExternalManual.testPitchClass^  r  r3   c                    t        j                  d      }t        |j                  d   j	                         d      }|j                          y r  r   r  r   r  r  rP   r  s      r1   testQuarterLengthz$TestExternalManual.testQuarterLengthc  s7    LL("1771:#5#5#7?UV	r3   c                `   dD ]  }t        j                  d      }t        |j                  d   j	                         d      }||j
                  _        |j                          t        |j                  d   j	                         d      }||j
                  _        |j                           y )Nr  r  r   r  r  )	r   r  r   r  r  r:   r   rP   r   )r,   r  r	  r
  s       r1   "testScatterPitchSpaceQuarterLengthz5TestExternalManual.testScatterPitchSpaceQuarterLengthh  s    !D^,A.qwwqz/A/A/CKa 1A"&AGGEEG.qwwqz/A/A/CKa 1A"&AGGEEG "r3   c                    t        j                  d      }t        |j                  d   j	                         d      }|j                          y r  )r   r  r   r  r  rP   r  s      r1   testScatterPitchClassOffsetz.TestExternalManual.testScatterPitchClassOffsetv  s7    LL(#AGGAJ$6$6$8@VW	r3   c                   t        j                  dd      }t        |j                  d   j	                         d      }|j                          t        |j                  d   j	                         d      }|j                          y )Nschumann_robert/opus41no1rT   r   zRobert Schumann (soprano voice)r  r   r  r   r  r  rP   r  r  s      r1   "testScatterPitchSpaceDynamicSymbolz5TestExternalManual.testScatterPitchSpaceDynamicSymbol{  sk    LL4a8*GGAJ 3
 	
2GGAJ 35 	
r3   c                    t        j                  dd      }t        |j                         j	                         d      }|j                          y )Nschoenberg/opus19r   zSchoenberg pitch spacer  )r   r  r  r  	stripTiesrP   r  s      r1   &testPlot3DPitchSpaceQuarterLengthCountz9TestExternalManual.testPlot3DPitchSpaceQuarterLengthCount  s;    LL,a0-aiik.C.C.E4LN	r3   c                :   ddl m} t        ddft        ddft        ddft
        ddft        ddft        ddft        t        j                  dd      dft        ddft        ddft        ddft        ddft        t        j                  dd      dft         |j"                  dft$        t        j                  d      d	ft&        t        j                  d      d	fg}t        j(                  d
      }|D ]  \  }}}||}nt+        j(                  |      }| ||d|      }n
 ||d      }|j-                          |j.                  j0                  dz   }	t3        t4        j7                         |	z        }
t4        j9                  d|
g       |j;                  |
        y)z
        Write a graphic file for all graphs, naming them after the appropriate class.
        This is used to generate documentation samples.
        r   )	testFilesNr#  rT   zRobert Schumann Opus 41 No 1zMozart Trio K581 Excerptzbach/bwv66.6.xmlzBach BWV 66.6r  r?  r@  rF  zwriting fp:)music21.musicxmlr+  r   r   r   r   r   r   r   r   getWorkr  r~  r
  r  r  r  mozartTrioK581ExcerptrW  rY  r  r   rP   r   r   r   r1  getRootTempDirr2  rH  )r,   r+  plotClassessDefaultplotClassNameworktitleStrr6   objrQ  rO  s              r1   writeAllPlotsz TestExternalManual.writeAllPlots  s    	/ !$- $-#T40+T48+T48$dD1./ / +D$7*D$73T4@3T4@3^^7;+- /,,') &..);<oNfnn-?@/RE$
L <</-8)M4| OOD)##A$hG#A$7GGI''&0B\002R78B##]B$78IIbM! .9r3   N)r   r   r   r  r  r  r  r  r  r  r!  r%  r)  r7  r{   r3   r1   r  r  5  s:    



@r3   r  c                  z    e Zd Zd Zd Zd Zd Zd Zd ZddZ	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)Testc                2    ddl m}  || t                      y )Nr   )testCopyAll)music21.test.commonTestr;  globals)r,   r;  s     r1   testCopyAndDeepcopyzTest.testCopyAndDeepcopy  s    7D')$r3   c                    t        j                  d      }t        |j                  d   j	                         d d      }|j                          y Nr  r   r  r?  )r   r  r
  r  r  rP   r  s      r1   testPitchSpaceDurationCountz Test.testPitchSpaceDurationCount  s=    LL(21771:3E3E3GTX9OQ	r3   c                    t        j                  d      }t        |j                  d   j	                         d d      }|j                          y )Nbachr   r  r?  r  r  s      r1   r  zTest.testPitchSpace  s9    LL 
 2 2 4Mcd	r3   c                    t        j                  d      }t        |j                  d   j	                         d d      }|j                          y r@  r  r  s      r1   r  zTest.testPitchClass  s>    LL(
 2 2 4+/&<> 	
r3   c                    t        j                  d      }t        |j                  d   j	                         d d      }|j                          y r@  r  r  s      r1   r  zTest.testQuarterLength  s?    LL("1771:#5#5#7.2)?A 	
r3   c                   t        j                  dd      }t        |j                  d   j	                         d d      }|j                          t        |j                  d   j	                         d d      }|j                          y )Nr'  rT   r   zSchoenberg (piano)r?  r$  r  s      r1   testPitchDurationzTest.testPitchDuration  sq    LL,a0*1771:+=+=+?6:1EG 	
21771:3E3E3G>B9MO 	
r3   Nc                    t        j                  d      }d}d}t        |j                         |d||d      }|j	                          | j                  |j                  j                  dg dgdg d	gg       y )
Nbach/bwv66.6   rS   i,  )r   r  r  r@  dpiMajor))zC#z#f0727a)Dz#ffd752)Ez#eeff9a)zF#z#b9f0ff)Az#bb9aff)Bz#ffb5ffMinor))c#z#8c0e16r   z#ffffffrS  )zf#z#558caarS  )r
  z#9b519b)r   r  rW  r  rP   assertEqualr#  r'   )r,   r@  r	  rQ  r  r
  s         r1   testWindowedzTest.testWindowed  s    LL(
 		2"#
#-38 	
++
 	
r3   c                P    g d}g d}t        ||d       }|j                          y )N)rI  zschoenberg/opus19/movement2zcorelli/opus3no1/1grave)ql1ql2ql3)r  r@  )r  rP   )r,   r  r  rh  s       r1   testFeatureszTest.testFeatures  s#    _
&Z6dK	r3   c                    t        j                  d      }|j                         }t        |d       }|j	                          y )Nz0josquin/laDeplorationDeLaMorteDeJohannesOckeghemr,  )r   r  mergeScoresr~  rP   )r,   or6   r
  s       r1   testPianoRollFromOpuszTest.testPianoRollFromOpus   s1    LLKLMMO)!=	r3   c           
     J   ddl m} |j                  d      }t        t	        j
                         d       }t        j                  g d      }t        j                  |d      |_
        | j                  |j                  |j                  |i       g d       t	        j
                         }|j                  t        j                  g d             |j                  t        j                  d	             |j                  t        j                  d
             t!        |d       }|j#                          | j                  |j$                  ddi fddi fddi fddi fddi fg       t	        j
                         }|j                  |j'                  dd             |j                  t        j                  d	             |j                  t        j                  d	             t)        |d       }|j#                          | j                  |j$                  ddi fddi fddi fddi fddi fg       t	        j
                         }|j                  |j'                  ddd             |j                  t        j                  d	d             t+        |d       }|j#                          | j                  |j$                  ddi fddi fg       t-        t	        j
                         d       }t        j                  |d      |_
        t        j.                  |d      |_        d|j0                  _        t        j                  g dd      }| j                  |j5                  |i       g dg dg       d|_        | j                  |j5                  |i       g ddgg       y )Nr   scalec4r,  )r
  r   rh   r   )G   <   >   )r
  rR  rh   c3c5rS   rT   rR   r  r   e3a3quarterLengthr  r   F)r  r  r  )r   ra  
MajorScaler   r   Streamr	   r!   r   r   r:   rT  r   r=   r   r    r   rP   r'   getChordr   r   r   r   r;   r   rm   r&   )r,   ra  scr
  r   r6   s         r1   testChordsAzTest.testChordsA'  s   !d#fmmo$7KK(%%a-22177ArBLQMMO	-./	4!	4!d3	 	1a*q!Rj1a*q!RjSTVWY[R\!]^MMO	T4()	4!	4!d3	 	1a*q!Rj1a*q!RjSTVWY[R\!]^MMO	T4q9:	4s34"16	 	1a*q!Rj!9: FMMO5%%a-((C0#KKs;44Q;&8	: &+"44Q;lSE=RSr3   c                :   ddl m} |j                  d      }t        j                         }|j                  |j                  ddd             |j                  |j                  dd	d
             |j                  t        j                  dd             t        |d       }d|j                  _        |j                          ddi fddi fddi fddi fd
di fd
di fd
di fd
di fd
di fd
di fd
di fd
di fd
di fddi fg}| j                  |j                  |       y )Nr   r`  rb  rh  ri  r  rj  b3rg        ?rf  rT   r,  F      J@     J@     K@     L@     M@      N@      O@      P@     @P@     P@     @Q@     Q@      R@       @      H@)r   ra  rl  r   rm  r=   rn  r   r    r   r:   r   rP   rT  r'   r,   ra  ro  r6   r
  r  s         r1   testChordsA2zTest.testChordsA2\  s"   !d#MMO	T4s;<	T4s;<	4q12*1>#	tR3b/Cr?S$PROtR3b/tR3b/tR3b/tR3b/Cr?tR" 	'r3   c                :   ddl m} |j                  d      }t        j                         }|j                  |j                  ddd             |j                  |j                  dd	d
             |j                  t        j                  dd             t        |d       }d|j                  _        |j                          ddi fddi fddi fddi fd
di fd
di fd
di fd
di fd
di fd
di fd
di fd
di fd
di fddi fg}| j                  |j                  |       y )Nr   r`  rb  rh  ri  r  rj  rr  rg  rs  rf  rT   r,  Fr  r   r  	      r  )r   ra  rl  r   rm  r=   rn  r   r    r   r:   r   rP   rT  r'   r  s         r1   testChordsA3zTest.testChordsA3q  s!   !d#MMO	T4s;<	T4s;<	4q12*1>#	q"Q|c1b\CB<r2asArlS!RL3PQSU,q"Q|c2r]S!RLq" 	'r3   c                   ddl m} |j                  d      }t        j                         }|j                  |j                  ddd             |j                  t        j                  dd	             |j                  |j                  d
dd             |j                  t        j                  dd	             | j                  |D cg c]  }|j                   c}g d       t        |d       }|j                          ddi fddi fddi fddi fddi fddi fddi fdd	i fddi fdd	i fg
}| j                  |j                  |       y c c}w )Nr   r`  rb  rh  ri  r  rj  rf  rT   rr  e4rs  d3)        r        @      @r,  r  r  r   r  r  r  r  r  )r   ra  rl  r   rm  r=   rn  r   r    rT  offsetr   rP   r'   )r,   ra  ro  r6   er
  r  s          r1   testChordsA4zTest.testChordsA4  s5   !d#MMO	T4s;<	4q12	T4s;<	4q12A.Aq!((A.0DE $A$7	q"Q|c1b\CB<q"r2asArlS!RLq" 	' /s   Ec                H   ddl m} |j                  d      }t        j                         }|j                  t        j                  d             |j                  |j                  ddd             |j                  t        j                  d	             |j                  |j                  d
dd             t        |d       }|j                          | j                  |j                  ddi fddi fddi fddi fddi fddi fddi fddi fddi fddi fddi fddi fg       y )Nr   r`  rb  frh  ri  r  rj  rh  rr  r  rs  r,  4      5   7   9   ;   r   rd  re  @   )r   ra  rl  r   rm  r=   r   Dynamicrn  r   rP   rT  r'   r,   ra  ro  r6   r
  s        r1   testChordsA5zTest.testChordsA5  s   !d#MMO	!!#&'	T4s;<	!!#&'	T4s;< +1>	2q"+Ar{RBK#%q"+Ar{RBK#%q"+Ar{RBK#%q"+Ar{RBK"I 	Jr3   c                 
   ddl m} |j                  d      }t        j                         }|j                  t        j                  d             |j                  |j                  ddd             |j                  |j                  d	d
d             t        |d       }|j                          dddi fddi fgi gdg i gdddi fgi gdg i gdddi fddi fgi gdddi fgi gdg i gdddi fgi gdg i gdddi fgi gdg i gdddi fgi gg}| j                  |j                  |       t        j                         }|j                  t        j                  d             |j                  |j                  ddd             |j                  |j                  d	d
d             t        |d       }|j                          dddi fgi gdg i gdg i gdg i gdddi fgi gdddi fgi gdg i gdddi fgi gdg i gdddi fgi gdg i gdddi fgi gdddi fgi gdg i gdddi fgi gdg i gdddi fgi gg}| j                  |j                  |       t        j                         }|j                  t        j                  d             |j                  |j                  ddd             |j                  |j                  d	d
d             |j                  |j                  ddd             |j                  |j                  ddd             |j                  t        j                  dd             t        |d       }d |j                  _        |j                          | j                  |j                  dd! dd"d#i fdd$d#i fdd%d#i fdd&d#i fdd'd#i fdd(d#i fdd)d#i fg       t        j                         }|j                  t        j                  d             |j                  |j                  ddd             |j                  |j                  d	d
d             |j                  |j                  ddd             |j                  |j                  ddd             |j                  t        j                  dd             t#        |d       }d |j                  _        |j                          | j                  |j                  dd* dd+d#i fdd,d#i fdd!d#i fdd-d#i fddd#i fddd#i fdd.d#i fdd+d#i fg       y )/Nr   r`  rb  rf  rh  ri  r  rj  rr  r  rs  r,  Cr  g      ?g      ?r   rM  rN  r   g      ?FGrO  rP  C3C4f4g5rR   rg  Fr  rt  rS   ru  rv  rw  r  rx  ry  r  r  r   r  rT   )r   ra  rl  r   rm  r=   r   r    rn  r~  rP   rT  r'   r  r
  r:   r   r  r  s         r1   testChordsBzTest.testChordsB  sd   !d#MMO	4!	T4s;<	T4s;<)!=	fb)C+<=rBb"fb)*B/b"fb)C+<=rBfb)*B/b"fb)*B/b"fb)*B/b"fb)*B/1 	' MMO	4!	T4s;<	T4s;<)!=	#vr*+R0b"b"b"fb)*B/fb)*B/b"fb)*B/b"fb)*B/b"fb)*B/#vr*+R0b"fb)*B/b"fb)*B/!1$ 	' MMO	4!	T4s;<	T4s;<	T4q9:	T4q9:	4q1221F#	!T1b'9Cq";MPSUY[\^`Oa(+T1b'9Cq";MPSUY[\^`Oa(+T1b'9'; 	<
 MMO	4!	T4s;<	T4s;<	T4q9:	T4q9:	4q1221F#	!Q2aB#qRSUW(+Q2(+Q2(+Q2aB#qRSUW'Z 	[r3   c           !        ddl m} |j                  d      }t        j                         }|j                  t        j                  d             |j                  ddd      }| j                  t        |      d	       | j                  |D cg c]  }|j                  j                   c}g d
       |j                  |       |j                  t        j                  d             |j                  |j                  ddd             |j                  t        j                  d             |j                  |j                  ddd             |j                  |j                  ddd             |j                  t        j                  dd             t        |d       }d|j                   _        |j%                          dddi fdddi fdddi fdddi fdddi fdddi fdddi fdddi fdddi fdddi fd ddi fd ddi fd!d"d#i fd!ddi fd$d"d#i fd$ddi fd%d"d#i fd%ddi fd&d"d#i fd&ddi fd'd"di fd'ddi fd(d"d#i fd(ddi fd)d"d#i fd)ddi fd*d"d#i fd*ddi fd+d"d#i fd+ddi fg}d,| _        | j                  |j(                  |       y c c}w )-Nr   r`  rb  r  rh  ri  r  rj  z!<music21.chord.Chord E3 F3 G3 A3>)rt  ru  rv  rw  mfrr  r  rs  ppr  r  rR   rg  r,  Frt  r  rS   ru  rv  rw  rx  r  ry  rz  r{  r|  r  rT   r}  r~  r  r  g     R@g      S@g     @S@g     S@i   )r   ra  rl  r   rm  r=   r   r  rn  rT  r5   r   psr   r    r  r:   r   rP   maxDiffr'   )r,   ra  ro  r6   r   r   r
  r  s           r1   testChordsB2zTest.testChordsB2  s   !d#MMO	!!#&'KKd#K6a"EFa0a!''**a02JK		!!$'(	T4s;<	!!$'(	T4q9:	T4q9:	4q1221F#	1b!D!Q#3dAq"5EaQRTVGW1b!D!Q#3dAq"5EaQRTVGW1b!D!Q#3dAq"5EaQRTVGW1b!D!Q#31b!D!Q#31b!D!Q#3dAq"5EaQRTVGW1b!D!Q#3dAq"5EaQRTVGW1b!D!Q#3dAq"5EaQRTVGW1b!D!Q#35 '3 1s   Jc                :   ddl m} |j                  d      }t        j                         }|j                  t        j                  d             |j                  t        j                  d             |j                  |j                  ddd	             |j                  t        j                  d
             |j                  |j                  ddd	             |j                  t        j                  d             |j                  |j                  ddd	             |j                  t        j                  dd	             t        |d       }d|j                  _        |j                          | j                  |j                   d   dddi f       y )Nr   r`  rb  r  rf  rh  ri  r  rj  r  rr  r  rs  r  r  r  rR   rg  r,  Frt  rS   )r   ra  rl  r   rm  r=   r   r  r   r    rn  r  r:   r   rP   rT  r'   r  s        r1   testChordsB3zTest.testChordsB33  s#   !d#MMO	!!#&'	4!	T4s;<	!!$'(	T4s;<	!!$'(	T4q9:	4q12-aDA#	S$2$67r3   c                j    t        j                  d      }t        |dd       }|j                          y )Nr  Bach)r   r@  )r   r  r  rP   r  s      r1   
testDolanAzTest.testDolanAH  s'    LL(!6d3	r3   r   )r   r   r   r>  rA  r  r  r  rG  rU  rZ  r^  rp  r  r  r  r  r  r  r  r  r{   r3   r1   r9  r9    sc    %


:2Tj(*(&(,J,[[|"(J8*r3   r9  __main__)Nr   
__future__r   r  numbersrK  r  typingrE   unittestmusic21.analysisr   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   music21.graphr   r   music21.graph.utilitiesr   r   Environmentr1  ProtoM21Objectr   rD   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r
  r  r  r)  r  rW  rY  ra  r\  r~  r  r  r  r  r  r  r  r  r  r  TestCaser  r9  
_DOC_ORDERr   mainTestr{   r3   r1   <module>r     s   #   	    & % & %             $ I '{&&|4Lg,, L`
0!!? 0>j%% >;W ;>A%C A4g @/W /hB
))? BJ+) +<1) 184Y 4@*j55 *&_ >_ B1_ 1p~)z00/ ~)B9" 9:-& -*|J11? |~IM I>8M 822JAA? 2js$! s$r*'' *"9
 9D0*44o 0fW${ W$xY** Yxz8 zD """!!	***%+
2 zGT r3   