
     Ng                        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
mZmZmZ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e         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)i fd*ee.ef         d+eee.                  fd,Z/dS ).    N)Enum)Path)DictOptionalSequenceTupleUnion)
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        ^/var/www/html/ai-engine/env/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    entropyr0   '   s    <4!888%W888>><>>>	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)r3   r4   r5   r6   r8   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itemsr2   _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 )Nr5   r6   z0Attributes 'lowest' and/or 'highest' missing in r;   )rD   AttributeErrordirr5   r6   rH   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 )Nr3   r4   z)Attributes 'avg' and/or 'std' missing in r;   )rD   rN   rO   r3   r4   rP   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).0rJ   rH   s     r    
<dictcomp>z&TensorData.to_dict.<locals>.<dictcomp>a   s%    99974##999r"   CLS)r?   	__class____name__rH   datas   ` r    to_dictzTensorData.to_dict_   s1    9999T[999n-Ur"   N)r\   
__module____qualname__	frozensetrA   rC   rL   propertyrQ   rS   r_   rV   r"   r    r2   r2   C   s        yZZZ[[HiIIIJJG
  
  
  + + X+
 $ $ X$
    r"   r2   c                   j    e Zd Zdeeeeef         f         fdZd Z	d Z
d Zd Zd Zd Zd	 Zd
 ZdS )TensorsDatar^   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 r;      r   r   r5   r6         )r5   r6   r7   r9   zUnexpected tuple for rz	, it has z elements: zValues must be TensorData not )calibration_methodr^   r@   
