
    2Vh0q                         d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dl	m
Z
 d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ 	 d dlZd Z ed	       G d
 d             ZddZd Zd Zd Zd ZddZy# e$ r dZY 6w xY w)    N)backend)keras_export)
saving_lib)	H5IOStore)naming)summary_utilsc                  @    	 ddl m}   |        yy# t        $ r Y yw xY w)z3Checks if the code is being executed in a notebook.r   get_ipythonTF)IPythonr   ImportErrorr
   s    L/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/saving/file_editor.pyis_ipython_notebookr      s,    ' =$ s    	zkeras.saving.KerasFileEditorc                       e Zd ZdZd Zd Zd ZddZd Zd Z	d	 Z
d
 Zd Zd Zd ZddZddZddZddZ	 ddZd Zd Zy)KerasFileEditora  Utility to inspect, edit, and resave Keras weights files.

    You will find this class useful when adapting
    an old saved weights file after having made
    architecture changes to a model.

    Args:
        filepath: The path to a local file to inspect and edit.

    Examples:

    ```python
    editor = KerasFileEditor("my_model.weights.h5")

    # Displays current contents
    editor.summary()

    # Remove the weights of an existing layer
    editor.delete_object("layers/dense_2")

    # Add the weights of a new layer
    editor.add_object("layers/einsum_dense", weights={"0": ..., "1": ...})

    # Save the weights of the edited model
    editor.resave_weights("edited_model.weights.h5")
    ```
    c                 ,   || _         d | _        d | _        d | _        t        j
                  j                  d      | _        |j                  d      rt        j                  |d      }t        t        j                  dz   |d      }|j                  t        j                  d      5 }|j                         }d d d        |j                  t        j                   d      5 }|j                         }d d d        t#        j$                        | _        t#        j$                        | _        n-|j                  d      rt        |d      }nt'        d	|       | j)                  |j*                        \  }}|j-                          || _        || _        | j
                  j3                  | j5                  d
             | j                  ,| j
                  j3                  | j7                  d
             y y # 1 sw Y   ExY w# 1 sw Y   xY w)NF)	highlightz.kerasrz.h5)archivemode.weights.h5r   zRInvalid filename: expected a `.keras` `.weights.h5` extension. Received: filepath=T)
rich_style)filepathmetadataconfigmodelrichconsoleConsoleendswithzipfileZipFiler   r   _VARS_FNAMEopen_CONFIG_FILENAMEread_METADATA_FILENAMEjsonloads
ValueError_extract_weights_from_storeh5_filecloseweights_dictobject_metadataprint_generate_filepath_info_generate_metadata_info)	selfr   zfweights_storefconfig_jsonmetadata_jsonr/   r0   s	            r   __init__zKerasFileEditor.__init__B   s    !
||++e+<X&3/B%&&.M
 44c: 'affh'66< ) !)**[1DK JJ}5DM}-%hS9M&&.Z1  )-(H(H!!)
%o 	(.47747HI==$LLt;;t;LM %1' ') )s   (G<!H	<H	Hc                 $    | j                          y)z/Prints the weight structure of the opened file.N)_weights_summary_clir4   s    r   summaryzKerasFileEditor.summaryn   s    !!#    c           
      0   
  j                   j                  d       i }t        ||       
 fd
t               } 
 j                  |ddddd|      \  }} 
| j                  ddddd|      \  }}||z  } j                   j                  d       |dk(  rId	} j                   j                  d
       |dk(  rd}	nd}	 j                   j                  d| d|	        n.d}|dk(  rd}	nd}	 j                   j                  d| d|	 d       |||dS )a)  Compares the opened file to a reference model.

        This method will list all mismatches between the
        currently opened file and the provided reference model.

        Args:
            reference_model: Model instance to compare to.

        Returns:
            Dict with the following keys:
            `'status'`, `'error_count'`, `'match_count'`.
            Status can be `'success'` or `'error'`.
            `'error_count'` is the number of mismatches found.
            `'match_count'` is the number of matching weights found.
        zRunning comparisonc                    |}|j                         D ]r  \  }	}
