import argparse
import re

import requests
import torch

# git clone https://github.com/salesforce/BLIP.git
from models.blip import blip_decoder
from models.blip_itm import blip_itm
from models.blip_vqa import blip_vqa
from PIL import Image
from torchvision import transforms
from torchvision.transforms.functional import InterpolationMode

from transformers import (
    BertTokenizer,
    BlipConfig,
    BlipForConditionalGeneration,
    BlipForImageTextRetrieval,
    BlipForQuestionAnswering,
)


def 	lowerCamelCase					(	UpperCamelCase     :				Optional[int]			,       UpperCamelCase     :				str							)   ->    Optional[int]:
		_lowerCamelCase				   =  'https://storage.googleapis.com/sfr-vision-language-research/BLIP/demo.jpg'
		_lowerCamelCase				   =  Image.open(requests.get(UpperCamelCase			,       stream=UpperCamelCase							).raw							).convert('RGB'							)

		_lowerCamelCase				   =  transforms.Compose(
		    [
		        transforms.Resize((image_size, image_size)			,       interpolation=InterpolationMode.BICUBIC							),
		        transforms.ToTensor(),
		        transforms.Normalize((0.48_145_466, 0.4_578_275, 0.40_821_073)			,       (0.26_862_954, 0.26_130_258, 0.27_577_711)							),
		    ]							)
		_lowerCamelCase				   =  transform(UpperCamelCase							).unsqueeze(0							).to(UpperCamelCase							)
		return image


def 	lowerCamelCase					(	UpperCamelCase     :				List[str]							)   ->    List[Any]:




		if "visual_encoder" in key:
				_lowerCamelCase				   =  re.sub('visual_encoder*'			,       'vision_model.encoder'			,       UpperCamelCase							)
		if "blocks" in key:
				_lowerCamelCase				   =  re.sub(R'blocks'			,       'layers'			,       UpperCamelCase							)
		if "attn" in key:
				_lowerCamelCase				   =  re.sub(R'attn'			,       'self_attn'			,       UpperCamelCase							)
		if "norm1" in key:
				_lowerCamelCase				   =  re.sub(R'norm1'			,       'layer_norm1'			,       UpperCamelCase							)
		if "norm2" in key:
				_lowerCamelCase				   =  re.sub(R'norm2'			,       'layer_norm2'			,       UpperCamelCase							)
		if "encoder.norm" in key:
				_lowerCamelCase				   =  re.sub(R'encoder.norm'			,       'post_layernorm'			,       UpperCamelCase							)
		if "encoder.patch_embed.proj" in key:
				_lowerCamelCase				   =  re.sub(R'encoder.patch_embed.proj'			,       'embeddings.patch_embedding'			,       UpperCamelCase							)

		if "encoder.pos_embed" in key:
				_lowerCamelCase				   =  re.sub(R'encoder.pos_embed'			,       'embeddings.position_embedding'			,       UpperCamelCase							)
		if "encoder.cls_token" in key:
				_lowerCamelCase				   =  re.sub(R'encoder.cls_token'			,       'embeddings.class_embedding'			,       UpperCamelCase							)

		if "self_attn" in key:
				_lowerCamelCase				   =  re.sub(R'self_attn.proj'			,       'self_attn.projection'			,       UpperCamelCase							)

		return key


