


import argparse
import json

import gdown
import numpy as np
import torch
from huggingface_hub import hf_hub_download

from transformers import TimesformerConfig, TimesformerForVideoClassification, VideoMAEImageProcessor







def   lowerCamelCase(      a__):
				_SCREAMING_SNAKE_CASE	     =TimesformerConfig()

				if "large" in model_name:
								_SCREAMING_SNAKE_CASE	     =96

				if "hr" in model_name:
								_SCREAMING_SNAKE_CASE	     =16
								_SCREAMING_SNAKE_CASE	     =448

				_SCREAMING_SNAKE_CASE	     ="huggingface/label-files"
				if "k400" in model_name:
								_SCREAMING_SNAKE_CASE	     =400
								_SCREAMING_SNAKE_CASE	     ="kinetics400-id2label.json"
				elif "k600" in model_name:
								_SCREAMING_SNAKE_CASE	     =600
								_SCREAMING_SNAKE_CASE	     ="kinetics600-id2label.json"
				elif "ssv2" in model_name:
								_SCREAMING_SNAKE_CASE	     =174
								_SCREAMING_SNAKE_CASE	     ="something-something-v2-id2label.json"
				else:
								raise ValueError('''Model name should either contain \'k400\', \'k600\' or \'ssv2\'.''')
				_SCREAMING_SNAKE_CASE	     =json.load(open(hf_hub_download(a__		,a__		,repo_type='''dataset''')		,'''r'''))
				_SCREAMING_SNAKE_CASE	     ={int(a__): v for k, v in idalabel.items()}
				_SCREAMING_SNAKE_CASE	     =idalabel
				_SCREAMING_SNAKE_CASE	     ={v: k for k, v in idalabel.items()}

				return config







