
    3j1             !         d Z ddlmZ ddlmZ ddlZddlZddlmZ ddlZddl	m
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  ej(                  d      Z G d dej,                        Z G d dej,                        Z G d dej,                        Z G d dej,                        Z G d dej,                        Z G d dej,                        Z G d dej,                        Z G d dej,                        Z G d dej,                        Z G d dej,                        Z  G d  d!ej,                        Z! G d" d#ej,                        Z" G d$ d%ej,                        Z# G d& d'ej,                        Z$ G d( d)ej,                        Z% G d* d+ej,                        Z& G d, d-ej,                        Z' G d. d/ej,                        Z( G d0 d1ej,                        Z) G d2 d3ej,                        Z* G d4 d5ej,                        Z+ G d6 d7ej,                        Z, G d8 d9ej,                        Z- G d: d;ej,                        Z. G d< d=ej,                        Z/ G d> d?ej,                        Z0 G d@ dAej,                        Z1 G dB dCej,                        Z2 G dD dEej,                        Z3 G dF dGej,                        Z4 G dH dIej,                        Z5 G dJ dKej,                        Z6 G dL dMej,                        Z7 G dN dOej,                        Z8 G dP dQej,                        Z9 G dR dSej,                        Z: G dT dUej,                        Z; G dV dWej,                        Z< G dX dYej,                        Z= G dZ d[ej,                        Z> G d\ d]ej,                        Z? G d^ d_ej,                        Z@ G d` daej,                        ZA G db dcej,                        ZB G dd deej,                        ZC G df dgej,                        ZD G dh diej,                        ZE G dj dkej,                        ZF G dl dmej,                        ZG G dn doej,                        ZH G dp dqej,                        ZI G dr dsej,                        ZJ G dt duej,                        ZK G dv dwej,                        ZL G dx dyej,                        ZM G dz d{ej,                        ZN G d| d}ej,                        ZO G d~ dej,                        ZP G d dej,                        ZQ G d dej,                        ZR G d dej,                        ZS G d dej,                        ZT G d dej,                        ZU G d dej,                        ZV G d dej,                        ZW G d dej,                        ZX G d dej,                        ZY G d dej,                        ZZ G d dej,                        Z[ G d dej,                        Z\ G d dej,                        Z] G d dej,                        Z^ G d dej,                        Z_ G d dej,                        Z` G d dej,                        Za G d dej,                        Zb G d dej,                        Zc G d dej,                        Zd G d dej,                        Ze G d dej,                        Zf G d dej,                        Zg G d dej,                        Zh G d dej,                        Zi G d dej,                        Zj G d dej,                        Zk G d dej,                        Zl G d dej,                        Zm G d dej,                        Zn G d dej,                        Zo G d dej,                        Zp G d dej,                        Zq G d dej,                        Zr G dĄ dej,                        Zs G dƄ dej,                        Zt G dȄ dej,                        Zu G dʄ dej,                        Zv G d̄ dej,                        Zw G d΄ dej,                        Zx G dЄ dej,                        Zy G d҄ dej,                        Zz G dԄ dej,                        Z{ G dք dej,                        Z| G d؄ dej,                        Z} G dڄ dej,                        Z~ G d܄ de~      Z G dބ de~      Z G d de~      Z G d de~      Z G d de~      Z G d de~      Z G d de~      Z G d de~      Z G d de~      Z G d de~      Z G d dej                        Z eddebecedeegfddeteuevewexeyeze{e|e}eeeeeeeeeegfddeeeeeeeeee e!e"e#e$e%de&e'e(dgfdde)e*e+e,e-e.e/e0e1e2e3e4e5e6e7e8e9e:e;e<e=e>e?e@eAdgfdg deCeDeEeFeGeHeIeJeKeLeMeNeOePeQdeReSeTeUeVeWeXeYeZdddde[e\e]e^e_e`eafddefegeheiejekelemeneodepeqderddddesgfdg dfg      Zd Zg eeeeeeeeee e!e"e#e$e%e&e'e(eteveye{eeeeeeeeeeeQeReSeTeUeVeWeXeYeZe[e\e]e^e_e`eaefegehe)e*e+e,e-e.e/e0e1e2e3e4e5e6e7e8e;e<e=e>Zd Z G d dej                        Zedk(  rddlZ ej$                  e       yy)z
The features implemented here are based on those found in jSymbolic and
defined in Cory McKay's MA Thesis, "Automatic Genre Classification of MIDI Recordings"
    )annotations)OrderedDictN)isclose)dedent)base)environment)exceptions21)
Instrumentzfeatures.jSymbolicc                  .     e Zd ZdZdZd fd	Zd Z xZS )MelodicIntervalHistogramFeatureaE  
    A features array with bins corresponding to the values of the melodic interval histogram.

    128 dimensions

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MelodicIntervalHistogramFeature(s)
    >>> f = fe.extract()
    >>> f.vector[0:5]
    [0.144..., 0.220..., 0.364..., 0.062..., 0.050...]
    M1c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )NdataOrStreamzMelodic Interval HistogramzYA features array with bins corresponding to the values of the melodic interval histogram.T    super__init__namedescriptionisSequential
dimensions	normalizeselfr   keywords	__class__s      G/DATA/.local/lib/python3.12/site-packages/music21/features/jSymbolic.pyr   z(MelodicIntervalHistogramFeature.__init__6   s@    ?l?h?0	L     c                v    t        | j                  d         D ]  \  }}|| j                  j                  |<     y)E
        Do processing necessary, storing result in feature.
        midiIntervalHistogramN)	enumeratedatafeaturevector)r   ivalues      r   processz'MelodicIntervalHistogramFeature.process@   s6     "$)),C"DEHAu%*DLL" Fr   N__name__
__module____qualname____doc__idr   r)   __classcell__r   s   @r   r   r   (   s    
 
B+r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )AverageMelodicIntervalFeaturez
    Average melodic interval (in semitones).

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.AverageMelodicIntervalFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [2.44...]
    M2c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zAverage Melodic Intervalz(Average melodic interval (in semitones).T   r   r   r   r   r   r   r   r   s      r   r   z&AverageMelodicIntervalFeature.__init__T   s6    ?l?h?.	E r   c                   g }| j                   d   }t        |      D ]&  \  }}t        |      D ]  }|j                  |        ( |st	        d      t        |      t        |      z  | j                  j                  d<   yr!   r"   input lacks notesr   N)	r$   r#   rangeappendJSymbolicFeatureExceptionsumlenr%   r&   )r   valueshistor'   r(   js         r   r)   z%AverageMelodicIntervalFeature.process\   sw     		12!%(HAu5\a  " ) +,?@@!$Vs6{!:Ar   r*   r+   r2   s   @r   r4   r4   H   s     
B;r   r4   c                  .     e Zd ZdZdZd fd	Zd Z xZS ) MostCommonMelodicIntervalFeaturez

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MostCommonMelodicIntervalFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [2]
    M3c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zMost Common Melodic Intervalz,Melodic interval with the highest frequency.Tr7   r   r8   r   s      r   r   z)MostCommonMelodicIntervalFeature.__init__v   s6    ?l?h?2	I r   c                    | j                   d   }t        |      }|j                  |      }|| j                  j                  d<   yr!   r"   r   N)r$   maxindexr%   r&   )r   rB   maxValuemaxIndexs       r   r)   z(MostCommonMelodicIntervalFeature.process~   s>    
 		12u:;;x(!)Ar   r*   r+   r2   s   @r   rE   rE   k   s     
B*r   rE   c                  .     e Zd ZdZdZd fd	Zd Z xZS )0DistanceBetweenMostCommonMelodicIntervalsFeaturez

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.DistanceBetweenMostCommonMelodicIntervalsFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [1]
    M4c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z.Distance Between Most Common Melodic IntervalszvAbsolute value of the difference between the most common melodic interval and the second most common melodic interval.Tr7   r   r8   r   s      r   r   z9DistanceBetweenMostCommonMelodicIntervalsFeature.__init__   s:    ?l?h?D	7 !r   c                   t        j                  | j                  d         }t        |      }|j	                  |      }d||<   t        |      }|j	                  |      }t        ||z
        | j                  j                  d<   yrI   )copydeepcopyr$   rJ   rK   absr%   r&   )r   rB   rL   rM   secondValuesecondIndexs         r   r)   z8DistanceBetweenMostCommonMelodicIntervalsFeature.process   sq    
 dii(?@Au:;;x(h%jkk+.!$X%;!<Ar   r*   r+   r2   s   @r   rO   rO      s     
B=r   rO   c                  .     e Zd ZdZdZd fd	Zd Z xZS )*MostCommonMelodicIntervalPrevalenceFeaturez
    Fraction of melodic intervals that belong to the most common interval.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MostCommonMelodicIntervalPrevalenceFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.364...]
    M5c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z'Most Common Melodic Interval PrevalencezFFraction of melodic intervals that belong to the most common interval.Tr7   r   r8   r   s      r   r   z3MostCommonMelodicIntervalPrevalenceFeature.__init__   s6    ?l?h?=	c r   c                    t        j                  | j                  d         }t        |      }t	        |      }|st        d      ||z  | j                  j                  d<   yr:   )rS   rT   r$   rJ   r?   r>   r%   r&   )r   rB   rL   counts       r   r)   z2MostCommonMelodicIntervalPrevalenceFeature.process   sV    
 dii(?@Au:E
+,?@@!)E!1Ar   r*   r+   r2   s   @r   rY   rY      s     
B
2r   rY   c                  .     e Zd ZdZdZd fd	Zd Z xZS ),RelativeStrengthOfMostCommonIntervalsFeaturez

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.RelativeStrengthOfMostCommonIntervalsFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.603...]
    M6c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z*Relative Strength of Most Common IntervalszFraction of melodic intervals that belong to the second most common interval divided by the fraction of melodic intervals belonging to the most common interval.Tr7   r   r8   r   s      r   r   z5RelativeStrengthOfMostCommonIntervalsFeature.__init__   s;    ?l?h?@	c !r   c                   t        j                  | j                  d         }t        |      }t	        |      }|j                  |      }d||<   t	        |      }|st        d      ||z  ||z  z  | j                  j                  d<   y)r!   r"   r   r;   N)	rS   rT   r$   r?   rJ   rK   r>   r%   r&   )r   rB   r]   rL   rM   rV   s         r   r)   z4RelativeStrengthOfMostCommonIntervalsFeature.process   s    
 dii(?@AE
u:;;x(h%j+,?@@"-"5(U:J!KAr   r*   r+   r2   s   @r   r_   r_      s     
BLr   r_   c                  .     e Zd ZdZdZd fd	Zd Z xZS )%NumberOfCommonMelodicIntervalsFeaturez
    Number of melodic intervals that represent at least 9% of all melodic intervals.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.NumberOfCommonMelodicIntervalsFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [3]
    M7c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z"Number of Common Melodic IntervalszPNumber of melodic intervals that represent at least 9% of all melodic intervals.Tr7   r   r8   r   s      r   r   z.NumberOfCommonMelodicIntervalsFeature.__init__  s9    ?l?h?8	D r   c                    | j                   d   }t        |      }|st        d      d}t        |      D ]  \  }}||z  dk\  s|dz  } || j                  j
                  d<   y)r!   r"   r;   r   
ףp=
?r7   N)r$   r?   r>   r#   r%   r&   )r   rB   totalpostr'   r]   s         r   r)   z-NumberOfCommonMelodicIntervalsFeature.process  sn     		12E
+,?@@!%(HAuu}$	 ) "&Ar   r*   r+   r2   s   @r   rd   rd      s     
B&r   rd   c                  .     e Zd ZdZdZd fd	Zd Z xZS )AmountOfArpeggiationFeaturea  
    Fraction of horizontal intervals that are repeated notes, minor thirds, major thirds,
    perfect fifths, minor sevenths, major sevenths, octaves, minor tenths or major tenths.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.AmountOfArpeggiationFeature(s)
    >>> f = fe.extract()
    >>> f.name
    'Amount of Arpeggiation'
    >>> f.vector
    [0.333...]
    M8c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zAmount of ArpeggiationzFraction of horizontal intervals that are repeated notes, minor thirds, major thirds, perfect fifths, minor sevenths, major sevenths, octaves, minor tenths or major tenths.Tr7   r   r8   r   s      r   r   z$AmountOfArpeggiationFeature.__init__*  s;    ?l?h?,	U !r   c                    | j                   d   }t        |      }|dk(  ryg d}t        |      }d}|D ]
  }|||   z  } |st        d      ||z  | j                  j                  d<   y)r!   r"   r   N)	r            
               r;   r$   r?   r>   r%   r&   r   rB   ri   targetsr]   ts         r   r)   z#AmountOfArpeggiationFeature.process4  sx     		12E
A:2E
AU1XE +,?@@!&Ar   r*   r+   r2   s   @r   rl   rl     s     
B/r   rl   c                  .     e Zd ZdZdZd fd	Zd Z xZS )RepeatedNotesFeaturez
    Fraction of notes that are repeated melodically

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.RepeatedNotesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.144...]
    M9c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zRepeated Notesz0Fraction of notes that are repeated melodically.Tr7   r   r8   r   s      r   r   zRepeatedNotesFeature.__init__S  s6    ?l?h?$	M r   c                    | j                   d   }t        |      }|dk(  rydg}t        |      }|st        d      d}|D ]
  }|||   z  } ||z  | j                  j                  d<   y)r!   r"   r   Nr;   rx   ry   s         r   r)   zRepeatedNotesFeature.process[  sz     		12E
A:#E
+,?@@AU1XE !&Ar   r*   r+   r2   s   @r   r}   r}   G  s     
B/r   r}   c                  .     e Zd ZdZdZd fd	Zd Z xZS )ChromaticMotionFeaturez
    Fraction of melodic intervals corresponding to a semitone.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.ChromaticMotionFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.220...]
    m10c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zChromatic Motionz;Fraction of melodic intervals corresponding to a semi-tone.Tr7   r   r8   r   s      r   r   zChromaticMotionFeature.__init__z  s6    ?l?h?&	X r   c                    | j                   d   }t        |      }|st        d      dg}d}|D ]
  }|||   z  } ||z  | j                  j                  d<   y)r!   r"   r;   r7   r   Nrx   ry   s         r   r)   zChromaticMotionFeature.process  g     		12E
+,?@@#AU1XE !&Ar   r*   r+   r2   s   @r   r   r   n       
B/r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )StepwiseMotionFeaturez
    Fraction of melodic intervals that corresponded to a minor or major second

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.StepwiseMotionFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.584...]
    M11c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zStepwise MotionzKFraction of melodic intervals that corresponded to a minor or major second.Tr7   r   r8   r   s      r   r   zStepwiseMotionFeature.__init__  s8    ?l?h?%	: r   c                    | j                   d   }t        |      }|st        d      ddg}d}|D ]
  }|||   z  } ||z  | j                  j                  d<   y)r!   r"   r;   r7      r   Nrx   ry   s         r   r)   zStepwiseMotionFeature.process  i     		12E
+,?@@a&AU1XE !&Ar   r*   r+   r2   s   @r   r   r     s     
B/r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )MelodicThirdsFeaturez
    Fraction of melodic intervals that are major or minor thirds

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MelodicThirdsFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.113...]
    M12c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zMelodic Thirdsz=Fraction of melodic intervals that are major or minor thirds.Tr7   r   r8   r   s      r   r   zMelodicThirdsFeature.__init__  s6    ?l?h?$	Z r   c                    | j                   d   }t        |      }|st        d      ddg}d}|D ]
  }|||   z  } ||z  | j                  j                  d<   y)r!   r"   r;   rp   rq   r   Nrx   ry   s         r   r)   zMelodicThirdsFeature.process  r   r   r*   r+   r2   s   @r   r   r     r   r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )MelodicFifthsFeaturez
    Fraction of melodic intervals that are perfect fifths

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MelodicFifthsFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.056...]
    M13c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zMelodic Fifthsz6Fraction of melodic intervals that are perfect fifths.Tr7   r   r8   r   s      r   r   zMelodicFifthsFeature.__init__  s6    ?l?h?$	S r   c                    | j                   d   }t        |      }|st        d      dg}d}|D ]
  }|||   z  } ||z  | j                  j                  d<   y)r!   r"   r;   rr   r   Nrx   ry   s         r   r)   zMelodicFifthsFeature.process  r   r   r*   r+   r2   s   @r   r   r     r   r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )MelodicTritonesFeaturez
    Fraction of melodic intervals that are tritones

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MelodicTritonesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.012...]
    M14c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zMelodic Tritonesz0Fraction of melodic intervals that are tritones.Tr7   r   r8   r   s      r   r   zMelodicTritonesFeature.__init__  s6    ?l?h?&	M r   c                    | j                   d   }t        |      }|st        d      dg}d}|D ]
  }|||   z  } ||z  | j                  j                  d<   y)r!   r"   r;      r   Nrx   ry   s         r   r)   zMelodicTritonesFeature.process  r   r   r*   r+   r2   s   @r   r   r     r   r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )MelodicOctavesFeaturez
    Fraction of melodic intervals that are octaves

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MelodicOctavesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.018...]
    M15c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zMelodic Octavesz/Fraction of melodic intervals that are octaves.Tr7   r   r8   r   s      r   r   zMelodicOctavesFeature.__init__/  s6    ?l?h?%	L r   c                    | j                   d   }t        |      }|st        d      g d}d}|D ]
  }|||   z  } ||z  | j                  j                  d<   y)r!   r"   r;   )	ru      0   <   H   T   `   l   x   r   Nrx   ry   s         r   r)   zMelodicOctavesFeature.process7  se     		12E
