
    z	iL                        S r SSKJr  SSKrSSKJr  SSKJr  SSKJ	r	  SSK
Jr  SSKrSSKJr  SS	KJr  SS
KJr  SSKJrJr  SSKJr   " S S5      rg)aC  
Core module of the timeline drawer.

This module provides the `DrawerCanvas` which is a collection of drawings.
The canvas instance is not just a container of drawing objects, as it also performs
data processing like binding abstract coordinates.


Initialization
~~~~~~~~~~~~~~
The `DataCanvas` is not exposed to users as they are implicitly initialized in the
interface function. It is noteworthy that the data canvas is agnostic to plotters.
This means once the canvas instance is initialized we can reuse this data
among multiple plotters. The canvas is initialized with a stylesheet.

    ```python
    canvas = DrawerCanvas(stylesheet=stylesheet)
    canvas.load_program(sched)
    canvas.update()
    ```

Once all properties are set, `.update` method is called to apply changes to drawings.

Update
~~~~~~
To update the image, a user can set new values to canvas and then call the `.update` method.

    ```python
    canvas.set_time_range(2000, 3000)
    canvas.update()
    ```

All stored drawings are updated accordingly. The plotter API can access to
drawings with `.collections` property of the canvas instance. This returns
an iterator of drawings with the unique data key.
If a plotter provides object handler for plotted shapes, the plotter API can manage
the lookup table of the handler and the drawings by using this data key.
    )annotationsN)Iterator)deepcopy)partial)Enum)circuit)Target)VisualizationError)drawingstypes)QiskitTimelineStylec                      \ rS rSrSrSS jr\SS j5       r\R                  SS j5       r\SS j5       r	SS jr
SSS	 jjrSS
 jrSSS jjrSSS jjrS rSS jrSS jrS S jr    S!S jrSrg)"DrawerCanvasC   zData container for drawings.c                   UR                   U l         UR                  U l        UR                  U l        0 U l        0 U l        / U l        0 U l        [        5       U l        [        5       U l	        SU l
        SU l        SU l        g)zCreate new data container.)r   r   r   N)	formatter	generatorlayout_collections_output_datasetbitsassigned_coordinatessetdisable_bitsdisable_types_time_rangevmaxvmin)self
stylesheets     \/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/visualization/timeline/core.py__init__DrawerCanvas.__init__F   s     $--#-- '' ACCE ')	=?! .1U'*u " 		    c                |    U R                   u  pX!-
  nXU R                  S   -  -
  nX#U R                  S   -  -   nXE4$ )zReturn current time range to draw.

Calculate net duration and add side margin to edge location.

Returns:
    Time window considering side margin.