def   lowerCamelCase(      a__):



				if "encoder." in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''encoder.'''		,'''''')
				if "cls_token" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''cls_token'''		,'''timesformer.embeddings.cls_token''')
				if "pos_embed" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''pos_embed'''		,'''timesformer.embeddings.position_embeddings''')
				if "time_embed" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''time_embed'''		,'''timesformer.embeddings.time_embeddings''')
				if "patch_embed.proj" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''patch_embed.proj'''		,'''timesformer.embeddings.patch_embeddings.projection''')
				if "patch_embed.norm" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''patch_embed.norm'''		,'''timesformer.embeddings.norm''')
				if "blocks" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''blocks'''		,'''timesformer.encoder.layer''')
				if "attn.proj" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''attn.proj'''		,'''attention.output.dense''')
				if "attn" in name and "bias" not in name and "temporal" not in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''attn'''		,'''attention.self''')
				if "attn" in name and "temporal" not in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''attn'''		,'''attention.attention''')
				if "temporal_norm1" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''temporal_norm1'''		,'''temporal_layernorm''')
				if "temporal_attn.proj" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''temporal_attn'''		,'''temporal_attention.output.dense''')
				if "temporal_fc" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''temporal_fc'''		,'''temporal_dense''')
				if "norm1" in name and "temporal" not in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''norm1'''		,'''layernorm_before''')
				if "norm2" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''norm2'''		,'''layernorm_after''')
				if "mlp.fc1" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''mlp.fc1'''		,'''intermediate.dense''')
				if "mlp.fc2" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''mlp.fc2'''		,'''output.dense''')
				if "norm.weight" in name and "fc" not in name and "temporal" not in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''norm.weight'''		,'''timesformer.layernorm.weight''')
				if "norm.bias" in name and "fc" not in name and "temporal" not in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''norm.bias'''		,'''timesformer.layernorm.bias''')
				if "head" in name:
								_SCREAMING_SNAKE_CASE	     =name.replace('''head'''		,'''classifier''')

				return name







def   lowerCamelCase(      a__		,a__):



				for key in orig_state_dict.copy().keys():
								_SCREAMING_SNAKE_CASE	     =orig_state_dict.pop(a__)

								if key.startswith('''model.'''):
												_SCREAMING_SNAKE_CASE	     =key.replace('''model.'''		,'''''')

								if "qkv" in key:
												_SCREAMING_SNAKE_CASE	     =key.split('''.''')
												_SCREAMING_SNAKE_CASE	     =int(key_split[1])
												_SCREAMING_SNAKE_CASE	     ="timesformer.encoder.layer."
												if "temporal" in key:
																_SCREAMING_SNAKE_CASE	     =".temporal_attention.attention.qkv."
												else:
																_SCREAMING_SNAKE_CASE	     =".attention.attention.qkv."
												if "weight" in key:
																_SCREAMING_SNAKE_CASE	     =val
												else:
																_SCREAMING_SNAKE_CASE	     =val
								else:
												_SCREAMING_SNAKE_CASE	     =val

				return orig_state_dict







def   lowerCamelCase(      ):
				_SCREAMING_SNAKE_CASE	     =hf_hub_download(
				    repo_id='''hf-internal-testing/spaghetti-video'''		,filename='''eating_spaghetti.npy'''		,repo_type='''dataset''')
				_SCREAMING_SNAKE_CASE	     =np.load(a__)
				return list(a__)







def   lowerCamelCase(      a__		,a__		,a__		,a__):
				_SCREAMING_SNAKE_CASE	     =get_timesformer_config(a__)

				_SCREAMING_SNAKE_CASE	     =TimesformerForVideoClassification(a__)

				# download original checkpoint, hosted on Google Drive
				_SCREAMING_SNAKE_CASE	     ="pytorch_model.bin"
				gdown.cached_download(a__		,a__		,quiet=a__)
				_SCREAMING_SNAKE_CASE	     =torch.load(a__		,map_location='''cpu''')
				if "model" in files:
								_SCREAMING_SNAKE_CASE	     =files["model"]
				elif "module" in files:
								_SCREAMING_SNAKE_CASE	     =files["module"]
				else:
								_SCREAMING_SNAKE_CASE	     =files["model_state"]
				_SCREAMING_SNAKE_CASE	     =convert_state_dict(a__		,a__)

				model.load_state_dict(a__)
				model.eval()

				# verify model on basic input
				_SCREAMING_SNAKE_CASE	     =VideoMAEImageProcessor(image_mean=[0.5, 0.5, 0.5]		,image_std=[0.5, 0.5, 0.5])
				_SCREAMING_SNAKE_CASE	     =prepare_video()
				_SCREAMING_SNAKE_CASE	     =image_processor(video[:8]		,return_tensors='''pt''')

				_SCREAMING_SNAKE_CASE	     =model(**a__)
				_SCREAMING_SNAKE_CASE	     =outputs.logits

				_SCREAMING_SNAKE_CASE	     =[
				    # Kinetics-400 checkpoints (hr = high resolution input of 448px instead of 224px)
				    "timesformer-base-finetuned-k400",
				    "timesformer-large-finetuned-k400",
				    "timesformer-hr-finetuned-k400",
				    # Kinetics-600 checkpoints (hr = high resolution input of 448px instead of 224px)
				    "timesformer-base-finetuned-k600",
				    "timesformer-large-finetuned-k600",
				    "timesformer-hr-finetuned-k600",
				    # Something-Something-v2 checkpoints (hr = high resolution input of 448px instead of 224px)
				    "timesformer-base-finetuned-ssv2",
				    "timesformer-large-finetuned-ssv2",
				    "timesformer-hr-finetuned-ssv2",
				]

				# NOTE: logits were tested with image_mean and image_std equal to [0.5, 0.5, 0.5] and [0.5, 0.5, 0.5]
				if model_name == "timesformer-base-finetuned-k400":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 400])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([-0.3016, -0.7713, -0.4205])
				elif model_name == "timesformer-base-finetuned-k600":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 600])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([-0.7267, -0.7466, 3.2404])
				elif model_name == "timesformer-base-finetuned-ssv2":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 174])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([-0.9059, 0.6433, -3.1457])
				elif model_name == "timesformer-large-finetuned-k400":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 400])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([0, 0, 0])
				elif model_name == "timesformer-large-finetuned-k600":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 600])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([0, 0, 0])
				elif model_name == "timesformer-large-finetuned-ssv2":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 174])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([0, 0, 0])
				elif model_name == "timesformer-hr-finetuned-k400":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 400])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([-0.9617, -3.7311, -3.7708])
				elif model_name == "timesformer-hr-finetuned-k600":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 600])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([2.5273, 0.7127, 1.8848])
				elif model_name == "timesformer-hr-finetuned-ssv2":
								_SCREAMING_SNAKE_CASE	     =torch.Size([1, 174])
								_SCREAMING_SNAKE_CASE	     =torch.tensor([-3.6756, -0.7513, 0.7180])
				else:
								raise ValueError(f"Model name not supported. Should be one of {model_names}")

				# verify logits
				assert logits.shape == expected_shape
				assert torch.allclose(logits[0, :3]		,a__		,atol=1e-4)
				print('''Logits ok!''')

				if pytorch_dump_folder_path is not None:
								print(f"Saving model and image processor to {pytorch_dump_folder_path}")
								image_processor.save_pretrained(a__)
								model.save_pretrained(a__)

				if push_to_hub:
								print('''Pushing to the hub...''')
								model.push_to_hub(f"fcakyon/{model_name}")


if __name__ == "__main__":
							snake_case_  :	Dict							  =							argparse.ArgumentParser()
							# Required parameters
							parser.add_argument(
							    '''--checkpoint_url''',
							    default='''https://drive.google.com/u/1/uc?id=17yvuYp9L4mn-HpIcK5Zo6K3UoOy1kA5l&export=download''',
							    type=str,
							    help=(
							        '''URL of the original PyTorch checkpoint (on Google Drive) you\'d like to convert. Should be a direct'''
							        ''' download link.'''
							    ),
							)
							parser.add_argument(
							    '''--pytorch_dump_folder_path''',
							    default='''''',
							    type=str,
							    help='''Path to the output PyTorch model directory.''',
							)
							parser.add_argument('''--model_name''', default='''timesformer-base-finetuned-k400''', type=str, help='''Name of the model.''')
							parser.add_argument(
							    '''--push_to_hub''', action='''store_true''', help='''Whether or not to push the converted model to the 🤗 hub.'''
							)

							snake_case_  :	Union[str, Any]							  =							parser.parse_args()
							convert_timesformer_checkpoint(
							    args.checkpoint_url, args.pytorch_dump_folder_path, args.model_name, args.push_to_hub
							)







