
    \`h                         d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dl	m
Z
 d dlZd dlZd dlmZmZmZmZ d dlZddlmZmZmZ dej        d	ej        d
ej        fdZ	 	 d-dej        d	ej        dedz  ded
ej        f
dZ G d d          Z G d d          Z G d de          Z G d de j                  Z  G d d          Z! G d de!          Z" G d de!          Z# G d de#          Z$ G d  d!e#          Z% G d" d#e#          Z& G d$ d%e j                  Z' G d& d'e'          Z(dd(ej)        d)di fd*e*e
z  d+ee*         dz  fd,Z+dS ).    N)Sequence)Enum)Path)
ModelProtoTensorProtohelpernumpy_helper   )
apply_plotload_model_with_shape_infersmooth_distributionpkqkreturnc                    t          j        | j        | j                  }| dd         t          j        | dd         |dd         z            z  |dd<   | dk    |dk    z  }d||<   | dk    |dk    z  }t           j        || <   |S )z
    See https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.rel_entr.html#scipy.special.rel_entr.
    Python implementation.
    dtypeNr   )npemptyshaper   loginf)r   r   resc2c1s        h/var/www/html/movieo_spanner_bot/venv/lib/python3.11/site-packages/onnxruntime/quantization/calibrate.pyrel_entrr      s    
 (2828
,
,
,CURVBqqqEBqqqEM***CF
'bAg	BCG
q&R!V	BvCHJ    baseaxisc                 X   ||dk    s
J d            |
J d            t          j        |                               t           j                  } d| z  t          j        | |d          z  } t          j        |                              t           j                  }t          j        | |          \  } }d|z  t          j        ||d          z  }t          | |          }t          j        ||          }||t          j        |          z  }|                    | j                  S )	z
    Simplifeied version of entropy.
    Source: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.entropy.html.
    This avoids taking a dependency on scipy just for this function.
    Nr   z0base={base} must be a positive number or `None`.z
qk is None      ?T)r    keepdimsr    )	r   asarrayastypefloat32sumbroadcast_arraysr   r   r   )r   r   r   r    vecss         r   entropyr,   '   s	    <4!888%W88#>><>>>	B		rz	*	*B	rBF2D4888	8B	B		rz	*	*B R((FB	rBF2D4888	8B
2r

C
sA	RVD\\88BHr   c                   z    e Zd Z eg d          Z eg d          Zd Zed             Zed             Z	d Z
dS )
TensorData)avgstdlowesthighesthist
hist_edgesbins)r/   r0   r1   r2   r4   c                    t          |                                          | _        |                                D ]\  }}|t          j        vr t          d|dt          j         d          |t          j        v rkt          |d          s"t          dt          |           d|          |j
        t          j        t          j        fvrt          d|j
         d|          t          | ||           d S )NzUnexpected value z not in .r   Unexpected type z for k=zUnexpected dtype )listkeys_attrsitemsr.   _allowed
ValueError_floatshasattrtyper   r   float16r'   setattr)selfkwargskvs       r   __init__zTensorData.__init__G   s   6;;==))LLNN 	  	 DAq
+++ !XQ!X!X*BU!X!X!XYYYJ&&&q'** O$%MQ%M%M%M%MNNN72:rz":::$%N%N%N%N%NOOOD!Q	  	 r   c                     t          | d          rt          | d          s t          dt          |            d          | j        | j        fS )Nr1   r2   z0Attributes 'lowest' and/or 'highest' missing in r7   )r@   AttributeErrordirr1   r2   rD   s    r   range_valuezTensorData.range_valueS   sZ    tX&& 	bgdI.F.F 	b !`TWX\T]T]!`!`!`aaaT\**r   c                     t          | d          rt          | d          s t          dt          |            d          | j        | j        fS )Nr/   r0   z)Attributes 'avg' and/or 'std' missing in r7   )r@   rJ   rK   r/   r0   rL   s    r   avg_stdzTensorData.avg_stdY   sW    tU## 	[74+?+? 	[ !YSQUYY!Y!Y!YZZZ$(##r   c                 L      fd j         D             } j        j        |d<   |S )Nc                 2    i | ]}|t          |          S  )getattr).0rF   rD   s     r   
<dictcomp>z&TensorData.to_dict.<locals>.<dictcomp>a   s%    99974##999r   CLS)r;   	__class____name__rD   datas   ` r   to_dictzTensorData.to_dict_   s1    9999T[999n-Ur   N)rX   
__module____qualname__	frozensetr=   r?   rH   propertyrM   rO   r[   rR   r   r   r.   r.   C   s        yZZZ[[HiIIIJJG
  
  
  + + X+
 $ $ X$
    r   r.   c                   `    e Zd Zdeeeez  f         fdZd Zd Z	d Z
d Zd Zd Zd	 Zd
 ZdS )TensorsDatarZ   c           
         || _         i | _        |                                D ]F\  }}t          |t                    s t          dt          |           d          t          |t                    r|t          j	        k    r9t          |          dk    r&t          |d         |d                   | j        |<   t          |          dk    r4t          |d         |d         |d         |d         	          | j        |<   t          d
|ddt          |           d| d          t          |t                    s t          dt          |           d          || j        |<   Hd S )NzKeys must be strings not r7      r   r
   r1   r2         )r1   r2   r3   r5   zUnexpected tuple for rz	, it has z elements: zValues must be TensorData not )calibration_methodrZ   r<   
isinstancestr	TypeErrorrA   tupleCalibrationMethodMinMaxlenr.   )rD   rh   rZ   rF   rG   s        r   rH   zTensorsData.__init__g   ss   "4	JJLL 	 	DAqa%% H FDGG F F FGGG!U## _%):)AAAc!ffPQkk#-QqT1Q4#H#H#HDIaLq66Q;;#-QqT1Q4aPQdYZ[\Y]#^#^#^DIaL ] ] ] ]c!ff ] ]YZ ] ] ]^^^a,, M Ka K K KLLLDIaLL	 	r   c              #   $   K   | j         E d {V  d S NrZ   rL   s    r   __iter__zTensorsData.__iter__y   s&      9r   c                     || j         v S rq   rr   rD   keys     r   __contains__zTensorsData.__contains__|   s    dir   c                     | j         |         S rq   rr   ru   s     r   __getitem__zTensorsData.__getitem__   s    y~r   c                 R    || j         vrt          d|d          || j         |<   d S )Nz)Only an existing tensor can be modified, z is not.)rZ   RuntimeError)rD   rv   values      r   __setitem__zTensorsData.__setitem__   s8    diZ3ZZZ[[[	#r   c                 4    | j                                         S rq   )rZ   r:   rL   s    r   r:   zTensorsData.keys   s    y~~r   c                 4    | j                                         S rq   )rZ   valuesrL   s    r   r   zTensorsData.values   s    y!!!r   c                 4    | j                                         S rq   )rZ   r<   rL   s    r   r<   zTensorsData.items   s    y   r   c                 :    | j         j        | j        | j        d}|S )N)rV   rZ   rh   )rW   rX   rZ   rh   rY   s     r   r[   zTensorsData.to_dict   s*     >*I"&"9
 

 r   N)rX   r\   r]   dictrj   r.   rl   rH   rs   rw   ry   r}   r:   r   r<   r[   rR   r   r   ra   ra   f   s        c:;M6M1N    $           
     " " "! ! !    r   ra   c                       e Zd ZdZdZdZdZdS )rm   r   r
   rc   rf   N)rX   r\   r]   rn   Entropy
PercentileDistributionrR   r   r   rm   rm      s"        FGJLLLr   rm   c                   l    e Zd Zed             Zej        defd            Zd Z	d Z
d Zdedefd	Zd
S )CalibrationDataReaderc                 X    t          |d          rt          |j                  pt          S )Nget_next)r@   callabler   NotImplemented)clssubclasss     r   __subclasshook__z&CalibrationDataReader.__subclasshook__   s(    *--M(8;L2M2M`R``r   r   c                     t           )z9generate the input data dict for ONNXinferenceSession runNotImplementedErrorrL   s    r   r   zCalibrationDataReader.get_next   s
     "!r   c                     | S rq   rR   rL   s    r   rs   zCalibrationDataReader.__iter__   s    r   c                 @    |                                  }|t          |S rq   )r   StopIteration)rD   results     r   __next__zCalibrationDataReader.__next__   s    >r   c                     t           rq   r   rL   s    r   __len__zCalibrationDataReader.__len__       !!r   start_index	end_indexc                     t           rq   r   )rD   r   r   s      r   	set_rangezCalibrationDataReader.set_range   r   r   N)rX   r\   r]   classmethodr   abcabstractmethodr   r   rs   r   r   intr   rR   r   r   r   r      s        a a [a 	"$ " " " "    " " ""S "S " " " " " "r   r   )	metaclassc                       e Zd Z	 	 	 	 	 ddeez  dee         dz  fdZdgfdZd	 Zd
e	fdZ
d Zd ZdefdZdefdZdS )CalibraterBaseNaugmented_model.onnxF
model_pathop_types_to_calibratec                 X   t          |t                    r"t          t          |                    | _        n9t          |t                    rt          |          | _        nt          d          || _        || _        || _        || _	        || _
        d| _        d| _        dg| _        dS )a  
        :param model_path: ONNX model to calibrate. It should be a model file path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param use_external_data_format: use external data format to store model which size is >= 2Gb.
        :param per_channel: whether to compute ranges per each channel.
        z model_path should be model path.NCPUExecutionProvider)ri   rj   r   r   modelr>   r   augmented_model_path	symmetricuse_external_data_formatper_channelaugment_modelinfer_sessionexecution_providers)rD   r   r   r   r   r   r   s          r   rH   zCalibraterBase.__init__   s    " j#&& 	A4T*5E5EFFDJJ