@torch.no_grad()
def 	lowerCamelCase					(	UpperCamelCase     :				Tuple			,       UpperCamelCase     :				Optional[Any]=None							)   ->    str:




		if config_path is not None:
				_lowerCamelCase				   =  BlipConfig.from_pretrained(UpperCamelCase							)
		else:
				_lowerCamelCase				   =  BlipConfig(projection_dim=5_12			,       text_config={}			,       vision_config={}							)

		_lowerCamelCase				   =  BlipForConditionalGeneration(UpperCamelCase							).eval()

		_lowerCamelCase				   =  'https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_capfilt_large.pth'

		_lowerCamelCase				   =  blip_decoder(pretrained=UpperCamelCase			,       image_size=3_84			,       vit='base'							)
		_lowerCamelCase				   =  pt_model.eval()

		_lowerCamelCase				   =  pt_model.state_dict()
		for key in modified_state_dict.copy():
				_lowerCamelCase				   =  modified_state_dict.pop(UpperCamelCase							)
				_lowerCamelCase				   =  rename_key(UpperCamelCase							)
				_lowerCamelCase				   =  value

		hf_model.load_state_dict(UpperCamelCase							)

		_lowerCamelCase				   =  3_84
		_lowerCamelCase				   =  load_demo_image(image_size=UpperCamelCase			,       device='cpu'							)
		_lowerCamelCase				   =  BertTokenizer.from_pretrained('bert-base-uncased'							)
		_lowerCamelCase				   =  tokenizer(['a picture of']							).input_ids

		_lowerCamelCase				   =  hf_model.generate(UpperCamelCase			,       UpperCamelCase							)

		assert out[0].tolist() == [3_05_22, 10_37, 38_61, 19_97, 10_37, 24_50, 35_64, 20_06, 19_96, 35_09, 20_07, 20_14, 38_99, 1_02]

		_lowerCamelCase				   =  hf_model.generate(UpperCamelCase							)

		assert out[0].tolist() == [3_05_22, 10_37, 24_50, 35_64, 20_06, 19_96, 35_09, 20_07, 20_14, 38_99, 1_02]

		if pytorch_dump_folder_path is not None:
				hf_model.save_pretrained(UpperCamelCase							)

		# model_url = 'https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_vqa.pth'
		_lowerCamelCase				   =  (
		    'https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_vqa_capfilt_large.pth'
		)

		_lowerCamelCase				   =  blip_vqa(pretrained=UpperCamelCase			,       image_size=UpperCamelCase			,       vit='base'							)
		vqa_model.eval()

		_lowerCamelCase				   =  vqa_model.state_dict()
		for key in modified_state_dict.copy():
				_lowerCamelCase				   =  modified_state_dict.pop(UpperCamelCase							)
				_lowerCamelCase				   =  rename_key(UpperCamelCase							)
				_lowerCamelCase				   =  value

		_lowerCamelCase				   =  BlipForQuestionAnswering(UpperCamelCase							)

		hf_vqa_model.load_state_dict(UpperCamelCase							)

		_lowerCamelCase				   =  ['How many dogs are in this image?']
		_lowerCamelCase				   =  tokenizer(UpperCamelCase			,       return_tensors='pt'							).input_ids

		_lowerCamelCase				   =  hf_vqa_model.generate(UpperCamelCase			,       UpperCamelCase							)
		print(tokenizer.decode(answer[0]							)							)

		assert tokenizer.decode(answer[0]							) == "[UNK] 1 [SEP]"
		if pytorch_dump_folder_path is not None:
				hf_vqa_model.save_pretrained(pytorch_dump_folder_path + '_vqa'							)

		_lowerCamelCase				   =  'https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_retrieval_coco.pth'

		_lowerCamelCase				   =  blip_itm(pretrained=UpperCamelCase			,       image_size=UpperCamelCase			,       vit='base'							)
		itm_model.eval()

		_lowerCamelCase				   =  itm_model.state_dict()
		for key in modified_state_dict.copy():
				_lowerCamelCase				   =  modified_state_dict.pop(UpperCamelCase							)
				_lowerCamelCase				   =  rename_key(UpperCamelCase							)
				_lowerCamelCase				   =  value

		_lowerCamelCase				   =  BlipForImageTextRetrieval(UpperCamelCase							)

		_lowerCamelCase				   =  ['A picture of a woman with a dog sitting in a beach']
		_lowerCamelCase				   =  tokenizer(
		    UpperCamelCase			,       return_tensors='pt'			,       padding='max_length'			,       truncation=UpperCamelCase			,       max_length=35			,       ).input_ids

		hf_itm_model.load_state_dict(UpperCamelCase							)
		hf_itm_model.eval()

		_lowerCamelCase				   =  hf_itm_model(UpperCamelCase			,       UpperCamelCase			,       use_itm_head=UpperCamelCase							)
		_lowerCamelCase				   =  hf_itm_model(UpperCamelCase			,       UpperCamelCase			,       use_itm_head=UpperCamelCase							)

		assert out[0].item() == 0.2_110_687_494_277_954
		assert torch.nn.functional.softmax(out_itm[0]			,       dim=1							)[:, 1].item() == 0.45_698_845_386_505_127

		if pytorch_dump_folder_path is not None:
				hf_itm_model.save_pretrained(pytorch_dump_folder_path + '_itm'							)


