
    1Vh3                     x    d Z ddlmZ ddlmZ ddlmZ  ej                         Zd Z	d Z
d Zd Zd	 Zd
 Zd Zy)aJ  Utilities for handling Keras model in graph plugin.

Two canonical types of Keras model are Functional and Sequential.
A model can be serialized as JSON and deserialized to reconstruct a model.
This utility helps with dealing with the serialized Keras model.

They have distinct structures to the configurations in shapes below:
Functional:
  config
    name: Name of the model. If not specified, it is 'model' with
          an optional suffix if there are more than one instance.
    input_layers: Keras.layers.Inputs in the model.
    output_layers: Layer names that are outputs of the model.
    layers: list of layer configurations.
      layer: [*]
        inbound_nodes: inputs to this layer.

Sequential:
  config
    name: Name of the model. If not specified, it is 'sequential' with
          an optional suffix if there are more than one instance.
    layers: list of layer configurations.
      layer: [*]

[*]: Note that a model can be a layer.
Please refer to https://github.com/tensorflow/tfjs-layers/blob/master/src/keras_format/model_serialization.ts
for more complete definition.
    )GraphDef)dtypes)
tb_loggingc              #   ,  K   d| f | j                  d      j                  d      rj| j                  d      j                  d      }| j                  d      j                  d      D ]&  }t        |      D ]  \  }}|r|d|n|}||f  ( yyw)aY  Walks the nested keras layer configuration in preorder.

    Args:
      keras_layer: Keras configuration from model.to_json.

    Yields:
      A tuple of (name_scope, layer_config).
      name_scope: a string representing a scope name, similar to that of tf.name_scope.
      layer_config: a dict representing a Keras layer configuration.
     configlayersname/N)get_walk_layers)keras_layer
name_scopelayersub_name_scopesublayers        T/home/dcms/DCMS/lib/python3.12/site-packages/tensorboard/plugins/graph/keras_util.pyr   r   4   s      {
x $$X. __X.226:
 __X.228< 	1E,8,? 1( &  *>:# 
 &x001	1 /s   BBc                     | r| d|S |S )a/  Returns scoped name for a node as a string in the form '<scope>/<node
    name>'.

    Args:
      name_scope: a string representing a scope name, similar to that of tf.name_scope.
      node_name: a string representing the current node name.

    Returns
      A string representing a scoped name.
    r    )r   	node_names     r   _scoped_namer   L   s     $i00    c                 F    | j                  d      j                  d      duS )zReturns True if layer is a model.

    Args:
      layer: a dict representing a Keras model configuration.

    Returns:
      bool: True if layer is a model.
    r   r	   N)r   )r   s    r   	_is_modelr   \   s#     99X""8,D88r   c                 4    t        | d   t        f      r| S | gS )a  Normalizes to a list of layers.

    Args:
      maybe_layers: A list of data[1] or a list of list of data.

    Returns:
      List of list of data.

    [1]: A Functional model has fields 'inbound_nodes' and 'output_layers' which can
    look like below:
    - ['in_layer_name', 0, 0]
    - [['in_layer_is_model', 1, 0], ['in_layer_is_model', 1, 1]]
    The data inside the list seems to describe [name, size, index].
    r   )
isinstancelist)maybe_layerss    r   _norm_to_list_of_layersr   h   s%      #<?TG<CO.r   c                 h   g }| j                  d      | j                  dg       D ]  }t        |t              s|j                  dg       D ]a  }t        |t              s|g}|D ]G  }|j                  di       j                  dg       }t	        |      dk  r4|j                  |dd        I c  |S )zOReturns a list of [name, size, index] for all inbound nodes of the given layer.inbound_nodesNargsr   keras_history   )r   r   dictr   lenappend)r   r!   maybe_inbound_nodeinbound_node_argsarghistorys         r   _get_inbound_nodesr,   |   s    Myy!-"'))OR"@ 	60$7 %7%;%;FB%G 	6! ""3T:):(;%, 6C!ggh377LG7|a' !((!5	6	6	6  r   c                 <   |j                  d      }|j                  d      st        d      t        | |j                  d            }|j                  d      }|j                  d      }t        |      }	t	        |xr |      }
t	        |	      }|r7|
r5t        ||	      D ]%  \  }}t        ||      }t        | |d         }|||<   ' nT|r|
st        | |	d   d         }n=|s;|r9|
r7t        |      dk(  sJ d	t              z         |d   }t        ||      }|||<   |
r/|r-t        |      }|D cg c]  }t        ||d          }}|||<   nF|j                  d      d
   }|j                  d      j                  d      }t        ||      }|g||<   |||fS c c}w )a  Updates input_to_in_layer, model_name_to_output, and prev_node_name
    based on the model_layer.

    Args:
      name_scope: a string representing a scope name, similar to that of tf.name_scope.
      model_layer: a dict representing a Keras model configuration.
      input_to_in_layer: a dict mapping Keras.layers.Input to inbound layer.
      model_name_to_output: a dict mapping Keras Model name to output layer of the model.
      prev_node_name: a string representing a previous, in sequential model layout,
                      node name.

    Returns:
      A tuple of (input_to_in_layer, model_name_to_output, prev_node_name).
      input_to_in_layer: a dict mapping Keras.layers.Input to inbound layer.
      model_name_to_output: a dict mapping Keras Model name to output layer of the model.
      prev_node_name: a string representing a previous, in sequential model layout,
                      node name.
    r   r	   zlayer is not a model.r
   input_layersoutput_layersr      zhCannot have multi-input Functional model when parent model is not Functional. Number of input layers: %d)r   