"""simple docstring"""







import unittest

import numpy as np

from transformers.testing_utils import require_torch, require_vision
from transformers.utils import is_torch_available, is_vision_available

from ...test_image_processing_common import ImageProcessingSavingTestMixin


if is_torch_available():
			import torch

if is_vision_available():
			from PIL import Image

			from transformers import CLIPImageProcessor


class     __UpperCAmelCase(   unittest.TestCase							):




						"""simple docstring"""




						def __init__(   self       ,  snake_case__       ,  snake_case__=7       ,  snake_case__=3       ,  snake_case__=18       ,  snake_case__=30       ,  snake_case__=400       ,  snake_case__=True       ,  snake_case__=None       ,  snake_case__=True       ,  snake_case__=None       ,  snake_case__=True       ,  snake_case__=[0.48_14_54_66, 0.4_57_82_75, 0.40_82_10_73]       ,  snake_case__=[0.26_86_29_54, 0.26_13_02_58, 0.27_57_77_11]       ,  snake_case__=True       ,  ):
												'''simple docstring'''
												lowercase__				:      int=       size if size is not None else {"shortest_edge": 20}
												lowercase__				:      int=       crop_size if crop_size is not None else {"height": 18, "width": 18}
												lowercase__				:      Union[str, Any]=       parent
												lowercase__				:      Optional[Any]=       batch_size
												lowercase__				:      List[str]=       num_channels
												lowercase__				:      str=       image_size
												lowercase__				:      Optional[int]=       min_resolution
												lowercase__				:      Union[str, Any]=       max_resolution
												lowercase__				:      List[Any]=       do_resize
												lowercase__				:      Any=       size
												lowercase__				:      Optional[Any]=       do_center_crop
												lowercase__				:      List[str]=       crop_size
												lowercase__				:      List[Any]=       do_normalize
												lowercase__				:      Optional[Any]=       image_mean
												lowercase__				:      Dict=       image_std
												lowercase__				:      Dict=       do_convert_rgb




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												return {
												    "do_resize": self.do_resize,
												    "size": self.size,
												    "do_center_crop": self.do_center_crop,
												    "crop_size": self.crop_size,
												    "do_normalize": self.do_normalize,
												    "image_mean": self.image_mean,
												    "image_std": self.image_std,
												    "do_convert_rgb": self.do_convert_rgb,
												}




						def 		UpperCAmelCase_       (   self       ,  snake_case__=False       ,  snake_case__=False       ,  snake_case__=False			):
												'''simple docstring'''
												assert not (numpify and torchify), "You cannot specify both numpy and PyTorch tensors at the same time"

												if equal_resolution:
																		lowercase__				:      Optional[Any]=       []
																		for i in range(self.batch_size			):
																								image_inputs.append(
																								    np.random.randint(
																								        255       ,  size=(self.num_channels, self.max_resolution, self.max_resolution)       ,  dtype=np.uinta			)			)
												else:
																		lowercase__				:      Optional[Any]=       []
																		for i in range(self.batch_size			):
																								lowercase__,	lowercase__				:      str=       np.random.choice(np.arange(self.min_resolution       ,  self.max_resolution			)       ,  2			)
																								image_inputs.append(np.random.randint(255       ,  size=(self.num_channels, width, height)       ,  dtype=np.uinta			)			)

												if not numpify and not torchify:
																		# PIL expects the channel dimension as last dimension
																		lowercase__				:      Dict=       [Image.fromarray(np.moveaxis(snake_case__       ,  0       ,  -1			)			) for x in image_inputs]

												if torchify:
																		lowercase__				:      Tuple=       [torch.from_numpy(snake_case__			) for x in image_inputs]

												return image_inputs