|dz   |	z   }||v r|	| vr|dz  }|j                  |       t        |
t              raj                  j                  d| d| d| d       j                  j                  d| d| d	t        |
j                                       j                  j                  d
| d| d| d       t        |
t              r$ | |	   ||	   ||||||      \  }}||z  }||z  }| |	   j                  |
j                  k7  rY|dz  }|j                  |       j                  j                  d| d| d|
j                   d| d| |	   j                   
       n|dz  }u ||fS )N/   z[color(160)]...Object [bold]z[/] present in z, missing from z[/]z    In , z contains the following keys: z[color(160)]...Weight [bold])error_countmatch_countchecked_pathsz/[color(160)]...Weight shape mismatch for [bold]z[/][/]
    In z: shape=z
    In )	itemsadd
isinstancedictr   r1   listkeysshape)targetref_spec
inner_pathtarget_nameref_namerE   rF   rG   base_inner_pathref_keyref_val_error_count_match_count_comparer4   s                r   rY   z)KerasFileEditor.compare.<locals>._compare   s    )O$,NN$4 2) ,s2W<
.&(1$K!%%j1!'40**::, G**2 4,,7==
 **%hZr* >3373G2HJ
 **::, G**2 4,,7==
  .19w )"# $/$/&3	2.L,  </K</Kg,,=#q(%))*5**))3 5&&.Z 0%%,]]O 4&&1] 3%%+G_%:%:$;= $q(e2)f ++r?    z
saved filezreference modelr   )rQ   rR   rS   rE   rF   rG   u?   ─────────────────────successz_[color(28)][bold]Comparison successful:[/] saved file is compatible with the reference model[/]rC   sz
    Found z matching weighterrorz[color(160)][bold]Found z errorz=:[/] saved file is not compatible with the reference model[/])statusrE   rF   )r   r1   get_weight_spec_of_saveablesetr/   )r4   reference_modelrP   rG   rE   rF   rW   _r^   pluralrY   s   `         @r   comparezKerasFileEditor.comparer   sf     	/0#OX>>	,@ #+$&'	$
 [ #)!'	
a 	|#\]!FLLG aLL[M)9&B FaLL*;-vfX FK K
 &&
 	
r?   Nc                   	 dv rt        d d      dv rdj                  d      }| j                  }|d d D ]  }||vrt        d d      ||   } |d   |vrt        d d       ||d          y d	fd			 	| j                        }|d
kD  rt        d d      |dk(  rt        d d      fd | j                         y )NrB   z[Argument `target_name` should be a leaf name, not a full path name. Received: target_name=''Path '' not found in model.source_namerR   r   c                 p    | D ]&  }t        | |   t              s| | |   ||      z  }( || v r|dz  }|S NrC   rJ   rK   )dnamecountkcount_occurencess       r   rs   z6KerasFileEditor._edit_object.<locals>.count_occurences  sQ     EA!!A$-!1!A$e!DDE 19QJEr?   rC   zName 'zA' occurs more than once in the model; try passing a complete pathzSource name 'zS' does not appear in the model. Use `editor.weights_summary()` to list all objects.c                 r    | D ]!  }t        | |   t              s | |          # | v r |        y y )Nrj   rn   )ro   rr   _editedit_fnrk   rR   s     r   ru   z+KerasFileEditor._edit_object.<locals>._edit'  sF     $A!!A$-ad$ !#A;KP $r?   )r   )r+   splitr/   )
r4   rv   rk   rR   elementsr/   eoccurrencesru   rs   s
    ```    @@r   _edit_objectzKerasFileEditor._edit_object   sG   "sk'9**5a9 
 +"((-H,,Lcr] /L($ -BC   ,A/ |</ 6+6K!LMM(2,K
 +4+<+<kJKQ [M *2 2  a #K= 1+ + Q $##$r?   c                 0    d }| j                  |||       y)a
  Rename an object in the file (e.g. a layer).

        Args:
            object_name: String, name or path of the
                object to rename (e.g. `"dense_2"` or
                `"layers/dense_2"`).
            new_name: String, new name of the object.
        c                 6    | |   | |<   | j                  |       y Npopr/   rk   rR   s      r   	rename_fnz0KerasFileEditor.rename_object.<locals>.rename_fn:  s    (4[(AL%[)r?   Nr{   )r4   object_namenew_namer   s       r   rename_objectzKerasFileEditor.rename_object0  s    	* 	)[(;r?   c                 0    dd}| j                  ||       y)zRemoves an object from the file (e.g. a layer).

        Args:
            object_name: String, name or path of the
                object to delete (e.g. `"dense_2"` or
                `"layers/dense_2"`).
        Nc                 &    | j                  |       y r~   r   r   s      r   	delete_fnz0KerasFileEditor.delete_object.<locals>.delete_fnI  s    [)r?   r~   r   )r4   r   r   s      r   delete_objectzKerasFileEditor.delete_object@  s    	* 	)[1r?   c                 0   t        |t              st        dt        |             d|v r\|j	                  d      }dj                  |dd       }| j                  }|dd D ]  }||vrt        d| d      ||   } |||d   <   y|| j                  |<   y)aF  Add a new object to the file (e.g. a layer).

        Args:
            object_path: String, full path of the
                object to add (e.g. `"layers/dense_2"`).
            weights: Dict mapping weight names to weight
                values (arrays),
                e.g. `{"0": kernel_value, "1": bias_value}`.
        Argument `weights` should be a dict where keys are weight names (usually '0', '1', etc.) and values are NumPy arrays. Received: type(weights)=rB   Nrg   rh   ri   )rJ   rK   r+   typerw   joinr/   )r4   object_pathweightsrx   partial_pathr/   ry   s          r   