D)) 	A4Z@@DJJ?@@@%:"$8!"(@%&!!$:#;   r   r   c                 <    || _         |                                  dS )zz
        reset the execution providers to execute the collect_data. It triggers to re-creating inference session.
        N)r   create_inference_session)rD   r   s     r   set_execution_providersz&CalibraterBase.set_execution_providers   s$     $7 %%'''''r   c                     t          j                    }t           j        j        |_        t          j        | j        || j                  | _        dS )z9
        create an OnnxRuntime InferenceSession.
        )sess_options	providersN)	onnxruntimeSessionOptionsGraphOptimizationLevelORT_DISABLE_ALLgraph_optimization_levelInferenceSessionr   r   r   )rD   r   s     r   r   z'CalibraterBase.create_inference_session   sO     #1330;0R0b-(9%%.
 
 
r   r   c                    d |j         j        D             }|                    d |j         j        D                        |                    d |j         j        D                        d |j         j        D             }t                      }t          j        t          j	        h}|j         j
        D ]}| j        r|j        | j        v rtt          j        |j        |j                  D ]T}||v rN||         }|j                            d          r,|j        j        j        |v r||vr|                    |           U||fS )z
        select input/output tensors of candidate nodes to calibrate.
        returns:
            tensors (set): set of tensor name.
            value_infos (dict): tensor name to value info.
        c                     i | ]
}|j         |S rR   namerT   vis     r   rU   z>CalibraterBase.select_tensors_to_calibrate.<locals>.<dictcomp>   s    DDDrrwDDDr   c                     i | ]
}|j         |S rR   r   )rT   ots     r   rU   z>CalibraterBase.select_tensors_to_calibrate.<locals>.<dictcomp>   s    EEEBBGREEEr   c                     i | ]
}|j         |S rR   r   )rT   its     r   rU   z>CalibraterBase.select_tensors_to_calibrate.<locals>.<dictcomp>   s    DDDBBGRDDDr   c                     h | ]	}|j         
S rR   r   )rT   inits     r   	<setcomp>z=CalibraterBase.select_tensors_to_calibrate.<locals>.<setcomp>   s    EEETtyEEEr   tensor_type)graph
value_infoupdateoutputinputinitializersetr   FLOATFLOAT16noder   op_type	itertoolschainrA   HasFieldr   	elem_typeadd)	rD   r   value_infosr   tensors_to_calibratetensor_type_to_calibrater   tensor_namer   s	            r   select_tensors_to_calibratez*CalibraterBase.select_tensors_to_calibrate   s`    EDU[-CDDDEE%+2DEEEFFFDD%+2CDDDEEEEEU[-DEEE"uu$/$5{7J#K K$ 
	B 
	BD- 	BA[1[1[#,?4:t{#K#K B BK"k11(5G,,];;B!#!4!>BZ!Z!Z!,K!?!?044[AAA#[00r   c                     | j         S )zP
        return: augmented onnx model. Call after calling augment_graph
        )r   rL   s    r   get_augment_modelz CalibraterBase.get_augment_model  s     zr   c                     t           )z
        abstract method: augment the input model to prepare for collecting data. It will:
            1. augment the model to be able to collect desired statistics data
            2. save augmented model to augmented_model_paths
        r   rL   s    r   augment_graphzCalibraterBase.augment_graph  s
     "!r   data_readerc                     t           )z
        abstract method: collect the tensors that will be used for range computation. It can be called multiple times.
        r   )rD   r   s     r   collect_datazCalibraterBase.collect_data  
     "!r   r   c                     t           )ze
        abstract method: compute data based on the calibration method stored in TensorsData
        r   rL   s    r   compute_datazCalibraterBase.compute_data"  r   r   )Nr   FFF)rX   r\   r]   rj   r   r   rH   r   r   r   r   r   r   r   r   ra   r   rR   r   r   r   r      s         7;3!& <  <$J <  (}t3 <  <  <  <D <R:R ( ( ( (

 

 

1 1 1 1 1:  " " ""(= " " " ""k " " " " " "r   r   c                   |     e Zd Z	 	 	 	 	 	 	 	 ddeez  dee         dz  f fdZd Zd	 Zd
e	fdZ
d ZdefdZ xZS )MinMaxCalibraterNr   F{Gz?r   r   c
                 \   t                                          ||||||	           g | _        d| _        t	          | j        j        j                  | _        d | j        j        j        D             | _	        || _
        |r|dk     s|dk    rt          d          || _        || _        dS )aw  
        :param model_path: ONNX model to calibrate. It is a model path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param moving_average: compute the moving average of the minimum and maximum values instead of the global minimum and maximum.
        :param averaging_constant: constant smoothing factor to use when computing the moving average.
        :param max_intermediate_outputs: maximum number of intermediate outputs before an intermediate range is computed.
        :param per_channel: whether to compute ranges per each channel.
        )r   r   r   r   r   Nc                     h | ]	}|j         
S rR   r   rT   r   s     r   r   z,MinMaxCalibrater.__init__.<locals>.<setcomp>L      &Y&Y&Yvv{&Y&Y&Yr   r   r
   z;Invalid averaging constant, which should not be < 0 or > 1.)superrH   intermediate_outputscalibrate_tensors_rangero   r   r   r   num_model_outputsmodel_original_outputsmoving_averager>   averaging_constantmax_intermediate_outputs)rD   r   r   r   r   r   r   r   r   r   rW   s             r   rH   zMinMaxCalibrater.__init__*  s    . 	"7!5%=# 	 	
 	
 	
 %'!'+$!$TZ%5%<!=!=&Y&YAQAX&Y&Y&Y#, 	\1A559Ka9O9OZ[[["4(@%%%r   c                                            j                  \  }}t          t          j                              t          j        t          j        dgt          j	                            } j        j
        j                            |           d  fd}|D ]} ||d            ||d           t          j         j         j         j                   dS )	z
        Adds ReduceMin and ReduceMax nodes to all quantization_candidates op type nodes in
        model and ensures their outputs are stored as part of the graph output
        :return: augmented ONNX model
        r   c                     |j         D ]0}t          j                            | |j                  r	|j        c S 1t          d|  d          )Nz&Model does not contain a version for 'z'.)opset_importonnxdefshasdomainversionr{   )r   r   r   s      r   get_op_versionz6MinMaxCalibrater.augment_graph.<locals>.get_op_version^  s]     % 2 0 09==,*=>> 0'////0SSSSTTTr   c                    d}| dz   |z   }|dz   }t           j                            || g|g||          }t           j                            d|g|g|          }d j        j        j        D             }|                    d j        j        j        D                        |                    d	 j        j        j        D                        | |v r||          j	        j
        j        }nt          d
| d          j        rt          ||          j	        j
        j        j                  }	dgt#          d|	          }
 |j                  dk     r.|j                            t          j        d|
                     nt+          t-          j                              }t1          j        t5          j        |
t4          j                  |          }|j                            |           j        j        j                            |           j        j        j                            ||g           j        j        j                            t          j         ||d g                     d S )Nr
   __Reshape)r#   r   Reshape)inputsoutputsr   c                     i | ]
}|j         |S rR   r   r   s     r   rU   zNMinMaxCalibrater.augment_graph.<locals>.add_reduce_min_max.<locals>.<dictcomp>w  s    MMM227BMMMr   c                     i | ]
}|j         |S rR   r   )rT   os     r   rU   zNMinMaxCalibrater.augment_graph.<locals>.add_reduce_min_max.<locals>.<dictcomp>x  s    KKKaKKKr   c                     i | ]
}|j         |S rR   r   )rT   is     r   rU   zNMinMaxCalibrater.augment_graph.<locals>.add_reduce_min_max.<locals>.<dictcomp>y  s    JJJaJJJr   z'Unable to guess tensor type for tensor zE, running shape inference before quantization may resolve this issue.r   rc      axesr   )!r   r   	make_noder   r   r   r   r   r   rA   r   r   r>   r   ro   r   dimrange	attributeappendmake_attributerj   uuiduuid4r	   
from_arrayr   arrayint64r   r   extendmake_tensor_value_info)r   reduce_op_namer#   reduce_outputintermediate_outputreduce_nodereshape_noder   	onnx_typetensor_rankreduced_axesreduce_axes_namereduce_axesr  reshape_shape_namerD   s                r   add_reduce_min_maxz:MinMaxCalibrater.augment_graph.<locals>.add_reduce_min_maxd  s    H (#->M"/*"<+//0C/Dx^k 0  K  ;00+-?@&(	 1  L NM1A1LMMMKKK4:3C3JKKKLLLJJ4:3C3IJJJKKKk))'49EO		 Zk Z Z Z    
E!+k":"?"K"Q"UVV !:E![$9$9:!>.$*==BB)001Fv|1\1\]]]]'*4:<<'8'8$"."9"(<WYW_:`:`:`br"s"sK%,,-=>>>J$077DDDJ!((+|)DEEEJ#**6+HXadhci+j+jkkkkkr   	ReduceMin	ReduceMaxsave_as_external_dataN)r   r   rj   r  r  r	   r  r   r  r  r   r   r  r   saver   r   )rD   tensorsr  reshape_shaper+  tensorr  r*  s   `     @@r   r   zMinMaxCalibrater.augment_graphS  s!    55djAA
 ..$/"RX0N0N0NPbcc
$++M:::	U 	U 	U,	l ,	l ,	l ,	l ,	l ,	l ,	l\  	4 	4Fv{333v{3333	J%"&"?	
 	
 	
 	
 	
 	
r   c                     g | _         d S rq   r   rL   s    r   clear_collected_dataz%MinMaxCalibrater.clear_collected_data      $&!!!r   r   c                 $   	 |                                 }|snl| j                            | j                            d |                     | j        1t          | j                  | j        k    r|                                  t          | j                  dk    r| j        t          d          | 
                                }t          |t                    s t          dt          |           d          |                                  d S )NTr   No data is collected.z+compute_data must return a TensorsData not r7   )r   r   r  r   runr   ro   r6  r   r>   r   ri   ra   rk   rA   )rD   r   r
  ts       r   r   zMinMaxCalibrater.collect_data  s   		, ))++F %,,T-?-C-CD&-Q-QRRR-9122d6SSS))+++		, t())Q..43O3W4555![)) 	VT$q''TTTUUU!!#####r   c                 t   |s|S |                                 D ]\  }}t          |t                    r|j        d         }|j        d         }n|\  }}t          ||         t                    r'||         j        d         }||         j        d         }n||         \  }}| j        r!|| j        ||z
  z  z   }	|| j        ||z
  z  z   }
n t          ||          }	t          ||          }
t          |t                    st          ||         t                    rt          |	|
          ||<   |	|
f||<   |S )Nr   r
   rd   )r<   ri   r.   rM   r   r   minmax)rD   	old_range	new_rangerv   r|   old_minold_maxnew_minnew_max	min_value	max_values              r   merge_rangezMinMaxCalibrater.merge_range  s]    	#//++ 	8 	8JC%,, )+A.+A.#( )C.*55 2#C.4Q7#C.4Q7#,S> " 2#d&=7AR&SS	#d&=7AR&SS		11	11	 %,, 8
9S>:0V0V 8!+9i!P!P!P	#"+Y!7	#r   r   c           
      .    t           j                  dk    r j        S  fdt          t           j        d                             D             fd j        D             }i |D ]E}|                                D ].\  }}                    |g                               |           /F j        d         fdt          dt                    d          D             } fdD             }g }t          dt                    d          D ]} j        rHt          j
        ||                  d          }	t          j
        ||d	z                     d          }
nGt          j        ||                  d          }	t          j        ||d	z                     d          }
 j        rUt          j        t          j        |	          t          j        |
          gd          }|                    | |f           |                    |	|
f           t          t           j        t%          t'          ||d
                              } j        r!                      j        |           _        n| _         j        S )z
        Compute the min-max range of tensor
        :return: dictionary mapping: {added node names: (ReduceMin, ReduceMax) pairs }
        r   c                 X    g | ]&}j                                         |         j        'S rR   )r   get_outputsr   )rT   r  rD   s     r   
<listcomp>z1MinMaxCalibrater.compute_data.<locals>.<listcomp>  s0    sssQ*6688;@sssr   c           	      N    g | ]!}t          t          |d                     "S Fstrictr   ziprT   r"  output_namess     r   rK  z1MinMaxCalibrater.compute_data.<locals>.<listcomp>  A     
 
 
# \#6uEEEFF
 
 
r   Nc                 R    g | ]#}|                              d           d         $S )r  r   )
rpartition)rT   r  added_output_namess     r   rK  z1MinMaxCalibrater.compute_data.<locals>.<listcomp>  s?     "
 "
 "
9:q!,,S11!4"
 "
 "
r   rc   c                 4    i | ]}|j         v||         S rR   )r   )rT   r  merged_output_dictrD   s     r   rU   z1MinMaxCalibrater.compute_data.<locals>.<dictcomp>  s5     $
 $
 $
)*ATMhDhDhA!!$DhDhDhr   r$   r
   FrN  )ro   r   r   r  r<   
setdefaultr  r   r   r   nanmeannanminnanmaxr   absra   rm   rn   r   rQ  rG  )rD   output_dicts_listdrF   rG   calibrate_tensor_namesmerged_added_output_dictpairsr  min_value_arraymax_value_arraymax_absolute_valuenew_calibrate_tensors_rangerW  rY  rS  s   `            @@@r   r   zMinMaxCalibrater.compute_data  s    t())Q..//ssss%PSTXTmnoTpPqPqJrJrsss
 
 
 
'+'@
 
 

  " 	? 	?A		 ? ?1"--a44;;A>>>>?)$*@*B*BC"
 "
 "
 "
>CAsK]G^G^`a>b>b"
 "
 "
$
 $
 $
 $
 $
.@$
 $
 $
  q#011155 	A 	AA" i"$*-EFXYZF[-\cd"e"e"e"$*-EFXYZ]^Y^F_-`gh"i"i"i"$),DEWXYEZ,[bc"d"d"d"$),DEWXY\]X]E^,_fg"h"h"h~ A%'Y0G0GP_I`I`/ahi%j%j%j"113EFGGGGo?@@@@&1$d3/EuUZ+[+[+[&\&\'
 '
# ' 	G+/+;+;D<XZu+v+vD((+FD(++r   )Nr   FFFr   NF)rX   r\   r]   rj   r   r   rH   r   r6  r   r   rG  ra   r   __classcell__rW   s   @r   r   r   )  s         7;3!&!%'A 'A$J'A  (}t3'A 'A 'A 'A 'A 'ARG
 G
 G
R' ' '$(= $ $ $ $(  B3,k 3, 3, 3, 3, 3, 3, 3, 3,r   r   c                   x     e Zd Z	 	 	 	 	 	 	 	 	 dd	eez  d
ee         dz  f fdZd Zd Zde	fdZ
defdZ xZS )HistogramCalibraterNr   F
percentile      -X@samer   r   c                 X   t                                          |||||           g | _        d| _        t	          | j        j        j                  | _        d | j        j        j        D             | _	        d| _
        || _        || _        || _        |	| _        d| _        |
| _        dS )a=  
        :param model_path: ONNX model to calibrate. It is a model path.
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param method: A string. One of ['entropy', 'percentile'].
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param num_bins: number of bins to create a new histogram for collecting tensor values.
        :param num_quantized_bins: number of quantized bins. Default 128.
        :param percentile: A float number between [0, 100]. Default 99.99.
        :param scenario: see :class:`DistributionCalibrater`
        )r   r   r   r   Nc                     h | ]	}|j         
S rR   r   r   s     r   r   z/HistogramCalibrater.__init__.<locals>.<setcomp>.  r   r   )r   rH   r   r   ro   r   r   r   r   r   	collectormethodnum_binsnum_quantized_binsrl  r   scenario)rD   r   r   r   r   rt  r   ru  rv  rl  rw  rW   s              r   rH   zHistogramCalibrater.__init__  s    2 	"7!5%= 	 	
 	
 	
 %'!'+$!$TZ%5%<!=!=&Y&YAQAX&Y&Y&Y# "4$$(! r   c                    |                      | j                  \  | _        }| j        D ]5}|| j        vr*| j        j        j                            ||                    6t          j        | j        | j	        | j
                   dS )z
        make all quantization_candidates op type nodes as part of the graph output.
        :return: augmented ONNX model
        r.  N)r   r   r   r   r   r   r  r   r0  r   r   )rD   r   r3  s      r   r   z!HistogramCalibrater.augment_graph7  s    
 261Q1QRVR\1]1].!;/ 	D 	DFT888
 '..{6/BCCC	J%"&"?	
 	
 	
 	
 	
 	
r   c                     g | _         d S rq   r5  rL   s    r   r6  z(HistogramCalibrater.clear_collected_dataG  r7  r   r   c                     d  j                                         D             }d  j                                         D             	 |                                }|sn j                             d|          }g }t          |          D ]L\  }}|         |v r(|                    t          j        |                     7|                    |           M j                            |           t           j                  dk    rt          d          fd j        D             }i |D ]E}	|	                                D ].\  }
}                    |
g                               |           /F fdD             } j        s8t           j         j         j         j         j         j        	           _         j                            |                                             dS )
zy
        Entropy Calibrator collects operators' tensors as well as generates tensor histogram for each operator.
        c                     h | ]	}|j         
S rR   r   rT   node_args     r   r   z3HistogramCalibrater.collect_data.<locals>.<setcomp>N  s    YYYX8=YYYr   c                     g | ]	}|j         
S rR   r   r|  s     r   rK  z4HistogramCalibrater.collect_data.<locals>.<listcomp>O  s    WWW(WWWr   TNr   r9  c           	      N    g | ]!}t          t          |d                     "S rM  rP  rR  s     r   rK  z4HistogramCalibrater.collect_data.<locals>.<listcomp>e  rT  r   c                 4    i | ]}|j         v ||         S rR   )r   )rT   r  merged_dictrD   s     r   rU   z4HistogramCalibrater.collect_data.<locals>.<dictcomp>o  s,    fff1qDLeGeGeQAGeGeGer   )rt  r   ru  rv  rl  rw  )r   
get_inputsrJ  r   r:  	enumerater  copyr   ro   r>   r<   rZ  rs  HistogramCollectorrt  r   ru  rv  rl  rw  collectr6  )rD   r   input_names_setr
  r  fixed_outputsoutput_indexr   r_  r`  rF   rG   clean_merged_dictr  rS  s   `            @@r   r   z HistogramCalibrater.collect_dataJ  sL    ZY9K9V9V9X9XYYYWWd6H6T6T6V6VWWW	< ))++F (,,T6::G M(1'(:(: 1 1$f-@@!((6):):;;;;!((0000%,,];;;	<" t())Q..4555
 
 
 
'+'@
 
 

 " 	8 	8A		 8 81&&q"--44Q77778 gfffffff~ 	/{.#'#:?  DN 	0111!!#####r   r   c                    | j         st          d          t          | t                    rt          j        }ndt          | t                    rt          j        }nBt          | t                    rt          j	        }n t          dt          |            d          t          || j                                                   S )z
        Compute the min-max range of tensor
        :return: dictionary mapping: {tensor name: (min value, max value)}
        z9No collector created and can't generate calibration data.zUnknown calibrater z". This method must be overwritten.)rs  r>   ri   EntropyCalibraterrm   r   PercentileCalibraterr   DistributionCalibraterr   rk   rA   ra   compute_collection_result)rD   cals     r   r   z HistogramCalibrater.compute_data~  s    
 ~ 	ZXYYYd-.. 	b#+CC233 	b#.CC455 	b#0CC`$t**```aaa3 H H J JKKKr   )	Nr   Frl  Frm  rn  ro  rp  )rX   r\   r]   rj   r   r   rH   r   r6  r   r   ra   r   rh  ri  s   @r   rk  rk  
  s         7;3!&*! *!$J*!  (}t3*! *! *! *! *! *!X
 
 
 ' ' '2$(= 2$ 2$ 2$ 2$hLk L L L L L L L Lr   rk  c                   P     e Zd Z	 	 	 	 	 	 	 d	deez  dee         dz  f fdZ xZS )
r  Nr   Fr,   rm  r   r   c	           
      Z    t                                          ||||||||           dS )a  
        :param model_path: ONNX model to calibrate. It is a model path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param method: A string. One of ['entropy', 'percentile', 'distribution'].
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param num_bins: number of bins to create a new histogram for collecting tensor values.
        :param num_quantized_bins: number of quantized bins. Default 128.
        )rt  r   ru  rv  Nr   rH   )
rD   r   r   r   r   rt  r   ru  rv  rW   s
            r   rH   zEntropyCalibrater.__init__  sH    * 	! $1 	 		
 		
 		
 		
 		
r   )Nr   Fr,   Frm  rm  rX   r\   r]   rj   r   r   rH   rh  ri  s   @r   r  r    sx         7;3!&
 
$J
  (}t3
 
 
 
 
 
 
 
 
 
r   r  c                   P     e Zd Z	 	 	 	 	 	 	 d
deez  dee         dz  f fd	Z xZS )r  Nr   Frl  rn  ro  r   r   c	           
      Z    t                                          ||||||||           dS )a  
        :param model_path: ONNX model to calibrate. It is a model path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param method: A string. One of ['entropy', 'percentile', 'distribution'].
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param num_quantized_bins: number of quantized bins. Default 128.
        :param percentile: A float number between [0, 100]. Default 99.99.
        )rt  r   ru  rl  Nr  )
rD   r   r   r   r   rt  r   ru  rl  rW   s
            r   rH   zPercentileCalibrater.__init__  sH    * 	! $! 	 		
 		
 		
 		
 		
r   )Nr   Frl  Frn  ro  r  ri  s   @r   r  r    sx         7;3!&
 
$J
  (}t3
 
 
 
 
 
 
 
 
 
r   r  c                   N     e Zd Z	 	 	 	 	 	 d
deez  dee         dz  f fd	Z xZS )r  Nr   Fdistributionrm  rp  r   r   c           	      X    t                                          |||||||           dS )a  
        :param model_path: ONNX model to calibrate. It is a model path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param method: A string. One of ['entropy', 'percentile', 'distribution'].
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param num_bins: number of bins to create a new histogram for collecting tensor values.
        :param scenario: for float 8 only, if `scenario="same"`,
            the algorithm weights and float 8 follow the same distribution,
            if `scenario="p3"`, it assumes the weights follow
            a gaussian law and float 8 ~ X^3 where X is a gaussian law
        )rt  ru  rw  Nr  )	rD   r   r   r   r   rt  ru  rw  rW   s	           r   rH   zDistributionCalibrater.__init__  sE    . 	! $ 	 	
 	
 	
 	
 	
r   )Nr   Fr  rm  rp  r  ri  s   @r   r  r    su         7;3!&
 
$J
  (}t3
 
 
 
 
 
 
 
 
 
r   r  c                   R    e Zd ZdZej        d             Zej        d             ZdS )CalibrationDataCollectorzL
    Base class for collecting data for calibration-based quantization.
    c                     t           )z
        Generate informative data based on given data.
            name_to_arr : dict
                tensor name to NDArray data
        r   rD   name_to_arrs     r   r  z CalibrationDataCollector.collect  s
     "!r   c                     t           )z?
        Get the optimal result among collection data.
        r   rL   s    r   r  z2CalibrationDataCollector.compute_collection_result  s
    
 "!r   N)rX   r\   r]   __doc__r   r   r  r  rR   r   r   r  r    s\          	" " " 	" " " " "r   r  c                   l    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zedd            Zd Zd ZdS )r  a`  
    Collecting histogram for each tensor. Percentile and Entropy method are supported.

    ref: https://github.com//apache/incubator-mxnet/blob/master/python/mxnet/contrib/quantization.py
    ref: https://docs.nvidia.com/deeplearning/tensorrt/pytorch-quantization-toolkit/docs/_modules/
                 pytorch_quantization/calib/histogram.html
    c                 h    i | _         || _        || _        || _        || _        || _        || _        d S rq   )histogram_dictrt  r   ru  rv  rl  rw  )rD   rt  r   ru  rv  rl  rw  s          r   rH   zHistogramCollector.__init__  s9     " "4$ r   c                     | j         S rq   )r  rL   s    r   get_histogram_dictz%HistogramCollector.get_histogram_dict   s    ""r   c                     t          d           | j        dv r|                     |          S | j        dk    r1| j        r|                     |          S |                     |          S t          d          )Nz/Collecting tensor data and making histogram ...>   r,   r  rl  DOnly 'entropy', 'percentile' or 'distribution' methods are supported)printrt  collect_valuer   collect_absolute_valuer>   r  s     r   r  zHistogramCollector.collect#  s    ?@@@ ;555%%k222[L((~ 722;???))+666cdddr   c                    |                                 D ]`\  }}t          |t                    r|D ]9}t          |t          j                  sJ dt          |           d|            :d |D             }t          |          dk    sJ d| d|            t          j        |          }n>t          |t          j                  s"t          dt          |           d|          |}|	                                }|j
        dk    r)t          j        |          }t          j        |          }n6t          j        d|j                  }t          j        d|j                  }t          j        |          }|| j        vrgt          j        || j                  \  }	}
|
                    |j                  }
|j        t          j        k    s
J d	            |	|
||f| j        |<   | j        |         }|d
         }|d         }t+          |d          sJ dt          |                       t+          |d          sJ dt          |                       |d         }|d         }t          j        |          }||d         k    rI|d         |d         z
  }t          j        |d         |z   ||z   |          }t          j        ||f          }t          j        ||          \  }	}
|
                    |j                  }
|	dt          |          xx         |z  cc<   |j        t          j        k    s
J d	            |	|
t1          ||          t3          ||          f| j        |<   bdS )z5
        Collect histogram on absolute value
        r8   z for tensor=c                     h | ]	}|j         
S rR   r   )rT   as     r   r   z<HistogramCollector.collect_absolute_value.<locals>.<setcomp>:  s    444a!'444r   r
   z6The calibration expects only one element type but got r   r   )r5   zMonly float32 or float16 is supported, every constant must be explicitly typedrc   rf   r   z'old_min should be a numpy array but is r   N)r<   ri   r9   r   ndarrayrA   ro   r%   r>   flattensizer\  r]  r  r   absoluter  	histogramru  r&   float64r@   arangehstackr=  r>  )rD   r  r3  data_arrarrdtypesdata_arr_nprE  rF  r3   r4   old_histogramrA  rB  old_histold_hist_edges	temp_amaxwidthnew_bin_edgess                      r   r  z)HistogramCollector.collect_absolute_value2  s    !, 1 1 3 3 4	s 4	sFH(D)) '# m mC%c2:66ll8l4PS998l8lbh8l8lll6l4484446{{a'''kVkkagkk ('' !j22"*55 ' !ZDNN!Z!ZPV!Z!Z[[[&%--//K!##Ik22	Ik22		HQk.?@@@	HQk.?@@@	+k22KT000#%<$-#P#P#P j'..{/@AA
"(BJ666c 766 04ZI.V#F++ $ 3F ;'*'*w00kk2k\`ah\i\i2k2kkk0w00kk2k\`ah\i\i2k2kkk0(+!.q!1Ik22	~b111*1-q0AAE$&InR.@5.H)V[J[]b$c$cM%'Y/N%O%ON#%<.#Q#Q#Q j'..{/@AA
_s8}}_%%%1%%%"(BJ666c 766 04ZWiAXAXZ]^egpZqZq.r#F++i4	s 4	sr   c           	         |                                 D ]E\  }}t          j        |          }|                                }|j        dk    r)t          j        |          }t          j        |          }n6t          j        d|j                  }t          j        d|j                  }t          j        t          t          |          t          |                    |j                  }|| j        v r0| j        |         }|                     |||||          | j        |<   t          j        || j        | |f          \  }}	||	|||f| j        |<   GdS )z1
        Collect histogram on real value
        r   r   r  N)r<   r   r%   r  r  r\  r]  r  r   r>  r^  r  merge_histogramr  ru  )