isinstancestr	TypeErrorrE   tupleCalibrationMethodMinMaxlenr2   )rH   rl   r^   rJ   rK   s        r    rL   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r^   rP   s    r    __iter__zTensorsData.__iter__y   s&      9r"   c                     || j         v S ru   rv   rH   keys     r    __contains__zTensorsData.__contains__|   s    dir"   c                     | j         |         S ru   rv   ry   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.)r^   RuntimeError)rH   rz   values      r    __setitem__zTensorsData.__setitem__   s8    diZ3ZZZ[[[	#r"   c                 4    | j                                         S ru   )r^   r>   rP   s    r    r>   zTensorsData.keys   s    y~~r"   c                 4    | j                                         S ru   )r^   valuesrP   s    r    r   zTensorsData.values   s    y!!!r"   c                 4    | j                                         S ru   )r^   r@   rP   s    r    r@   zTensorsData.items   s    y   r"   c                 :    | j         j        | j        | j        d}|S )N)rZ   r^   rl   )r[   r\   r^   rl   r]   s     r    r_   zTensorsData.to_dict   s*     >*I"&"9
 

 r"   N)r\   r`   ra   r   rn   r	   r2   r   rL   rw   r{   r}   r   r>   r   r@   r_   rV   r"   r    re   re   f   s        c5UAR;S6S1T    $           
     " " "! ! !    r"   re   c                       e Zd ZdZdZdZdZdS )rq   r   r   rg   rj   N)r\   r`   ra   rr   Entropy
PercentileDistributionrV   r"   r    rq   rq      s"        FGJLLLr"   rq   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)rD   callabler   NotImplemented)clssubclasss     r    __subclasshook__z&CalibrationDataReader.__subclasshook__   s(    x,,L(:K1L1L^P^^r"   r   c                     t           )z9generate the input data dict for ONNXinferenceSession runNotImplementedErrorrP   s    r    r   zCalibrationDataReader.get_next   s
     "!r"   c                     | S ru   rV   rP   s    r    rw   zCalibrationDataReader.__iter__   s    r"   c                 @    |                                  }|t          |S ru   )r   StopIteration)rH   results     r    __next__zCalibrationDataReader.__next__   s    >r"   c                     t           ru   r   rP   s    r    __len__zCalibrationDataReader.__len__       !!r"   start_index	end_indexc                     t           ru   r   )rH   r   r   s      r    	set_rangezCalibrationDataReader.set_range   r   r"   N)r\   r`   ra   classmethodr   abcabstractmethoddictr   rw   r   r   intr   rV   r"   r    r   r      s        _ _ [_ 	"$ " " " "    " " ""S "S " " " " " "r"   r   )	metaclassc                       e Zd Z	 	 	 	 	 ddeeef         deee                  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)rm   rn   r   r   modelrB   r   augmented_model_path	symmetricuse_external_data_formatper_channelaugment_modelinfer_sessionexecution_providers)rH   r   r   r   r   r   r   s          r    rL   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)rH   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   )rH   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 rV   namerX   vis     r    rY   z>CalibraterBase.select_tensors_to_calibrate.<locals>.<dictcomp>   s    DDDrrwDDDr"   c                     i | ]
}|j         |S rV   r   )rX   ots     r    rY   z>CalibraterBase.select_tensors_to_calibrate.<locals>.<dictcomp>   s    EEEBBGREEEr"   c                     i | ]
}|j         |S rV   r   )rX   its     r    rY   z>CalibraterBase.select_tensors_to_calibrate.<locals>.<dictcomp>   s    DDDBBGRDDDr"   c                     h | ]	}|j         
S rV   r   )rX   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chainrE   HasFieldr   	elem_typeadd)	rH   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   rP   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   rP   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   )rH   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   rP   s    r    compute_datazCalibraterBase.compute_data"  r   r"   )Nr   FFF)r\   r`   ra   r	   rn   r   r   r   rL   r   r   r
   r   r   r   r   r   re   r   rV   r"   r    r   r      s         :>3!& <  <#t)$ <  (6 <  <  <  <D <R:R ( ( ( (

 

 

1 1 1 1 1:  " " ""(= " " " ""k " " " " " "r"   r   c                        e Zd Z	 	 	 	 	 	 	 	 ddeeef         deee                  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 rV   r   rX   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.)superrL   intermediate_outputscalibrate_tensors_rangers   r   r   r   num_model_outputsmodel_original_outputsmoving_averagerB   averaging_constantmax_intermediate_outputs)rH   r   r   r   r   r   r   r   r   r   r[   s             r    rL   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 rV   r   r   s     r    rY   zNMinMaxCalibrater.augment_graph.<locals>.add_reduce_min_max.<locals>.<dictcomp>w  s    MMM227BMMMr"   c                     i | ]
}|j         |S rV   r   )rX   os     r    rY   zNMinMaxCalibrater.augment_graph.<locals>.add_reduce_min_max.<locals>.<dictcomp>x  s    KKKaKKKr"   c                     i | ]
}|j         |S rV   r   )rX   is     r    rY   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   rg      axesr   )!r  r   	make_noder   r   r   r   r   r   rE   r   r   rB   r   rs   r   dimrange	attributeappendmake_attributern   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_namerH   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		 [k [ [ [    
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   rn   r  r  r   r  r   r   r!  r   r   r  r  saver   r   )rH   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 ru   r   rP   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 r;   )r   r   r  r   runr   rs   r:  r   rB   r   rm   re   ro   rE   )rH   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   rh   )r@   rm   r2   rQ   r   r   minmax)rH   	old_range	new_rangerz   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        rct          j        t          j        |	          t          j        |
          gd          }|                    t          | |g                     |                    t          |	|
g                     )t!          t"          j        t'          t)          ||                              } 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 rV   )r   get_outputsr   )rX   r  rH   s     r    
<listcomp>z1MinMaxCalibrater.compute_data.<locals>.<listcomp>  s0    sssQ*6688;@sssr"   c                 J    g | ]}t          t          |                     S rV   r   ziprX   r&  output_namess     r    rO  z1MinMaxCalibrater.compute_data.<locals>.<listcomp>  9     
 
 
=PD\#67788
 
 
r"   Nc                 R    g | ]#}|                              d           d         $S )r  r   )
rpartition)rX   r  added_output_namess     r    rO  z1MinMaxCalibrater.compute_data.<locals>.<listcomp>  s?     "
 "
 "
9:q!,,S11!4"
 "
 "
r"   rg   c                 4    i | ]}|j         v||         S rV   )r   )rX   r  merged_output_dictrH   s     r    rY   z1MinMaxCalibrater.compute_data.<locals>.<dictcomp>  s5     $
 $
 $
)*ATMhDhDhA!!$DhDhDhr"   r(   r   )rs   r   r   r  r@   
setdefaultr  r   r   r   meanrA  rB  r   absrp   re   rq   rr   r   rR  rK  )rH   output_dicts_listdrJ   rK   calibrate_tensor_namesmerged_added_output_dictpairsr  min_value_arraymax_value_arraymax_absolute_valuenew_calibrate_tensors_rangerX  rZ  rT  s   `            @@@r    r   zMinMaxCalibrater.compute_data  s    t())Q..//ssss%PSTXTmnoTpPqPqJrJrsss
 
 
 