add_objectzKerasFileEditor.add_objectN  s     '4(+ ,0=/;  +"((-H88HSbM2L,,Lcr] /L($ .CD   ,A/ *1L"&-4Dk*r?   c                 :    dfd	}| j                  |       y)aC  Removes a weight from an existing object.

        Args:
            object_name: String, name or path of the
                object from which to remove the weight
                (e.g. `"dense_2"` or `"layers/dense_2"`).
            weight_name: String, name of the weight to
                delete (e.g. `"0"`).
        Nc                     | |   vr.t        d d dt        | |   j                                      | |   j                         y )NzWeight z not found in object z. Weights found: )r+   rL   rM   r   )r/   rk   rR   r   weight_names      r   delete_weight_fnz7KerasFileEditor.delete_weight.<locals>.delete_weight_fnz  sg    ,{";; k] +!!, .&L5::<=>@  %))+6r?   r~   r   )r4   r   r   r   s    `` r   delete_weightzKerasFileEditor.delete_weighto  s    	7 	*K8r?   c                     t        t              st        dt                     dfd	}| j	                  ||       y)a}  Add one or more new weights to an existing object.

        Args:
            object_name: String, name or path of the
                object to add the weights to
                (e.g. `"dense_2"` or `"layers/dense_2"`).
            weights: Dict mapping weight names to weight
                values (arrays),
                e.g. `{"0": kernel_value, "1": bias_value}`.
        r   Nc                 .    | |   j                         y r~   )update)r/   rk   rR   r   s      r   add_weight_fnz2KerasFileEditor.add_weights.<locals>.add_weight_fn  s    %,,W5r?   r~   )rJ   rK   r+   r   r{   )r4   r   r   r   s     ` r   add_weightszKerasFileEditor.add_weights  sH     '4(+ ,0=/; 	6 	-5r?   c                     t        |      }|j                  d      st        d|       t        |d      }fd | j                  |d       |j                          y)	zSave the edited weights file.

        Args:
            filepath: Path to save the file to.
                Must be a `.weights.h5` file.
        r   zTInvalid `filepath` argument: expected a `.weights.h5` extension. Received: filepath=wr   c                     i }| j                         D ]2  \  }}t        |t              r|s | |   ||dz   |z          .|||<   4 |r/|j                  |      }|j                         D ]
  \  }}|||<    y y )NrB   rQ   )rH   rJ   rK   make)r/   r6   rQ   vars_to_createrp   value	var_store_saves          r   r   z#KerasFileEditor.save.<locals>._save  s    N+113 
1eeT*(.)'1C'7$'> ,1N4(
1 )..z:	#1#7#7#9 ,KD%&+IdO, r?   rZ   r   N)strr!   r+   r   r/   r.   )r4   r   r6   r   s      @r   savezKerasFileEditor.save  sk     x=  /&&.Z1 
 "(5	,$ 	d2>r?   c                 &    | j                  |       y r~   )r   )r4   r   s     r   resave_weightszKerasFileEditor.resave_weights  s    		(r?   c                 :   |xs i }i }|j                   j                         D ]
  \  }}|||<    |r|||<   t        j                         }|j	                         D ]  }|dz   |z   }||   }	t        |	t        j                        r3t        |	      dk(  r9d|	j	                         v rt        |	d         dk(  r]t        |	d      rKd|	j	                         v r| j                  |	d   ||      \  ||<   }| j                  |	||      \  ||<   }|	d   ||<    ||fS )NrB   r   varsrM   )r   rQ    )attrsrH   collectionsOrderedDictrM   rJ   h5pyGrouplenhasattrr,   )
r4   datar   rQ   r0   rr   vresultkeyr   s
             r   r,   z+KerasFileEditor._extract_weights_from_store  sE   >rJJ$$& 	#DAq!"OA	##2HZ ((*99; 	(C#c)C/JIE%,u:?UZZ\)c%-.@A.Euf%UZZ\),0,L,LfZ -M -)F3K -1,L,LZ -M -)F3K $Bis'	(( xr?   c                 ~    |r'd| j                    d}t        j                  |       }nd| j                    d}d| S )Nrf   zKeras model file )r   r   highlight_symbol)r4   r   r   s      r   r2   z'KerasFileEditor._generate_filepath_info  sI    4==/+H'88BCH4==/+H"8*--r?   c                 @    t        j                  | j                        S r~   )pprintpformatr   )r4   r   s     r   _generate_config_infoz%KerasFileEditor._generate_config_info  s    ~~dkk**r?   c                     | j                   d   }| j                   d   }|r,t        j                  |       }t        j                  |       }d| d| S )Nkeras_version
date_savedzSaved with Keras z	 - date: )r   r   r   )r4   r   versiondates       r   r3   z'KerasFileEditor._generate_metadata_info  sZ    --0}}\*&77@AG#44T:;D"7)9TF;;r?   c                    t        |j                               D ]S  \  }\  }}|dz   |z   }|t        |      dz
  k(  }	|rd}d}
n|	rd}
nd}
t        |t              rt        j                  |      }| |
 | }|| j                  v r!| j                  |   }d|v r|d   }|d| d	z  }| j                  j                  |       |	rd
}nd}||z   }| j                  ||dz   |||       t        |d      rVt        j                  |      }| j                  j                  | |
 | dd|j                   d|j                   z          0| j                  j                  | |
 | d|        V y )NrB   rC   Fz> u   └─ u   ├─ rp   z ('z')z    u   │   )is_firstprefixrQ   rN   :z shape=, dtype=z: )	enumeraterH   r   rJ   rK   r   	bold_textr0   r   r1   _print_weights_structurer   rN   dtype)r4   r/   indentr   r   rQ   idxr   r   is_last	connectorbold_keyobject_labelr   rp   appended
new_prefixs                    r   r   z(KerasFileEditor._print_weights_structure  s    "+<+=+=+?!@ (	MC#u#c)C/JS.22G  	%	%	%&(2237"()XJ?!5!55#33J?H)'/$#dV26""<0%H'H#h.
--QJ%%) .  5'*,66s;HLL&&!(9+hZq9#EKK=FG
 LL&&&)SEE7'KLQ(	Mr?   c                 t    | j                   j                  d       | j                  | j                  d       y )NWeights structurez  )r   )r   r1   r   r/   r=   s    r   r<   z$KerasFileEditor._weights_summary_cli&  s.    ./%%d&7&7%Hr?   c                     dfd	d}t                | | j                        z  }t        j                  j                  t        j                  j	                  |             y )Nc           	      d   d}| j                         D ]  \  }}t        |t              r4|r2|d| ddz   d| dz   dz   d| d	z    ||d
z   |dz
        z   dz   z  }J|d| dd| dz   | d|j                   z   d|j                   d	z   d| d| dz   t        |       z   dz   dz   z  } |S )NrZ   z<details style="margin-left: zpx;">z<summary style="zfont-size: zem; zfont-weight: bold;z">z
</summary>   rC   z
</details>z<summary style="font-size: zem;">z	 : shape=r   z<div style="margin-left: zpx;"margin-top: z</div>)rH   rJ   rK   rN   r   display_weight)
dictionarymargin_left	font_sizehtmlr   r   _generate_html_weightss         r   r   zLKerasFileEditor._weights_summary_interactive.<locals>._generate_html_weights+  sJ   D(..0 
UeT*u7}EJ,-'	{$78 // se:.	/
 1!;#3Y] ''
D 7}EJ7	{%HI E5;;-89 %U[[M<=))4 6((3}E;	; ,E235 ## '	'D4 Kr?   r   )r   rC   )initialize_id_counterr/   ipythondisplayHTML)r4   outputr   s     @r   _weights_summary_interactivez,KerasFileEditor._weights_summary_interactive*  sL    	< %():):;; 4 4V <=r?   r~   )NrZ   )F)r   TrZ   rZ   )__name__
__module____qualname____doc__r:   r>   rd   r{   r   r   r   r   r   r   r   r,   r2   r   r3   r   r<   r   r   r?   r   r   r   $   ss    8*NX$F
P4%l< 25B9.60#J @.+< LN+MZI#>r?   r   c                 Z   ddl m} |xs
 t               }t        |       |v ry t	        | d      rhi }| j                  |       |rSt        |j                               }|D ]5  }||   }t        j                  |j                  |j                        ||<   7 |j                  t        |              t        j                  |       D ]c  \  }}	t        |	|      ri }
t!        |	|
|       |
s%|
||<   +t        |	t"        t$        t&        t        f      sLi }
t)        |	|
|       |
s_|
||<   e y )Nr   KerasSaveablesave_own_variables)rN   r   visited_saveables)keras.src.saving.keras_saveabler   r`   idr   r   sortedrM   r   KerasTensorrN   r   rI   r   _walk_saveablerJ   r_   rL   rK   tupleget_weight_spec_of_container)saveablespecr   r   storerM   rr   val
child_attr	child_objsub_specs              r   r_   r_   P  s'   =)2SU 
(|((x-.##E*%**,'D PAh!--CIISYYOQP "X,'!+!:!:8!D ,
Ii/H'"3
 #+Z 	D$s#;<H("3
 #+Z %,r?   c                 R   ddl m} i }t        | t              rt	        | j                               } | D ]q  }t        ||      st        j                  |j                  j                        }||v r||xx   dz  cc<   | d||    }nd||<   i }t        |||       |sm|||<   s y )Nr   r   rC   rb   r   )r   r   rJ   rK   rL   valuesr   to_snake_case	__class__r   r_   )	containerr   r   r   
used_namesr   rp   r   s           r   r   r   y  s    =J)T"))+,	 &h.''(:(:(C(CDDz!4 A% qD!1 23#$
4 H'"3
 %T
&r?   c                      da y )Nr   div_id_counterr   r?   r   r   r     s    Nr?   c                      t         dz  a y rm   r  r   r?   r   increment_id_counterr    s    aNr?   c                      t         S r~   r  r   r?   r   get_id_counterr	    s    r?   c                 8  	
 d 
d 	d }d	
fd	}| j                   dk(  r| dt        j                  f   } t        j                  | |d      } | j	                  d| j
                  d         }  