+,?@@8AU1XE !&Ar   r*   r+   r2   s   @r   r   r   #  r   r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )DirectionOfMotionFeaturea  
    Returns the fraction of melodic intervals that are rising rather than falling.
    Unisons are omitted.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.DirectionOfMotionFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.470...]
    m17c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zDirection of MotionzBFraction of melodic intervals that are rising rather than falling.Tr7   r   r8   r   s      r   r   z!DirectionOfMotionFeature.__init__T  s6    ?l?h?)	_ r   c                   d}d}g }| j                   j                  dkD  rKt        | j                   j                        D ](  }| j                   d   |   d   }|j                  |       * n | j                   d   }|j                  |       |D ]  }|D ]  }|dkD  r|dz  }|dk  s|dz  } ! |s|st	        d      |||z   z  | j
                  j                  d<   y)r!   r   partscontourListr7   r;   N)r$   
partsCountr<   r=   r>   r%   r&   )r   risingfallingcBundler'   cListcs          r   r)   z DirectionOfMotionFeature.process\  s     99!#499//0		'*1-m<u% 1 IIm,ENN5!Eq5aKFUqLG	   6+,?@@!'7V+;!<Ar   r*   r+   r2   s   @r   r   r   G  s    	 
B=r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )DurationOfMelodicArcsFeaturea  
    Average number of notes that separate melodic peaks and troughs
    in any part. This is calculated as the total number of intervals
    (not counting unisons) divided by the number of times the melody
    changes direction.

    Example: C D E D C D E C C
    Intervals: [0] 2 2 -2 -2 2 2 -4 0
    Changes direction (equivalent to +/- sign) three times.
    There are seven non-unison (nonzero) intervals.
    Thus, the duration of arcs is 7/3 ~= 2.333...

    >>> s = converter.parse("tinyNotation: c' d' e' d' c' d' e'2 c'2 c'2")
    >>> fe = features.jSymbolic.DurationOfMelodicArcsFeature(s)
    >>> fe.extract().vector
    [2.333...]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.DurationOfMelodicArcsFeature(s)
    >>> fe.extract().vector
    [1.74...]
    M18c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zDuration of Melodic ArcszAverage number of notes that separate melodic peaks and troughs in any part. This is calculated as the total number of intervals (not counting unisons) divided by the number of times the melody changes direction.Tr7   r   r8   r   s      r   r   z%DurationOfMelodicArcsFeature.__init__  s;    ?l?h?.	S !r   c                   g }| j                   j                  dkD  rKt        | j                   j                        D ](  }| j                   d   |   d   }|j                  |       * n | j                   d   }|j                  |       d}d}d}d}d}|D ]K  }|}	|D ]B  }
|
dk7  r|dz  }|	|k(  r|
dk  s|dz  }|}	 |	|k(  r|
dkD  s+|dz  }|}	3|
dkD  r|}	;|
dk  sA|}	D M |dk(  rd}n||z  }|| j                  j
                  d<   yr!   r   r   r   r7   N)r$   r   r<   r=   r%   r&   )r   r   r'   r   direction_changesnonUnison_intervals	ASCENDING
DESCENDING
STATIONARYcurrent_directionintervalduration_of_melodic_arcss               r   r)   z$DurationOfMelodicArcsFeature.process  sG    99!#499//0		'*1-m<u% 1 IIm,ENN5! 	

E *!q='1,'$	1!|)Q.),6)&*4!|)Q.),5)!|,5)!A,6) " & !'($':=N'N$!9Ar   r*   r+   r2   s   @r   r   r   v  s    , 
B	/:r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )SizeOfMelodicArcsFeatureaE  
    Average span (in semitones) between melodic peaks and troughs
    in any part. Each time the melody changes direction begins a
    new arc. The average size of melodic arcs is defined as the
    total size of melodic intervals between changes of directions -
    or between the start of the melody and the first change of
    direction - divided by the number of direction changes.

    Example: C D E D C E D C C
    Intervals: [0] 2 2 -2 -2 2 2 -4 0
    Changes direction (equivalent to +/- sign) three times.
    The total sum of interval distance up to the last change
    of direction is 12. We don't count the last interval,
    the descending major third, because it is not between
    changes of direction.
    Thus, the average size of melodic arcs is 12/3 = 4.

    >>> s = converter.parse("tinyNotation: c' d' e' d' c' d' e'2 c'2 c'2")
    >>> fe = features.jSymbolic.SizeOfMelodicArcsFeature(s)
    >>> fe.extract().vector
    [4.0]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.SizeOfMelodicArcsFeature(s)
    >>> fe.extract().vector
    [4.84...]
    M19c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zSize of Melodic Arcsae  Average span (in semitones) between melodic peaks and troughs in any part. Each time the melody changes direction begins a new arc. The average size ofmelodic arcs is defined as the total size of melodicintervals between changes of directions - or betweenthe start of the melody and the first change ofdirection - divided by the number of direction changes.Tr7   r   r8   r   s      r   r   z!SizeOfMelodicArcsFeature.__init__  s;    ?l?h?*	V !r   c                   g }| j                   j                  dkD  rKt        | j                   j                        D ](  }| j                   d   |   d   }|j                  |       * n | j                   d   }|j                  |       d}d}d}d}d}|D ]  }|}	d}
|D ]  }|	|k(  r2|dkD  r|
t	        |      z  }
|dk  s"||
z  }|dz  }|}	t	        |      }
:|	|k(  r2|dk  r|
t	        |      z  }
S|dkD  sY||
z  }|dz  }|}	t	        |      }
q|dkD  r|}	|
t	        |      z  }
|dk  s|}	|
t	        |      z  }
  |dk(  rd}n||z  }|| j
                  j                  d<   yr   )r$   r   r<   r=   rU   r%   r&   )r   r   r'   r   r   sum_of_intervalsr   r   r   r   this_arc_intervalr   size_of_melodic_arcss                r   r)   z SizeOfMelodicArcsFeature.process  s    99!#499//0		'*1-m<u% 1 IIm,ENN5! 	

E * !!$	1!|)S]:)!A(,==()Q.),6),/M)&*4!|)S]:)!A(,==()Q.),5),/M)!|,5))S]:)!A,6))S]:)7 " B !#$ #36G#G !5Ar   r*   r+   r2   s   @r   r   r     s    6 
B=6r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS ) MostCommonPitchPrevalenceFeaturez
    Fraction of Notes corresponding to the most common pitch.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MostCommonPitchPrevalenceFeature(s)
    >>> fe.extract().vector[0]
    0.116...
    P1c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   zMost Common Pitch Prevalencez<Fraction of Note Ons corresponding to the most common pitch.Tr7   Fr   r   r   r   r   r   r   discreter   s      r   r   z)MostCommonPitchPrevalenceFeature.__init__G  s=    ?l?h?2	Y r   c                    | j                   d   }|st        d      t        |j                               }t	        |j                               }||z  | j
                  j                  d<   yr!   pitches.midiPitchHistogramr;   r   N)r$   r>   rJ   rA   r?   r%   r&   )r   rB   pcMaxpcCounts       r   r)   z(MostCommonPitchPrevalenceFeature.processP  s\     		67+,?@@ ELLN#elln%!&Ar   r*   r+   r2   s   @r   r   r   <  s     
B1r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )%MostCommonPitchClassPrevalenceFeaturez
    Fraction of Notes corresponding to the most common pitch class.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MostCommonPitchClassPrevalenceFeature(s)
    >>> fe.extract().vector
    [0.196...]
    P2c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   z"Most Common Pitch Class PrevalencezBFraction of Note Ons corresponding to the most common pitch class.Tr7   Fr   r   r   s      r   r   z.MostCommonPitchClassPrevalenceFeature.__init__j  s=    ?l?h?8	_ r   c                    | j                   d   }|j                  t        |            }t        |      }|st	        d      ||   |z  | j
                  j                  d<   yr!   pitches.pitchClassHistogramr;   r   N)r$   rK   rJ   r?   r>   r%   r&   )r   rB   pcr   s       r   r)   z-MostCommonPitchClassPrevalenceFeature.processs  s\     		78 [[U$e*+,?@@!&rW!4Ar   r*   r+   r2   s   @r   r   r   _  s     
B5r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )#RelativeStrengthOfTopPitchesFeaturez
    The frequency of the 2nd most common pitch divided by the frequency of the most common pitch.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.RelativeStrengthOfTopPitchesFeature(s)
    >>> fe.extract().vector
    [0.947...]
    P3c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   z Relative Strength of Top Pitchesz]The frequency of the 2nd most common pitch divided by the frequency of the most common pitch.Tr7   Fr   r   r   s      r   r   z,RelativeStrengthOfTopPitchesFeature.__init__  s@    ?l?h?6	Q r   c                *   | j                   d   }	 |j                  d      dd \  }}t        |d   |d   z        | j                  j                  d<   y# t
        $ r t        d      t        t        f$ r d| j                  j                  d<   Y yw xY w)r!   r   r   Nr7   r   r;           )	r$   most_commonfloatr%   r&   ZeroDivisionErrorr>   
IndexError
ValueErrorr   rB   pMaxpSeconds       r   r)   z+RelativeStrengthOfTopPitchesFeature.process  s     		67	)!--a0!4MD'%*71:Q+?%@DLL"  	A+,?@@J' 	)%(DLL"	)s   AA ;BBr*   r+   r2   s   @r   r   r     s     
B)r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )(RelativeStrengthOfTopPitchClassesFeaturez

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.RelativeStrengthOfTopPitchClassesFeature(s)
    >>> fe.extract().vector
    [0.906...]
    P4c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   z&Relative Strength of Top Pitch ClassesziThe frequency of the 2nd most common pitch class divided by the frequency of the most common pitch class.Tr7   Fr   r   r   s      r   r   z1RelativeStrengthOfTopPitchClassesFeature.__init__  s@    ?l?h?<	W r   c                    t        j                  | j                  d         }|j                  t	        |            }||   }|st        d      d||<   |j                  t	        |            }||   }||z  | j                  j                  d<   yr   )rS   rT   r$   rK   rJ   r>   r%   r&   )r   rB   	pIndexMax	pCountMaxpIndexSecondpCountSeconds         r   r)   z0RelativeStrengthOfTopPitchClassesFeature.process  s    
 dii(EFG KKE
+	)$	+,?@@i{{3u:.\*!-	!9Ar   r*   r+   r2   s   @r   r   r     s     
B:r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )&IntervalBetweenStrongestPitchesFeaturez
    Absolute value of the difference between the pitches of the two most common MIDI pitches.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.IntervalBetweenStrongestPitchesFeature(s)
    >>> fe.extract().vector
    [5]
    P5c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z"Interval Between Strongest PitcheszYAbsolute value of the difference between the pitches of the two most common MIDI pitches.Tr7   r   r8   r   s      r   r   z/IntervalBetweenStrongestPitchesFeature.__init__  s9    ?l?h?8	O r   c                   | j                   d   }	 |j                  d      dd \  }}t        |d   |d   z
        | j                  j                  d<   y# t
        t        f$ r d| j                  j                  d<   Y yw xY w)r!   r   r   Nr   r   )r$   r   rU   r%   r&   r   r   r   s       r   r)   z.IntervalBetweenStrongestPitchesFeature.process  s     		67	)!--a0!4MD'%(d1g)=%>DLL"J' 	)%(DLL"	)s   AA (A?>A?r*   r+   r2   s   @r   r   r     s     
B)r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )+IntervalBetweenStrongestPitchClassesFeaturez

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.IntervalBetweenStrongestPitchClassesFeature(s)
    >>> fe.extract().vector
    [5]
    P6c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z(Interval Between Strongest Pitch ClasseszeAbsolute value of the difference between the pitch classes of the two most common MIDI pitch classes.Tr7   r   r8   r   s      r   r   z4IntervalBetweenStrongestPitchClassesFeature.__init__  s9    ?l?h?>	Q r   c                   t        j                  | j                  d         }|j                  t	        |            }d||<   |j                  t	        |            }t        ||z
        | j                  j                  d<   yr!   r   r   N)rS   rT   r$   rK   rJ   rU   r%   r&   )r   rB   r   r   s       r   r)   z3IntervalBetweenStrongestPitchClassesFeature.process  sl     dii(EFG KKE
+	i{{3u:. "%Y%=!>Ar   r*   r+   r2   s   @r   r   r     s     
B?r   r   c                  .     e Zd ZdZdZd fd	Zd Z xZS )NumberOfCommonPitchesFeaturez
    Number of pitches that account individually for at least 9% of all notes.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.NumberOfCommonPitchesFeature(s)
    >>> fe.extract().vector
    [3]
    P7c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zNumber of Common PitcheszINumber of pitches that account individually for at least 9% of all notes.Tr7   r   r8   r   s      r   r   z%NumberOfCommonPitchesFeature.__init__!  s8    ?l?h?.	< r   c                    | j                   d   }t        |j                               }d}|j                         D ]  }||z  dk\  s|dz  } || j                  j                  d<   y)r!   r   r   rh   r7   N)r$   r?   rA   r%   r&   )r   rB   ri   rj   r]   s        r   r)   z$NumberOfCommonPitchesFeature.process*  sc     		67ELLN#\\^Eu}$	 $ "&Ar   r*   r+   r2   s   @r   r  r    s     
B
&r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )PitchVarietyFeaturez
    Number of pitches used at least once.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.PitchVarietyFeature(s)
    >>> fe.extract().vector
    [24]
    P8c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zPitch Varietyz%Number of pitches used at least once.Tr7   r   r8   r   s      r   r   zPitchVarietyFeature.__init__B  s6    ?l?h?#	B r   c                    | j                   d   }d}t        |      D ]  \  }}|dk\  s|dz  } || j                  j                  d<   y)r!   r   r   r7   Nr$   r#   r%   r&   r   rB   rj   r'   r]   s        r   r)   zPitchVarietyFeature.processJ  sQ     		67!%(HAuz	 ) "&Ar   r*   r+   r2   s   @r   r  r  7       
B	&r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )PitchClassVarietyFeaturez
    Number of pitch classes used at least once.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.PitchClassVarietyFeature(s)
    >>> fe.extract().vector
    [10]
    P9c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zPitch Class Varietyz+Number of pitch classes used at least once.Tr7   r   r8   r   s      r   r   z!PitchClassVarietyFeature.__init__a  s6    ?l?h?)	H r   c                    | j                   d   }d}t        |      D ]  \  }}|dk\  s|dz  } || j                  j                  d<   y)r!   r   r   r7   Nr  r  s        r   r)   z PitchClassVarietyFeature.processi  sQ     		78!%(HAuz	 ) "&Ar   r*   r+   r2   s   @r   r  r  V  r  r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )RangeFeaturez
    Difference between highest and lowest pitches. In semitones

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.RangeFeature(s)
    >>> fe.extract().vector
    [34]
    P10c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   Rangez.Difference between highest and lowest pitches.Tr7   r   r8   r   s      r   r   zRangeFeature.__init__  s6    ?l?h?	K r   c                    | j                   d   }|st        d      t        |j                               }t	        |j                               }||z
  | j
                  j                  d<   yr   )r$   r>   minkeysrJ   r%   r&   )r   rB   minIndexrM   s       r   r)   zRangeFeature.process  s[     		67+,?@@uzz|$uzz|$!)H!4Ar   r*   r+   r2   s   @r   r  r  u  s     
B
5r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )MostCommonPitchFeaturez
    Bin label of the most common pitch.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MostCommonPitchFeature(s)
    >>> fe.extract().vector
    [61]
    P11c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   zMost Common Pitchz#Bin label of the most common pitch.Tr7   Fr   r   r   s      r   r   zMostCommonPitchFeature.__init__  s=    ?l?h?'	@ r   c                    | j                   d   }	 |j                  d      d   d   }|| j                  j                  d<   y# t        $ r d| j                  j                  d<   Y yw xY w)r!   r   r7   r   r   N)r$   r   r%   r&   r   )r   rB   
pNumberMaxs      r   r)   zMostCommonPitchFeature.process  si     		67	)**1-a03J%/DLL" 	)%(DLL"	)s   0A "A'&A'r*   r+   r2   s   @r   r!  r!    s     
B	)r   r!  c                  .     e Zd ZdZdZd fd	Zd Z xZS )PrimaryRegisterFeaturez
    Average MIDI pitch.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.PrimaryRegisterFeature(s)
    >>> fe.extract().vector
    [61.12...]
    P12c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   zPrimary RegisterzAverage MIDI pitch.Tr7   Fr   r   r   s      r   r   zPrimaryRegisterFeature.__init__  s=    ?l?h?&	0 r   c                    | j                   d   }|st        d      t        j                  |D cg c]  }|j                   c}      | j
                  j                  d<   yc c}w )r!   pitchesr;   r   N)r$   r>   
statisticsmeanpsr%   r&   )r   rB   ps      r   r)   zPrimaryRegisterFeature.process  sT     		)$+,?@@!+1F1!$$1F!GA1Fs   A"r*   r+   r2   s   @r   r'  r'    s     
BHr   r'  c                  .     e Zd ZdZdZd fd	Zd Z xZS )ImportanceOfBassRegisterFeaturez
    Fraction of Notes between MIDI pitches 0 and 54.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.ImportanceOfBassRegisterFeature(s)
    >>> fe.extract().vector
    [0.184...]
    P13c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   zImportance of Bass Registerz3Fraction of Note Ons between MIDI pitches 0 and 54.Tr7   Fr   r   r   s      r   r   z(ImportanceOfBassRegisterFeature.__init__  s=    ?l?h?1	P r   c                   | j                   d   }|st        d      g }|j                         D ]  \  }}|dk  s|j                  |        t	        |      }|t	        |j                               z  | j                  j                  d<   y)r!   r   r;   6   r   Nr$   r>   itemsr=   r?   rA   r%   r&   r   rB   matchesr'   r]   