zmargin.left_percentzmargin.right_percent)r   r   )r   t0t1durationnew_t0new_t1s         r!   
time_rangeDrawerCanvas.time_range`   sN     !!70E!FFF0F!GGG~r$   c                    Xl         g)zUpdate time range to draw.N)r   )r   	new_ranges     r!   r+   r,   q   s
     %r$   c              #  T   #    U R                   R                  5        Sh  vN   g N7f)zReturn currently active entries from drawing data collection.

The object is returned with unique name as a key of an object handler.
When the horizontal coordinate contains `AbstractCoordinate`,
the value is substituted by current time range preference.
N)r   items)r   s    r!   collectionsDrawerCanvas.collectionsv   s      ''--///s   (&(c                    U R                   S   (       dC  UR                   Vs/ s H&  n[        U[        R                  5      (       a  M$  UPM(     snUl        XR
                  UR                  '   gs  snf )zAdd drawing to collections.

If the given object already exists in the collections,
this interface replaces the old object instead of adding new entry.

Args:
    data: New drawing to add.
control.show_clbitsN)r   r   
isinstancer   Clbitr   data_key)r   databs      r!   add_dataDrawerCanvas.add_data   sP     ~~34$(IIRIqZ7==5QIRDI+/$--( Ss   #A1
A1Nc           
     	  ^ [         R                  4n[        TS5      c0  SSKJn  SSKJn  [        R                  " S[        SS9   U" TS	USS
9m[        TR                  TR                  5       GH  u  px[        UR                   5      [        UR"                  5      -   n	[%        U	5       GH  u  p['        UR(                  U5      (       Gd  Ub  SnUR+                  UR(                  R                  5      nUbQ  UR+                  [-        U4S jUR                    5       5      5      nUb   [        US5      nUb  UR/                  U5      nUR                  S:X  a  UR(                  R0                  nUc&  [        SUR(                  R                   SU
 S35      eO2UR                  S:X  a  UR(                  R0                  nO[        S5      e[2        R4                  " UUR(                  UU	U
S9nU R6                  S    HG  n[        USS5      (       a
  [9        UTS9nU" XR:                  S9 H  nU R=                  U5        M     MI     [?        U	5      S:  a  U
S:X  a  USU-  -   n[2        R@                  " UUR(                  R                  U	S9nU R6                  S    HH  n[        USS5      (       a
  [9        UTS9nU" UU R:                  S9 H  nU R=                  U5        M     MJ     ['        UR(                  [         R                  5      (       d  GMl  [2        R                  " XyU
S9nU R6                  S    HH  n[        USS5      (       a
  [9        UTS9nU" UU R:                  S9 H  nU R=                  U5        M     MJ     GM     GM      [        TR                   5      [        TR"                  5      -   U l!        U RB                   H]  nU R6                  S     HG  n[        USS5      (       a
  [9        UTS9nU" XR:                  S9 H  nU R=                  U5        M     MI     M_     [E        TRF                  U R:                  S!   5      nU RI                  SUS"9  g! U a  n[        STR                   S35      UeSnAff = f)#a  Load quantum circuit and create drawing..

.. deprecated:: 1.3
   Visualization of unscheduled circuits with the timeline drawer has been
   deprecated in Qiskit 1.3.
   This circuit should be transpiled with a scheduler, despite having instructions
   with explicit durations.

.. deprecated:: 1.3
   Targets with duration-less operations are going to error in Qiskit 2.0.

Args:
    program: Scheduled circuit object to draw.
    target: The target the circuit is scheduled for. This contains backend information
        including the instruction durations used in scheduling.

Raises:
   VisualizationError: When circuit is not scheduled.
_op_start_timesNr   )	transpile)TranspilerErrorzVisualizing un-scheduled circuit with timeline drawer has been deprecated. This circuit should be transpiled with scheduler though it consists of instructions with explicit durations.   )
stacklevelalap)scheduling_methodtargetoptimization_levelzInput circuit z\ is not scheduled and it contains operations with unknown delays. This cannot be visualized.c              3  Z   >#    U  H   nTR                  U5      R                  v   M"     g 7fN)find_bitindex).0xprograms     r!   	<genexpr>,DrawerCanvas.load_program.<locals>.<genexpr>   s$     %\I[Ag&6&6q&9&?&?I[s   (+r(   delayz&Target doesn't contain a duration for z on .zCTarget not specified this is required to provide instruction timing)r&   operandr(   r   bit_positiongatesaccepts_programF)rL   )r            ?)r&   opnamer   
gate_links)r&   r   rR   barriersr   zmargin.minimum_duration)t_startt_end)%r   Barriergetattrqiskitr>   qiskit.transpilerr?   warningswarnDeprecationWarningr
   namezipop_start_timesr8   listqubitsclbits	enumerater5   	operationgettupleseconds_to_dtr(   r   ScheduledGater   r   r   r:   lenGateLinkr   max	_durationset_time_range)r   rL   rD   not_gate_liker>   r?   exr&   instructionr   bit_posbitr(   op_props
inst_propsgate_sourcegendatumline_poslink_sourcebarrier_sourcer[   s    `                    r!   load_programDrawerCanvas.load_program   s4   ( !*7-.6(9MM8 ##&,!'(	  #7#9#97<<HOB**+d;3E3E.FFD )$!+"7"7GG)#'#)::k.C.C.H.H#I#/)1 %%\I[I[%\ \*J  *5+2:z+J#+#7/5/C/CH/MH&++w6'2'<'<'E'EH#+"4 H#.#8#8#=#=">d7)1!N#  , %))W4#.#8#8#A#A0a  #("5"5 + 5 5!)!%,#K  $~~g6"3(95AA")#w"?C%(%OE MM%0 &P  7
 4y1}A#%h#6&+nn'0E0E0J0JQU' $(>>,#?C&s,=uEE&-c7&C),[DNN)S $e 4 *T $@
 k33W__EE%*]]bRY%ZN#~~j9"3(95AA")#w"?C%(4>>%RE MM%0 &S  :o !0  I~ (4+??	99C~~f-3 1599!#w7C ?EMM%( @	 .  G%%t~~6O'PQAU3a # ($W\\N 3Q Q s   	Q# #R)RRc                    X4U l         g)zSet time range to draw.