TXTm
 
 
  " 	? 	?A		 ? ?1"--a44;;A>>>>?)$*@*B*BC"
 "
 "
 "
>CAsK]G^G^`a>b>b"
 "
 "
$
 $
 $
 $
 $
.@$
 $
 $
  q#011155 	H 	HA" f"$'*BCUVWCX*Y`a"b"b"b"$'*BCUVWZ[V[C\*]de"f"f"f"$&)ABTUVBW)X_`"a"a"a"$&)ABTUVYZUZB[)\cd"e"e"e~ H%'VRVO-D-Dbf_F]F],^ef%g%g%g"U%7$79K#LMMNNNNUO_#EFFGGGG&12C2JDQTUkmrQsQsLtLt&u&u#' 	G+/+;+;D<XZu+v+vD((+FD(++r"   )Nr   FFFr   NF)r\   r`   ra   r	   rn   r   r   r   rL   r   r:  r   r   rK  re   r   __classcell__r[   s   @r    r   r   )  s         :>3!&!%'A 'A#t)$'A  (6'A 'A 'A 'A 'A 'ARG
 G
 G
R' ' '$(= $ $ $ $(  B0,k 0, 0, 0, 0, 0, 0, 0, 0,r"   r   c                        e Zd Z	 	 	 	 	 	 	 	 	 dd	eeef         d
eee                  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 rV   r   r   s     r    r   z/HistogramCalibrater.__init__.<locals>.<setcomp>+  r   r"   )r   rL   r   r   rs   r   r   r   r   r   	collectormethodnum_binsnum_quantized_binsrk  r   scenario)rH   r   r   r   r   rs  r   rt  ru  rk  rv  r[   s              r    rL   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
        r2  N)r   r   r   r   r   r   r  r  r4  r   r   )rH   r   r7  s      r    r   z!HistogramCalibrater.augment_graph4  s    
 261Q1QRVR\1]1].!;/ 	D 	DFT888
 '..{6/BCCC	J%"&"?	
 	
 	
 	
 	
 	
r"   c                     g | _         d S ru   r9  rP   s    r    r:  z(HistogramCalibrater.clear_collected_dataD  r;  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 rV   r   rX   node_args     r    r   z3HistogramCalibrater.collect_data.<locals>.<setcomp>K  s    YYYX8=YYYr"   c                     g | ]	}|j         
S rV   r   r{  s     r    rO  z4HistogramCalibrater.collect_data.<locals>.<listcomp>L  s    WWW(WWWr"   TNr   r=  c                 J    g | ]}t          t          |                     S rV   rQ  rS  s     r    rO  z4HistogramCalibrater.collect_data.<locals>.<listcomp>b  rU  r"   c                 4    i | ]}|j         v ||         S rV   )r   )rX   r  merged_dictrH   s     r    rY   z4HistogramCalibrater.collect_data.<locals>.<dictcomp>k  s,    fff1qDLeGeGeQAGeGeGer"   )rs  r   rt  ru  rk  rv  )r   
get_inputsrN  r   r>  	enumerater  copyr   rs   rB   r@   r[  rr  HistogramCollectorrs  r   rt  ru  rk  rv  collectr:  )rH   r   input_names_setr  r  fixed_outputsoutput_indexr   r^  r_  rJ   rK   clean_merged_dictr  rT  s   `            @@r    r   z HistogramCalibrater.collect_dataG  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
 
 
 