matchedSums         r   r)   z'ImportanceOfBassRegisterFeature.process  }     		67+,?@@HAuBwu% & \
!+c%,,..A!AAr   r*   r+   r2   s   @r   r1  r1         
BBr   r1  c                  .     e Zd ZdZdZd fd	Zd Z xZS )!ImportanceOfMiddleRegisterFeaturez
    Fraction of Notes between MIDI pitches 55 and 72

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.ImportanceOfMiddleRegisterFeature(s)
    >>> fe.extract().vector
    [0.766...]
    P14c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   zImportance of Middle Registerz4Fraction of Note Ons between MIDI pitches 55 and 72.Tr7   Fr   r   r   s      r   r   z*ImportanceOfMiddleRegisterFeature.__init__  s=    ?l?h?3	Q r   c                ,   | j                   d   }|st        d      g }|j                         D ]%  \  }}d|cxk  rdk  sn |j                  |       ' t	        |      }|t	        |j                               z  | j                  j                  d<   y)r!   r   r;   7   r   r   Nr6  r8  s         r   r)   z)ImportanceOfMiddleRegisterFeature.process  s     		67+,?@@HAuQ}"}u% & \
!+c%,,..A!AAr   r*   r+   r2   s   @r   r>  r>    r<  r   r>  c                  .     e Zd ZdZdZd fd	Zd Z xZS )ImportanceOfHighRegisterFeaturez
    Fraction of Notes between MIDI pitches 73 and 127.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.ImportanceOfHighRegisterFeature(s)
    >>> fe.extract().vector
    [0.049...]
    P15c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   zImportance of High Registerz5Fraction of Note Ons between MIDI pitches 73 and 127.Tr7   Fr   r   r   s      r   r   z(ImportanceOfHighRegisterFeature.__init__(  s=    ?l?h?1	R r   c                   | j                   d   }|st        d      g }|j                         D ]  \  }}|dk\  s|j                  |        t	        |      }|t	        |j                               z  | j                  j                  d<   y)r!   r   r;   I   r   Nr6  r8  s         r   r)   z'ImportanceOfHighRegisterFeature.process1  r;  r   r*   r+   r2   s   @r   rD  rD    r<  r   rD  c                  .     e Zd ZdZdZd fd	Zd Z xZS )MostCommonPitchClassFeaturez
    Bin label of the most common pitch class.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MostCommonPitchClassFeature(s)
    >>> fe.extract().vector
    [1]
    P16c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zMost Common Pitch Classz)Bin label of the most common pitch class.Tr7   r   r8   r   s      r   r   z$MostCommonPitchClassFeature.__init__M  s6    ?l?h?-	F r   c                    | j                   d   }|j                  t        |            }|| j                  j                  d<   yr  r$   rK   rJ   r%   r&   )r   rB   r   s      r   r)   z#MostCommonPitchClassFeature.processU  s9     		78KKE
+	!*Ar   r*   r+   r2   s   @r   rJ  rJ  B  s     
B+r   rJ  c                  .     e Zd ZdZdZd fd	Zd Z xZS )DominantSpreadFeaturez
    Not implemented

    Largest number of consecutive pitch classes separated by perfect
    5ths that accounted for at least 9% each of the notes.
    P17c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zDominant SpreadzwLargest number of consecutive pitch classes separated by perfect 5ths that accounted for at least 9% each of the notes.Tr7   r   r8   r   s      r   r   zDominantSpreadFeature.__init__g  s9    ?l?h?%	] r   c                    t        d      Nznot yet implementedr>   r   s    r   r)   zDominantSpreadFeature.processp      '(=>>r   r*   r+   r2   s   @r   rP  rP  ^       
B?r   rP  c                  .     e Zd ZdZdZd fd	Zd Z xZS )StrongTonalCentresFeaturez
    Not implemented

    Number of peaks in the fifths pitch histogram that each account
    for at least 9% of all Note Ons.
    P18c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zStrong Tonal Centresz`Number of peaks in the fifths pitch histogram that each account for at least 9% of all Note Ons.Tr7   r   r8   r   s      r   r   z"StrongTonalCentresFeature.__init__~  s8    ?l?h?*	? r   c                    t        d      rT  rU  rV  s    r   r)   z!StrongTonalCentresFeature.process  rW  r   r*   r+   r2   s   @r   rZ  rZ  u  rX  r   rZ  c                  .     e Zd ZdZdZd fd	Zd Z xZS )BasicPitchHistogramFeatureaB  
    A feature extractor that finds a features array with bins corresponding
    to the values of the basic pitch histogram.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.BasicPitchHistogramFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.006..., 0.0, 0.0, 0.006..., 0.006..., 0.030...,
     0.0, 0.036..., 0.012..., 0.0, 0.006..., 0.018..., 0.061..., 0.0,
     0.042..., 0.073..., 0.012..., 0.092..., 0.0, 0.116..., 0.061...,
     0.006..., 0.085..., 0.018..., 0.110..., 0.0, 0.042..., 0.055...,
     0.0, 0.049..., 0.0, 0.042..., 0.0, 0.0, 0.006..., 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
    P19c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   zBasic Pitch HistogramzTA features array with bins corresponding to the values of the basic pitch histogram.Tr   r   r   r   s      r   r   z#BasicPitchHistogramFeature.__init__  s@    ?l?h?+	C r   c                    | j                   d   j                         D ]  \  }}|| j                  j                  |<     y)r!   r   N)r$   r7  r%   r&   r   r'   r]   s      r   r)   z"BasicPitchHistogramFeature.process  s:     		">?EEGHAu%*DLL" Hr   r*   r+   r2   s   @r   r_  r_    s    * 
B+r   r_  c                  .     e Zd ZdZdZd fd	Zd Z xZS )PitchClassDistributionFeaturea  
    A feature array with 12 entries where the first holds the frequency
    of the bin of the pitch class histogram with the highest frequency,
    and the following entries holding the successive bins of the histogram,
    wrapping around if necessary.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.PitchClassDistributionFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.196..., 0.073..., 0.006..., 0.098..., 0.036..., 0.177..., 0.0,
     0.085..., 0.134..., 0.018..., 0.171..., 0.0]
    P20c                |    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        d| _        y )Nr   zPitch Class DistributionzA feature array with 12 entries where the first holds the frequency of the bin of the pitch class histogram with the highest frequency, and the following entries holding the successive bins of the histogram, wrapping around if necessary.Tru   Fr   )r   r   r   r   r   r   r   r   r   s      r   r   z&PitchClassDistributionFeature.__init__  sI    ?l?h?.	b !r   c                   dg| j                   z  }t        | j                  d         D ]
  \  }}|||<    |j                  t	        |            }t        |      D ].  \  }}|| j
                  j                  ||z
  | j                   z  <   0 y)r!   r   r   N)r   r#   r$   rK   rJ   r%   r&   )r   tempr'   r]   mvals         r   r)   z%PitchClassDistributionFeature.process  s    
 sT__$!$)),I"JKHAuDG L JJs4y!oFAs=@DLLQ$// 9: &r   r*   r+   r2   s   @r   re  re    s     
BAr   re  c                  .     e Zd ZdZdZd fd	Zd Z xZS )FifthsPitchHistogramFeaturea  
    A feature array with bins corresponding to the values of the 5ths pitch class
    histogram. Instead of the bins being arranged according to semitones --
    [C, C#, D, etc.] -- they are arranged according to the circle of fifths:
    [C, G, D, A, E, B, F#, C#, G#, D#, A#, F]. Viewing such a histogram
    may draw attention to the prevalence of a tonal center, including the
    prevalence of dominant relationships in the piece.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.FifthsPitchHistogramFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.0, 0.0, 0.073..., 0.134..., 0.098..., 0.171..., 0.177..., 0.196...,
     0.085..., 0.006..., 0.018..., 0.036...]
    P21c                    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        i | _        t        d      D ]  }d|z  dz  | j                  |<    y )Nr   zFifths Pitch HistogramzXA feature array with bins corresponding to the values of the 5ths pitch class histogram.Tru   rr   r   )	r   r   r   r   r   r   r   _mappingr<   )r   r   r   r'   r   s       r   r   z$FifthsPitchHistogramFeature.__init__  sl    ?l?h?,	:  rA !A|DMM! r   c                    t        | j                  d         D ]+  \  }}|| j                  j                  | j                  |   <   - y)r!   r   N)r#   r$   r%   r&   rp  rc  s      r   r)   z#FifthsPitchHistogramFeature.process  s?     "$)),I"JKHAu49DLLa 01 Lr   r*   r+   r2   s   @r   rm  rm    s     
B,:r   rm  c                  .     e Zd ZdZdZd fd	Zd Z xZS )QualityFeaturea  
    Set to 0 if the key signature indicates that
    a recording is major, set to 1 if it indicates
    that it is minor.  In jSymbolic, this is set to 0 if key signature is unknown.

    See features.native.QualityFeature for a music21 improvement on this method

    Example: Handel, Rinaldo Aria (musicxml) is explicitly encoded as being in Major:

    >>> s = corpus.parse('handel/rinaldo/lascia_chio_pianga')
    >>> fe = features.jSymbolic.QualityFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.QualityFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [1]
    P22c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   Qualityz
            Set to 0 if the key signature indicates that
            a recording is major, set to 1 if it indicates
            that it is minor and set to 0 if key signature is unknown.
            Tr7   r   r8   r   s      r   r   zQualityFeature.__init__$  s:    ?l?h?	
 !r   c                    | j                   d   }d}|D ](  }|j                  dk(  rd} n|j                  dk(  s&d} n |d}|| j                  j                  d<   y)r!   zflat.getElementsByClass(Key)Nmajorr   minorr7   )r$   moder%   r&   )r   allKeys
keyFeaturexs       r   r)   zQualityFeature.process0  sk     )):;
Avv 
7"
  J!+Ar   r*   r+   r2   s   @r   rs  rs    s    * 
B
,r   rs  c                  .     e Zd ZdZdZd fd	Zd Z xZS )GlissandoPrevalenceFeaturez
    Not yet implemented in music21

    Number of Note Ons that have at least one MIDI Pitch Bend associated
    with them divided by total number of pitched Note Ons.
    P23c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zGlissando Prevalencez{Number of Note Ons that have at least one MIDI Pitch Bend associated with them divided by total number of pitched Note Ons.Tr7   r   r8   r   s      r   r   z#GlissandoPrevalenceFeature.__init__L  s9    ?l?h?*	` r   c                    t        d      rT  rU  rV  s    r   r)   z"GlissandoPrevalenceFeature.processU  rW  r   r*   r+   r2   s   @r   r  r  C  rX  r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )AverageRangeOfGlissandosFeaturea(  
    Not yet implemented in music21

    Average range of MIDI Pitch Bends, where "range" is defined
    as the greatest value of the absolute difference between 64 and the
    second data byte of all MIDI Pitch Bend messages falling between the
    Note On and Note Off messages of any note
    P24c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zAverage Range Of GlissandoszAverage range of MIDI Pitch Bends, where "range" is defined as the greatest value of the absolute difference between 64 and the second data byte of all MIDI Pitch Bend messages falling between the Note On and Note Off messages of any note.Tr7   r   r8   r   s      r   r   z(AverageRangeOfGlissandosFeature.__init__e  s:    ?l?h?1	+
 !r   c                    t        d      rT  rU  rV  s    r   r)   z'AverageRangeOfGlissandosFeature.processq  rW  r   r*   r+   r2   s   @r   r  r  Z       
B
?r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )VibratoPrevalenceFeaturez
    Not yet implemented in music21

    Number of notes for which Pitch Bend messages change direction at least twice divided by
    total number of notes that have Pitch Bend messages associated with them.

    P25c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zVibrato PrevalencezNumber of notes for which Pitch Bend messages change direction at least twice divided by total number of notes that have Pitch Bend messages associated with them.Tr7   r   r8   r   s      r   r   z!VibratoPrevalenceFeature.__init__  s;    ?l?h?(	R !r   c                    t        d      rT  rU  rV  s    r   r)   z VibratoPrevalenceFeature.process  rW  r   r*   r+   r2   s   @r   r  r  v       
B?r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )PrevalenceOfMicrotonesFeaturez
    not yet implemented

    Number of Note Ons that are preceded by isolated MIDI Pitch Bend
    messages as a fraction of the total number of Note Ons.'

    P26c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zPrevalence Of MicrotoneszxNumber of Note Ons that are preceded by isolated MIDI Pitch Bend messages as a fraction of the total number of Note Ons.Tr7   r   r8   r   s      r   r   z&PrevalenceOfMicrotonesFeature.__init__  sB     	%l 	%#	% /	[ r   c                    t        d      rT  rU  rV  s    r   r)   z%PrevalenceOfMicrotonesFeature.process  rW  r   r*   r+   r2   s   @r   r  r    r  r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )StrongestRhythmicPulseFeaturea  
    Bin label of the beat bin of the peak with the highest frequency.

    >>> sch = corpus.parse('schoenberg/opus19', 2)
    >>> for p in sch.parts:
    ...     p.insert(0, tempo.MetronomeMark('Langsam', 70))
    >>> fe = features.jSymbolic.StrongestRhythmicPulseFeature(sch)
    >>> f = fe.extract()
    >>> f.vector[0]
    140

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.StrongestRhythmicPulseFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [96]
    R1c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zStrongest Rhythmic Pulsez5Bin label of the beat bin with the highest frequency.Tr7   r   r8   r   s      r   r   z&StrongestRhythmicPulseFeature.__init__  s6    ?l?h?.	R r   c                    | j                   d   }|j                  t        |            | j                  j                  d<   y Nzflat.secondsMap.beatHistogramr   rN  r   	beatHistos     r   r)   z%StrongestRhythmicPulseFeature.process  s2    II=>	!*Y!@Ar   r*   r+   r2   s   @r   r  r    s    $ 
BAr   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )#SecondStrongestRhythmicPulseFeaturea  
    Bin label of the beat bin of the peak with the second-highest frequency.

    >>> sch = corpus.parse('schoenberg/opus19', 2)
    >>> for p in sch.parts:
    ...     p.insert(0, tempo.MetronomeMark('Langsam', 70))
    >>> fe = features.jSymbolic.SecondStrongestRhythmicPulseFeature(sch)
    >>> f = fe.extract()
    >>> f.vector[0]
    70

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.SecondStrongestRhythmicPulseFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [192]

    R2c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zSecond Strongest Rhythmic PulsezHBin label of the beat bin of the peak with the second highest frequency.Tr7   r   r8   r   s      r   r   z,SecondStrongestRhythmicPulseFeature.__init__  s9    ?l?h?5	A r   c                    t        j                   | j                  d         }|j                  t        |            }d||<   |j                  t        |            | j                  j
                  d<   y r  )rS   r$   rK   rJ   r%   r&   )r   r  highestIndexs      r   r)   z+SecondStrongestRhythmicPulseFeature.process  sW    IIdii(GHI	 s9~6"#	,!*Y!@Ar   r*   r+   r2   s   @r   r  r    s    $ 
BAr   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS ).HarmonicityOfTwoStrongestRhythmicPulsesFeatureaf  
    The bin label of the higher (in terms of bin label) of the two beat bins of the
    peaks with the highest frequency divided by the bin label of the lower.

    >>> sch = corpus.parse('schoenberg/opus19', 2)
    >>> for p in sch.parts:
    ...     p.insert(0, tempo.MetronomeMark('Langsam', 70))
    >>> fe = features.jSymbolic.HarmonicityOfTwoStrongestRhythmicPulsesFeature(sch)
    >>> f = fe.extract()
    >>> f.vector[0]
    2.0

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.HarmonicityOfTwoStrongestRhythmicPulsesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.5]

    R3c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z,Harmonicity of Two Strongest Rhythmic PulseszThe bin label of the higher (in terms of bin label) of the two beat bins of the peaks with the highest frequency divided by the bin label of the lower.Tr7   r   r8   r   s      r   r   z7HarmonicityOfTwoStrongestRhythmicPulsesFeature.__init__
  s;    ?l?h?B	E !r   c                   t        j                   | j                  d         }|j                  t        |            }d||<   |j                  t        |            }t	        ||z        | j
                  j                  d<   y r  )rS   r$   rK   rJ   r   r%   r&   )r   r  r  secondHighests       r   r)   z6HarmonicityOfTwoStrongestRhythmicPulsesFeature.process  sf    IIdii(GHI	 s9~6"#	,!I7!&|m'C!DAr   r*   r+   r2   s   @r   r  r    s    & 
BEr   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )'StrengthOfStrongestRhythmicPulseFeatureaD  
    Frequency of the beat bin with the highest frequency.

    >>> sch = corpus.parse('schoenberg/opus19', 2)
    >>> for p in sch.parts:
    ...     p.insert(0, tempo.MetronomeMark('Langsam', 70))
    >>> fe = features.jSymbolic.StrengthOfStrongestRhythmicPulseFeature(sch)
    >>> fe.extract().vector[0]
    0.853...
    R4c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z$Strength of Strongest Rhythmic Pulsez5Frequency of the beat bin with the highest frequency.Tr7   r   r8   r   s      r   r   z0StrengthOfStrongestRhythmicPulseFeature.__init__*  s6    ?l?h?:	R r   c                ~    | j                   d   }t        |      t        |      z  | j                  j                  d<   y r  )r$   rJ   r?   r%   r&   r  s     r   r)   z/StrengthOfStrongestRhythmicPulseFeature.process2  s2    II=>	!$Y#i.!@Ar   r*   r+   r2   s   @r   r  r    s    	 