rD   r  r3  r  rE  rF  	thresholdr  r3   r4   s
             r   r  z HistogramCollector.collect_valuel  sc    !, 1 1 3 3 	 	FHz(++H''))H}q  Ih//	Ih//		HQhn===	HQhn===	S^^S^^!D!DHN[[[I,,, $ 3F ;.2.B.B!8Y	9/ /#F++ $&<$-QZPZ\eOf#g#g#g j/#F++)	 	r   c                 R   |\  }}}}	}
||
k    rPt          j        |t          |          |
 |
f          \  }}||z   |t          ||          t	          |	|          |
fS |
dk    r0t          j        |t          |          | |f          \  }}||z  }nqt          |          }d|
z  |z  }t          ||
z
  |z  dz             }|d|z  z   }||z  |
z   }t          j        ||| |f          \  }}||||z
  xx         |z  cc<   ||t          ||          t	          |	|          |fS )Nr  r   rc   r
   )r   r  ro   r=  r>  r   )rD   r  r  rC  rD  new_thresholdr  r  rA  rB  old_thresholdnew_histr  r3   r4   old_num_bins
old_stridehalf_increased_binsnew_num_binss                      r   r  z"HistogramCollector.merge_histogram  s   FSC>7G]M)),xX~WdFefffKHa8#GW%%GW%%  !!#%<#h--Q^P^`mOn#o#o#o j "8}}.=
&)==+HZ*WZ[*[&\&\#+a2E.EE 3j @= P#%<,P]~_lNm#n#n#n j(<:M+MMNNNRZZNNNGW%%GW%% r   c                 f   | j         rt          | j                   dk    rt          d          t          d| j        d           | j        dk    r|                                 S | j        dk    r|                                 S | j        dk    r|                                 S t          d          )	Nr   z=Histogram has not been collected. Please run collect() first.z0Finding optimal threshold for each tensor using z algorithm ...r,   rl  r  r  )r  ro   r>   r  rt  compute_entropycompute_percentilecompute_distributionrL   s    r   r  z,HistogramCollector.compute_collection_result  s    " 	^c$*=&>&>!&C&C\]]]^^^^___;)##'')))[L((**,,,[N**,,...cdddr   c                    | j         dk     s| j         dk    rt          d          | j        }| j         }i }t          dt	          |                      t          d| j                    t          dd|z
   d| d	           |                                D ]\  }}|d         }|d
         }|                                }t          j	        ||z            }	| j
        r_t          j        |	|dz            }