TXTm
 
 
 " 	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.)rr  rB   rm   EntropyCalibraterrq   r   PercentileCalibraterr   DistributionCalibraterr   ro   rE   re   compute_collection_result)rH   cals     r    r   z HistogramCalibrater.compute_dataz  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   Frk  Frl  rm  rn  ro  )r\   r`   ra   r	   rn   r   r   r   rL   r   r:  r   r   re   r   rg  rh  s   @r    rj  rj    s         :>3!&*! *!#t)$*!  (6*! *! *! *! *! *!X
 
 
 ' ' '1$(= 1$ 1$ 1$ 1$fLk L L L L L L L Lr"   rj  c                   `     e Zd Z	 	 	 	 	 	 	 d	deeef         deee                  f fdZ xZ	S )
r  Nr   Fr0   rl  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.
        )rs  r   rt  ru  Nr   rL   )
rH   r   r   r   r   rs  r   rt  ru  r[   s
            r    rL   zEntropyCalibrater.__init__  sH    * 	! $1 	 		
 		
 		
 		
 		
r"   )Nr   Fr0   Frl  rl  
r\   r`   ra   r	   rn   r   r   r   rL   rg  rh  s   @r    r  r    s}         :>3!&
 
#t)$
  (6
 
 
 
 
 
 
 
 
 
r"   r  c                   `     e Zd Z	 	 	 	 	 	 	 d
deeef         deee                  f fd	Z xZ	S )r  Nr   Frk  rm  rn  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.
        )rs  r   rt  rk  Nr  )
rH   r   r   r   r   rs  r   rt  rk  r[   s
            r    rL   zPercentileCalibrater.__init__  sH    * 	! $! 	 		
 		
 		
 		
 		
r"   )Nr   Frk  Frm  rn  r  rh  s   @r    r  r    s}         :>3!&
 
#t)$
  (6
 
 
 
 
 
 
 
 
 
r"   r  c                   ^     e Zd Z	 	 	 	 	 	 d
deeef         deee                  f fd	Z xZ	S )r  Nr   Fdistributionrl  ro  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
        )rs  rt  rv  Nr  )	rH   r   r   r   r   rs  rt  rv  r[   s	           r    rL   zDistributionCalibrater.__init__  sE    . 	! $ 	 	
 	
 	
 	
 	
r"   )Nr   Fr  rl  ro  r  rh  s   @r    r  r    sz         :>3!&
 
#t)$
  (6
 
 
 
 
 
 
 
 
 
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   rH   name_to_arrs     r    r  z CalibrationDataCollector.collect  s
     "!r"   c                     t           )z?
        Get the optimal result among collection data.
        r   rP   s    r    r  z2CalibrationDataCollector.compute_collection_result  s
    
 "!r"   N)r\   r`   ra   __doc__r   r   r  r  rV   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 ru   )histogram_dictrs  r   rt  ru  rk  rv  )rH   rs  r   rt  ru  rk  rv  s          r    rL   zHistogramCollector.__init__  s9     " "4$ r"   c                     | j         S ru   )r  rP   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 ...>   r0   r  rk  DOnly 'entropy', 'percentile' or 'distribution' methods are supported)printrs  collect_valuer   collect_absolute_valuerB   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 ]m\  }}t          |t                    r|D ]9}t          |t          j                  sJ dt          |           d|            :t          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	            |	|
t          ||          t          ||          f| j        |<   odS )z5
        Collect histogram on absolute value
        r<   z for tensor=c              3   $   K   | ]}|j         V  d S ru   r   )rX   as     r    	<genexpr>z<HistogramCollector.collect_absolute_value.<locals>.<genexpr>6  s$      77QW777777r"   r   z6The calibration expects only one element type but got r   r   )r9   zMonly float32 or float16 is supported, every constant must be explicitly typedrg   rj   r   z'old_min should be a numpy array but is r  N)r@   rm   r=   r   ndarrayrE   r   rs   r)   rB   flattensizerA  rB  r   r   absoluter  	histogramrt  r*   float64rD   arangehstack)rH   r  r7  data_arrarrdtypesdata_arr_nprI  rJ  r7   r8   old_histogramrE  rF  old_histold_hist_edges	temp_amaxwidthnew_bin_edgess                      r    r  z)HistogramCollector.collect_absolute_value.  s    !, 1 1 3 3 4	s 4	sFH(D)) '# m mC%c2:66ll8l4PS998l8lbh8l8lllll77h77777KK1$$$jFjj`fjj %$$ j22"*55 ' !ZDNN!Z!ZPV!Z!Z[[[&%--//K!##F;//	F;//		HQk.?@@@	HQk.?@@@	+k22KT000#%<$-#P#P#P j'..{/@AA