BAr   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )-StrengthOfSecondStrongestRhythmicPulseFeaturea]  
    Frequency of the beat bin of the peak with the second-highest frequency.

    >>> sch = corpus.parse('schoenberg/opus19', 2)
    >>> for p in sch.parts:
    ...     p.insert(0, tempo.MetronomeMark('Langsam', 70))
    >>> fe = features.jSymbolic.StrengthOfSecondStrongestRhythmicPulseFeature(sch)
    >>> fe.extract().vector[0]
    0.121...
    R5c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z+Strength of Second Strongest Rhythmic PulsezHFrequency of the beat bin of the peak with the second highest frequency.Tr7   r   r8   r   s      r   r   z6StrengthOfSecondStrongestRhythmicPulseFeature.__init__E  s9    ?l?h?A	A r   c                    t        j                   | j                  d         }t        |      }|j                  t	        |            }d||<   t	        |      }||z  | j
                  j                  d<   y r  )rS   r$   r?   rK   rJ   r%   r&   )r   r  sumHistor  r  s        r   r)   z5StrengthOfSecondStrongestRhythmicPulseFeature.processN  sa    IIdii(GHI	y> s9~6"#	,I!.!9Ar   r*   r+   r2   s   @r   r  r  7  s    	 
B:r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )0StrengthRatioOfTwoStrongestRhythmicPulsesFeaturea  
    The frequency of the higher (in terms of frequency) of the two beat bins
    corresponding to the peaks with the highest frequency divided by the frequency of the lower.

    >>> sch = corpus.parse('schoenberg/opus19', 2)
    >>> for p in sch.parts:
    ...     p.insert(0, tempo.MetronomeMark('Langsam', 70))
    >>> fe = features.jSymbolic.StrengthRatioOfTwoStrongestRhythmicPulsesFeature(sch)
    >>> fe.extract().vector[0]
    7.0

    R6c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z/Strength Ratio of Two Strongest Rhythmic PulseszThe frequency of the higher (in terms of frequency) of the two beat bins corresponding to the peaks with the highest frequency divided by the frequency of the lower.Tr7   r   r8   r   s      r   r   z9StrengthRatioOfTwoStrongestRhythmicPulsesFeature.__init__i  s;    ?l?h?E	O !r   c                    t        j                   | j                  d         }t        |      }|j                  |      }d||<   t        |      }||z  | j                  j
                  d<   y r  )rS   r$   rJ   rK   r%   r&   )r   r  
theHighestr  r  s        r   r)   z8StrengthRatioOfTwoStrongestRhythmicPulsesFeature.processs  s]    IIdii(GHI	^
 z2"#	,I!+m!;Ar   r*   r+   r2   s   @r   r  r  Y  s     
B<r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )3CombinedStrengthOfTwoStrongestRhythmicPulsesFeatureau  
    The sum of the frequencies of the two beat bins of the peaks with the highest frequencies.

    >>> sch = corpus.parse('schoenberg/opus19', 2)
    >>> for p in sch.parts:
    ...     p.insert(0, tempo.MetronomeMark('Langsam', 70))
    >>> fe = features.jSymbolic.CombinedStrengthOfTwoStrongestRhythmicPulsesFeature(sch)
    >>> fe.extract().vector[0]
    0.975...
    R7c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z2Combined Strength of Two Strongest Rhythmic PulseszZThe sum of the frequencies of the two beat bins of the peaks with the highest frequencies.Tr7   r   r8   r   s      r   r   z<CombinedStrengthOfTwoStrongestRhythmicPulsesFeature.__init__  s9    ?l?h?H	I r   c                    t        j                   | j                  d         }t        |      }t        |      }|j	                  |      }d||<   t        |      }||z   |z  | j
                  j                  d<   y r  )rS   r$   r?   rJ   rK   r%   r&   )r   r  r  r  r  r  s         r   r)   z;CombinedStrengthOfTwoStrongestRhythmicPulsesFeature.process  sk    IIdii(GHI	y>^
 z2"#	,I",}"<!HAr   r*   r+   r2   s   @r   r  r  ~  s    	 
B	Ir   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )NumberOfStrongPulsesFeaturez^
    Not yet implemented

    Number of beat peaks with normalized frequencies over 0.1.

    R8c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zNumber of Strong Pulsesz:Number of beat peaks with normalized frequencies over 0.1.Tr7   r   r8   r   s      r   r   z$NumberOfStrongPulsesFeature.__init__  s6    ?l?h?-	W r   c                    t        d      rT  rU  rV  s    r   r)   z#NumberOfStrongPulsesFeature.process  rW  r   r*   r+   r2   s   @r   r  r    s     
B?r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )NumberOfModeratePulsesFeaturez^
    Not yet implemented

    Number of beat peaks with normalized frequencies over 0.01.
    R9c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zNumber of Moderate Pulsesz;Number of beat peaks with normalized frequencies over 0.01.Tr7   r   r8   r   s      r   r   z&NumberOfModeratePulsesFeature.__init__  s6    ?l?h?/	X r   c                    t        d      rT  rU  rV  s    r   r)   z%NumberOfModeratePulsesFeature.process  rW  r   r*   r+   r2   s   @r   r  r    s    
 
B?r   r  c                  (     e Zd ZdZdZd fd	Z xZS )%NumberOfRelativelyStrongPulsesFeaturez
    not yet implemented

    Number of beat peaks with frequencies at least 30% as high as the
    frequency of the bin with the highest frequency.
    R10c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z"Number of Relatively Strong PulseszrNumber of beat peaks with frequencies at least 30% as high as the frequency of the bin with the highest frequency.Tr7   r   r8   r   s      r   r   z.NumberOfRelativelyStrongPulsesFeature.__init__  s9    ?l?h?8	S r   r*   r,   r-   r.   r/   r0   r   r1   r2   s   @r   r  r    s     
B r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )RhythmicLoosenessFeaturea8  
    not yet implemented

    Average width of beat histogram peaks (in beats per minute).
    Width is measured for all peaks with frequencies at least 30% as high as the highest peak,
    and is defined by the distance between the points on the peak in question that are
    30% of the height of the peak.
    R11c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zRhythmic Loosenessa:  
            Average width of beat histogram peaks (in beats per minute).
            Width is measured for all peaks with frequencies at least 30% as high as the
            highest peak, and is defined by the distance between the points on the peak in
            question that are 30% of the height of the peak.Tr7   r   r   r   r   r   r   r   r   r   s      r   r   z!RhythmicLoosenessFeature.__init__  sD    ?l?h?(	! #@ A
 !r   c                    t        d      rT  rU  rV  s    r   r)   z RhythmicLoosenessFeature.process  rW  r   r*   r+   r2   s   @r   r  r    r  r   r  c                  "    e Zd ZdZdZddZd Zy)PolyrhythmsFeaturea  
    Not yet implemented

    Number of beat peaks with frequencies at least 30% of the highest frequency
    whose bin labels are not integer multiples or factors
    (using only multipliers of 1, 2, 3, 4, 6 and 8) (with an accepted
    error of +/- 3 bins) of the bin label of the peak with the highest frequency.
    This number is then divided by the total number of beat bins with frequencies
    over 30% of the highest frequency.
    R12Nc                    t        j                  j                  | fd|i| d| _        d| _        d| _        d| _        y )Nr   Polyrhythmsa  
        Number of beat peaks with frequencies at least 30% of the highest frequency
        whose bin labels are not integer multiples or factors
        (using only multipliers of 1, 2, 3, 4, 6 and 8) (with an accepted
        error of +/- 3 bins) of the bin label of the peak with the highest frequency.
        This number is then divided by the total number of beat bins with frequencies
        over 30% of the highest frequency.Tr7   )featuresModuleFeatureExtractorr   r   r   r   r   )r   r   r   s      r   r   zPolyrhythmsFeature.__init__  sL    ''00 	=>J	=3;	= "	. !r   c                    t        d      rT  rU  rV  s    r   r)   zPolyrhythmsFeature.process  rW  r   r*   )r,   r-   r.   r/   r0   r   r)   r   r   r   r  r    s    	 
B ?r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )RhythmicVariabilityFeaturezi
    Not yet implemented

    Standard deviation of the bin values (except the first 40 empty ones).
    R13c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zRhythmic VariabilityzFStandard deviation of the bin values (except the first 40 empty ones).Tr7   r   r8   r   s      r   r   z#RhythmicVariabilityFeature.__init__%  s6    ?l?h?*	c r   c                    t        d      rT  rU  rV  s    r   r)   z"RhythmicVariabilityFeature.process-  rW  r   r*   r+   r2   s   @r   r  r    s    
 
B?r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )BeatHistogramFeaturez
    Not yet implemented

    A feature extractor that finds a feature array with entries corresponding to the frequency
    values of each of the bins of the beat histogram (except the first 40 empty ones).

    R14c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   zBeat HistogramzA feature array with entries corresponding to the frequency values of each of the bins of the beat histogram (except the first 40 empty ones).T   Fr   r   r   s      r   r   zBeatHistogramFeature.__init__<  sB    ?l?h?$	@ !r   c                    t        d      rT  rU  rV  s    r   r)   zBeatHistogramFeature.processG  rW  r   r*   r+   r2   s   @r   r  r  2  s     
B	?r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )NoteDensityFeaturea  
    Gives the average number of notes per second, taking into account
    the tempo at any moment in the piece.  Unlike jSymbolic, music21
    quantizes notes from MIDI somewhat before running this test; this
    function is meant to be run on encoded MIDI scores rather than
    recorded MIDI performances.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.NoteDensityFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [7.244...]
    R15c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zNote Densityz#Average number of notes per second.Tr7   r   r8   r   s      r   r   zNoteDensityFeature.__init__\  s6    ?l?h?"	@ r   c                
   | j                   d   }|D cg c]  }|d   	 }}|j                          |sd| j                  j                  d<   y t	        t        |            |d   z  | j                  j                  d<   y c c}w )Nflat.secondsMapendTimeSecondsr   r   r   )r$   sortr%   r&   r   r@   r   
secondsMapbundle	end_timess       r   r)   zNoteDensityFeature.processd  s{    YY01
 =GGJ&V,-J	G%(DLL"%*3y>%:Yr]%JDLL" Hs   B r*   r+   r2   s   @r   r  r  L  s     
BKr   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )AverageNoteDurationFeaturea{  
    Average duration of notes in seconds.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.AverageNoteDurationFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.552...]

    >>> s.insert(0, tempo.MetronomeMark(number=240))
    >>> fe = features.jSymbolic.AverageNoteDurationFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.220858...]
    R17c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zAverage Note Durationz%Average duration of notes in seconds.Tr7   r   r8   r   s      r   r   z#AverageNoteDurationFeature.__init__  s6    ?l?h?+	B r   c                    | j                   d   }|st        d      d}|D ]
  }||d   z  } |t        |      z  | j                  j                  d<   y Nr  r;   r   durationSecondsr   r$   r>   r@   r%   r&   )r   r  ri   r  s       r   r)   z"AverageNoteDurationFeature.process  s\    YY01
+,?@@ FV-..E !!&Z!8Ar   r*   r+   r2   s   @r   r  r  r  s      
B9r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS ) VariabilityOfNoteDurationFeaturear  
    Standard deviation of note durations in seconds.

    # In this piece, we have:
    #     9 half notes or tied pair of quarters
    #     98 untied quarters or tied pair of eighths
    #     56 untied eighths
    # BPM = 120 means a half note is a second.
    # Mean duration should thus be 0.44171779141104295
    # and standard deviation should be  0.17854763448902145

    >>> s = corpus.parse('bwv66.6')
    >>> for p in s.parts:
    ...     p.insert(0, tempo.MetronomeMark(number=120))
    >>> fe = features.jSymbolic.VariabilityOfNoteDurationFeature(s)
    >>> f = fe.extract()
    >>> f.vector[0]
    0.178...
    R18c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zVariability of Note Durationz0Standard deviation of note durations in seconds.Tr7   r   r8   r   s      r   r   z)VariabilityOfNoteDurationFeature.__init__  s6    ?l?h?2	M r   c                    | j                   d   }|st        d      g }|D ]  }|j                  |d           t        j                  |      | j
                  j                  d<   y )Nr  r;   r  r   )r$   r>   r=   r,  pstdevr%   r&   )r   r  note_durationsr  s       r   r)   z(VariabilityOfNoteDurationFeature.process  sb    YY01
+,?@@ F!!&):";< !!+!2!2>!BAr   r*   r+   r2   s   @r   r  r    s    & 
BCr   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )MaximumNoteDurationFeaturez
    Duration of the longest note (in seconds).

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MaximumNoteDurationFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [1.25]
    R19c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zMaximum Note Durationz*Duration of the longest note (in seconds).Tr7   r   r8   r   s      r   r   z#MaximumNoteDurationFeature.__init__  s6    ?l?h?+	G r   c                    | j                   d   }|st        d      d}|D ]  }|d   |kD  s|d   } || j                  j                  d<   y r  r$   r>   r%   r&   )r   r  
maxSecondsr  s       r   r)   z"MaximumNoteDurationFeature.process  s^    YY01
+,?@@
 F'(:5#$56
 ! ",Ar   r*   r+   r2   s   @r   r  r    s     
B,r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )MinimumNoteDurationFeaturez
    Duration of the shortest note (in seconds).

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MinimumNoteDurationFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.3125]
    R20c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zMinimum Note Durationz+Duration of the shortest note (in seconds).Tr7   r   r8   r   s      r   r   z#MinimumNoteDurationFeature.__init__  s6    ?l?h?+	H r   c                    | j                   d   }|st        d      |d   d   }|D ]  }|d   |k  s|d   } || j                  j                  d<   y )Nr  r;   r   r  r  )r   r  
minSecondsr  s       r   r)   z"MinimumNoteDurationFeature.process  sh    YY01
+,?@@]#45
 F'(:5#$56
 ! ",Ar   r*   r+   r2   s   @r   r	  r	    s     
B	,r   r	  c                  .     e Zd ZdZdZd fd	Zd Z xZS )StaccatoIncidenceFeaturea  
    Number of notes with durations of less than a 10th of a second divided by
    the total number of notes in the recording.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.StaccatoIncidenceFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.0]
    R21c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zStaccato IncidencezuNumber of notes with durations of less than a 10th of a second divided by the total number of notes in the recording.Tr7   r   r8   r   s      r   r   z!StaccatoIncidenceFeature.__init__	  s9    ?l?h?(	a r   c                    | j                   d   }|st        d      d}|D ]  }|d   dk  s|dz  } |t        |      z  | j                  j                  d<   y )Nr  r;   r   r  g?r7   r  )r   r  r]   r  s       r   r)   z StaccatoIncidenceFeature.process	  se    YY01
+,?@@ F'(4/
 ! "'Z!8Ar   r*   r+   r2   s   @r   r  r    s    	 
B9r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS ) AverageTimeBetweenAttacksFeatureaI  
    Average time in seconds between Note On events (regardless of channel).

    >>> s = corpus.parse('bwv66.6')
    >>> for p in s.parts:
    ...     p.insert(0, tempo.MetronomeMark(number=120))
    >>> fe = features.jSymbolic.AverageTimeBetweenAttacksFeature(s)
    >>> f = fe.extract()
    >>> print(f.vector)
    [0.35]
    R22c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zAverage Time Between AttackszGAverage time in seconds between Note On events (regardless of channel).Tr7   r   r8   r   s      r   r   z)AverageTimeBetweenAttacksFeature.__init__0	  s6    ?l?h?2	d r   c                   | j                   d   }|D cg c]  }|d   	 }}|st        d      |j                          g }t        |      D ]E  \  }}|t	        |      dz
  k(  r n/||dz      }||z
  }t        |dd      r5|j                  |       G t        |      t	        |      z  | j                  j                  d<   y c c}w 	Nr  offsetSecondsr;   r7   r   Hz>abs_tolr   )
r$   r>   r  r#   r@   r   r=   r?   r%   r&   	r   r  r  onsetsdifferencesr'   ooNextdifs	            r   r)   z(AverageTimeBetweenAttacksFeature.process8	  s    YY01
8BC
f&)
C+,?@@f%DAqCK!O#1q5ME!)C3T2""3' & "%[!1C4D!DA Ds   Cr*   r+   r2   s   @r   r  r  !	  s    
 
BEr   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )&VariabilityOfTimeBetweenAttacksFeaturea  
    Standard deviation of the times, in seconds, between Note On events (regardless of channel).

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.VariabilityOfTimeBetweenAttacksFeature(s)
    >>> f = fe.extract()
    >>> print(f.vector)
    [0.1875]
    R23c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z#Variability of Time Between Attacksz\Standard deviation of the times, in seconds, between Note On events (regardless of channel).Tr7   r   r8   r   s      r   r   z/VariabilityOfTimeBetweenAttacksFeature.__init__Y	  s9    ?l?h?9	N r   c                   | j                   d   }|D cg c]  }|d   	 }}|st        d      |j                          g }t        |      D ]E  \  }}|t	        |      dz
  k(  r n/||dz      }||z
  }t        |dd      r5|j                  |       G t        j                  |      | j                  j                  d<   y c c}w r  )r$   r>   r  r#   r@   r   r=   r,  r  r%   r&   r  s	            r   r)   z.VariabilityOfTimeBetweenAttacksFeature.processb	  s    YY01
