






"""simple docstring"""







import argparse
import os

import align
import numpy as np
import requests
import tensorflow as tf
import torch
from PIL import Image
from tokenizer import Tokenizer

from transformers import (
    AlignConfig,
    AlignModel,
    AlignProcessor,
    BertConfig,
    BertTokenizer,
    EfficientNetConfig,
    EfficientNetImageProcessor,
)
from transformers.utils import logging


logging.set_verbosity_info()
__a							:						Optional[Any]   							=			logging.get_logger(__name__)





def 							SCREAMING_SNAKE_CASE							(   lowerCamelCase_):
					a__ 							=	tf.image.resize(lowerCamelCase_			,  (346, 346))
					a__ 							=	tf.image.crop_to_bounding_box(lowerCamelCase_			,  (346 - 289) // 2			,  (346 - 289) // 2			,  289			,  289)
					return image





def 							SCREAMING_SNAKE_CASE							(   ):
					a__ 							=	EfficientNetConfig.from_pretrained('''google/efficientnet-b7''')
					a__ 							=	289
					a__ 							=	640
					a__ 							=	{'''0''': '''LABEL_0''', '''1''': '''LABEL_1'''}
					a__ 							=	{'''LABEL_0''': 0, '''LABEL_1''': 1}
					a__ 							=	[]

					a__ 							=	BertConfig()
					a__ 							=	AlignConfig.from_text_vision_configs(
					    text_config=lowerCamelCase_			,  vision_config=lowerCamelCase_			,  projection_dim=640)
					return config





def 							SCREAMING_SNAKE_CASE							(   ):
					a__ 							=	'''http://images.cocodataset.org/val2017/000000039769.jpg'''
					a__ 							=	Image.open(requests.get(lowerCamelCase_			,  stream=lowerCamelCase_).raw)
					return im





def 							SCREAMING_SNAKE_CASE							(   ):
					a__ 							=	EfficientNetImageProcessor(
					    do_center_crop=lowerCamelCase_			,  rescale_factor=1 / 127.5			,  rescale_offset=lowerCamelCase_			,  do_normalize=lowerCamelCase_			,  include_top=lowerCamelCase_			,  resample=Image.BILINEAR			,  )
					a__ 							=	BertTokenizer.from_pretrained('''bert-base-uncased''')
					a__ 							=	64
					a__ 							=	AlignProcessor(image_processor=lowerCamelCase_			,  tokenizer=lowerCamelCase_)
					return processor





def 							SCREAMING_SNAKE_CASE							(   lowerCamelCase_):
					# EfficientNet image encoder
					a__ 							=	[v.split('''_''')[0].split('''block''')[1] for v in original_param_names if v.startswith('''block''')]
					a__ 							=	list(set(lowerCamelCase_))
					a__ 							=	sorted(lowerCamelCase_)
					a__ 							=	len(lowerCamelCase_)
					a__ 							=	{b: str(lowerCamelCase_) for b, i in zip(lowerCamelCase_			,  range(lowerCamelCase_))}

					a__ 							=	[]
					rename_keys.append(('''stem_conv/kernel:0''', '''embeddings.convolution.weight'''))
					rename_keys.append(('''stem_bn/gamma:0''', '''embeddings.batchnorm.weight'''))
					rename_keys.append(('''stem_bn/beta:0''', '''embeddings.batchnorm.bias'''))
					rename_keys.append(('''stem_bn/moving_mean:0''', '''embeddings.batchnorm.running_mean'''))
					rename_keys.append(('''stem_bn/moving_variance:0''', '''embeddings.batchnorm.running_var'''))

					for b in block_names:
										a__ 							=	block_name_mapping[b]
										rename_keys.append((f'block{b}_expand_conv/kernel:0', f'encoder.blocks.{hf_b}.expansion.expand_conv.weight'))
										rename_keys.append((f'block{b}_expand_bn/gamma:0', f'encoder.blocks.{hf_b}.expansion.expand_bn.weight'))
										rename_keys.append((f'block{b}_expand_bn/beta:0', f'encoder.blocks.{hf_b}.expansion.expand_bn.bias'))
										rename_keys.append(
										    (f'block{b}_expand_bn/moving_mean:0', f'encoder.blocks.{hf_b}.expansion.expand_bn.running_mean'))
										rename_keys.append(
										    (f'block{b}_expand_bn/moving_variance:0', f'encoder.blocks.{hf_b}.expansion.expand_bn.running_var'))
										rename_keys.append(
										    (f'block{b}_dwconv/depthwise_kernel:0', f'encoder.blocks.{hf_b}.depthwise_conv.depthwise_conv.weight'))
										rename_keys.append((f'block{b}_bn/gamma:0', f'encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.weight'))
										rename_keys.append((f'block{b}_bn/beta:0', f'encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.bias'))
										rename_keys.append(
										    (f'block{b}_bn/moving_mean:0', f'encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.running_mean'))
										rename_keys.append(
										    (f'block{b}_bn/moving_variance:0', f'encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.running_var'))

										rename_keys.append((f'block{b}_se_reduce/kernel:0', f'encoder.blocks.{hf_b}.squeeze_excite.reduce.weight'))
										rename_keys.append((f'block{b}_se_reduce/bias:0', f'encoder.blocks.{hf_b}.squeeze_excite.reduce.bias'))
										rename_keys.append((f'block{b}_se_expand/kernel:0', f'encoder.blocks.{hf_b}.squeeze_excite.expand.weight'))
										rename_keys.append((f'block{b}_se_expand/bias:0', f'encoder.blocks.{hf_b}.squeeze_excite.expand.bias'))
										rename_keys.append(
										    (f'block{b}_project_conv/kernel:0', f'encoder.blocks.{hf_b}.projection.project_conv.weight'))
										rename_keys.append((f'block{b}_project_bn/gamma:0', f'encoder.blocks.{hf_b}.projection.project_bn.weight'))
										rename_keys.append((f'block{b}_project_bn/beta:0', f'encoder.blocks.{hf_b}.projection.project_bn.bias'))
										rename_keys.append(
										    (f'block{b}_project_bn/moving_mean:0', f'encoder.blocks.{hf_b}.projection.project_bn.running_mean'))
										rename_keys.append(
										    (f'block{b}_project_bn/moving_variance:0', f'encoder.blocks.{hf_b}.projection.project_bn.running_var'))

					a__ 							=	{}
					for item in rename_keys:
										if item[0] in original_param_names:
															a__ 							=	'''vision_model.''' + item[1]

    # BERT text encoder
					a__ 							=	[]
					a__ 							=	'''tf_bert_model/bert'''
					a__ 							=	'''text_model'''
					for i in range(12):
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/self/query/kernel:0',
										        f'{new}.encoder.layer.{i}.attention.self.query.weight',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/self/query/bias:0',
										        f'{new}.encoder.layer.{i}.attention.self.query.bias',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/self/key/kernel:0',
										        f'{new}.encoder.layer.{i}.attention.self.key.weight',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/self/key/bias:0',
										        f'{new}.encoder.layer.{i}.attention.self.key.bias',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/self/value/kernel:0',
										        f'{new}.encoder.layer.{i}.attention.self.value.weight',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/self/value/bias:0',
										        f'{new}.encoder.layer.{i}.attention.self.value.bias',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/output/dense/kernel:0',
										        f'{new}.encoder.layer.{i}.attention.output.dense.weight',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/output/dense/bias:0',
										        f'{new}.encoder.layer.{i}.attention.output.dense.bias',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/output/LayerNorm/gamma:0',
										        f'{new}.encoder.layer.{i}.attention.output.LayerNorm.weight',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/attention/output/LayerNorm/beta:0',
										        f'{new}.encoder.layer.{i}.attention.output.LayerNorm.bias',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/intermediate/dense/kernel:0',
										        f'{new}.encoder.layer.{i}.intermediate.dense.weight',
										    ))
										rename_keys.append(
										    (
										        f'{old}/encoder/layer_._{i}/intermediate/dense/bias:0',
										        f'{new}.encoder.layer.{i}.intermediate.dense.bias',
										    ))
										rename_keys.append(
										    (f'{old}/encoder/layer_._{i}/output/dense/kernel:0', f'{new}.encoder.layer.{i}.output.dense.weight'))
										rename_keys.append(
										    (f'{old}/encoder/layer_._{i}/output/dense/bias:0', f'{new}.encoder.layer.{i}.output.dense.bias'))
										rename_keys.append(
										    (f'{old}/encoder/layer_._{i}/output/LayerNorm/gamma:0', f'{new}.encoder.layer.{i}.output.LayerNorm.weight'))
										rename_keys.append(
										    (f'{old}/encoder/layer_._{i}/output/LayerNorm/beta:0', f'{new}.encoder.layer.{i}.output.LayerNorm.bias'))

					rename_keys.append((f'{old}/embeddings/word_embeddings/weight:0', f'{new}.embeddings.word_embeddings.weight'))
					rename_keys.append(
					    (f'{old}/embeddings/position_embeddings/embeddings:0', f'{new}.embeddings.position_embeddings.weight'))
					rename_keys.append(
					    (f'{old}/embeddings/token_type_embeddings/embeddings:0', f'{new}.embeddings.token_type_embeddings.weight'))
					rename_keys.append((f'{old}/embeddings/LayerNorm/gamma:0', f'{new}.embeddings.LayerNorm.weight'))
					rename_keys.append((f'{old}/embeddings/LayerNorm/beta:0', f'{new}.embeddings.LayerNorm.bias'))

					rename_keys.append((f'{old}/pooler/dense/kernel:0', f'{new}.pooler.dense.weight'))
					rename_keys.append((f'{old}/pooler/dense/bias:0', f'{new}.pooler.dense.bias'))
					rename_keys.append(('''dense/kernel:0''', '''text_projection.weight'''))
					rename_keys.append(('''dense/bias:0''', '''text_projection.bias'''))
					rename_keys.append(('''dense/bias:0''', '''text_projection.bias'''))
					rename_keys.append(('''temperature:0''', '''temperature'''))

					for item in rename_keys:
										if item[0] in original_param_names:
															a__ 							=	item[1]
					return key_mapping