t          j        ||
         |j                   t          j        ||
         |j                  f||<   nzd|z
  dz  }t          j        |	d|z
            }
t          j        |	|          }t          j        ||         |j                  t          j        ||
         |j                  f||<   |d         }|d         }||         d         |k     r|||         d
         f||<   ||         d
         |k    r||         d         |f||<   g ||         |d d         R ||<   t          j                            dd          dv rt#          ||           |S )Nr   d   z<Invalid percentile. Must be in range 0 <= percentile <= 100.Number of tensors : Number of histogram bins : zPercentile : (g      Y@,)r
   r   g      i@r"   rc   rf   QUANTIZATION_DEBUG0r
   1)rl  r>   r  r  ro   ru  r<   r(   r   cumsumr   searchsortedr  r   osenvirongetr   )rD   r  rl  thresholds_dictr3  r  r3   r4   totalcdf	idx_rightpercent_to_cut_one_sideidx_leftrE  rF  s                  r   r  z%HistogramCollector.compute_percentile  s   ?Q$/C"7"7[\\\,_
:S%8%8::;;;;DM;;<<<Auz1AAJAAABBB!/!5!5!7!7 	- 	-FIQ<D"1JHHJJE)D5L))C~ OCe1CDD	 Xj3:;KLLLLHZ	2*:JKKK+''
 ,1:+=*F'OC7N1NOO	?30GHHHZ19IJJJHZ	2*:JKKK+' "!I!!Iv&q)I55+4of6Ma6P*Q'v&q)I55+:6+B1+Ey*Q'&K(?&K$rr(&K&KOF#z~~2C88HDD4,,,r   c                    | j         }| j        }i }t          dt          |                      t          d| j         d           t          d| j                    |                                D ]p\  }}|                     ||          }|||<   g ||d d         R ||<   t          j        	                    dd          dv rt          |d	         |d
                    q|S )Nr  r  z: (The number may increase depends on the data it collects)zNumber of quantized bins : rc   r  r  r  r   r
   )r  rv  r  ro   ru  r<   get_entropy_thresholdr  r  r  r   )rD   r  rv  r  r3  r  optimal_thresholds          r   r  z"HistogramCollector.compute_entropy  s   ,!4:S%8%8::;;;uDMuuuvvvED,CEEFFF!/!5!5!7!7 	7 	7FI $ : :9FX Y Y&7OF#&J(9&JIbqbM&J&JOF# z~~2C88HDD9Q<1666r   r
   c                 "   |dk    rt          d| d          |d d         |dd          z   dz  }|dk    r| |z                                  |                                 z  }| |dz  z                                  |                                 z  |dz  z
  dz  }t          j        ||j                  t          j        ||j                  fS t          |          |k    rt          |          dz  dk    r| ||z  z                                  |                                 z  }| ||z  |z
  dz  z                                  |                                 z  dz  }t          j        ||j                  t          j        ||j                  fS t          j        |          |z  }d|t          j        |          <   d|t          j        |          <   t          j        |          |z  |z  }| |z                                  |                                 z  }| |dz  z                                  |                                 z  |dz  z
  dz  }t          j        ||j                  t          j        ||j                  fS )	Nr   zpower=z <= 0 is invalid.r   r
   g      ?rc   r   )	r>   r(   r   r  r   r   r^  isnanisinf)r3   r4   powerr   r/   r0   facts          r   _avg_stdzHistogramCollector._avg_std  sW   A::>e>>>???SbS/JqrrN2c9A::&=%%''$((**4C619$))++dhhjj836AcIC8Cz'7888"(3jN^:_:_:___u::3u::>Q#6#6&%-',,..;CFEMC/A55::<<txxzzIcQC8Cz'7888"(3jN^:_:_:___vf~~& RXd^^ RXd^^5(4/f}!!##dhhjj0vqy %%''$((**4sAv=#Ex:#3444bhs*JZ6[6[6[[[r   c           
         | j         dk     rt          d          | j        }i }t          dt	          |                      t          d| j                     t          d| j        d           |                                D ]=\  }}|d         }|d         }|j        t          j	        k    sJ | j        d	k    r| 
                    ||d
          \  }}n6| j        dk    r| 
                    ||d
          \  }}nt          d          |j        t          j	        k    sJ |j        t          j	        k    sJ |j        t          j	        k    sJ t          |||||                                |                                          ||<   t          j                            dd          dv rt#          ||           ?|S )Ni   z3Invalid num_bins. Must be in range 512 <= num_bins.r  r  zScenario : r  r   r
   rp  )r  p3gUUUUUU?z,Invalid scenario. Must be in {'same', 'p3'}.)r/   r0   r3   r4   r1   r2   r  r  r  )ru  r>   r  r  ro   rw  r<   r   r   r  r  r.   r=  r>  r  r  r  r   )	rD   r  r  r3  r  r3   r4   avg_coefstd_coefs	            r   r  z'HistogramCollector.compute_distribution  s   =3RSSS,:S%8%8::;;;;DM;;<<<.DM...///!/!5!5!7!7 	- 	-FIQ<D"1J#rz1111}&&%)]]41]%M%M"(($&&%)]]49]%U%U"(( !OPPP>RZ////>RZ////#rz1111&0%!~~''"((' ' 'OF# z~~2C88HDD4,,,r   c           	         |d         }|d         }|j         }|dz  }|dz  }|d         j        t          j        ||z
  dz             }fdt	          |j                   D             }	t	          ||dz   d          D ]:}