8BC
f&)
C+,?@@f%DAqCK!O#1q5ME!)C3T2""3' & ",!2!2;!?A Ds   Cr*   r+   r2   s   @r   r$  r$  L	  s     
B@r   r$  c                  .     e Zd ZdZdZd fd	Zd Z xZS ),AverageTimeBetweenAttacksForEachVoiceFeaturea  
    Average of average times in seconds between Note On events on individual channels
    that contain at least one note.

    >>> s = corpus.parse('bwv66.6')
    >>> for p in s.parts:
    ...     p.insert(0, tempo.MetronomeMark(number=120))
    >>> fe = features.jSymbolic.AverageTimeBetweenAttacksForEachVoiceFeature(s)
    >>> f = fe.extract()
    >>> print(f.vector[0])
    0.442...
    R24c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z+Average Time Between Attacks For Each VoicezqAverage of average times in seconds between Note On events on individual channels that contain at least one note.Tr7   r   r8   r   s      r   r   z5AverageTimeBetweenAttacksForEachVoiceFeature.__init__	  s9    ?l?h?A	U r   c                
   g }g }| j                   j                  dkD  r]t        | j                   j                        D ]:  }| j                   d   |   d   }|D cg c]  }|d   	 }}|j                  |       < n2| j                   d   }|D cg c]  }|d   	 }}|j                  |       |D ]  }|j	                          g }t        |      D ]E  \  }}|t        |      dz
  k(  r n/||dz      }	|	|z
  }
t        |
dd      r5|j                  |
       G |st        d	      |j                  t        |      t        |      z          t        |      t        |      z  | j                  j                  d<   y c c}w c c}w 
Nr   r   r  r  r7   r   r  r  zat least one part lacks notes)r$   r   r<   r=   r  r#   r@   r   r>   r?   r%   r&   )r   onsetsByPart	avgByPartr'   r  r  r  r  r   r!  r"  s              r   r)   z4AverageTimeBetweenAttacksForEachVoiceFeature.process	  sz   	99!#499//0!YYw/23DE
@JK
f&1
K##F+ 1
 #45J<FGJ&f_-JFG'"FKKMK!&)1Fa'q1uaisC6&&s+ * /0OPPS-K0@@A #  "%Y#i.!@A/ L Hs   E;F r*   r+   r2   s   @r   r)  r)  u	  s     
BAr   r)  c                  .     e Zd ZdZdZd fd	Zd Z xZS )9AverageVariabilityOfTimeBetweenAttacksForEachVoiceFeaturea  
    Average standard deviation, in seconds, of time between Note On events on individual
    channels that contain at least one note.

    >>> s = corpus.parse('bwv66.6')
    >>> for p in s.parts:
    ...     p.insert(0, tempo.MetronomeMark(number=120))
    >>> fe = features.jSymbolic.AverageVariabilityOfTimeBetweenAttacksForEachVoiceFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.177...]
    R25c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z:Average Variability of Time Between Attacks For Each Voicez}Average standard deviation, in seconds, of time between Note On events on individual channels that contain at least one note.Tr7   r   r8   r   s      r   r   zBAverageVariabilityOfTimeBetweenAttacksForEachVoiceFeature.__init__	  s:    ?l?h?P	1 !r   c                   g }g }| j                   j                  dkD  r]t        | j                   j                        D ]:  }| j                   d   |   d   }|D cg c]  }|d   	 }}|j                  |       < n2| j                   d   }|D cg c]  }|d   	 }}|j                  |       |D ]  }|j	                          g }t        |      D ]E  \  }}|t        |      dz
  k(  r n/||dz      }	|	|z
  }
t        |
dd      r5|j                  |
       G |st        d	      |j                  t        j                  |              t        |      t        |      z  | j                  j                  d<   y c c}w c c}w r-  )r$   r   r<   r=   r  r#   r@   r   r>   r,  r  r?   r%   r&   )r   r.  stdDeviationByPartr'   r  r  r  r  r   r!  r"  s              r   r)   zAAverageVariabilityOfTimeBetweenAttacksForEachVoiceFeature.process	  s~   99!#499//0!YYw/23DE
@JK
f&1
K##F+ 1
 #45J<FGJ&f_-JFG'"FKKMK!&)1Fa'q1uaisC6&&s+ * /0OPP%%j&7&7&DE # #&&8"9$'(:$;#<A- L Hs   E9E>r*   r+   r2   s   @r   r1  r1  	  s     
B=r   r1  c                  .     e Zd ZdZdZd fd	Zd Z xZS )InitialTempoFeaturez
    Tempo in beats per minute at the start of the recording.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.InitialTempoFeature(s)
    >>> f = fe.extract()
    >>> f.vector  # a default
    [96.0]
    R30c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zInitial Tempoz8Tempo in beats per minute at the start of the recording.Tr7   r   r8   r   s      r   r   zInitialTempoFeature.__init__6
  s6    ?l?h?#	U r   c                    | j                   d   }|d   d   }|j                         | j                  j                  d<   y )NmetronomeMarkBoundariesr   r   )r$   getQuarterBPMr%   r&   )r   triplesmms      r   r)   zInitialTempoFeature.process>
  s;    ))56QZ]!#!1!1!3Ar   r*   r+   r2   s   @r   r7  r7  )
  s     
B4r   r7  c                  .     e Zd ZdZdZd fd	Zd Z xZS )InitialTimeSignatureFeaturea=  
    A feature array with two elements. The first is the numerator of the first occurring
    time signature and the second is the denominator of the first occurring time signature.
    Both are set to 0 if no time signature is present.

    >>> s1 = stream.Stream()
    >>> s1.append(meter.TimeSignature('3/4'))
    >>> fe = features.jSymbolic.InitialTimeSignatureFeature(s1)
    >>> fe.extract().vector
    [3, 4]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.InitialTimeSignatureFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [4, 4]
    R31c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zInitial Time SignaturezA feature array with two elements. The first is the numerator of the first occurring time signature and the second is the denominator of the first occurring time signature. Both are set to 0 if no time signature is present.Tr   r   r8   r   s      r   r   z$InitialTimeSignatureFeature.__init__[
  s;    ?l?h?,	\ !r   c                    | j                   d   }|sy |d   }t        j                  d|g       |d   j                  | j                  j
                  d<   |d   j                  | j                  j
                  d<   y )N&flat.getElementsByClass(TimeSignature)r   zfound tsr7   )r$   environLocal
printDebug	numeratorr%   r&   denominator)r   elementstss      r   r)   z#InitialTimeSignatureFeature.processf
  so    99EFa[R 01!)!!6!6A!)!!8!8Ar   r*   r+   r2   s   @r   r@  r@  F
  s    $ 
B	9r   r@  c                  .     e Zd ZdZdZd fd	Zd Z xZS )CompoundOrSimpleMeterFeaturea  
    Set to 1 if the initial meter is compound (numerator of time signature
    is greater than or equal to 6 and is evenly divisible by 3) and to 0 if it is simple
    (if the above condition is not fulfilled).

    >>> s1 = stream.Stream()
    >>> s1.append(meter.TimeSignature('3/4'))
    >>> fe = features.jSymbolic.CompoundOrSimpleMeterFeature(s1)
    >>> fe.extract().vector
    [0]

    >>> s2 = stream.Stream()
    >>> s2.append(meter.TimeSignature('9/8'))
    >>> fe.setData(s2)  # change the data
    >>> fe.extract().vector
    [1]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.CompoundOrSimpleMeterFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0]
    R32c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zCompound Or Simple MeterzSet to 1 if the initial meter is compound (numerator of time signature is greater than or equal to 6 and is evenly divisible by 3) and to 0 if it is simple (if the above condition is not fulfilled).Tr7   r   r8   r   s      r   r   z%CompoundOrSimpleMeterFeature.__init__
  s;    ?l?h?.	I !r   c                    | j                   d   }|r0	 |d   j                  }|dk(  rd| j                  j
                  d<   y y y # t        j                  $ r Y y w xY w)NrD  r   Compoundr7   )r$   beatDivisionCountNamer	   TimeSignatureExceptionr%   r&   )r   rI  	countNames      r   r)   z$CompoundOrSimpleMeterFeature.process
  sj    99EF$QK==	 J&)*##A& '   66 s   A AAr*   r+   r2   s   @r   rL  rL  p
  s    0 
B		+r   rL  c                  .     e Zd ZdZdZd fd	Zd Z xZS )TripleMeterFeaturea!  
    Set to 1 if numerator of initial time signature is 3, set to 0 otherwise.

    >>> s1 = stream.Stream()
    >>> s1.append(meter.TimeSignature('5/4'))
    >>> fe = features.jSymbolic.TripleMeterFeature(s1)
    >>> fe.extract().vector
    [0]

    >>> s2 = stream.Stream()
    >>> s2.append(meter.TimeSignature('3/4'))
    >>> fe.setData(s2)  # change the data
    >>> fe.extract().vector
    [1]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.TripleMeterFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0]
    R33c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zTriple MeterzISet to 1 if numerator of initial time signature is 3, set to 0 otherwise.Tr7   r   r8   r   s      r   r   zTripleMeterFeature.__init__
  s8    ?l?h?"	2 r   c                    | j                   d   }|r-|d   j                  dk(  rd| j                  j                  d<   y y y )NrD  r   rp   r7   r$   rG  r%   r&   r   rI  s     r   r)   zTripleMeterFeature.process
  s@    99EF--2%&DLL" 38r   r*   r+   r2   s   @r   rU  rU  
  s    , 
B'r   rU  c                  .     e Zd ZdZdZd fd	Zd Z xZS )QuintupleMeterFeaturea'  
    Set to 1 if numerator of initial time signature is 5, set to 0 otherwise.

    >>> s1 = stream.Stream()
    >>> s1.append(meter.TimeSignature('5/4'))
    >>> fe = features.jSymbolic.QuintupleMeterFeature(s1)
    >>> fe.extract().vector
    [1]

    >>> s2 = stream.Stream()
    >>> s2.append(meter.TimeSignature('3/4'))
    >>> fe.setData(s2)  # change the data
    >>> fe.extract().vector
    [0]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.QuintupleMeterFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0]
    R34c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zQuintuple MeterzISet to 1 if numerator of initial time signature is 5, set to 0 otherwise.Tr7   r   r8   r   s      r   r   zQuintupleMeterFeature.__init__
  s8    ?l?h?%	2 r   c                    | j                   d   }|r-|d   j                  dk(  rd| j                  j                  d<   y y y )NrD  r      r7   rY  rZ  s     r   r)   zQuintupleMeterFeature.process
  s@    99EF--2%&DLL" 38r   r*   r+   r2   s   @r   r\  r\  
  s    , 
B'r   r\  c                  .     e Zd ZdZdZd fd	Zd Z xZS )ChangesOfMeterFeatureab  
    Returns 1 if the time signature is changed one or more
    times during the recording.

    >>> s1 = stream.Stream()
    >>> s1.append(meter.TimeSignature('3/4'))
    >>> fe = features.jSymbolic.ChangesOfMeterFeature(s1)
    >>> fe.extract().vector
    [0]

    >>> s2 = stream.Stream()
    >>> s2.append(meter.TimeSignature('3/4'))
    >>> s2.append(meter.TimeSignature('4/4'))
    >>> fe.setData(s2)  # change the data
    >>> fe.extract().vector
    [1]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.ChangesOfMeterFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0]
    R35c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zChanges of MeterzPSet to 1 if the time signature is changed one or more times during the recordingTr7   r   r8   r   s      r   r   zChangesOfMeterFeature.__init__  s8    ?l?h?&	9 r   c                    | j                   d   }t        |      dk  ry |d   }|dd  D ].  }|j                  |      rd| j                  j                  d<    y  y )NrD  r7   r   )r$   r@   
ratioEqualr%   r&   )r   rI  firstes       r   r)   zChangesOfMeterFeature.process  s^    99EFx=A!"A##A&)*##A& r   r*   r+   r2   s   @r   rb  rb  
  s    . 
Br   rb  c                  .     e Zd ZdZdZd fd	Zd Z xZS )DurationFeaturea2  
    A feature extractor that extracts the duration of the piece in seconds.

    >>> s = corpus.parse('bwv66.6')
    >>> for p in s.parts:
    ...     p.insert(0, tempo.MetronomeMark(number=120))
    >>> fe = features.jSymbolic.DurationFeature(s)
    >>> f = fe.extract()
    >>> f.vector[0]
    18.0
    R36c                n    t        |   dd|i| d| _        d| _        d| _        d| _        d| _        y )Nr   Durationz+The total duration in seconds of the music.Fr7   r   r   r   s      r   r   zDurationFeature.__init__/  s=    ?l?h?	H!r   c                    | j                   d   }|st        d      |D cg c]  }|d   	 }}|j                          |d   | j                  j                  d<   y c c}w )Nr  zinput lacks durationr  r   r   )r$   r>   r  r%   r&   r  s       r   r)   zDurationFeature.process8  se    YY01
+,BCC =GGJ&V,-J	G!*2A Hs   Ar*   r+   r2   s   @r   rj  rj  !  s    
 
B/r   rj  c                  (     e Zd ZdZdZd fd	Z xZS )OverallDynamicRangeFeaturezj
    Not implemented

    The maximum loudness minus the minimum loudness value.

    TODO: implement
    D1c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zOverall Dynamic Rangez6The maximum loudness minus the minimum loudness value.Tr7   r   r8   r   s      r   r   z#OverallDynamicRangeFeature.__init__Q  s6    ?l?h?+	S r   r*   r  r2   s   @r   rp  rp  G  s     
B r   rp  c                  (     e Zd ZdZdZd fd	Z xZS )VariationOfDynamicsFeaturezh
    Not implemented

    Standard deviation of loudness levels of all notes.

    TODO: implement

    D2c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zVariation of Dynamicsz3Standard deviation of loudness levels of all notes.Tr7   r   r8   r   s      r   r   z#VariationOfDynamicsFeature.__init__e  s6    ?l?h?+	P r   r*   r  r2   s   @r   rt  rt  Z  s     
B r   rt  c                  (     e Zd ZdZdZd fd	Z xZS )%VariationOfDynamicsInEachVoiceFeaturez
    Not implemented

    The average of the standard deviations of loudness levels within each
    channel that contains at least one note.

    TODO: implement

    D3c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z#Variation of Dynamics In Each VoiceznThe average of the standard deviations of loudness levels within each channel that contains at least one note.Tr7   r   r8   r   s      r   r   z.VariationOfDynamicsInEachVoiceFeature.__init__z  s9    ?l?h?9	Z r   r*   r  r2   s   @r   rx  rx  n  s     
B r   rx  c                  (     e Zd ZdZdZd fd	Z xZS )&AverageNoteToNoteDynamicsChangeFeaturez
    Not implemented

    Average change of loudness from one note to the next note in the
    same channel (in MIDI velocity units).

    TODO: implement

    D4c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z$Average Note To Note Dynamics ChangezgAverage change of loudness from one note to the next note in the same channel (in MIDI velocity units).Tr7   r   r8   r   s      r   r   z/AverageNoteToNoteDynamicsChangeFeature.__init__  s9    ?l?h?:	L r   r*   r  r2   s   @r   r|  r|    s     
B r   r|  c                  .     e Zd ZdZdZd fd	Zd Z xZS )'MaximumNumberOfIndependentVoicesFeaturea  
    Maximum number of different channels in which notes have sounded simultaneously.
    Here, Parts are treated as channels.

    >>> s = corpus.parse('handel/rinaldo/lascia_chio_pianga')
    >>> fe = features.jSymbolic.MaximumNumberOfIndependentVoicesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [3]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.MaximumNumberOfIndependentVoicesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [4]
    T1c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z$Maximum Number of Independent VoiceszuMaximum number of different channels in which notes have sounded simultaneously. Here, Parts are treated as channels.Tr7   r   r8   r   s      r   r   z0MaximumNumberOfIndependentVoicesFeature.__init__  s9    ?l?h?:	` r   c                   d}| j                   d   D ]^  }t        j                         }|j                  D ]$  }|j                  D ]  }|j                  |        & t        |t        |            }` || j                  j                  d<   y )Nr   'chordify.flat.getElementsByClass(Chord))
r$   r   Groupsr+  groupsr=   rJ   r@   r%   r&   r   foundr   gr/  gSubs         r   r)   z/MaximumNumberOfIndependentVoicesFeature.process  sx    DEA AYYHHDHHTN %  s1v&E F "'Ar   r*   r+   r2   s   @r   r  r    s    " 
B'r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )'AverageNumberOfIndependentVoicesFeaturea  
    Average number of different channels in which notes have sounded simultaneously.
    Rests are not included in this calculation. Here, Parts are treated as voices

    >>> s = corpus.parse('handel/rinaldo/lascia_chio_pianga')
    >>> fe = features.jSymbolic.AverageNumberOfIndependentVoicesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [1.528...]

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.AverageNumberOfIndependentVoicesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [3.90...]
    T2c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z$Average Number of Independent VoiceszAverage number of different channels in which notes have sounded simultaneously. Rests are not included in this calculation. Here, Parts are treated as voicesTr7   r   r8   r   s      r   r   z0AverageNumberOfIndependentVoicesFeature.__init__  s;    ?l?h?:	M !r   c                h   g }| j                   d   D ]c  }t        j                         }|j                  D ]$  }|j                  D ]  }|j                  |        & |j                  t        |             e |st        d      t        |      t        |      z  | j                  j                  d<   y )Nr  r;   r   )r$   r   r  r+  r  r=   r@   r>   r?   r%   r&   r  s         r   r)   z/AverageNumberOfIndependentVoicesFeature.process  s    DEA AYYHHDHHTN %  LLQ  F +,?@@!$Uc%j!8Ar   r*   r+   r2   s   @r   r  r    s      