@require_torch
@require_vision
class     __UpperCAmelCase(   SCREAMING_SNAKE_CASE__  ,  unittest.TestCase							):




						"""simple docstring"""




						__lowerCamelCase				       =					CLIPImageProcessor if is_vision_available() else None




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												lowercase__				:      List[Any]=       CLIPImageProcessingTester(self			)




						@property
						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												return self.image_processor_tester.prepare_image_processor_dict()




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												lowercase__				:      Dict=       self.image_processing_class(**self.image_processor_dict			)
												self.assertTrue(hasattr(snake_case__       ,  "do_resize"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "size"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "do_center_crop"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "center_crop"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "do_normalize"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "image_mean"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "image_std"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "do_convert_rgb"			)			)




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												lowercase__				:      List[str]=       self.image_processing_class.from_dict(self.image_processor_dict			)
												self.assertEqual(image_processor.size       ,  {"shortest_edge": 20}			)
												self.assertEqual(image_processor.crop_size       ,  {"height": 18, "width": 18}			)

												lowercase__				:      Dict=       self.image_processing_class.from_dict(self.image_processor_dict       ,  size=42       ,  crop_size=84			)
												self.assertEqual(image_processor.size       ,  {"shortest_edge": 42}			)
												self.assertEqual(image_processor.crop_size       ,  {"height": 84, "width": 84}			)




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												pass




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												# Initialize image_processing
												lowercase__				:      int=       self.image_processing_class(**self.image_processor_dict			)
												# create random PIL images
												lowercase__				:      Optional[Any]=       self.image_processor_tester.prepare_inputs(equal_resolution=snake_case__			)
												for image in image_inputs:
																		self.assertIsInstance(snake_case__       ,  Image.Image			)

												# Test not batched input
												lowercase__				:      List[str]=       image_processing(image_inputs[0]       ,  return_tensors="pt"			).pixel_values
												self.assertEqual(
												    encoded_images.shape       ,  (
												        1,
												        self.image_processor_tester.num_channels,
												        self.image_processor_tester.crop_size["height"],
												        self.image_processor_tester.crop_size["width"],
												    )       ,  )

												# Test batched
												lowercase__				:      Dict=       image_processing(snake_case__       ,  return_tensors="pt"			).pixel_values
												self.assertEqual(
												    encoded_images.shape       ,  (
												        self.image_processor_tester.batch_size,
												        self.image_processor_tester.num_channels,
												        self.image_processor_tester.crop_size["height"],
												        self.image_processor_tester.crop_size["width"],
												    )       ,  )




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												# Initialize image_processing
												lowercase__				:      Any=       self.image_processing_class(**self.image_processor_dict			)
												# create random numpy tensors
												lowercase__				:      Tuple=       self.image_processor_tester.prepare_inputs(equal_resolution=snake_case__       ,  numpify=snake_case__			)
												for image in image_inputs:
																		self.assertIsInstance(snake_case__       ,  np.ndarray			)

												# Test not batched input
												lowercase__				:      Dict=       image_processing(image_inputs[0]       ,  return_tensors="pt"			).pixel_values
												self.assertEqual(
												    encoded_images.shape       ,  (
												        1,
												        self.image_processor_tester.num_channels,
												        self.image_processor_tester.crop_size["height"],
												        self.image_processor_tester.crop_size["width"],
												    )       ,  )

												# Test batched
												lowercase__				:      int=       image_processing(snake_case__       ,  return_tensors="pt"			).pixel_values
												self.assertEqual(
												    encoded_images.shape       ,  (
												        self.image_processor_tester.batch_size,
												        self.image_processor_tester.num_channels,
												        self.image_processor_tester.crop_size["height"],
												        self.image_processor_tester.crop_size["width"],
												    )       ,  )




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												# Initialize image_processing
												lowercase__				:      Optional[Any]=       self.image_processing_class(**self.image_processor_dict			)
												# create random PyTorch tensors
												lowercase__				:      Union[str, Any]=       self.image_processor_tester.prepare_inputs(equal_resolution=snake_case__       ,  torchify=snake_case__			)
												for image in image_inputs:
																		self.assertIsInstance(snake_case__       ,  torch.Tensor			)

												# Test not batched input
												lowercase__				:      Any=       image_processing(image_inputs[0]       ,  return_tensors="pt"			).pixel_values
												self.assertEqual(
												    encoded_images.shape       ,  (
												        1,
												        self.image_processor_tester.num_channels,
												        self.image_processor_tester.crop_size["height"],
												        self.image_processor_tester.crop_size["width"],
												    )       ,  )

												# Test batched
												lowercase__				:      Union[str, Any]=       image_processing(snake_case__       ,  return_tensors="pt"			).pixel_values
												self.assertEqual(
												    encoded_images.shape       ,  (
												        self.image_processor_tester.batch_size,
												        self.image_processor_tester.num_channels,
												        self.image_processor_tester.crop_size["height"],
												        self.image_processor_tester.crop_size["width"],
												    )       ,  )