if __name__ == "__main__":
				A						=			argparse.ArgumentParser()
				parser.add_argument('--pytorch_dump_folder_path', default=None, type=str, help='Path to the output PyTorch model.')
				parser.add_argument('--config_path', default=None, type=str, help='Path to hf config.json of model to convert')
				A						=			parser.parse_args()

				convert_blip_checkpoint(args.checkpoint_path, args.pytorch_dump_folder_path, args.config_path)

"""simple docstring"""

import json
import pathlib
import unittest

import numpy as np

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

from ...test_image_processing_common import ImageProcessingSavingTestMixin, prepare_image_inputs


if is_torch_available():
   import torch

if is_vision_available():
   from PIL import Image

   from transformers import DetaImageProcessor
class   _UpperCAmelCase				(		unittest.TestCase				):




      def __init__(				self ,							lowercase_ ,							lowercase_=7 ,							lowercase_=3 ,							lowercase_=3_0 ,							lowercase_=4_0_0 ,							lowercase_=True ,							lowercase_=None ,							lowercase_=True ,							lowercase_=[0.5, 0.5, 0.5] ,							lowercase_=[0.5, 0.5, 0.5] ,							lowercase_=True ,							lowercase_=1 / 2_5_5 ,							lowercase_=True ,							)    ->       Union[str, Any]:
          # by setting size["longest_edge"] > max_resolution we're effectively not testing this :p
          UpperCAmelCase          =       size if size is not None else {'shortest_edge': 1_8, 'longest_edge': 1_3_3_3}
          UpperCAmelCase          =       parent
          UpperCAmelCase          =       batch_size
          UpperCAmelCase          =       num_channels
          UpperCAmelCase          =       min_resolution
          UpperCAmelCase          =       max_resolution
          UpperCAmelCase          =       do_resize
          UpperCAmelCase          =       size
          UpperCAmelCase          =       do_normalize
          UpperCAmelCase          =       image_mean
          UpperCAmelCase          =       image_std
          UpperCAmelCase          =       do_rescale
          UpperCAmelCase          =       rescale_factor
          UpperCAmelCase          =       do_pad




      def      a_   (				self				)    ->       int:
          return {
              "do_resize": self.do_resize,
              "size": self.size,
              "do_normalize": self.do_normalize,
              "image_mean": self.image_mean,
              "image_std": self.image_std,
              "do_rescale": self.do_rescale,
              "rescale_factor": self.rescale_factor,
              "do_pad": self.do_pad,
          }




      def      a_   (				self ,							lowercase_ ,							lowercase_=False				)    ->       Union[str, Any]:
          if not batched:
              UpperCAmelCase          =       image_inputs[0]
              if isinstance(lowercase_ ,							Image.Image				):
                  UpperCAmelCase      ,				UpperCAmelCase          =       image.size
              else:
                  UpperCAmelCase      ,				UpperCAmelCase          =       image.shape[1], image.shape[2]
              if w < h:
                  UpperCAmelCase          =       int(self.size['shortest_edge'] * h / w				)
                  UpperCAmelCase          =       self.size['shortest_edge']
              elif w > h:
                  UpperCAmelCase          =       self.size['shortest_edge']
                  UpperCAmelCase          =       int(self.size['shortest_edge'] * w / h				)
              else:
                  UpperCAmelCase          =       self.size['shortest_edge']
                  UpperCAmelCase          =       self.size['shortest_edge']

          else:
              UpperCAmelCase          =       []
              for image in image_inputs:
                  UpperCAmelCase      ,				UpperCAmelCase          =       self.get_expected_values([image]				)
                  expected_values.append((expected_height, expected_width)				)
              UpperCAmelCase          =       max(lowercase_ ,							key=lambda lowercase_				: item[0]				)[0]
              UpperCAmelCase          =       max(lowercase_ ,							key=lambda lowercase_				: item[1]				)[1]

          return expected_height, expected_width