||
z
  }t          ||
z   dz   |          }||         ||         f|	|
|z
  <   t          j        |||                   }|                                }t          |d|                   }t          ||d                   }|dxx         |z  cc<   |dxx         |z  cc<   |dk    	                    t          j
                  }t          j        |t          j
                  }|j         |z  }t	          |          D ]&}||z  }||z   }t          |||                   ||<   '|dxx         t          |||z  d                   z  cc<   t          j        |j         t          j
                  }t	          |          D ]9}||z  }||z   }t          |||                   }|dk    r||         |z  |||<   :t          |          }t          |          }||!t          j        t          j                  }n$t          j        t          ||                    }|||
|z
  <   <t          j        |          }|	|         }|d         }|d         }|d         |k     r
||d         f}|d         |k    r
|d         |f}t!          |d         d	          sJ t!          |d         d	          sJ |S )
aF  Given a dataset, find the optimal threshold for quantizing it.
        The reference distribution is `q`, and the candidate distribution is `p`.
        `q` is a truncated version of the original distribution.
        Ref: http://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inference-with-tensorrt.pdf
        r   r
   rc   c                 h    g | ].}t          j        d           t          j        d           f/S )r   r   )r   r  )rT   r  r   s     r   rK  z<HistogramCollector.get_entropy_threshold.<locals>.<listcomp>I  s<    nnnqrx///!51I1I1IJnnnr   Nr   r   rf   r   )r  r   r   zerosr  r=  r  deepcopyr(   r&   r  r   r  r   r,   argminr@   )rD   r  rv  r3   r4   ru  zero_bin_indexnum_half_quantized_binkl_divergence