| j
                  d         \  }}| j	                  ||| j
                  d         } d	D ]0  }| j
                  |   |kD  s || | j
                  |   |z  |
      } 2 | | j                         z
  | j                         | j                         z
  dz   z  }  ||       }|S )Nc                     t        t        j                  |             }t        |dd      D ]"  }| |z  dk(  s|}| |z  }||kD  r||fc S ||fc S  y )Nr   rg   )intnpsqrtrange)numsqrt_numiMNs        r   _find_factors_closest_to_sqrtz5display_weight.<locals>._find_factors_closest_to_sqrt  s^    rwws|$xB' 	AQw!|1Hq5a4K!t	r?   c                 ,    d| d    d| d    d| d    dS )Nzrgba(r   rD   rC      z, 1)r   )r   s    r   _color_from_rbgz'display_weight.<locals>._color_from_rbg  s)    uQxj58*BuQxj==r?   c                    |dk(  r{| d d d d d | j                   d   | j                   d   |z  z
  f   }t        j                  || j                   d   | j                   d   d|f      }t        j                  |d      }|S |dk(  r{| d d d | j                   d   | j                   d   |z  z
  d d f   }t        j                  || j                   d   d|| j                   d   f      }t        j                  |d      }|S |dk(  r{| d | j                   d   | j                   d   |z  z
  d d d d f   }t        j                  |d|| j                   d   | j                   d   f      }t        j                  |d      }|S t	        d      )Nr  r   rC   rg      axiszAxis must be 0, 1, or 2.)rN   r  reshapemeanr+   )arrnr  trimmed_arrreshapedmean_valuess         r   _reduce_3d_array_by_meanz0display_weight.<locals>._reduce_3d_array_by_mean  s   19a$GciilciilQ6F&G$GGHKzzciilCIIaL"a@H ''(3K& # QYa!D399Q<399Q<!3C#D!DaGHKzzciilB399Q<@H ''(3K  QYA		!		!q0@ AA1aGHKzzb!SYYq\399Q<@H ''(3K
  788r?   c                    | j                   \  }}} |      \  }}	 ddlm} |r|j	                  |       }n^| t        j                  |       z
  t        j                  |       t        j                  |       z
  z  }t        j                  |||gd      }|dd df   dz  j                  d      }d	}	t        |      D ]4  }