@require_torch
@require_vision
class   _UpperCAmelCase				(		SCREAMING_SNAKE_CASE_  ,      unittest.TestCase				):
      __SCREAMING_SNAKE_CASE :				Union[str, Any]				   =						DetaImageProcessor if is_vision_available() else None




      def      a_   (				self				)    ->       List[Any]:
          UpperCAmelCase          =       DetaImageProcessingTester(self				)




      @property
      def      a_   (				self				)    ->       Optional[Any]:
          return self.image_processor_tester.prepare_image_processor_dict()




      def      a_   (				self				)    ->       Dict:
          UpperCAmelCase          =       self.image_processing_class(**self.image_processor_dict				)
          self.assertTrue(hasattr(lowercase_ ,							'image_mean'				)				)
          self.assertTrue(hasattr(lowercase_ ,							'image_std'				)				)
          self.assertTrue(hasattr(lowercase_ ,							'do_normalize'				)				)
          self.assertTrue(hasattr(lowercase_ ,							'do_resize'				)				)
          self.assertTrue(hasattr(lowercase_ ,							'do_rescale'				)				)
          self.assertTrue(hasattr(lowercase_ ,							'do_pad'				)				)
          self.assertTrue(hasattr(lowercase_ ,							'size'				)				)




      def      a_   (				self				)    ->       int:
          UpperCAmelCase          =       self.image_processing_class.from_dict(self.image_processor_dict				)
          self.assertEqual(image_processor.size ,							{'shortest_edge': 1_8, 'longest_edge': 1_3_3_3}				)
          self.assertEqual(image_processor.do_pad ,							lowercase_				)




      def      a_   (				self				)    ->       int:
          pass




      def      a_   (				self				)    ->       Union[str, Any]:
          # Initialize image_processing
          UpperCAmelCase          =       self.image_processing_class(**self.image_processor_dict				)
          # create random PIL images
          UpperCAmelCase          =       prepare_image_inputs(self.image_processor_tester ,							equal_resolution=lowercase_				)
          for image in image_inputs:
              self.assertIsInstance(lowercase_ ,							Image.Image				)

          # Test not batched input
          UpperCAmelCase          =       image_processing(image_inputs[0] ,							return_tensors='pt'				).pixel_values

          UpperCAmelCase      ,				UpperCAmelCase          =       self.image_processor_tester.get_expected_values(lowercase_				)

          self.assertEqual(
              encoded_images.shape ,							(1, self.image_processor_tester.num_channels, expected_height, expected_width) ,							)

          # Test batched
          UpperCAmelCase      ,				UpperCAmelCase          =       self.image_processor_tester.get_expected_values(lowercase_ ,							batched=lowercase_				)

          UpperCAmelCase          =       image_processing(lowercase_ ,							return_tensors='pt'				).pixel_values
          self.assertEqual(
              encoded_images.shape ,							(
                  self.image_processor_tester.batch_size,
                  self.image_processor_tester.num_channels,
                  expected_height,
                  expected_width,
              ) ,							)




      def      a_   (				self				)    ->       Tuple:
          # Initialize image_processing
          UpperCAmelCase          =       self.image_processing_class(**self.image_processor_dict				)
          # create random numpy tensors
          UpperCAmelCase          =       prepare_image_inputs(self.image_processor_tester ,							equal_resolution=lowercase_ ,							numpify=lowercase_				)
          for image in image_inputs:
              self.assertIsInstance(lowercase_ ,							np.ndarray				)

          # Test not batched input
          UpperCAmelCase          =       image_processing(image_inputs[0] ,							return_tensors='pt'				).pixel_values

          UpperCAmelCase      ,				UpperCAmelCase          =       self.image_processor_tester.get_expected_values(lowercase_				)

          self.assertEqual(
              encoded_images.shape ,							(1, self.image_processor_tester.num_channels, expected_height, expected_width) ,							)

          # Test batched
          UpperCAmelCase          =       image_processing(lowercase_ ,							return_tensors='pt'				).pixel_values

          UpperCAmelCase      ,				UpperCAmelCase          =       self.image_processor_tester.get_expected_values(lowercase_ ,							batched=lowercase_				)

          self.assertEqual(
              encoded_images.shape ,							(
                  self.image_processor_tester.batch_size,
                  self.image_processor_tester.num_channels,
                  expected_height,
                  expected_width,
              ) ,							)




      def      a_   (				self				)    ->       Optional[Any]:
          # Initialize image_processing
          UpperCAmelCase          =       self.image_processing_class(**self.image_processor_dict				)
          # create random PyTorch tensors
          UpperCAmelCase          =       prepare_image_inputs(self.image_processor_tester ,							equal_resolution=lowercase_ ,							torchify=lowercase_				)
          for image in image_inputs:
              self.assertIsInstance(lowercase_ ,							torch.Tensor				)

          # Test not batched input
          UpperCAmelCase          =       image_processing(image_inputs[0] ,							return_tensors='pt'				).pixel_values

          UpperCAmelCase      ,				UpperCAmelCase          =       self.image_processor_tester.get_expected_values(lowercase_				)

          self.assertEqual(
              encoded_images.shape ,							(1, self.image_processor_tester.num_channels, expected_height, expected_width) ,							)

          # Test batched
          UpperCAmelCase          =       image_processing(lowercase_ ,							return_tensors='pt'				).pixel_values

          UpperCAmelCase      ,				UpperCAmelCase          =       self.image_processor_tester.get_expected_values(lowercase_ ,							batched=lowercase_				)

          self.assertEqual(
              encoded_images.shape ,							(
                  self.image_processor_tester.batch_size,
                  self.image_processor_tester.num_channels,
                  expected_height,
                  expected_width,
              ) ,							)




      @slow
      def      a_   (				self				)    ->       str:
          # prepare image and target
          UpperCAmelCase          =       Image.open('./tests/fixtures/tests_samples/COCO/000000039769.png'				)
          with open('./tests/fixtures/tests_samples/COCO/coco_annotations.txt' ,							'r'				) as f:
              UpperCAmelCase          =       json.loads(f.read()				)

          UpperCAmelCase          =       {'image_id': 3_9_7_6_9, 'annotations': target}

          # encode them
          UpperCAmelCase          =       DetaImageProcessor()
          UpperCAmelCase          =       image_processing(images=lowercase_ ,							annotations=lowercase_ ,							return_tensors='pt'				)

          # verify pixel values
          UpperCAmelCase          =       torch.Size([1, 3, 8_0_0, 1_0_6_6]				)
          self.assertEqual(encoding['pixel_values'].shape ,							lowercase_				)

          UpperCAmelCase          =       torch.tensor([0.2_7_9_6, 0.3_1_3_8, 0.3_4_8_1]				)
          self.assertTrue(torch.allclose(encoding['pixel_values'][0, 0, 0, :3] ,							lowercase_ ,							atol=1E-4				)				)

          # verify area
          UpperCAmelCase          =       torch.tensor([5_8_8_7.9_6_0_0, 1_1_2_5_0.2_0_6_1, 4_8_9_3_5_3.8_4_3_8, 8_3_7_1_2_2.7_5_0_0, 1_4_7_9_6_7.5_1_5_6, 1_6_5_7_3_2.3_4_3_8]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['area'] ,							lowercase_				)				)
          # verify boxes
          UpperCAmelCase          =       torch.Size([6, 4]				)
          self.assertEqual(encoding['labels'][0]['boxes'].shape ,							lowercase_				)
          UpperCAmelCase          =       torch.tensor([0.5_5_0_3, 0.2_7_6_5, 0.0_6_0_4, 0.2_2_1_5]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['boxes'][0] ,							lowercase_ ,							atol=1E-3				)				)
          # verify image_id
          UpperCAmelCase          =       torch.tensor([3_9_7_6_9]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['image_id'] ,							lowercase_				)				)
          # verify is_crowd
          UpperCAmelCase          =       torch.tensor([0, 0, 0, 0, 0, 0]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['iscrowd'] ,							lowercase_				)				)
          # verify class_labels
          UpperCAmelCase          =       torch.tensor([7_5, 7_5, 6_3, 6_5, 1_7, 1_7]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['class_labels'] ,							lowercase_				)				)
          # verify orig_size
          UpperCAmelCase          =       torch.tensor([4_8_0, 6_4_0]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['orig_size'] ,							lowercase_				)				)
          # verify size
          UpperCAmelCase          =       torch.tensor([8_0_0, 1_0_6_6]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['size'] ,							lowercase_				)				)




      @slow
      def      a_   (				self				)    ->       Any:
          # prepare image, target and masks_path
          UpperCAmelCase          =       Image.open('./tests/fixtures/tests_samples/COCO/000000039769.png'				)
          with open('./tests/fixtures/tests_samples/COCO/coco_panoptic_annotations.txt' ,							'r'				) as f:
              UpperCAmelCase          =       json.loads(f.read()				)

          UpperCAmelCase          =       {'file_name': '000000039769.png', 'image_id': 3_9_7_6_9, 'segments_info': target}

          UpperCAmelCase          =       pathlib.Path('./tests/fixtures/tests_samples/COCO/coco_panoptic'				)

          # encode them
          UpperCAmelCase          =       DetaImageProcessor(format='coco_panoptic'				)
          UpperCAmelCase          =       image_processing(images=lowercase_ ,							annotations=lowercase_ ,							masks_path=lowercase_ ,							return_tensors='pt'				)

          # verify pixel values
          UpperCAmelCase          =       torch.Size([1, 3, 8_0_0, 1_0_6_6]				)
          self.assertEqual(encoding['pixel_values'].shape ,							lowercase_				)

          UpperCAmelCase          =       torch.tensor([0.2_7_9_6, 0.3_1_3_8, 0.3_4_8_1]				)
          self.assertTrue(torch.allclose(encoding['pixel_values'][0, 0, 0, :3] ,							lowercase_ ,							atol=1E-4				)				)

          # verify area
          UpperCAmelCase          =       torch.tensor([1_4_7_9_7_9.6_8_7_5, 1_6_5_5_2_7.0_4_6_9, 4_8_4_6_3_8.5_9_3_8, 1_1_2_9_2.9_3_7_5, 5_8_7_9.6_5_6_2, 7_6_3_4.1_1_4_7]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['area'] ,							lowercase_				)				)
          # verify boxes
          UpperCAmelCase          =       torch.Size([6, 4]				)
          self.assertEqual(encoding['labels'][0]['boxes'].shape ,							lowercase_				)
          UpperCAmelCase          =       torch.tensor([0.2_6_2_5, 0.5_4_3_7, 0.4_6_8_8, 0.8_6_2_5]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['boxes'][0] ,							lowercase_ ,							atol=1E-3				)				)
          # verify image_id
          UpperCAmelCase          =       torch.tensor([3_9_7_6_9]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['image_id'] ,							lowercase_				)				)
          # verify is_crowd
          UpperCAmelCase          =       torch.tensor([0, 0, 0, 0, 0, 0]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['iscrowd'] ,							lowercase_				)				)
          # verify class_labels
          UpperCAmelCase          =       torch.tensor([1_7, 1_7, 6_3, 7_5, 7_5, 9_3]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['class_labels'] ,							lowercase_				)				)
          # verify masks
          UpperCAmelCase          =       8_2_2_8_7_3
          self.assertEqual(encoding['labels'][0]['masks'].sum().item() ,							lowercase_				)
          # verify orig_size
          UpperCAmelCase          =       torch.tensor([4_8_0, 6_4_0]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['orig_size'] ,							lowercase_				)				)
          # verify size
          UpperCAmelCase          =       torch.tensor([8_0_0, 1_0_6_6]				)
          self.assertTrue(torch.allclose(encoding['labels'][0]['size'] ,							lowercase_				)				)