def 							SCREAMING_SNAKE_CASE							(   lowerCamelCase_			,  lowerCamelCase_			,  lowerCamelCase_):
					list(hf_params.keys())

					for key, value in tf_params.items():
										if key not in key_mapping:
															continue

										a__ 							=	key_mapping[key]
										if "_conv" in key and "kernel" in key:
															a__ 							=	torch.from_numpy(lowerCamelCase_).permute(3			,  2			,  0			,  1)
										elif "embeddings" in key:
															a__ 							=	torch.from_numpy(lowerCamelCase_)
										elif "depthwise_kernel" in key:
															a__ 							=	torch.from_numpy(lowerCamelCase_).permute(2			,  3			,  0			,  1)
										elif "kernel" in key:
															a__ 							=	torch.from_numpy(np.transpose(lowerCamelCase_))
										elif "temperature" in key:
															a__ 							=	value
										elif "bn/gamma" or "bn/beta" in key:
															a__ 							=	torch.from_numpy(np.transpose(lowerCamelCase_)).squeeze()
										else:
															a__ 							=	torch.from_numpy(lowerCamelCase_)

										# Replace HF parameters with original TF model parameters
										hf_params[hf_key].copy_(lowerCamelCase_)





@torch.no_grad()
def 							SCREAMING_SNAKE_CASE							(   lowerCamelCase_			,  lowerCamelCase_			,  lowerCamelCase_			,  lowerCamelCase_):
					a__ 							=	64
					a__ 							=	Tokenizer(lowerCamelCase_)
					a__ 							=	align.Align('''efficientnet-b7'''			,  '''bert-base'''			,  640			,  lowerCamelCase_			,  tok.get_vocab_size())
					original_model.compile()
					original_model.load_weights(lowerCamelCase_)

					a__ 							=	original_model.trainable_variables
					a__ 							=	original_model.non_trainable_variables
					a__ 							=	{param.name: param.numpy() for param in tf_params}
					for param in tf_non_train_params:
										a__ 							=	param.numpy()
					a__ 							=	list(tf_params.keys())

					# Load HuggingFace model
					a__ 							=	get_align_config()
					a__ 							=	AlignModel(lowerCamelCase_).eval()
					a__ 							=	hf_model.state_dict()

					# Create src-to-dst parameter name mapping dictionary
					print('''Converting parameters...''')
					a__ 							=	rename_keys(lowerCamelCase_)
					replace_params(lowerCamelCase_			,  lowerCamelCase_			,  lowerCamelCase_)

					# Initialize processor
					a__ 							=	get_processor()
					a__ 							=	processor(
					    images=prepare_img()			,  text='''A picture of a cat'''			,  padding='''max_length'''			,  max_length=64			,  return_tensors='''pt''')

					# HF model inference
					hf_model.eval()
					with torch.no_grad():
										a__ 							=	hf_model(**lowerCamelCase_)

					a__ 							=	outputs.image_embeds.detach().numpy()
					a__ 							=	outputs.text_embeds.detach().numpy()

					# Original model inference
					a__ 							=	False
					a__ 							=	EfficientNetImageProcessor(
					    do_center_crop=lowerCamelCase_			,  do_rescale=lowerCamelCase_			,  do_normalize=lowerCamelCase_			,  include_top=lowerCamelCase_			,  resample=Image.BILINEAR			,  )
					a__ 							=	tf_image_processor(images=prepare_img()			,  return_tensors='''tf'''			,  data_format='''channels_last''')['''pixel_values''']
					a__ 							=	tok(tf.constant(['''A picture of a cat''']))

					a__ 							=	original_model.image_encoder(lowerCamelCase_			,  training=lowerCamelCase_)
					a__ 							=	original_model.text_encoder(lowerCamelCase_			,  training=lowerCamelCase_)

					a__ 							=	tf.nn.la_normalize(lowerCamelCase_			,  axis=-1)
					a__ 							=	tf.nn.la_normalize(lowerCamelCase_			,  axis=-1)

					# Check whether original and HF model outputs match  -> np.allclose
					if not np.allclose(lowerCamelCase_			,  lowerCamelCase_			,  atol=1E-3):
										raise ValueError('''The predicted image features are not the same.''')
					if not np.allclose(lowerCamelCase_			,  lowerCamelCase_			,  atol=1E-3):
										raise ValueError('''The predicted text features are not the same.''')
					print('''Model outputs match!''')

					if save_model:
										# Create folder to save model
										if not os.path.isdir(lowerCamelCase_):
															os.mkdir(lowerCamelCase_)
										# Save converted model and image processor
										hf_model.save_pretrained(lowerCamelCase_)
										processor.save_pretrained(lowerCamelCase_)

					if push_to_hub:
										# Push model and image processor to hub
										print('''Pushing converted ALIGN to the hub...''')
										processor.push_to_hub('''align-base''')
										hf_model.push_to_hub('''align-base''')