d	}|d|
d d f   D ]  }|D ]  } |      }|d
| dz  }  |	d| dz  }	6 |||z  z  }t                t               }d| d| d| d| d| d| d| d| d| d| d| d| d|	 d}|S # t        $ r d }Y 'w xY w)Nr   )cmrg   r  .r     uint8rZ   z+<div class="cell" style="background-color: z	;"></div>zH
                        <div class="matrix">
                          z8
                        </div>
                        z*
            <div class="unique-container_zE">
                  <style>
                      .unique-container_zm .subplots {
                      display: inline-grid;
                      grid-template-columns: repeat(a  , 1fr);
                      column-gap: 5px;  /* Minimal horizontal gap */
                      row-gap: 5px;     /* Small vertical gap */
                      margin: 0;
                      padding: 0;
                    }
                    .unique-container_zk .matrix {
                      display: inline-grid;
                      grid-template-columns: repeat(rD   z6px);
                      grid-template-rows: repeat(zpx);
                      gap: 1px;
                      margin: 0;
                      padding: 0;
                    }
                    .unique-container_z& .cell {
                      width: z"px;
                      height: a3  px;
                      display: flex;
                      justify-content: center;
                      align-items: center;
                      font-size: 5px;
                      font-weight: bold;
                      color: white;
                    }
                     .unique-container_z {
                      margin-top: 20px;
                      margin-bottom: 20px;
                    }
                  </style>
                  <div class="subplots">
                    zC
                  </div>
                  </div>
                )rN   