@require_torch
@require_vision
class     __UpperCAmelCase(   SCREAMING_SNAKE_CASE__  ,  unittest.TestCase							):




						"""simple docstring"""




						__lowerCamelCase				       =					CLIPImageProcessor if is_vision_available() else None




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												lowercase__				:      Optional[int]=       CLIPImageProcessingTester(self       ,  num_channels=4			)
												lowercase__				:      Optional[Any]=       3




						@property
						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												return self.image_processor_tester.prepare_image_processor_dict()




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												lowercase__				:      List[str]=       self.image_processing_class(**self.image_processor_dict			)
												self.assertTrue(hasattr(snake_case__       ,  "do_resize"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "size"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "do_center_crop"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "center_crop"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "do_normalize"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "image_mean"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "image_std"			)			)
												self.assertTrue(hasattr(snake_case__       ,  "do_convert_rgb"			)			)




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												pass




						def 		UpperCAmelCase_       (   self			):
												'''simple docstring'''
												# Initialize image_processing
												lowercase__				:      int=       self.image_processing_class(**self.image_processor_dict			)
												# create random PIL images
												lowercase__				:      int=       self.image_processor_tester.prepare_inputs(equal_resolution=snake_case__			)
												for image in image_inputs:
																		self.assertIsInstance(snake_case__       ,  Image.Image			)

												# Test not batched input
												lowercase__				:      Optional[int]=       image_processing(image_inputs[0]       ,  return_tensors="pt"			).pixel_values
												self.assertEqual(
												    encoded_images.shape       ,  (
												        1,
												        self.expected_encoded_image_num_channels,
												        self.image_processor_tester.crop_size["height"],
												        self.image_processor_tester.crop_size["width"],
												    )       ,  )

												# Test batched
												lowercase__				:      Any=       image_processing(snake_case__       ,  return_tensors="pt"			).pixel_values
												self.assertEqual(
												    encoded_images.shape       ,  (
												        self.image_processor_tester.batch_size,
												        self.expected_encoded_image_num_channels,
												        self.image_processor_tester.crop_size["height"],
												        self.image_processor_tester.crop_size["width"],
												    )       ,  )