thresholdsr  r   r   sliced_distributionpleft_outliers_countright_outliers_countnonzerosquantized_binsnum_merged_binsindexstartendqnormdivmin_kl_divergence_idxr  rE  rF  r   s                                 @r   r  z(HistogramCollector.get_entropy_threshold;  s    |q\
9!Q!3q!8!"2H!H1!LMMnnnnTYZgZlTmTmnnn
  -~/A1EE .	< .	<A(1,KNQ.2H==I6@6MzZcOd5eJq112"&-[5J0K"L"L $((**A"%d<K<&8"9"9#&tIJJ'7#8#8 aDDD''DDDbEEE))EEE Qrx00H  X&8IIIN16:LLO 122 L L/o-(+,?c	,J(K(Ku%%2#&9:L:^:`:`&a"b"bb rx000A122 @ @/o-8E#I.//199#1%#84#?AeCiL#A&&A#A&&AyAIhrvU333hwq!}}E:::8;M!4455 "	- 8 8&'<=aL	aL	Q)++!*,=a,@ AQ)++!21!5y A(+W55555(+W55555  r   N)r
   )rX   r\   r]   r  rH   r  r  r  r  r  r  r  r  staticmethodr  r  r  rR   r   r   r  r    s         ! ! !# # #e e e8s 8s 8st  @  @e e e, , ,\  * \ \ \ \\*& & &PX! X! X! X! X!r   r  r   Fr   r   c                 
   d }|t           j        k    r|                    dd          }|                    dd          }	|                    dd          }