B9r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )-VariabilityOfNumberOfIndependentVoicesFeatureaG  
    Standard deviation of number of different channels in which notes have sounded simultaneously.
    Rests are not included in this calculation.

    >>> s = corpus.parse('bwv66.6')
    >>> fe = features.jSymbolic.VariabilityOfNumberOfIndependentVoicesFeature(s)
    >>> f = fe.extract()
    >>> f.vector
    [0.449...]
    T3c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z+Variability of Number of Independent VoiceszStandard deviation of number of different channels in which notes have sounded simultaneously. Rests are not included in this calculation.Tr7   r   r8   r   s      r   r   z6VariabilityOfNumberOfIndependentVoicesFeature.__init__  s;    ?l?h?A	@ !r   c                d   g }| j                   d   D ]c  }t        j                         }|j                  D ]$  }|j                  D ]  }|j                  |        & |j                  t        |             e |r-t        j                  |      | j                  j                  d<   y t        d      )Nr  r   r;   )r$   r   r  r+  r  r=   r@   r,  r  r%   r&   r>   r  s         r   r)   z5VariabilityOfNumberOfIndependentVoicesFeature.process  s    DEA AYYHHDHHTN %  LLQ  F %/%6%6u%=DLL"+,?@@r   r*   r+   r2   s   @r   r  r    s    	 
BAr   r  c                  (     e Zd ZdZdZd fd	Z xZS )!VoiceEqualityNumberOfNotesFeaturez
    Not implemented

    TODO: implement

    Standard deviation of the total number of Note Ons in each channel
    that contains at least one note.
    T4c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z Voice Equality - Number of NoteszcStandard deviation of the total number of Note Ons in each channel that contains at least one note.Tr7   r   r8   r   s      r   r   z*VoiceEqualityNumberOfNotesFeature.__init__+  s9    ?l?h?6	O r   r*   r  r2   s   @r   r  r     s     
B r   r  c                  (     e Zd ZdZdZd fd	Z xZS ) VoiceEqualityNoteDurationFeature/
    Not implemented

    TODO: implement

    T5c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zVoice Equality - Note DurationzmStandard deviation of the total duration of notes in seconds in each channel that contains at least one note.Tr7   r   r8   r   s      r   r   z)VoiceEqualityNoteDurationFeature.__init__>  s9    ?l?h?4	O r   r*   r  r2   s   @r   r  r  5       
B r   r  c                  (     e Zd ZdZdZd fd	Z xZS )VoiceEqualityDynamicsFeaturer  T6c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zVoice Equality - DynamicszbStandard deviation of the average volume of notes in each channel that contains at least one note.Tr7   r   r8   r   s      r   r   z%VoiceEqualityDynamicsFeature.__init__Q  s9    ?l?h?/	O r   r*   r  r2   s   @r   r  r  H  r  r   r  c                  (     e Zd ZdZdZd fd	Z xZS ) VoiceEqualityMelodicLeapsFeaturer  T7c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zVoice Equality - Melodic Leapsz
            Standard deviation
            of the average melodic leap in MIDI pitches
            for each channel that contains at least one note.Tr7   r   r  r   s      r   r   z)VoiceEqualityMelodicLeapsFeature.__init__d  sD    ?l?h?4	! #A B !r   r*   r  r2   s   @r   r  r  [  s     
B	 	r   r  c                  (     e Zd ZdZdZd fd	Z xZS )VoiceEqualityRangeFeaturez
    Not implemented

    Standard deviation of the differences between the highest and lowest
    pitches in each channel that contains at least one note.
    T8c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zVoice Equality - Rangez
            Standard deviation of the differences between the
            highest and lowest pitches in each channel that contains at least one note.Tr7   r   r  r   s      r   r   z"VoiceEqualityRangeFeature.__init__y  sD    ?l?h?,	! #[ \ !r   r*   r  r2   s   @r   r  r  p  s     
B r   r  c                  (     e Zd ZdZdZd fd	Z xZS )ImportanceOfLoudestVoiceFeature.
    Not implemented

    TODO: implement
    T9c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zImportance of Loudest Voicez
            Difference between the average loudness
            of the loudest channel and the average loudness of the other channels
            that contain at least one note.Tr7   r   r  r   s      r   r   z(ImportanceOfLoudestVoiceFeature.__init__  sB    ?l?h?1	! #/ 0 !r   r*   r  r2   s   @r   r  r    s    
 
B	 	r   r  c                  (     e Zd ZdZdZd fd	Z xZS )"RelativeRangeOfLoudestVoiceFeaturer  T10c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zRelative Range of Loudest Voicez
            Difference between the highest note and the lowest note
            played in the channel with the highest average loudness divided by the difference
            between the highest note and the lowest note overall in the piece.Tr7   r   r  r   s      r   r   z+RelativeRangeOfLoudestVoiceFeature.__init__  sD    ?l?h?5	! #R S !r   r*   r  r2   s   @r   r  r        
 
B	 	r   r  c                  (     e Zd ZdZdZd fd	Z xZS )RangeOfHighestLineFeaturer  T12c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zRange of Highest Linez
            Difference between the highest note and the lowest note
            played in the channel with the highest average pitch divided by the difference
            between the highest note and the lowest note in the piece.Tr7   r   r  r   s      r   r   z"RangeOfHighestLineFeature.__init__  sD    ?l?h?+	! #J K !r   r*   r  r2   s   @r   r  r    r  r   r  c                  (     e Zd ZdZdZd fd	Z xZS )'RelativeNoteDensityOfHighestLineFeaturer  T13c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   z%Relative Note Density of Highest Linez
            Number of Note Ons in the channel with the highest average
            pitch divided by the average number of Note Ons in all channels that contain at
            least one note.Tr7   r   r  r   s      r   r   z0RelativeNoteDensityOfHighestLineFeature.__init__  sB    ?l?h?;	! #   !r   r*   r  r2   s   @r   r  r         
B	 	r   r  c                  (     e Zd ZdZdZd fd	Z xZS )#MelodicIntervalsInLowestLineFeaturer  T15c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   z Melodic Intervals in Lowest Linez
            Average melodic interval in semitones of the channel
            with the lowest average pitch divided by the average melodic interval of all
            channels that contain at least two notes.Tr7   r   r  r   s      r   r   z,MelodicIntervalsInLowestLineFeature.__init__  sB    ?l?h?6	! #9 : !r   r*   r  r2   s   @r   r  r    r  r   r  c                  (     e Zd ZdZdZd fd	Z xZS )VoiceSeparationFeaturez
    Not implemented

    Average separation in semitones between the average pitches of consecutive
    channels (after sorting based/non-average pitch) that contain at least one note.
    T20c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zVoice Separationz
            Average separation in semi-tones between the average pitches of
            consecutive channels (after sorting based/non average pitch) that contain at
            least one note.Tr7   r   r  r   s      r   r   zVoiceSeparationFeature.__init__  sB    ?l?h?&	! #   !r   r*   r  r2   s   @r   r  r    r  r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS ) PitchedInstrumentsPresentFeaturea  
    Which pitched General MIDI Instruments are present. There is one entry
    for each instrument, which is set to 1.0 if there is at least one Note On
    in the recording corresponding to the instrument and to 0.0 if there is not.

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.AcousticGuitar())
    >>> s1.append(note.Note())
    >>> s1.append(instrument.Tuba())
    >>> s1.append(note.Note())
    >>> fe = features.jSymbolic.PitchedInstrumentsPresentFeature(s1)
    >>> fe.extract().vector
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    Default instruments will lack a `.midiProgram`, so they raise exceptions:

    >>> i = instrument.Instrument()
    >>> i.midiProgram is None
    True
    >>> s2 = stream.Stream()
    >>> s2.append(i)
    >>> s2.append(note.Note())
    >>> fe2 = features.jSymbolic.PitchedInstrumentsPresentFeature(s2)
    >>> fe2.extract()
    Traceback (most recent call last):
    music21.features.jSymbolic.JSymbolicFeatureException:
    <music21.instrument.Instrument ''> lacks a midiProgram
    I1c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zPitched Instruments Presenta  
            Which pitched General MIDI Instruments are present.
            There is one entry for each instrument, which is set to 1.0 if there is at
            least one Note On in the recording corresponding to the instrument and to
            0.0 if there is not.Tr   r   r  r   s      r   r   z)PitchedInstrumentsPresentFeature.__init__&  sB    ?l?h?1	! #$ %
 !r   c                   | j                   d   }|st        d      |j                  D ]  }|j                  t              j                         }|j                         j                  sA|j                  &t        |      xs t        |      }t        | d      d| j                  j                  |j                  <    y)r!   partitionByInstrumentinput lacks instrumentsN lacks a midiProgramr7   )r$   r>   r   getElementsByClassr
   rg  recursenotesmidiProgramstrreprr%   r&   )r   sr/  r'   iStrs        r   r)   z(PitchedInstrumentsPresentFeature.process2  s     II-. +,EFFA$$Z0668Ayy{  ==(q6,T!WD3tf<P4QRR56##AMM2 r   r*   r+   r2   s   @r   r  r    s     B 
B
7r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )"UnpitchedInstrumentsPresentFeaturea  
    Not yet implemented

    Which unpitched MIDI Percussion Key Map instruments are present.
    There is one entry for each instrument, which is set to 1.0 if there is
    at least one Note On in the recording corresponding to the instrument and to
    0.0 if there is not. It should be noted that only instruments 35 to 81 are included here,
    as they are the ones that meet the official standard. They are numbered in this
    array from 0 to 46.
    I2c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   zUnpitched Instruments Presenta  
            Which unpitched MIDI Percussion Key Map instruments are present.
            There is one entry for each instrument, which is set to 1.0 if there is at least one
            Note On in the recording corresponding to the instrument and to 0.0 if there is not.
            It should be noted that only instruments 35 to 81 are included here, as they are the
            ones that meet the official standard. They are numbered in this array from 0 to 46.T/   r   r  r   s      r   r   z+UnpitchedInstrumentsPresentFeature.__init__U  sD    ?l?h?3	! #c d !r   c                    t        d      rT  rU  rV  s    r   r)   z*UnpitchedInstrumentsPresentFeature.processb  rW  r   r*   r+   r2   s   @r   r  r  E  s    	 
B?r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS ))NotePrevalenceOfPitchedInstrumentsFeaturea  

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.AcousticGuitar())
    >>> s1.repeatAppend(note.Note(), 4)
    >>> s1.append(instrument.Tuba())
    >>> s1.append(note.Note())
    >>> fe = features.jSymbolic.NotePrevalenceOfPitchedInstrumentsFeature(s1)
    >>> fe.extract().vector
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0.8..., 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2...,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    `.midiProgram` cannot be None:

    >>> s1.getInstruments().first().midiProgram = None
    >>> fe2 = features.jSymbolic.NotePrevalenceOfPitchedInstrumentsFeature(s1)
    >>> fe2.extract()
    Traceback (most recent call last):
    music21.features.jSymbolic.JSymbolicFeatureException: Acoustic Guitar lacks a midiProgram
    I3c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z&Note Prevalence of Pitched InstrumentszThe fraction of (pitched) notes played by each General MIDI Instrument. There is one entry for each instrument, which is set to the number of Note Ons played using the corresponding MIDI patch divided by the total number of Note Ons in the recording.Tr   r   r8   r   s      r   r   z2NotePrevalenceOfPitchedInstrumentsFeature.__init__  s;    ?l?h?<	X
 !r   c                   | j                   d   }t        | j                   d         }|st        d      |j                  D ]  }|j	                  t
              j                         }|j                         j                  }|sC|j                  &t        |      xs t        |      }t        | d      t        |      |z  | j                  j                  |j                  <    y)r!   r  r   r;   Nr  )r$   r?   r>   r   r  r
   rg  r  r  r  r  r  r@   r%   r&   )r   r  ri   r/  r'   pNotesr  s          r   r)   z1NotePrevalenceOfPitchedInstrumentsFeature.process  s     II-.DII;<= +,?@@A$$Z0668AYY[&&F==(q6,T!WD3tf<P4QRR58[55H##AMM2 r   r*   r+   r2   s   @r   r  r  g  s    2 
B
Ir   r  c                  (     e Zd ZdZdZd fd	Z xZS )+NotePrevalenceOfUnpitchedInstrumentsFeaturer  I4c                r    t        |   dd|i| d| _        t        d      | _        d| _        d| _        y )Nr   z(Note Prevalence of Unpitched Instrumentsa  
            The fraction of (unpitched) notes played by each General MIDI
            Percussion Key Map Instrument. There is one entry for each instrument, which is set
            to the number of Note Ons played using the corresponding MIDI note value divided by
            the total number of Note Ons in the recording. It should be noted that only instruments
            35 to 81 are included here, as they are the ones that meet the official standard.
            They are numbered in this array from 0 to 46.Tr  r   r  r   s      r   r   z4NotePrevalenceOfUnpitchedInstrumentsFeature.__init__  sB    ?l?h?>	! #= > !r   r*   r  r2   s   @r   r  r    s     
B r   r  c                  (     e Zd ZdZdZd fd	Z xZS ))TimePrevalenceOfPitchedInstrumentsFeaturea  
    Not implemented

    The fraction of the total time of the recording in
    which a note was sounding for each (pitched) General
    MIDI Instrument. There is one entry for each instrument,
    which is set to the total time in seconds during which a
    given instrument was sounding one or more notes divided by the total length
    in seconds of the piece.'

    TODO: implement

    I5c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z&Time Prevalence of Pitched Instrumentsa>  The fraction of the total time of the recording in which a note was sounding for each (pitched) General MIDI Instrument. There is one entry for each instrument, which is set to the total time in seconds during which a given instrument was sounding one or more notes divided by the total length in seconds of the piece.Tr   r   r8   r   s      r   r   z2TimePrevalenceOfPitchedInstrumentsFeature.__init__  s;    ?l?h?<	a
 !r   r*   r  r2   s   @r   r  r    s     
B
 
r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )6VariabilityOfNotePrevalenceOfPitchedInstrumentsFeaturea  
    Standard deviation of the fraction of Note Ons played
    by each (pitched) General MIDI instrument that is
    used to play at least one note.

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.AcousticGuitar())
    >>> s1.repeatAppend(note.Note(), 5)
    >>> s1.append(instrument.Tuba())
    >>> s1.append(note.Note())
    >>> fe = features.jSymbolic.VariabilityOfNotePrevalenceOfPitchedInstrumentsFeature(s1)
    >>> fe.extract().vector
    [0.33333...]

    I6c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z5Variability of Note Prevalence of Pitched InstrumentszStandard deviation of the fraction of Note Ons played by each (pitched) General MIDI instrument that is used to play at least one note.Tr7   r   r8   r   s      r   r   z?VariabilityOfNotePrevalenceOfPitchedInstrumentsFeature.__init__  s:    ?l?h?K	> !r   c                X   | j                   d   }t        | j                   d         }|st        d      |st        d      g }|j                  D ]_  }|j	                  t
              j                         }|j                         j                  }|sC|j                  t        |      |z         a t        |      t        |      z  }|D cg c]  }t        ||z
  d       }	}t        j                  t        |	      t        |	      z        | j                  j                  d<   y c c}w )Nr  r   r  r;   r   r   )r$   r?   r>   r   r  r
   rg  r  r  r=   r@   powmathsqrtr%   r&   )