if __name__ == "__main__":
	__a							:						str   							=			argparse.ArgumentParser()
	# Required parameters
	parser.add_argument(
	    '--checkpoint_path',
	    default='./weights/model-weights',
	    type=str,
	    help='Path to the pretrained TF ALIGN checkpoint.',
	)
	parser.add_argument(
	    '--pytorch_dump_folder_path',
	    default='hf_model',
	    type=str,
	    help='Path to the output PyTorch model directory.',
	)
	parser.add_argument('--save_model', action='store_true', help='Save model to local')
	parser.add_argument('--push_to_hub', action='store_true', help='Push model and image processor to the hub')

	__a							:						List[str]   							=			parser.parse_args()
	convert_align_checkpoint(args.checkpoint_path, args.pytorch_dump_folder_path, args.save_model, args.push_to_hub)










"""simple docstring"""







# Lint as: python3
import sys
from collections.abc import Mapping
from typing import TYPE_CHECKING

import numpy as np
import pyarrow as pa

from .. import config
from ..utils.py_utils import map_nested
from .formatting import TensorFormatter


if TYPE_CHECKING:
	import tensorflow as tf







class 							_SCREAMING_SNAKE_CASE    (	TensorFormatter[Mapping, 'tf.Tensor', Mapping]				):





							"""simple docstring"""





							def __init__( self:  Union[str, Any]					,		__A:  Union[str, Any]=None					,		**__A:  Union[str, Any]     ):

												'''simple docstring'''

												super().__init__(features=__A     )
												a__ 							=	tf_tensor_kwargs
												import tensorflow as tf  # noqa: import tf at initialization




							def 			lowercase		( self:  Optional[int]					,		__A:  List[Any]     ):

												'''simple docstring'''

												import tensorflow as tf

												if isinstance(__A					,		__A     ) and column:
																	if all(
																	    isinstance(__A					,		tf.Tensor     ) and x.shape == column[0].shape and x.dtype == column[0].dtype for x in column     ):
																						return tf.stack(__A     )
																	elif all(
																	    isinstance(__A					,		(tf.Tensor, tf.RaggedTensor)     ) and x.ndim == 1 and x.dtype == column[0].dtype
																	    for x in column     ):
																						# only rag 1-D tensors, otherwise some dimensions become ragged even though they were consolidated
																						return tf.ragged.stack(__A     )

												return column




							def 			lowercase		( self:  int					,		__A:  Optional[Any]     ):

												'''simple docstring'''

												import tensorflow as tf

												if value is None:
																	return value

												a__ 							=	{}

												if isinstance(__A					,		(np.number, np.ndarray)     ) and np.issubdtype(value.dtype					,		np.integer     ):
																	a__ 							=	{'''dtype''': tf.intaa}
												elif isinstance(__A					,		(np.number, np.ndarray)     ) and np.issubdtype(value.dtype					,		np.floating     ):
																	a__ 							=	{'''dtype''': tf.floataa}
												elif config.PIL_AVAILABLE and "PIL" in sys.modules:
																	import PIL.Image

																	if isinstance(__A					,		PIL.Image.Image     ):
																						a__ 							=	np.asarray(__A     )

												return tf.convert_to_tensor(__A					,		**{**default_dtype, **self.tf_tensor_kwargs}     )




							def 			lowercase		( self:  List[Any]					,		__A:  str     ):

												'''simple docstring'''

												import tensorflow as tf

												# support for torch, tf, jax etc.
												if config.TORCH_AVAILABLE and "torch" in sys.modules:
																	import torch

																	if isinstance(__A					,		torch.Tensor     ):
																						return self._tensorize(data_struct.detach().cpu().numpy()[()]     )
												if hasattr(__A					,		'''__array__'''     ) and not isinstance(__A					,		tf.Tensor     ):
																	a__ 							=	data_struct.__array__()
												# support for nested types like struct of list of struct
												if isinstance(__A					,		np.ndarray     ):
																	if data_struct.dtype == object:  # tf tensors cannot be instantied from an array of objects
																						return self._consolidate([self.recursive_tensorize(__A     ) for substruct in data_struct]     )
												elif isinstance(__A					,		(list, tuple)     ):
																	return self._consolidate([self.recursive_tensorize(__A     ) for substruct in data_struct]     )
												return self._tensorize(__A     )




							def 			lowercase		( self:  int					,		__A:  dict     ):

												'''simple docstring'''

												return map_nested(self._recursive_tensorize					,		__A					,		map_list=__A     )




							def 			lowercase		( self:  Tuple					,		__A:  pa.Table     ):

												'''simple docstring'''

												a__ 							=	self.numpy_arrow_extractor().extract_row(__A     )
												a__ 							=	self.python_features_decoder.decode_row(__A     )
												return self.recursive_tensorize(__A     )




							def 			lowercase		( self:  Dict					,		__A:  pa.Table     ):

												'''simple docstring'''

												a__ 							=	self.numpy_arrow_extractor().extract_column(__A     )
												a__ 							=	self.python_features_decoder.decode_column(__A					,		pa_table.column_names[0]     )
												a__ 							=	self.recursive_tensorize(__A     )
												a__ 							=	self._consolidate(__A     )
												return column





							def 			lowercase		( self:  Tuple					,		__A:  pa.Table     ):

												'''simple docstring'''

												a__ 							=	self.numpy_arrow_extractor().extract_batch(__A     )
												a__ 							=	self.python_features_decoder.decode_batch(__A     )
												a__ 							=	self.recursive_tensorize(__A     )
												for column_name in batch:
																	a__ 							=	self._consolidate(batch[column_name]     )
												return batch