Args:
    t_start: Left boundary of drawing in units of cycle time.
    t_end: Right boundary of drawing in units of cycle time.
N)r+   )r   rZ   r[   s      r!   rs   DrawerCanvas.set_time_range
  s     #*r$   c                    U(       a  U R                   R                  U5        gU R                   R                  U5        g)zInterface method to control visibility of bits.

Specified object in the blocked list will not be shown.

Args:
    bit: A qubit or classical bit object to disable.
    remove: Set `True` to disable, set `False` to enable.
N)r   adddiscard)r   rx   removes      r!   set_disable_bitsDrawerCanvas.set_disable_bits  s/     !!#&%%c*r$   c                    [        U[        5      (       a  [        UR                  5      nOUnU(       a  U R                  R                  U5        gU R                  R                  U5        g)zInterface method to control visibility of data types.

Specified object in the blocked list will not be shown.

Args:
    data_type: A drawing data type to disable.
    remove: Set `True` to disable, set `False` to enable.
N)r5   r   strvaluer   r   r   )r   	data_typer   data_type_strs       r!   set_disable_typeDrawerCanvas.set_disable_type!  sO     i&&	0M%M""=1&&}5r$   c                   U R                   R                  5         U R                  R                  5         U R                  S   * nU R                  S   " U R
                  5       Hh  n[        U[        R                  5      (       a  U R                  S   (       d  M8  U R                  U5      (       d  MP  US-
  nX0R                  U'   US-
  nMj     SU l
        XR                  S   -
  U l        0 n0 nU R                  R                  5        H  u  pg[        U5      nU R                  UR                   5      Ul        U R                  UR"                  5      Ul        UR$                  ['        [(        R*                  R,                  R.                  5      :X  a  XU'   M  XU'   M     UR1                  U R3                  U5      5        UR                  5        H+  u  pgU R5                  U5      (       d  M  XpR                   U'   M-     g)zbUpdate all collections.

This method should be called before the canvas is passed to the plotter.
z
margin.topbit_arranger4   rV   r   zmargin.bottomN)r   clearr   r   r   r   r5   r   r6   _check_bit_visibler   r   r   r0   r   _bind_coordinatexvalsyvalsr   r   r   LineType	GATE_LINKr   update_check_link_overlap_check_data_visible)	r   y0rx   offsettemp_gate_links	temp_datar7   r8   new_datas	            r!   r   DrawerCanvas.update4  s   
 	""$!!'') nn\**;;}-dii8C#w}}--dnnEZ6[**3//#XF-3%%c*#B 9 	88	 	"//557NH~H!224::>HN!224::>HN~~U^^%=%=%C%C!DD,4)&.(# 8 	11/BC (oo/NH''--15$$X. 0r$   c                  ^ ^^^ [        [        R                  R                  R                  5      /m[        [        R
                  R                  R                  5      [        [        R                  R                  R                  5      /mU 4S jnU 4S jnUUU 4S jnX#U/n[        U4S jU 5       5      (       a  gg)zA helper function to check if the data is visible.

Args:
    data: Drawing object to test.

Returns:
    Return `True` if the data is visible.
c                   > TR                   u  p[        R                  " U R                  5      U:  d$  [        R                  " U R                  5      U:  a  gg)z2If data is located outside the current time range.FT)r+   nprq   r   min)_datar&   r'   r   s      r!   _time_range_check;DrawerCanvas._check_data_visible.<locals>._time_range_checkm  s=    __FBvvekk"R'266%+++>+Cr$   c                P   > [        U4S jU R                   5       5      (       a  gg)z#If any associated bit is not shown.c              3  @   >#    U  H  oTR                   ;  v   M     g 7frG   )r   )rJ   rx   r   s     r!   rM   RDrawerCanvas._check_data_visible.<locals>._associated_bit_check.<locals>.<genexpr>v  s     N:Cd777:s   FT)allr   )r   r   s    r!   _associated_bit_check?DrawerCanvas._check_data_visible.<locals>._associated_bit_checkt  s    N5::NNNr$   c                  > U R                   [        [        R                  R                  R
                  5      :X  a?  U R                   Vs/ s H  oTR                  ;  d  M  UPM     nn[        U5      S:  a  g gU R                   T;   a  TR                  S   (       d  gU R                   T;   a  TR                  S   (       d  ggs  snf )zIf data is valid.   Fzcontrol.show_barrierszcontrol.show_delaysT)
r   r   r   r   r   r   r   r   ro   r   )r   rx   active_bits	_barriers_delaysr   s      r!   _data_check5DrawerCanvas._check_data_visible.<locals>._data_checkz  s    #enn&>&>&D&D"EE.3jjYjstGXGX<XsjY{#a'  ( 	 I-dnnE\6]G+DNNCX4Y Zs   C"Cc              3  2   >#    U  H  o" T5      v   M     g 7frG    )rJ   checkr8   s     r!   rM   3DrawerCanvas._check_data_visible.<locals>.<genexpr>  s     /uuT{{s   TF)	r   r   r   BARRIERr   BoxTypeDELAY	LabelTyper   )r   r8   r   r   r   checksr   r   s   ``    @@r!   r    DrawerCanvas._check_data_visible`  s     //5567	u}}**0013u7L7L7R7R3ST		
	 $KH////r$   c                   [        [        R                  R                  R                  5      [        [        R
                  R                  R                  5      /nXR                  ;   a  gU R                  S   (       a  gU R                  R                  5        H&  nXR                  ;   d  M  UR                  U;   d  M&    g   g)zA helper function to check if the bit is visible.

Args:
    bit: Bit object to test.

Returns:
    Return `True` if the bit is visible.
Fzcontrol.show_idleT)r   r   r   
SCHED_GATEr   
SymbolTypeFRAMEr   r   r   valuesr   r   )r   rx   _gatesr8   s       r!   r   DrawerCanvas._check_bit_visible  s     emm..445s5;K;K;Q;Q;W;W7XY###>>-.%%,,.DiiDNNf$< / r$   c           	        ^  SU 4S jjn [         R                  " U[        S9$ ! [         a.    [         R                  " [	        [        X!5      5      [        S9s $ f = f)zA helper function to bind actual coordinates to an `AbstractCoordinate`.

Args:
    vals: Sequence of coordinate objects associated with a drawing.

Returns:
    Numpy data array with substituted values.
c                ~  > U [         R                  R                  :X  a  TR                  S   $ U [         R                  R                  :X  a  TR                  S   $ U [         R                  R
                  :X  a  TR                  $ U [         R                  R                  :X  a  TR                  $ [        SU  S35      e)Nr   rU   zCoordinate z is not supported.)
r   AbstractCoordinateLEFTr+   RIGHTTOPr   BOTTOMr   r
   )valr   s    r!   
substitute1DrawerCanvas._bind_coordinate.<locals>.substitute  s    e..333q))e..444q))e..222yy e..555yy ${3%7I%JKKr$   )dtype)r   ztypes.Coordinate)r   asarrayfloat	TypeErrorrf   map)r   valsr   s   `  r!   r   DrawerCanvas._bind_coordinate  sL    		L	H::d%00 	H::d3z#89GG	Hs   $ 5AAc                  ^ ^^ T R                   S   T R                   S   -
  nT R                  S   U-  nS
U 4S jjm/ n[        TR                  5       5      n[	        U5      S:  Ga  UR                  5       n[        5       nUR                  U5        USSS2    GHO  n[        R                  " TU   R                  S   TU   R                  S   -
  5      U:  d  MC  T" TU   5      n	T" TU   5      n
[        R                  " U	5      [        R                  " U
5      -
  n[        R                  " U	5      [        R                  " U
5      -
  n[        R                  " U	5      [        R                  " U
5      -
  n[        R                  " U	5      [        R                  " U
5      -
  nX-  S:  a  X-  S:  a  GM   UR                  UR                  UR                  U5      5      5        GMR     UR                  [        U5      5        [	        U5      S:  a  GM  0 nU H  n[	        U5      S:  a  [        R                  " U Vs/ s H  nTU   R                  S   PM     sn5      n[!        UUU4S jS9nUS	U-  [	        U5      S-
  -  -
  n[#        U5       H  u  nnTU   nUUU-  -   /Ul
        UX'   M     M  US   nTU   X'   M     TR                  5        Vs0 s H  oX   _M	     sn$ s  snf s  snf )zHelper method to check overlap of bit links.

This method dynamically shifts horizontal position of links if they are overlapped.
rU   r   zmargin.link_interval_percentc           	        > [         R                  " U R                   Vs/ s H-  nTR                  R	                  U[         R
                  5      PM/     sn5      $ s  snf rG   )r   arrayr   r   rk   nan)linkrx   r   s     r!   y_coords2DrawerCanvas._check_link_overlap.<locals>.y_coords  sD    88SWS\S\]S\CT66::3GS\]^^]s   4ANc                B   > [         R                  " T" TU    5      5      $ rG   )r   nanmax)rK   linksr   s    r!   <lambda>2DrawerCanvas._check_link_overlap.<locals>.<lambda>  s    RYYxPUVWPXGY=Zr$   )keyrV   )r   zdrawings.GateLinkData)r+   r   rf   keysro   popr   r   r   absr   nanminr   rI   appendmeansortedri   )r   r   r(   allowed_overlapoverlapped_group	data_keysref_keyoverlapsr   y0sy1sv1v2v3v4	new_links	xpos_meansorted_keysx0indr8   r   s   ``                   @r!   r    DrawerCanvas._check_link_overlap  s    ??1%(::..)GH8S	_ -/&	)nq mmoGuHLL! 266%...q1E#J4D4DQ4GGH?Z"5>2C"5:.C3"))C.8B3"))C.8B3"))C.8B3"))C.8BGaKBGaK Y]]9??33G%HI ' ##DN3! )nq & 	(H8}q GGH$MHSU3Z%5%5a%8H$MN	$X3Z[!6#h-!:K!LL )+ 6HC :D"$s_'<"<!=DJ%)IN !7
 qk!&s	 ) 05zz|<|Y^#|<< %N =s   K/
K4)r   r   r   r   r   r   r   r   r   r   r+   r   r   )r    r   )returntuple[int, int])r.   r  )r   z-Iterator[tuple[str, drawings.ElementaryData]])r8   drawings.ElementaryDatarG   )rL   zcircuit.QuantumCircuitrD   zTarget | None)rZ   intr[   r  )T)rx   
types.Bitsr   bool)r   ztypes.DataTypesr   r  )r8   r  r   r  )rx   r  r   r  )r   zIterator[types.Coordinate]r   z
np.ndarray)r    dict[str, drawings.GateLinkData]r   r  )__name__
__module____qualname____firstlineno____doc__r"   propertyr+   setterr1   r:   r   rs   r   r   r   r   r   r   r   __static_attributes__r   r$   r!   r   r   C   s    &4    % % 0 00z4x++6&*6X*X,H43=53=	)3=r$   r   )r  
__future__r   r`   collections.abcr   copyr   	functoolsr   enumr   numpyr   r^   r   qiskit.transpiler.targetr	   qiskit.visualization.exceptionsr
   qiskit.visualization.timeliner   r   (qiskit.visualization.timeline.stylesheetr   r   r   r$   r!   <module>r     s=   %L #  $      + > 9 Hl= l=r$   