r   r  ri   collr/  r'   r  r-  npartials
             r   r)   z>VariabilityOfNotePrevalenceOfPitchedInstrumentsFeature.process  s    II-.DII;<=+,EFF+,?@@A$$Z0668AYY[&&FCK%/0  4y3t9$-12T3q4x#T2!%3w<#g,+F!GA 3s   D'r*   r+   r2   s   @r   r  r    s     
BHr   r  c                  (     e Zd ZdZdZd fd	Z xZS )8VariabilityOfNotePrevalenceOfUnpitchedInstrumentsFeaturea[  
    Not implemented

    Standard deviation of the fraction of Note Ons played by each (unpitched) MIDI Percussion Key
    Map instrument that is used to play at least one note. It should be noted that only
    instruments 35 to 81 are included here, as they are the ones that are included in the
    official standard.

    TODO: implement

    I7c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   z7Variability of Note Prevalence of Unpitched Instrumentsa  Standard deviation of the fraction of Note Ons played by each (unpitched) MIDI Percussion Key Map instrument that is used to play at least one note. It should be noted that only instruments 35 to 81 are included here, as they are the ones that are included in the official standard.Tr7   r   r8   r   s      r   r   zAVariabilityOfNotePrevalenceOfUnpitchedInstrumentsFeature.__init__"  s>    ?l?h?M	O 	
 !r   r*   r  r2   s   @r   r  r    s    
 
B
 
r   r  c                  .     e Zd ZdZdZd fd	Zd Z xZS )!NumberOfPitchedInstrumentsFeaturear  
    Total number of General MIDI patches that are used to play at least one note.

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.AcousticGuitar())
    >>> s1.append(note.Note())
    >>> s1.append(instrument.Tuba())
    >>> s1.append(note.Note())
    >>> fe = features.jSymbolic.NumberOfPitchedInstrumentsFeature(s1)
    >>> fe.extract().vector
    [2]

    I8c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zNumber of Pitched InstrumentszMTotal number of General MIDI patches that are used to play at least one note.Tr7   r   r8   r   s      r   r   z*NumberOfPitchedInstrumentsFeature.__init__?  s8    ?l?h?3	6 r   c                    | j                   d   }d}|st        d      |j                  D ]"  }|j                         j                  s|dz  }$ || j
                  j                  d<   y)r!   r  r   r  r7   N)r$   r>   r   r  r  r%   r&   )r   r  r]   r/  s       r   r)   z)NumberOfPitchedInstrumentsFeature.processH  sc     II-.+,EFFAyy{  
  "'Ar   r*   r+   r2   s   @r   r  r  /  s     
B'r   r  c                  (     e Zd ZdZdZd fd	Z xZS )#NumberOfUnpitchedInstrumentsFeaturea  
    Not implemented

    Number of distinct MIDI Percussion Key Map patches that were used to play at
    least one note. It should be noted that only instruments 35 to 81 are
    included here, as they are the ones that are included in the official standard.

    TODO: implement
    I9c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zNumber of Unpitched InstrumentszNumber of distinct MIDI Percussion Key Map patches that were used to play at least one note. It should be noted that only instruments 35 to 81 are included here, as they are the ones that are included in the official standard.Tr7   r   r8   r   s      r   r   z,NumberOfUnpitchedInstrumentsFeature.__init__d  s;    ?l?h?5	J !r   r*   r  r2   s   @r   r  r  W  s     
B	 	r   r  c                  (     e Zd ZdZdZd fd	Z xZS )PercussionPrevalenceFeaturez
    Not implemented

    Total number of Note Ons corresponding to unpitched percussion instruments
    divided by the total number of Note Ons in the recording.
    I10c                `    t        |   dd|i| d| _        d| _        d| _        d| _        y )Nr   zPercussion PrevalencezTotal number of Note Ons corresponding to unpitched percussion instruments divided by total number of Note Ons in the recording.Tr7   r   r8   r   s      r   r   z$PercussionPrevalenceFeature.__init__z  s9    ?l?h?+	` r   r*   r  r2   s   @r   r  r  p  s     
B r   r  c                  *     e Zd ZdZd fd	Zd Z xZS )InstrumentFractionFeaturez
    TODO: Add description of feature

    This subclass is in-turn subclassed by all FeatureExtractors that
    look at the proportional usage of an Instrument
    c                6    t        |   dd|i| g | _        y )Nr   r   )r   r   _targetProgramsr   s      r   r   z"InstrumentFractionFeature.__init__  s"    ?l?h?  "r   c                   | j                   d   }t        | j                   d         }d}|st        d      |st        d      |j                  D ]d  }|j	                  t
              j                         }|j                  | j                  v s?|t        |j                         j                        z  }f ||z  | j                  j                  d<   y)r!   r  r   r   r  r;   N)r$   r?   r>   r   r  r
   rg  r  r	  r@   r  r  r%   r&   )r   r  ri   r]   r/  r'   s         r   r)   z!InstrumentFractionFeature.process  s     II-.DII;<=+,EFF+,?@@A$$Z0668A}} 4 44QYY[..//  "'Ar   r*   )r,   r-   r.   r/   r   r)   r1   r2   s   @r   r  r    s    "/r   r  c                  (     e Zd ZdZdZd fd	Z xZS )StringKeyboardFractionFeaturea  
    Fraction of all Note Ons belonging to string keyboard patches
    (General MIDI patches 1 to 8).

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.Piano())
    >>> s1.repeatAppend(note.Note(), 9)
    >>> s1.append(instrument.Tuba())
    >>> s1.append(note.Note())
    >>> fe = features.jSymbolic.StringKeyboardFractionFeature(s1)
    >>> fe.extract().vector
    [0.9...]
    I11c                    t        |   dd|i| d| _        d| _        d| _        d| _        t        d      | _        y )Nr   zString Keyboard Fractionz\Fraction of all Note Ons belonging to string keyboard patches (General MIDI patches 1 to 8).Tr7      r   )r   r   r   r   r   r   r<   r	  r   s      r   r   z&StringKeyboardFractionFeature.__init__  sD    ?l?h?.	= $Qxr   r*   r  r2   s   @r   r  r         
B	( 	(r   r  c                  (     e Zd ZdZdZd fd	Z xZS )AcousticGuitarFractionFeaturea  
    A feature extractor that extracts the fraction of all Note Ons belonging to
    acoustic guitar patches (General MIDI patches 25 and 26).

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.AcousticGuitar())
    >>> s1.repeatAppend(note.Note(), 3)
    >>> s1.append(instrument.Tuba())
    >>> s1.append(note.Note())
    >>> fe = features.jSymbolic.AcousticGuitarFractionFeature(s1)
    >>> fe.extract().vector
    [0.75]
    I12c                r    t        |   dd|i| d| _        d| _        d| _        d| _        ddg| _        y )	Nr   zAcoustic Guitar Fractionz_Fraction of all Note Ons belonging to acoustic guitar patches (General MIDI patches 25 and 26).Tr7   r      r   r   r   r   r   r   r   r	  r   s      r   r   z&AcousticGuitarFractionFeature.__init__  sE    ?l?h?.	@  "Bxr   r*   r  r2   s   @r   r  r    r  r   r  c                  (     e Zd ZdZdZd fd	Z xZS )ElectricGuitarFractionFeaturea.  
    >>> s1 = stream.Stream()
    >>> s1.append(instrument.ElectricGuitar())
    >>> s1.repeatAppend(note.Note(), 4)
    >>> s1.append(instrument.Tuba())
    >>> s1.repeatAppend(note.Note(), 4)
    >>> fe = features.jSymbolic.ElectricGuitarFractionFeature(s1)
    >>> fe.extract().vector
    [0.5]
    I13c                    t        |   dd|i| d| _        d| _        d| _        d| _        t        t        dd            | _        y )	Nr   zElectric Guitar Fractionz^Fraction of all Note Ons belonging to electric guitar patches (General MIDI patches 27 to 32).Tr7          r   	r   r   r   r   r   r   listr<   r	  r   s      r   r   z&ElectricGuitarFractionFeature.__init__  sL    ?l?h?.	W #E"bM2r   r*   r  r2   s   @r   r  r    s    	 
B	3 	3r   r  c                  (     e Zd ZdZdZd fd	Z xZS )ViolinFractionFeaturea  
    Fraction of all Note Ons belonging to violin patches (General MIDI
    patches 41 or 111).

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.Violin())
    >>> s1.repeatAppend(note.Note(), 2)
    >>> s1.append(instrument.Tuba())
    >>> s1.repeatAppend(note.Note(), 8)
    >>> fe = features.jSymbolic.ViolinFractionFeature(s1)
    >>> fe.extract().vector
    [0.2...]
    I14c                r    t        |   dd|i| d| _        d| _        d| _        d| _        ddg| _        y )	Nr   zViolin FractionzVFraction of all Note Ons belonging to violin patches (General MIDI patches 41 or 111).Tr7   (   n   r   r  r   s      r   r   zViolinFractionFeature.__init__	  sE    ?l?h?%	@  "Cyr   r*   r  r2   s   @r   r   r     s     
B	) 	)r   r   c                  (     e Zd ZdZdZd fd	Z xZS )SaxophoneFractionFeaturea  
    Fraction of all Note Ons belonging to saxophone patches (General MIDI
    patches 65 through 68).
    # NOTE: incorrect

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.SopranoSaxophone())
    >>> s1.repeatAppend(note.Note(), 6)
    >>> s1.append(instrument.Tuba())
    >>> s1.repeatAppend(note.Note(), 4)
    >>> fe = features.jSymbolic.SaxophoneFractionFeature(s1)
    >>> print(fe.extract().vector[0])
    0.6
    I15c                r    t        |   dd|i| d| _        d| _        d| _        d| _        g d| _        y )Nr   zSaxophone Fractionz]Fraction of all Note Ons belonging to saxophone patches (General MIDI patches 65 through 68).Tr7   )@   A   B   C   r   r  r   s      r   r   z!SaxophoneFractionFeature.__init__&  sA    ?l?h?(	D /r   r*   r  r2   s   @r   r&  r&    s     
B	0 	0r   r&  c                  (     e Zd ZdZdZd fd	Z xZS )BrassFractionFeaturea  
    A feature extractor that extracts the fraction of all Note Ons
    belonging to brass patches (General MIDI patches 57 through 68).

    TODO: Conflict in source: only does 57-62?

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.SopranoSaxophone())
    >>> s1.repeatAppend(note.Note(), 6)
    >>> s1.append(instrument.Tuba())
    >>> s1.repeatAppend(note.Note(), 4)
    >>> fe = features.jSymbolic.BrassFractionFeature(s1)
    >>> print(fe.extract().vector[0])
    0.4
    I16c                    t        |   dd|i| d| _        d| _        d| _        d| _        t        t        dd            | _        y )	Nr   zBrass FractionzYFraction of all Note Ons belonging to brass patches (General MIDI patches 57 through 68).Tr7   8   >   r   r  r   s      r   r   zBrassFractionFeature.__init__E  sL    ?l?h?$	D #E"bM2r   r*   r  r2   s   @r   r.  r.  2        
B	3 	3r   r.  c                  (     e Zd ZdZdZd fd	Z xZS )WoodwindsFractionFeaturea  
    Fraction of all Note Ons belonging to woodwind patches
    (General MIDI patches 69 through 76).

    TODO: Conflict in source: does 69-79?

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.Flute())
    >>> s1.repeatAppend(note.Note(), 3)
    >>> s1.append(instrument.Tuba())
    >>> s1.repeatAppend(note.Note(), 7)
    >>> fe = features.jSymbolic.WoodwindsFractionFeature(s1)
    >>> print(fe.extract().vector[0])
    0.3
    I17c                    t        |   dd|i| d| _        d| _        d| _        d| _        t        t        dd            | _        y )	Nr   zWoodwinds Fractionz\Fraction of all Note Ons belonging to woodwind patches (General MIDI patches 69 through 76).Tr7   D   P   r   r  r   s      r   r   z!WoodwindsFractionFeature.__init__d  sL    ?l?h?(	D #E"bM2r   r*   r  r2   s   @r   r5  r5  Q  r3  r   r5  c                  (     e Zd ZdZdZd fd	Z xZS ) OrchestralStringsFractionFeaturea  
    Fraction of all Note Ons belonging to orchestral strings patches
    (General MIDI patches 41 or 47).

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.Violoncello())
    >>> s1.repeatAppend(note.Note(), 4)
    >>> s1.append(instrument.Tuba())
    >>> s1.repeatAppend(note.Note(), 6)
    >>> fe = features.jSymbolic.OrchestralStringsFractionFeature(s1)
    >>> print(fe.extract().vector[0])
    0.4
    I18c                    t        |   dd|i| d| _        d| _        d| _        d| _        t        t        dd            | _        y )	Nr   zOrchestral Strings FractionzaFraction of all Note Ons belonging to orchestral strings patches (General MIDI patches 41 or 47).Tr7   )   .   r   r  r   s      r   r   z)OrchestralStringsFractionFeature.__init__  sK    ?l?h?1	? #E"bM2r   r*   r  r2   s   @r   r;  r;  p  s     
B	3 	3r   r;  c                  (     e Zd ZdZdZd fd	Z xZS )StringEnsembleFractionFeaturez
    Not implemented

    Fraction of all Note Ons belonging to string ensemble patches
    (General MIDI patches 49 to 52).
    I19c                r    t        |   dd|i| d| _        d| _        d| _        d| _        g d| _        y )Nr   zString Ensemble Fractionz^Fraction of all Note Ons belonging to string ensemble patches (General MIDI patches 49 to 52).Tr7   )r   1   2   3   r   r  r   s      r   r   z&StringEnsembleFractionFeature.__init__  s@    ?l?h?.	? /r   r*   r  r2   s   @r   rA  rA    s     