matplotlibr&  r   jetr  minmaxstackastyper  r  r	  )matrixsubplot_sizerowscols
num_slicesr  r  r&  
rgb_matrixsubplot_htmlr  	cell_htmlrowrgbcolor	cell_sizediv_id	html_coder  r  s                     r   _create_matrix_htmlz+display_weight.<locals>._create_matrix_html  s   !'dJ,Z81	% J 266&>1v/J :z:"FRPJ bqb)C/77@
z" 	AI!#q!),  C+C0E4497 ;!"I  !$+ & L	  !QX.	!**0 2))/ 1556C 8' (.h /559F"YK H226r) E'
 (.h /'[ )(k *( )/x 0 "N #G&	P S  	B	s   D= =EErC   .rg   r   )r   rC   r  r  gh㈵>)iH  )ndimr  newaxisswapaxesr  rN   r+  r,  )weightr  	thresholdr$  r=  r  r  reduce_axisr<  r  r  s            @@r   r   r     s   
>6Pd {{aRZZ([[r*F^^BR 01F(a9DAq^^Aq&,,r"23F  <<$y0-[)Y6 F vzz|#

vzz|(Cd(JKF#F+Ir?   r~   )rg      )r   r)   r   r"   r   numpyr  rich.consoler   	keras.srcr   keras.src.api_exportr   keras.src.savingr   keras.src.saving.saving_libr   keras.src.utilsr   r   r   r   r   r   r   r_   r   r   r  r	  r   r   r?   r   <module>rL     s            - ' 1 " )

 ,-h> h> .h>V&,R&2

Q[  Gs   A3 3A=<A=