ValueErrorr   r,   boolzipr&   r   )r   model_layerinput_to_in_layermodel_name_to_outputprev_node_namelayer_configr   r.   r/   r!   is_functional_modelis_parent_functional_modelinput_layerinbound_nodeinput_layer_nameinbound_node_namer	   r   layer_names
last_layerlast_layer_nameoutput_nodes                         r   _update_dictsrD      s   2 ??8,LH%011Z)9)9&)ABI##N3L $$_5M&{3M|=> "&m!4!&9),\=)I 	D%K+I{C ,Za I2C./	D 
$,? &j-2B12EF&< A% 	
<>A+>NO	
% #1o'	;?.<*+}(7FLMU|IuQx8MM*5Y'!%%h/3
$..266v>"9o>+6-Y'3^DD Ns   0Fc                    i }i }t               }d}t        |       D ]'  \  }}t        |      rt        |||||      \  }}}&|j	                  d      }t        ||j	                  d            }|j                  j                         }	||	_        |j	                  d      4|j	                  d      j                  d      }
|
|	j                  d   _        |j	                  d      }d}d}t        |t              r%d|v r!|j	                  d      j	                  d      }n||}|5	 t        j                  |      }|j                   |	j                  d   _        n|d	}|rt&        j)                  d
|       |j	                  d      gt+        |      D ]X  \  }}}t        ||      }|j	                  ||g      }|t-        |      k  r||   n|d   }|	j.                  j1                  |       Z n||	j.                  j1                  |       ||v r*|	j.                  j1                  |j	                  |             |	j                  }* |S # t$        $ r d	}Y w xY w)a  Returns a GraphDef representation of the Keras model in a dict form.

    Note that it only supports models that implemented to_json().

    Args:
      keras_layer: A dict from Keras model.to_json().

    Returns:
      A GraphDef representation of the layers in the model.
    Nr   r
   
class_nameasciikeras_classdtypeFTz8Unsupported dtype value in graph model config (json):
%sr!   r1   )r   r   r   rD   r   r   nodeaddr
   encodeattrsr   r%   r   as_dtypeas_datatype_enumtype	TypeErrorloggerwarningr,   r&   inputr'   )r   input_to_layerr7   gr8   r   r   r9   r   node_defkeras_cls_namedtype_or_policyrI   has_unsupported_valuetf_dtyper
   sizeindexinbound_nameinbound_node_names
input_names                        r   keras_model_to_graph_defrb      s    N
A N)+6 W'
EU
 $	$ yy* \-=-=f-EF	66::<!99\"."YY|4;;GDN-;HMM-(*&**73 %
 ot,_1L#''155f=E(#E-!??51.6.G.Gg&+ ($(! 
 NNK 99_%1%7%> 2!dE+J=
 &:%=%= <.&" s#566 'u-+B/ 
 %%j1122 'NN!!.1&NN!!."4"4Y"?@!oW'r Ha  -(,%-s   %3I		IIN)__doc__"tensorboard.compat.proto.graph_pb2r   "tensorboard.compat.tensorflow_stubr   tensorboard.utilr   
get_loggerrS   r   r   r   r   r,   rD   rb   r   r   r   <module>rh      sN    8 8 5 ' 
			 10 	9(.FERlr   