B	0 	0r   rA  c                  (     e Zd ZdZdZd fd	Z xZS )!ElectricInstrumentFractionFeaturea  
    Fraction of all Note Ons belonging to electric instrument patches
    (General MIDI patches 5, 6, 17, 19, 27 through 32, 24 through 40).

    >>> s1 = stream.Stream()
    >>> s1.append(instrument.ElectricOrgan())
    >>> s1.repeatAppend(note.Note(), 8)
    >>> s1.append(instrument.Tuba())
    >>> s1.repeatAppend(note.Note(), 2)
    >>> fe = features.jSymbolic.ElectricInstrumentFractionFeature(s1)
    >>> print(fe.extract().vector[0])
    0.8
    I20c                r    t        |   dd|i| d| _        d| _        d| _        d| _        g d| _        y )Nr   zElectric Instrument Fractionz|Fraction of all Note Ons belonging to electric instrument patches (General MIDI patches 5, 6, 17, 19, 27 to 32 or 34 to 40).Tr7   )rq   r`  rw      r                 !   "   #   $   %   &   '   r   r  r   s      r   r   z*ElectricInstrumentFractionFeature.__init__  sD    ?l?h?2	Y  Dr   r*   r  r2   s   @r   rH  rH    s     
B
D 
Dr   rH  c                      e Zd Zy)r>   N)r,   r-   r.   r   r   r   r>   r>     s    r   r>   DIMPRTC)NNNNNNNNNNNNNNNNNNNNNNNNNNNNNc                    	 t         |    |   S # t        $ r t        d|        t        $ r t        d|  d|       w xY w)aa  
    Typical usage:

    >>> t5 = features.jSymbolic.getExtractorByTypeAndNumber('T', 5)
    >>> t5.__name__
    'VoiceEqualityNoteDurationFeature'
    >>> bachExample = corpus.parse('bach/bwv66.6')
    >>> fe = t5(bachExample)

    Features unimplemented in jSymbolic but documented in the dissertation return None

    >>> features.jSymbolic.getExtractorByTypeAndNumber('C', 20) is None
    True

    Totally unknown features return an exception:

    >>> features.jSymbolic.getExtractorByTypeAndNumber('L', 900)
    Traceback (most recent call last):
    music21.features.jSymbolic.JSymbolicFeatureException: Could not find
        any jSymbolic features of type L

    >>> features.jSymbolic.getExtractorByTypeAndNumber('C', 200)
    Traceback (most recent call last):
    music21.features.jSymbolic.JSymbolicFeatureException: jSymbolic
        features of type C do not have number 200

    You could also find all the feature extractors this way:

    >>> fs = features.jSymbolic.extractorsById
    >>> for k in fs:
    ...     for i in range(len(fs[k])):
    ...       if fs[k][i] is not None:
    ...         n = fs[k][i].__name__
    ...         if fs[k][i] not in features.jSymbolic.featureExtractors:
    ...            n += ' (not implemented)'
    ...         print(f'{k} {i} {n}')
    D 1 OverallDynamicRangeFeature (not implemented)
    D 2 VariationOfDynamicsFeature (not implemented)
    D 3 VariationOfDynamicsInEachVoiceFeature (not implemented)
    D 4 AverageNoteToNoteDynamicsChangeFeature (not implemented)
    I 1 PitchedInstrumentsPresentFeature
    I 2 UnpitchedInstrumentsPresentFeature (not implemented)
    I 3 NotePrevalenceOfPitchedInstrumentsFeature
    I 4 NotePrevalenceOfUnpitchedInstrumentsFeature (not implemented)
    I 5 TimePrevalenceOfPitchedInstrumentsFeature (not implemented)
    I 6 VariabilityOfNotePrevalenceOfPitchedInstrumentsFeature
    I 7 VariabilityOfNotePrevalenceOfUnpitchedInstrumentsFeature (not implemented)
    I 8 NumberOfPitchedInstrumentsFeature
    I 9 NumberOfUnpitchedInstrumentsFeature (not implemented)
    I 10 PercussionPrevalenceFeature (not implemented)
    I 11 StringKeyboardFractionFeature
    I 12 AcousticGuitarFractionFeature
    I 13 ElectricGuitarFractionFeature
    I 14 ViolinFractionFeature
    I 15 SaxophoneFractionFeature
    I 16 BrassFractionFeature
    I 17 WoodwindsFractionFeature
    I 18 OrchestralStringsFractionFeature
    I 19 StringEnsembleFractionFeature
    I 20 ElectricInstrumentFractionFeature
    M 1 MelodicIntervalHistogramFeature
    M 2 AverageMelodicIntervalFeature
    M 3 MostCommonMelodicIntervalFeature
    M 4 DistanceBetweenMostCommonMelodicIntervalsFeature
    M 5 MostCommonMelodicIntervalPrevalenceFeature
    M 6 RelativeStrengthOfMostCommonIntervalsFeature
    M 7 NumberOfCommonMelodicIntervalsFeature
    M 8 AmountOfArpeggiationFeature
    M 9 RepeatedNotesFeature
    M 10 ChromaticMotionFeature
    M 11 StepwiseMotionFeature
    M 12 MelodicThirdsFeature
    M 13 MelodicFifthsFeature
    M 14 MelodicTritonesFeature
    M 15 MelodicOctavesFeature
    M 17 DirectionOfMotionFeature
    M 18 DurationOfMelodicArcsFeature
    M 19 SizeOfMelodicArcsFeature
    P 1 MostCommonPitchPrevalenceFeature
    P 2 MostCommonPitchClassPrevalenceFeature
    P 3 RelativeStrengthOfTopPitchesFeature
    P 4 RelativeStrengthOfTopPitchClassesFeature
    P 5 IntervalBetweenStrongestPitchesFeature
    P 6 IntervalBetweenStrongestPitchClassesFeature
    P 7 NumberOfCommonPitchesFeature
    P 8 PitchVarietyFeature
    P 9 PitchClassVarietyFeature
    P 10 RangeFeature
    P 11 MostCommonPitchFeature
    P 12 PrimaryRegisterFeature
    P 13 ImportanceOfBassRegisterFeature
    P 14 ImportanceOfMiddleRegisterFeature
    P 15 ImportanceOfHighRegisterFeature
    P 16 MostCommonPitchClassFeature
    P 17 DominantSpreadFeature (not implemented)
    P 18 StrongTonalCentresFeature (not implemented)
    P 19 BasicPitchHistogramFeature
    P 20 PitchClassDistributionFeature
    P 21 FifthsPitchHistogramFeature
    P 22 QualityFeature
    P 23 GlissandoPrevalenceFeature (not implemented)
    P 24 AverageRangeOfGlissandosFeature (not implemented)
    P 25 VibratoPrevalenceFeature (not implemented)
    R 1 StrongestRhythmicPulseFeature (not implemented)
    R 2 SecondStrongestRhythmicPulseFeature (not implemented)
    R 3 HarmonicityOfTwoStrongestRhythmicPulsesFeature (not implemented)
    R 4 StrengthOfStrongestRhythmicPulseFeature (not implemented)
    R 5 StrengthOfSecondStrongestRhythmicPulseFeature (not implemented)
    R 6 StrengthRatioOfTwoStrongestRhythmicPulsesFeature (not implemented)
    R 7 CombinedStrengthOfTwoStrongestRhythmicPulsesFeature (not implemented)
    R 8 NumberOfStrongPulsesFeature (not implemented)
    R 9 NumberOfModeratePulsesFeature (not implemented)
    R 10 NumberOfRelativelyStrongPulsesFeature (not implemented)
    R 11 RhythmicLoosenessFeature (not implemented)
    R 12 PolyrhythmsFeature (not implemented)
    R 13 RhythmicVariabilityFeature (not implemented)
    R 14 BeatHistogramFeature (not implemented)
    R 15 NoteDensityFeature
    R 17 AverageNoteDurationFeature
    R 18 VariabilityOfNoteDurationFeature
    R 19 MaximumNoteDurationFeature
    R 20 MinimumNoteDurationFeature
    R 21 StaccatoIncidenceFeature
    R 22 AverageTimeBetweenAttacksFeature
    R 23 VariabilityOfTimeBetweenAttacksFeature
    R 24 AverageTimeBetweenAttacksForEachVoiceFeature
    R 25 AverageVariabilityOfTimeBetweenAttacksForEachVoiceFeature
    R 30 InitialTempoFeature
    R 31 InitialTimeSignatureFeature
    R 32 CompoundOrSimpleMeterFeature
    R 33 TripleMeterFeature
    R 34 QuintupleMeterFeature
    R 35 ChangesOfMeterFeature
    R 36 DurationFeature
    T 1 MaximumNumberOfIndependentVoicesFeature
    T 2 AverageNumberOfIndependentVoicesFeature
    T 3 VariabilityOfNumberOfIndependentVoicesFeature
    T 4 VoiceEqualityNumberOfNotesFeature (not implemented)
    T 5 VoiceEqualityNoteDurationFeature (not implemented)
    T 6 VoiceEqualityDynamicsFeature (not implemented)
    T 7 VoiceEqualityMelodicLeapsFeature (not implemented)
    T 8 VoiceEqualityRangeFeature (not implemented)
    T 9 ImportanceOfLoudestVoiceFeature (not implemented)
    T 10 RelativeRangeOfLoudestVoiceFeature (not implemented)
    T 12 RangeOfHighestLineFeature (not implemented)
    T 13 RelativeNoteDensityOfHighestLineFeature (not implemented)
    T 15 MelodicIntervalsInLowestLineFeature (not implemented)
    T 20 VoiceSeparationFeature (not implemented)
    z.Could not find any jSymbolic features of type zjSymbolic features of type z do not have number )extractorsByIdKeyErrorr>   r   )extractorTypenumbers     r   getExtractorByTypeAndNumberre  z  sl    lWm,V44 N'<]OLN 	N W')-8LVHUW 	WWs    1?c            	         d} d}t         D ]O  }t         |   }t        t        |            D ]-  }||   	||   j                  }| dz  } ||   t        v s)|dz  }/ Q t        d| d|  d|| z   d       y)z^
    >>> features.jSymbolic.getCompletionStats()
    completion stats: 72/112 (0.6428...)
    r   Nr7   zcompletion stats: /z ())ra  r<   r@   r,   featureExtractorsprint)
countTotalcountCompletekgroupr'   unused_ns         r   getCompletionStatsrp  t  s    
 JMq!s5z"AQx# 8,,a
800!Q&M #  
}oQzl"]Z=W<XXY
Z[r   c                      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d Zd Zd Zd Zd Zd Zd Zd Zd Zy)Testc                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   streampitchnotefeaturesc2)p5r}  r}  p4r~  r~  g      @)music21ru  rw  ry  r{  StreamPitchr=   NoterS   rT   	transpose	jSymbolicr4   extractassertEqualr&   
r   ru  rw  ry  r{  r  r/  r'   fefs
             r   !testAverageMelodicIntervalFeaturez&Test.testAverageMelodicIntervalFeature  s    "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 ==a@JJLC5)r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  )r}  r}  r}  r~  r~  r~  r~  r`  )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  rE   r  r  r&   r  s
             r   $testMostCommonMelodicIntervalFeaturez)Test.testMostCommonMelodicIntervalFeature  s    "! $MMOKK	4==+,-;AAAHHTYYt}}Q/01 < @@CJJLA3'r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  	r}  r}  r}  r~  r~  r~  r~  m2m3r   )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  rO   r  r  r&   r  s
             r   4testDistanceBetweenMostCommonMelodicIntervalsFeaturez9Test.testDistanceBetweenMostCommonMelodicIntervalsFeature  s    "! $MMOKK	4==+,-GAAAHHTYYt}}Q/01 H PPQRSJJLA3'r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  )r}  r}  r~  r~  r~  r~  r  r        ?)r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  rY   r  r  r&   r  s
             r   .testMostCommonMelodicIntervalPrevalenceFeaturez3Test.testMostCommonMelodicIntervalPrevalenceFeature  s    "! $MMOKK	4==+,-AAAAHHTYYt}}Q/01 B JJ1MJJLC5)r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  r  g      ?)r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r_   r  r  r&   r  s
             r   0testRelativeStrengthOfMostCommonIntervalsFeaturez5Test.testRelativeStrengthOfMostCommonIntervalsFeature  s    "! $MMOKK	4==+,-GAAAHHTYYt}}Q/01 H LLQOJJLD6*r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  )r}  r~  r~  r~  r~  r~  r~  r~  r~  r~  r~  r  r  r7   )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  rd   r  r  r&   r  s
             r   )testNumberOfCommonMelodicIntervalsFeaturez.Test.testNumberOfCommonMelodicIntervalsFeature  s    "! $MMOKK	4==+,-_AAAHHTYYt}}Q/01 ` EEaHJJLA3'r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  )r  r  r5   rF   r}  p8r  )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  rl   r  r  r&   r  s
             r   testAmountOfArpeggiationFeaturez$Test.testAmountOfArpeggiationFeature  s    "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 ;;A>JJLC5)r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  )p1r  r  r5   rF   r}  r  )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r}   r  r  r&   r  s
             r   testRepeatedNotesFeaturezTest.testRepeatedNotesFeature  s    "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 44Q7JJLC5)r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  r  r  r  r5   rF   r}  r  )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  r  r&   r  s
             r   testChromaticMotionFeaturezTest.testChromaticMotionFeature  s    "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 66q9JJLC5)r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  r  gUUUUUU?)r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  r  r&   r  s
             r   testStepwiseMotionFeaturezTest.testStepwiseMotionFeature$      "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 55a8JJLE7+r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  r  UUUUUU?)r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  r  r&   r  s
             r   testMelodicThirdsFeaturezTest.testMelodicThirdsFeature5      "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 44Q7JJLE7+r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  )r  r  r  r5   r}  r}  gUUUUUU?)r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  r  r&   r  s
             r   testMelodicFifthsFeaturezTest.testMelodicFifthsFeatureF  r  r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  )r  r  r  r5   r}  d5r  )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  r  r&   r  s
             r   testMelodicTritonesFeaturezTest.testMelodicTritonesFeatureW  s    "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 66q9JJLE7+r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )	Nr   rt  rv  rx  rz  r|  r  r  r  r5   r}  r  r  )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  r  r&   r  s
             r   testMelodicOctavesFeaturezTest.testMelodicOctavesFeatureh  r  r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       |j                         }|j                  d      }|j                  |j                  t        j                  |                   d	D ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   d
g       |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       y )Nr   rt  rv  rx  rz  r|  r        ?)r  r  -m2-M2-p5r  r  )r  r  r  r  r  -p8r   )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  r  r&   r  s
             r   testDirectionOfMotionFeaturez!Test.testDirectionOfMotionFeaturey  s   "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 88;JJLC5) MMOKK	4==+,-8AAAHHTYYt}}Q/01 9 88;JJLC5) MMOKK	4==+,-;AAAHHTYYt}}Q/01 < 88;JJLC5)r   c                   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j                  |	j                   dg       |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	| j#                  |	j                   d   d	       y )
Nr   rt  rv  rx  rz  r|  r  r  r  r  r5   r}  r  r  r  g?)r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  r  r&   assertAlmostEqualr  s
             r    testDurationOfMelodicArcsFeaturez%Test.testDurationOfMelodicArcsFeature  s]   "! $
 MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 <<Q?JJLA3'MMOKK	4==+,-DAAAHHTYYt}}Q/01 E <<Q?JJLqxx{E2r   c                \   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	|j                         }|j                  d      }|j                  |j                  t        j                  |                   dD ]F  }|j                  |      }|j                  |j                  t        j                  |                   H |j                  j                  |      }|j                         }	y )	Nr   rt  rv  rx  rz  r|  r  r  )r  ru  rw  ry  r{  r  r  r=   r  rS   rT   r  r  r   r  )
r   ru  rw  ry  r{  r  r/  r'   r  unused_fs
             r   testSizeOfMelodicArcsFeaturez!Test.testSizeOfMelodicArcsFeature  s/   "! $MMOKK	4==+,-5AAAHHTYYt}}Q/01 6 88;::< MMOKK	4==+,-DAAAHHTYYt}}Q/01 E 88;::<r   c                d   ddl m} ddl m} ddl m} ddl m} |j                         }|j                  d|j                  d             |j                  d|j                  d	             |j                  d
|j                  d	             |j                  d|j                  d	             |j                  d|j                  d	             |j                  d|j                  d	             |j                  d|j                  d	             |j                  d|j                  d	             |j                  d|j                  d
	             |j                  j                  |      }|j                         }| j                  |j                  d   d       |j                         }|j                  d|j                  d             |j                  d|j                  d	             |j                  d
|j                  d	             |j                  d|j                  d	             |j                  d|j                  d	             |j                  d|j                  d	             |j                  d|j                  d	             |j                  d|j                  d	             |j                  d|j                  d
	             |j                  j                  |      }|j                         }| j                  |j                  d   d       y )Nr   rt  rx  temporz  r   )rd  r  )quarterLengthr7   rr   r   r   rp   r`  rq   r     g      @)r  ru  ry  r  r{  r  insertMetronomeMarkr  r  r  r  r  r&   )r   ru  ry  r  r{  r  r  r  s           r   testNoteDensityFeatureAzTest.testNoteDensityFeatureA  s`   " !$MMO	E''r'23	DIIAI./	DIIAI./	DIIAI./	DIIAI./	DIIAI./	DIIAI./	DIIAI./	DIIAI./2215JJLqxx{C0MMO	E''s'34	DIIAI./	DIIAI./	DIIAI./	DIIAI./	DIIAI./	DIIAI./	DIIAI./	DIIAI./ 2215JJLqxx{C0r   c           	     *   ddl m} |j                  j                  }d}d}|D ]P  }t	        t        ||               D ]4  }||   |   |dz  }||   |   |j                  j                  v s0|dz  }6 R t        j                  d|d|d||z  g       y )Nr   rz  r7   z	fe total:zfe implementedpercent)	r  r{  r  ra  r<   r@   ri  rE  rF  )r   r{  fsfeTotalfeImplementedrm  r'   s          r   testFeatureCountzTest.testFeatureCount  s    $..A3r!u:&a58'qLG!uQx8#5#5#G#GG%*	 '  	g7G!.	=7;R!T 	Ur   c                   ddl m} ddl m} |j                  dd      }|j                  D ]$  }|j                  d|j                  dd             & t        |      }|j                         }| j                  d|j                  d          y )	Nr   )corpusr  zschoenberg/opus19r   LangsamF   g     a@)r  r  r  parser   r  r  r  r  r  r&   )r   r  r  schr/  r  r  s          r   testBeatHistogramzTest.testBeatHistogram	  so    "!ll.2AHHQ++Ir:; *3/JJL,r   N)r,   r-   r.   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r   rr  rr    si    *$($("*"+"("*"*"*",",",",","$*L3: 4#1JU-r   rr  __main__)r/   
__future__r   collectionsr   rS   r  r   r,  textwrapr   unittestr  r   r   r	   music21.featuresr  music21.instrumentr
   EnvironmentrE  r  r   r4   rE   rO   rY   r_   rd   rl   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r!  r'  r1  r>  rD  rJ  rP  rZ  r_  re  rm  rs  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r	  r  r  r$  r)  r1  r7  r@  rL  rU  r\  rb  rj  rp  rt  rx  r|  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r&  r.  r5  r;  rA  rH  FeatureExceptionr>   ra  re  ri  rp  TestCaserr  r,   mainTestr   r   r   <module>r     sy   # #           3 )&{&&';<+n&E&E +@ ;N$C$C  ;F*~'F'F *<"=''"=J2''2D$L''$LN!&N,K,K !&H)/."A"A )/X$/>:: $/N!/^<< !/H"/N;; "/J!/>:: !/H!/>:: !/H!/^<< !/H!/N;; !/H,=~>> ,=^S:>#B#B S:li6~>> i6` 1~'F'F  1F 5N,K,K  5F").*I*I ")J%:~/N/N %:P )^-L-L  )F!?''!?H&>#B#B &B&.99 &>&~>> &>5>22 5@)^<< )@H^<< H<"Bn&E&E "BJ"B(G(G "BJ"Bn&E&E "BJ+."A"A +8?N;; ?.? ? ? ?.'+!@!@ '+T*AN$C$C *AZ&:."A"A &:R4,^44 4,n?!@!@ ?.?n&E&E ?8?~>> ?2?N$C$C ?8AN$C$C AD#A.*I*I #AL'E'''ETAn.M.M A4:'':D"<''"<J I'' IF?."A"A ?,?N$C$C ?*N,K,K &?~>> ?8?88 ?D?!@!@ ?*?>:: ?4#K88 #KL"9!@!@ "9J%C~'F'F %CP,!@!@ ,@,!@!@ ,@9~>> 9D(E~'F'F (EV&@^-L-L &@R6A''6Ar9=''9=v4.99 4:'9."A"A '9T/+>#B#B /+d&'88 &'R%'N;; %'P+N;; +\/n55 /L!@!@ &!@!@ (N,K,K ,^-L-L 6('n.M.M ('V*9n.M.M *9Z&A''&AR(G(G *~'F'F &>#B#B &~'F'F * ? ? (n&E&E ()H)H ( ? ? (n.M.M *.*I*I (^<< 2@7~'F'F @7F?)H)H ?D;I'';I|''6''>1H''1Hh''8%'(G(G %'P.*I*I 2."A"A (/ ? ? /@($= (:($= (:3$= 34)5 ):08 0:34 3>38 3>3'@ 3:0$= 0.D(A D<	 ? ? 	 ""-.  	(*131>@)+#%%%  (%)+ . 	'%(824-# $ + . 	(-+0.3$ ')'#!"%#"' 7 : 	 &&%& 	,& 	7	&
 	0& 	6& 	9& 	<& 	$& 	&& 	.& 	!& 	& 	#& 	&  	!&" 	#&$ 	#%&& 	)'&( 	#)&* 	#+&, 	!-&. 	)/&0 	/1&2 	53&4 	B5&6 	7&8 	9&: 	;&< 	=&> 	?&@ 	$A&B 	%C&D 	E&F 	G&H 	I&J 	K& &N 	//5)($(!'*!/++ . 	  cq qh]W@W#W "W %	W
 5W /W 1W *W  W W W W W W W  !W" #W$ !%W& 'W* %+W, .-W. ;/W0 &1W2 "3W4 "5W6 "7W8 9W: ;W< =W> ?W@ %AWB "CWD &EWN OWP QWR %SWT UWV WWX YWZ %[W\ +]W^ 1_W` >aWd eWf  gWh !iWj kWl mWn oWp qWt ,uWv ,wWx 2yW| %}W~ *W@ (AWB -CWD +EWF 0GWH !IWJ KWL MWN OWP QWR SWT $UWV &WWX $YWZ  [W\ ]W^ "_W`  aWb cW t\&J-8 J-Z zGT r   