%333b 433/3ZI.V#F++ $ 3F ;'*'*w00kk2k\`ah\i\i2k2kkkkw00kk2k\`ah\i\i2k2kkkk(+!.q!1F;//	~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%%%%333b 433/3Z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  rA  rB  r   r   r]  r  merge_histogramr  rt  )
rH   r  r7  r  rI  rJ  	thresholdr  r7   r8   s
             r    r  z HistogramCollector.collect_valueh  sc    !, 1 1 3 3 	 	FHz(++H''))H}q  F8,,	F8,,		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   rg   r   )r   r  rs   rA  rB  r   )rH   r  r  rG  rH  new_thresholdr  r  rE  rF  old_thresholdnew_histr  r7   r8   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 ...r0   rk  r  r  )r  rs   rB   r  rs  compute_entropycompute_percentilecompute_distributionrP   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&   rg   rj   QUANTIZATION_DEBUGr   1)rk  rB   r  r  rs   rt  r@   r,   r   cumsumr   searchsortedr   r   osenvirongetr   )rH   r  rk  thresholds_dictr7  r  r7   r8   totalcdf	idx_rightpercent_to_cut_one_sideidx_leftrI  rJ  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~~2A66(BB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 : rg   r  r   r  r   )r  ru  r  rs   rt  r@   get_entropy_thresholdr  r  r  r   )rH   r  ru  r  r7  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~~2A66(BB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      ?rg   r   )	rB   r,   r   r   r   r   r]  isnanisinf)r7   r8   powerr   r3   r4   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   ro  )r  p3gUUUUUU?z,Invalid scenario. Must be in {'same', 'p3'}.)r3   r4   r7   r8   r5   r6   r  r  )rt  rB   r  r  rs   rv  r@   r   r   r  r  r2   rA  rB  r  r  r  r   )	rH   r  r  r7  r  r7   r8   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~~2A66(BB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   rg   c                 h    g | ].}t          j        d           t          j        d           f/S )r   r   )r   r   )rX   r  r   s     r    rO  z<HistogramCollector.get_entropy_threshold.<locals>.<listcomp>E  s<    nnnqrx///!51I1I1IJnnnr"   Nr  r   rj   r   )r  r   r   zerosr  rA  r  deepcopyr,   r*   r!  r   r   r   r0   argminrD   )rH   r  ru  r7   r8   rt  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  rI  rJ  r   s                                 @r    r  z(HistogramCollector.get_entropy_threshold7  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   )r\   r`   ra   r  rL   r  r  r  r  r  r  r  r  staticmethodr  r  r  rV   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          | |||||          }|r*|
                                 |                                 |S t          d|           )Nr   Fr   r   r   r   r   )r   r   r   r   r   r   rt  rl  ru  )r   r   rt  ru  rm  rk  rn  T)r   r   rt  rk  rv  ro  )r   rt  rv  zUnsupported calibration method )rq   rr   r  r   r   r  r   r  r   r  r   r   rB   )r   r   r   calibrate_methodr   extra_options
calibratorr   r   r   r   r   rt  ru  rk  rv  s                   r    create_calibratorr    s]    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+! %=
 
 

    """++---
I7GII
J
JJr"   )Nr   )0r   r  r   r  r  enumr   pathlibr   typingr   r   r   r   r	   numpyr   r  r
   r   r   r   r   quant_utilsr   r   r   r  r!   floatr   r0   r2   re   rq   ABCMetar   r   r   rj  r  r  r  r  r  rr   rn   r  rV   r"   r    <module>r     s   


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



 5/ 	
 Z   8               F1 1 1 1 1 1 1 1h       " " " " "ck " " " "4k" k" k" k" k" k" k" k"\[, [, [, [, [,~ [, [, [,|CL CL CL CL CL. CL CL CLL
 
 
 
 
+ 
 
 
D
 
 
 
 
. 
 
 
D 
  
  
  
  
0  
  
  
F" " " " " " " " ",E! E! E! E! E!1 E! E! E!T 6:/&-"KK KKdKK#HSM2KK KK KK KK KK KKr"   