|                    dd           }|                    dd          }t          | |||||	|
||	  	        }n#|t           j        k    rY|                    d	d
          }|                    dd
          }|                    dd          }t          | ||||||          }n|t           j        k    rY|                    d	d          }|                    dd          }|                    dd          }t          | ||||||          }nQ|t           j        k    rA|                    d	d          }|                    dd          }t          | |||||          }|r3|
                                 |r||_        |                                 |S t          d|           )Nr   Fr   r   r   r   r   )r   r   r   r   r   r   ru  rm  rv  )r   r   ru  rv  rn  rl  ro  T)r   r   ru  rl  rw  rp  )r   ru  rw  zUnsupported calibration method )rm   rn   r  r   r   r  r   r  r   r  r   r   r   r>   )r   r   r   calibrate_methodr   r   extra_options
calibratorr   r   r   r   r   ru  rv  rl  rw  s                    r   create_calibratorr    sm    J,333!%%k599	&**+;UCC*../CTJJ#0#4#45OQU#V#V #''u==%! %=)1%=#

 

 



 
.6	6	6 $$Z55*../CSII!%%k599	&! %=1
 
 


 
.9	9	9 $$Z66"&&|V<<
!%%k488	)! %=!
 
 


 
.;	;	; $$Z66 $$Z88+! %=
 
 

    """ 	7-6J*++---
I7GII
J
JJr   )Nr   ),r   r  r   r  r  collections.abcr   enumr   pathlibr   numpyr   r   r   r   r   r	   r   quant_utilsr   r   r   r  r   floatr   r,   r.   ra   rm   ABCMetar   r   r   rk  r  r  r  r  r  rn   rj   r  rR   r   r   <module>r     s   


      				  $ $ $ $ $ $                  > > > > > > > > > > > >     U U U U U U U U U U  
    " 	 



 $, 	
 Z   8               F1 1 1 1 1 1 1 1h       " " " " "ck " " " "4k" k" k" k" k" k" k" k"\^, ^, ^, ^, ^,~ ^, ^, ^,BDL DL DL DL DL. DL DL DLN
 
 
 
 
+ 
 
 
D
 
 
 
 
. 
 
 
D 
  
  
  
  
0  
  
  
F" " " " " " " " ",E! E! E! E! E!1 E! E! E!T 37/&-"NK NK:NK#C=4/NK NK NK NK NK NKr   